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 66dcd18c8SClément Léger #ifndef DRIVERS_GPIO_H 76dcd18c8SClément Léger #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 356dcd18c8SClément Léger enum gpio_dir { 366dcd18c8SClément Léger GPIO_DIR_OUT, 376dcd18c8SClément Léger GPIO_DIR_IN 386dcd18c8SClément Léger }; 396dcd18c8SClément Léger 406dcd18c8SClément Léger enum gpio_level { 416dcd18c8SClément Léger GPIO_LEVEL_LOW, 426dcd18c8SClément Léger GPIO_LEVEL_HIGH 436dcd18c8SClément Léger }; 446dcd18c8SClément Léger 456dcd18c8SClément Léger enum gpio_interrupt { 466dcd18c8SClément Léger GPIO_INTERRUPT_DISABLE, 476dcd18c8SClément Léger GPIO_INTERRUPT_ENABLE 486dcd18c8SClément Léger }; 496dcd18c8SClément Léger 5083f24981SEtienne Carriere struct gpio; 5183f24981SEtienne Carriere struct gpio_ops; 5283f24981SEtienne Carriere 536dcd18c8SClément Léger struct gpio_chip { 546dcd18c8SClément Léger const struct gpio_ops *ops; 556dcd18c8SClément Léger }; 566dcd18c8SClément Léger 576dcd18c8SClément Léger struct gpio_ops { 5824b364c8SEtienne Carriere /* Get GPIO direction current configuration */ 596dcd18c8SClément Léger enum gpio_dir (*get_direction)(struct gpio_chip *chip, 606dcd18c8SClément Léger unsigned int gpio_pin); 6124b364c8SEtienne Carriere /* Set GPIO direction configuration */ 626dcd18c8SClément Léger void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin, 636dcd18c8SClément Léger enum gpio_dir direction); 6424b364c8SEtienne Carriere /* Get GPIO current level */ 656dcd18c8SClément Léger enum gpio_level (*get_value)(struct gpio_chip *chip, 666dcd18c8SClément Léger unsigned int gpio_pin); 6724b364c8SEtienne Carriere /* Set GPIO level */ 686dcd18c8SClément Léger void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin, 696dcd18c8SClément Léger enum gpio_level value); 7024b364c8SEtienne Carriere /* Get GPIO interrupt state */ 716dcd18c8SClément Léger enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip, 726dcd18c8SClément Léger unsigned int gpio_pin); 7324b364c8SEtienne Carriere /* Enable or disable a GPIO interrupt */ 746dcd18c8SClément Léger void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin, 756dcd18c8SClément Léger enum gpio_interrupt enable_disable); 7683f24981SEtienne Carriere /* Release GPIO resources */ 7783f24981SEtienne Carriere void (*put)(struct gpio_chip *chip, struct gpio *gpio); 786dcd18c8SClément Léger }; 796dcd18c8SClément Léger 804fc179b6SThomas Perrot /* 814fc179b6SThomas Perrot * struct gpio - GPIO pin description 824fc179b6SThomas Perrot * @chip: GPIO controller chip reference 834fc179b6SThomas Perrot * @dt_flags: Pin boolean properties set from DT node 844fc179b6SThomas Perrot * @pin: Pin number in GPIO controller 854fc179b6SThomas Perrot */ 864fc179b6SThomas Perrot struct gpio { 874fc179b6SThomas Perrot struct gpio_chip *chip; 884fc179b6SThomas Perrot uint32_t dt_flags; 894fc179b6SThomas Perrot unsigned int pin; 904fc179b6SThomas Perrot }; 914fc179b6SThomas Perrot 924fc179b6SThomas Perrot static inline bool gpio_ops_is_valid(const struct gpio_ops *ops) 934fc179b6SThomas Perrot { 944fc179b6SThomas Perrot return ops->set_direction && ops->get_direction && ops->get_value && 954fc179b6SThomas Perrot ops->set_value; 964fc179b6SThomas Perrot } 974fc179b6SThomas Perrot 984fc179b6SThomas Perrot static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir) 994fc179b6SThomas Perrot { 1004fc179b6SThomas Perrot gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir); 1014fc179b6SThomas Perrot } 1024fc179b6SThomas Perrot 1034fc179b6SThomas Perrot static inline enum gpio_dir gpio_get_direction(struct gpio *gpio) 1044fc179b6SThomas Perrot { 1054fc179b6SThomas Perrot return gpio->chip->ops->get_direction(gpio->chip, gpio->pin); 1064fc179b6SThomas Perrot } 1074fc179b6SThomas Perrot 1084fc179b6SThomas Perrot static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value) 1094fc179b6SThomas Perrot { 1104fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW) 1114fc179b6SThomas Perrot value = !value; 1124fc179b6SThomas Perrot 1134fc179b6SThomas Perrot gpio->chip->ops->set_value(gpio->chip, gpio->pin, value); 1144fc179b6SThomas Perrot } 1154fc179b6SThomas Perrot 1164fc179b6SThomas Perrot static inline enum gpio_level gpio_get_value(struct gpio *gpio) 1174fc179b6SThomas Perrot { 1184fc179b6SThomas Perrot enum gpio_level value = GPIO_LEVEL_LOW; 1194fc179b6SThomas Perrot 1204fc179b6SThomas Perrot value = gpio->chip->ops->get_value(gpio->chip, gpio->pin); 1214fc179b6SThomas Perrot 1224fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW) 1234fc179b6SThomas Perrot value = !value; 1244fc179b6SThomas Perrot 1254fc179b6SThomas Perrot return value; 1264fc179b6SThomas Perrot } 1274fc179b6SThomas Perrot 12883f24981SEtienne Carriere static inline void gpio_put(struct gpio *gpio) 12983f24981SEtienne Carriere { 13083f24981SEtienne Carriere assert(!gpio || (gpio->chip && gpio->chip->ops)); 13183f24981SEtienne Carriere 13283f24981SEtienne Carriere if (gpio && gpio->chip->ops->put) 13383f24981SEtienne Carriere gpio->chip->ops->put(gpio->chip, gpio); 13483f24981SEtienne Carriere } 13583f24981SEtienne Carriere 1364fc179b6SThomas Perrot #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO) 1374fc179b6SThomas Perrot /** 1384fc179b6SThomas Perrot * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle 1394fc179b6SThomas Perrot * 140*8fd620f7SEtienne Carriere * @pargs: Pointer to devicetree description of the GPIO controller to parse 1414fc179b6SThomas Perrot * @res: Output result code of the operation: 1424fc179b6SThomas Perrot * TEE_SUCCESS in case of success 1434fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1444fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error. 1454fc179b6SThomas Perrot * 1464fc179b6SThomas Perrot * Returns a struct gpio pointer pointing to a GPIO instance matching 1474fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case 1484fc179b6SThomas Perrot * @res provides the error code. 1494fc179b6SThomas Perrot */ 150*8fd620f7SEtienne Carriere struct gpio *gpio_dt_alloc_pin(struct dt_pargs *pargs, TEE_Result *res); 1514fc179b6SThomas Perrot 1524fc179b6SThomas Perrot /** 1534fc179b6SThomas Perrot * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in 1544fc179b6SThomas Perrot * 'gpios' property 1554fc179b6SThomas Perrot * 1564fc179b6SThomas Perrot * @fdt: Device tree to work on 1574fc179b6SThomas Perrot * @nodeoffset: Node offset of the subnode containing a 'gpios' property 1584fc179b6SThomas Perrot * @index: GPIO pin index in '*-gpios' property 1594fc179b6SThomas Perrot * @gpio_name: Name of the GPIO pin 1604fc179b6SThomas Perrot * @gpio: Output GPIO pin reference upon success 1614fc179b6SThomas Perrot * 1624fc179b6SThomas Perrot * Return TEE_SUCCESS in case of success 1634fc179b6SThomas Perrot * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1644fc179b6SThomas Perrot * Return a TEE_Result compliant code in case of error 1654fc179b6SThomas Perrot */ 1664fc179b6SThomas Perrot TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, 1674fc179b6SThomas Perrot unsigned int index, const char *gpio_name, 1684fc179b6SThomas Perrot struct gpio **gpio); 1694fc179b6SThomas Perrot #else 1704fc179b6SThomas Perrot static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused, 1714fc179b6SThomas Perrot int nodeoffset __unused, 1724fc179b6SThomas Perrot unsigned int index __unused, 1734fc179b6SThomas Perrot const char *gpio_name __unused, 1744fc179b6SThomas Perrot struct gpio **gpio) 1754fc179b6SThomas Perrot { 1764fc179b6SThomas Perrot *gpio = NULL; 1774fc179b6SThomas Perrot return TEE_ERROR_NOT_SUPPORTED; 1784fc179b6SThomas Perrot } 1794fc179b6SThomas Perrot 180*8fd620f7SEtienne Carriere static inline struct gpio *gpio_dt_alloc_pin(struct dt_pargs *pargs __unused, 1814fc179b6SThomas Perrot TEE_Result *res) 1824fc179b6SThomas Perrot { 1834fc179b6SThomas Perrot *res = TEE_ERROR_NOT_SUPPORTED; 1844fc179b6SThomas Perrot return NULL; 1854fc179b6SThomas Perrot } 1864fc179b6SThomas Perrot #endif /*CFG_DT*/ 1874fc179b6SThomas Perrot 1884fc179b6SThomas Perrot /** 1894fc179b6SThomas Perrot * gpio_dt_get_func - Typedef of function to get GPIO instance from 1904fc179b6SThomas Perrot * devicetree properties 1914fc179b6SThomas Perrot * 192*8fd620f7SEtienne Carriere * @pargs: Pointer to GPIO phandle and its argument in the FDT 1934fc179b6SThomas Perrot * @data: Pointer to the data given at gpio_dt_register_provider() call 1944fc179b6SThomas Perrot * @res: Output result code of the operation: 1954fc179b6SThomas Perrot * TEE_SUCCESS in case of success 1964fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1974fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error. 1984fc179b6SThomas Perrot * 1994fc179b6SThomas Perrot * Returns a struct GPIO pointer pointing to a GPIO instance matching 2004fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case 2014fc179b6SThomas Perrot * @res provides the error code. 2024fc179b6SThomas Perrot */ 203*8fd620f7SEtienne Carriere typedef struct gpio *(*gpio_dt_get_func)(struct dt_pargs *pargs, void *data, 204*8fd620f7SEtienne Carriere TEE_Result *res); 2054fc179b6SThomas Perrot 2064fc179b6SThomas Perrot /** 2074fc179b6SThomas Perrot * gpio_dt_register_provider() - Register a GPIO controller provider 2084fc179b6SThomas Perrot * 2094fc179b6SThomas Perrot * @fdt: Device tree to work on 2104fc179b6SThomas Perrot * @nodeoffset: Node offset of the GPIO controller 2114fc179b6SThomas Perrot * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio 2124fc179b6SThomas Perrot * @data: Opaque reference which will be passed to the get_dt_gpio callback 2134fc179b6SThomas Perrot * Returns TEE_Result value 2144fc179b6SThomas Perrot */ 2154fc179b6SThomas Perrot static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset, 2164fc179b6SThomas Perrot gpio_dt_get_func get_dt_gpio, 2174fc179b6SThomas Perrot void *data) 2184fc179b6SThomas Perrot { 2194fc179b6SThomas Perrot return dt_driver_register_provider(fdt, nodeoffset, 2204fc179b6SThomas Perrot (get_of_device_func)get_dt_gpio, 2214fc179b6SThomas Perrot data, DT_DRIVER_GPIO); 2224fc179b6SThomas Perrot } 2234fc179b6SThomas Perrot 2246dcd18c8SClément Léger #endif /* DRIVERS_GPIO_H */ 225