16dcd18c8SClément Léger /* SPDX-License-Identifier: BSD-2-Clause */ 26dcd18c8SClément Léger /* 36dcd18c8SClément Léger * Copyright (c) 2016, Linaro Limited 46dcd18c8SClément Léger */ 56dcd18c8SClément Léger 6d50fee03SEtienne Carriere #ifndef __DRIVERS_GPIO_H 7d50fee03SEtienne Carriere #define __DRIVERS_GPIO_H 86dcd18c8SClément Léger 983f24981SEtienne Carriere #include <assert.h> 104fc179b6SThomas Perrot #include <dt-bindings/gpio/gpio.h> 114fc179b6SThomas Perrot #include <kernel/dt_driver.h> 124fc179b6SThomas Perrot #include <stdint.h> 134fc179b6SThomas Perrot #include <tee_api_types.h> 144fc179b6SThomas Perrot 154fc179b6SThomas Perrot /** 164fc179b6SThomas Perrot * GPIO_DT_DECLARE - Declare a GPIO controller driver with a single 174fc179b6SThomas Perrot * device tree compatible string. 184fc179b6SThomas Perrot * 194fc179b6SThomas Perrot * @__name: GPIO controller driver name 204fc179b6SThomas Perrot * @__compat: Compatible string 214fc179b6SThomas Perrot * @__probe: GPIO controller probe function 224fc179b6SThomas Perrot */ 234fc179b6SThomas Perrot #define GPIO_DT_DECLARE(__name, __compat, __probe) \ 244fc179b6SThomas Perrot static const struct dt_device_match __name ## _match_table[] = { \ 254fc179b6SThomas Perrot { .compatible = __compat }, \ 264fc179b6SThomas Perrot { } \ 274fc179b6SThomas Perrot }; \ 284fc179b6SThomas Perrot DEFINE_DT_DRIVER(__name ## _dt_driver) = { \ 294fc179b6SThomas Perrot .name = # __name, \ 304fc179b6SThomas Perrot .type = DT_DRIVER_GPIO, \ 314fc179b6SThomas Perrot .match_table = __name ## _match_table, \ 324fc179b6SThomas Perrot .probe = __probe, \ 334fc179b6SThomas Perrot } 344fc179b6SThomas Perrot 35*39d1e320SPatrick Delaunay #define GPIO_FLAGS_BIT_DIR_SET BIT(0) 36*39d1e320SPatrick Delaunay #define GPIO_FLAGS_BIT_DIR_OUT BIT(1) 37*39d1e320SPatrick Delaunay #define GPIO_FLAGS_BIT_DIR_VAL BIT(2) 38*39d1e320SPatrick Delaunay 39*39d1e320SPatrick Delaunay /** 40*39d1e320SPatrick Delaunay * enum gpio_flags - Optional flags that are used to configure direction and 41*39d1e320SPatrick Delaunay * output value. These values cannot be OR'd. 42*39d1e320SPatrick Delaunay * 43*39d1e320SPatrick Delaunay * @GPIOD_ASIS: Don't change anything 44*39d1e320SPatrick Delaunay * @GPIO_IN: Set line to input mode 45*39d1e320SPatrick Delaunay * @GPIO_OUT_LOW: Set line to output and drive it low 46*39d1e320SPatrick Delaunay * @GPIO_OUT_HIGH: Set line to output and drive it high 47*39d1e320SPatrick Delaunay 48*39d1e320SPatrick Delaunay */ 49*39d1e320SPatrick Delaunay enum gpio_flags { 50*39d1e320SPatrick Delaunay GPIO_ASIS = 0, 51*39d1e320SPatrick Delaunay GPIO_IN = GPIO_FLAGS_BIT_DIR_SET, 52*39d1e320SPatrick Delaunay GPIO_OUT_LOW = GPIO_FLAGS_BIT_DIR_SET | GPIO_FLAGS_BIT_DIR_OUT, 53*39d1e320SPatrick Delaunay GPIO_OUT_HIGH = GPIO_FLAGS_BIT_DIR_SET | GPIO_FLAGS_BIT_DIR_OUT | 54*39d1e320SPatrick Delaunay GPIO_FLAGS_BIT_DIR_VAL, 55*39d1e320SPatrick Delaunay }; 56*39d1e320SPatrick Delaunay 576dcd18c8SClément Léger enum gpio_dir { 586dcd18c8SClément Léger GPIO_DIR_OUT, 596dcd18c8SClément Léger GPIO_DIR_IN 606dcd18c8SClément Léger }; 616dcd18c8SClément Léger 626dcd18c8SClément Léger enum gpio_level { 636dcd18c8SClément Léger GPIO_LEVEL_LOW, 646dcd18c8SClément Léger GPIO_LEVEL_HIGH 656dcd18c8SClément Léger }; 666dcd18c8SClément Léger 676dcd18c8SClément Léger enum gpio_interrupt { 686dcd18c8SClément Léger GPIO_INTERRUPT_DISABLE, 696dcd18c8SClément Léger GPIO_INTERRUPT_ENABLE 706dcd18c8SClément Léger }; 716dcd18c8SClément Léger 7283f24981SEtienne Carriere struct gpio; 7383f24981SEtienne Carriere struct gpio_ops; 7483f24981SEtienne Carriere 756dcd18c8SClément Léger struct gpio_chip { 766dcd18c8SClément Léger const struct gpio_ops *ops; 776dcd18c8SClément Léger }; 786dcd18c8SClément Léger 796dcd18c8SClément Léger struct gpio_ops { 8024b364c8SEtienne Carriere /* Get GPIO direction current configuration */ 816dcd18c8SClément Léger enum gpio_dir (*get_direction)(struct gpio_chip *chip, 826dcd18c8SClément Léger unsigned int gpio_pin); 8324b364c8SEtienne Carriere /* Set GPIO direction configuration */ 846dcd18c8SClément Léger void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin, 856dcd18c8SClément Léger enum gpio_dir direction); 8624b364c8SEtienne Carriere /* Get GPIO current level */ 876dcd18c8SClément Léger enum gpio_level (*get_value)(struct gpio_chip *chip, 886dcd18c8SClément Léger unsigned int gpio_pin); 8924b364c8SEtienne Carriere /* Set GPIO level */ 906dcd18c8SClément Léger void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin, 916dcd18c8SClément Léger enum gpio_level value); 9224b364c8SEtienne Carriere /* Get GPIO interrupt state */ 936dcd18c8SClément Léger enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip, 946dcd18c8SClément Léger unsigned int gpio_pin); 9524b364c8SEtienne Carriere /* Enable or disable a GPIO interrupt */ 966dcd18c8SClément Léger void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin, 976dcd18c8SClément Léger enum gpio_interrupt enable_disable); 9883f24981SEtienne Carriere /* Release GPIO resources */ 9983f24981SEtienne Carriere void (*put)(struct gpio_chip *chip, struct gpio *gpio); 1006dcd18c8SClément Léger }; 1016dcd18c8SClément Léger 1024fc179b6SThomas Perrot /* 1034fc179b6SThomas Perrot * struct gpio - GPIO pin description 1044fc179b6SThomas Perrot * @chip: GPIO controller chip reference 1054fc179b6SThomas Perrot * @dt_flags: Pin boolean properties set from DT node 1064fc179b6SThomas Perrot * @pin: Pin number in GPIO controller 1074fc179b6SThomas Perrot */ 1084fc179b6SThomas Perrot struct gpio { 1094fc179b6SThomas Perrot struct gpio_chip *chip; 1104fc179b6SThomas Perrot uint32_t dt_flags; 1114fc179b6SThomas Perrot unsigned int pin; 1124fc179b6SThomas Perrot }; 1134fc179b6SThomas Perrot 1144fc179b6SThomas Perrot static inline bool gpio_ops_is_valid(const struct gpio_ops *ops) 1154fc179b6SThomas Perrot { 1164fc179b6SThomas Perrot return ops->set_direction && ops->get_direction && ops->get_value && 1174fc179b6SThomas Perrot ops->set_value; 1184fc179b6SThomas Perrot } 1194fc179b6SThomas Perrot 1204fc179b6SThomas Perrot static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir) 1214fc179b6SThomas Perrot { 1224fc179b6SThomas Perrot gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir); 1234fc179b6SThomas Perrot } 1244fc179b6SThomas Perrot 1254fc179b6SThomas Perrot static inline enum gpio_dir gpio_get_direction(struct gpio *gpio) 1264fc179b6SThomas Perrot { 1274fc179b6SThomas Perrot return gpio->chip->ops->get_direction(gpio->chip, gpio->pin); 1284fc179b6SThomas Perrot } 1294fc179b6SThomas Perrot 1304fc179b6SThomas Perrot static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value) 1314fc179b6SThomas Perrot { 1324fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW) 1334fc179b6SThomas Perrot value = !value; 1344fc179b6SThomas Perrot 1354fc179b6SThomas Perrot gpio->chip->ops->set_value(gpio->chip, gpio->pin, value); 1364fc179b6SThomas Perrot } 1374fc179b6SThomas Perrot 1384fc179b6SThomas Perrot static inline enum gpio_level gpio_get_value(struct gpio *gpio) 1394fc179b6SThomas Perrot { 1404fc179b6SThomas Perrot enum gpio_level value = GPIO_LEVEL_LOW; 1414fc179b6SThomas Perrot 1424fc179b6SThomas Perrot value = gpio->chip->ops->get_value(gpio->chip, gpio->pin); 1434fc179b6SThomas Perrot 1444fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW) 1454fc179b6SThomas Perrot value = !value; 1464fc179b6SThomas Perrot 1474fc179b6SThomas Perrot return value; 1484fc179b6SThomas Perrot } 1494fc179b6SThomas Perrot 15083f24981SEtienne Carriere static inline void gpio_put(struct gpio *gpio) 15183f24981SEtienne Carriere { 15283f24981SEtienne Carriere assert(!gpio || (gpio->chip && gpio->chip->ops)); 15383f24981SEtienne Carriere 15483f24981SEtienne Carriere if (gpio && gpio->chip->ops->put) 15583f24981SEtienne Carriere gpio->chip->ops->put(gpio->chip, gpio); 15683f24981SEtienne Carriere } 15783f24981SEtienne Carriere 158*39d1e320SPatrick Delaunay /** 159*39d1e320SPatrick Delaunay * gpio_configure() - Configure a GPIO controller 160*39d1e320SPatrick Delaunay * 161*39d1e320SPatrick Delaunay * @gpio: GPIO pin 162*39d1e320SPatrick Delaunay * @flags: requester flags of GPIO 163*39d1e320SPatrick Delaunay * 164*39d1e320SPatrick Delaunay * Return TEE_SUCCESS in case of success 165*39d1e320SPatrick Delaunay * Return a TEE_Result compliant code in case of error 166*39d1e320SPatrick Delaunay */ 167*39d1e320SPatrick Delaunay TEE_Result gpio_configure(struct gpio *gpio, enum gpio_flags flags); 168*39d1e320SPatrick Delaunay 1694fc179b6SThomas Perrot #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO) 1704fc179b6SThomas Perrot /** 1714fc179b6SThomas Perrot * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle 1724fc179b6SThomas Perrot * 1738fd620f7SEtienne Carriere * @pargs: Pointer to devicetree description of the GPIO controller to parse 1744fc179b6SThomas Perrot * @res: Output result code of the operation: 1754fc179b6SThomas Perrot * TEE_SUCCESS in case of success 1764fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1774fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error. 1784fc179b6SThomas Perrot * 1794fc179b6SThomas Perrot * Returns a struct gpio pointer pointing to a GPIO instance matching 1804fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case 1814fc179b6SThomas Perrot * @res provides the error code. 1824fc179b6SThomas Perrot */ 183b357d34fSEtienne Carriere TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **gpio); 1844fc179b6SThomas Perrot 1854fc179b6SThomas Perrot /** 1864fc179b6SThomas Perrot * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in 187a37f67edSPatrick Delaunay * 'gpios' or 'gpio' properties with or without prefixes. 1884fc179b6SThomas Perrot * 1894fc179b6SThomas Perrot * @fdt: Device tree to work on 190a37f67edSPatrick Delaunay * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio' 191a37f67edSPatrick Delaunay * property. 192a37f67edSPatrick Delaunay * @index: GPIO pin index in 'gpios' property find in device tree. 193a37f67edSPatrick Delaunay * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree, 194a37f67edSPatrick Delaunay * can be NULL to search for 'gpios' or 'gpio' properties 1954fc179b6SThomas Perrot * @gpio: Output GPIO pin reference upon success 1964fc179b6SThomas Perrot * 1974fc179b6SThomas Perrot * Return TEE_SUCCESS in case of success 1984fc179b6SThomas Perrot * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1994fc179b6SThomas Perrot * Return a TEE_Result compliant code in case of error 2004fc179b6SThomas Perrot */ 2014fc179b6SThomas Perrot TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, 2024fc179b6SThomas Perrot unsigned int index, const char *gpio_name, 2034fc179b6SThomas Perrot struct gpio **gpio); 204*39d1e320SPatrick Delaunay 205*39d1e320SPatrick Delaunay /** 206*39d1e320SPatrick Delaunay * gpio_dt_cfg_by_index() - Get a GPIO controller at a specific index in 207*39d1e320SPatrick Delaunay * 'gpios' or 'gpio' properties (possibly prefixed) and configure it with 208*39d1e320SPatrick Delaunay * flags. 209*39d1e320SPatrick Delaunay * 210*39d1e320SPatrick Delaunay * @fdt: Device tree to work on 211*39d1e320SPatrick Delaunay * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio' 212*39d1e320SPatrick Delaunay * property. 213*39d1e320SPatrick Delaunay * @index: GPIO pin index in 'gpios' property to get in device tree. 214*39d1e320SPatrick Delaunay * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree, 215*39d1e320SPatrick Delaunay * can be NULL to search for 'gpios' or 'gpio' properties 216*39d1e320SPatrick Delaunay * @flags: Configuration flags for the GPIO 217*39d1e320SPatrick Delaunay * @gpio: Output GPIO pin reference upon success 218*39d1e320SPatrick Delaunay * 219*39d1e320SPatrick Delaunay * Return TEE_SUCCESS in case of success 220*39d1e320SPatrick Delaunay * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 221*39d1e320SPatrick Delaunay * Return a TEE_Result compliant code in case of error 222*39d1e320SPatrick Delaunay */ 223*39d1e320SPatrick Delaunay TEE_Result gpio_dt_cfg_by_index(const void *fdt, int nodeoffset, 224*39d1e320SPatrick Delaunay unsigned int index, const char *gpio_name, 225*39d1e320SPatrick Delaunay enum gpio_flags flags, struct gpio **gpio); 2264fc179b6SThomas Perrot #else 2274fc179b6SThomas Perrot static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused, 2284fc179b6SThomas Perrot int nodeoffset __unused, 2294fc179b6SThomas Perrot unsigned int index __unused, 2304fc179b6SThomas Perrot const char *gpio_name __unused, 231b357d34fSEtienne Carriere struct gpio **gpio __unused) 2324fc179b6SThomas Perrot { 2334fc179b6SThomas Perrot return TEE_ERROR_NOT_SUPPORTED; 2344fc179b6SThomas Perrot } 2354fc179b6SThomas Perrot 236*39d1e320SPatrick Delaunay static inline TEE_Result gpio_dt_cfg_by_index(const void *fdt __unused, 237*39d1e320SPatrick Delaunay int nodeoffset __unused, 238*39d1e320SPatrick Delaunay unsigned int index __unused, 239*39d1e320SPatrick Delaunay const char *gpio_name __unused, 240*39d1e320SPatrick Delaunay enum gpio_flags flags __unused, 241*39d1e320SPatrick Delaunay struct gpio **gpio __unused) 242*39d1e320SPatrick Delaunay { 243*39d1e320SPatrick Delaunay return TEE_ERROR_NOT_SUPPORTED; 244*39d1e320SPatrick Delaunay } 245*39d1e320SPatrick Delaunay 246b357d34fSEtienne Carriere static inline TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs __unused, 247b357d34fSEtienne Carriere struct gpio **gpio __unused) 2484fc179b6SThomas Perrot { 249b357d34fSEtienne Carriere return TEE_ERROR_NOT_SUPPORTED; 2504fc179b6SThomas Perrot } 2514fc179b6SThomas Perrot #endif /*CFG_DT*/ 2524fc179b6SThomas Perrot 2534fc179b6SThomas Perrot /** 2544fc179b6SThomas Perrot * gpio_dt_get_func - Typedef of function to get GPIO instance from 2554fc179b6SThomas Perrot * devicetree properties 2564fc179b6SThomas Perrot * 2578fd620f7SEtienne Carriere * @pargs: Pointer to GPIO phandle and its argument in the FDT 2584fc179b6SThomas Perrot * @data: Pointer to the data given at gpio_dt_register_provider() call 2594fc179b6SThomas Perrot * @res: Output result code of the operation: 2604fc179b6SThomas Perrot * TEE_SUCCESS in case of success 2614fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 2624fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error. 2634fc179b6SThomas Perrot * 2644fc179b6SThomas Perrot * Returns a struct GPIO pointer pointing to a GPIO instance matching 2654fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case 2664fc179b6SThomas Perrot * @res provides the error code. 2674fc179b6SThomas Perrot */ 268b357d34fSEtienne Carriere typedef TEE_Result (*gpio_dt_get_func)(struct dt_pargs *pargs, void *data, 269b357d34fSEtienne Carriere struct gpio **out_gpio); 2704fc179b6SThomas Perrot 2714fc179b6SThomas Perrot /** 2724fc179b6SThomas Perrot * gpio_dt_register_provider() - Register a GPIO controller provider 2734fc179b6SThomas Perrot * 2744fc179b6SThomas Perrot * @fdt: Device tree to work on 2754fc179b6SThomas Perrot * @nodeoffset: Node offset of the GPIO controller 2764fc179b6SThomas Perrot * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio 2774fc179b6SThomas Perrot * @data: Opaque reference which will be passed to the get_dt_gpio callback 2784fc179b6SThomas Perrot * Returns TEE_Result value 2794fc179b6SThomas Perrot */ 2804fc179b6SThomas Perrot static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset, 2814fc179b6SThomas Perrot gpio_dt_get_func get_dt_gpio, 2824fc179b6SThomas Perrot void *data) 2834fc179b6SThomas Perrot { 2844fc179b6SThomas Perrot return dt_driver_register_provider(fdt, nodeoffset, 2854fc179b6SThomas Perrot (get_of_device_func)get_dt_gpio, 2864fc179b6SThomas Perrot data, DT_DRIVER_GPIO); 2874fc179b6SThomas Perrot } 2884fc179b6SThomas Perrot 289d50fee03SEtienne Carriere #endif /* __DRIVERS_GPIO_H */ 290