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 9*83f24981SEtienne 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 50*83f24981SEtienne Carriere struct gpio; 51*83f24981SEtienne Carriere struct gpio_ops; 52*83f24981SEtienne 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 { 586dcd18c8SClément Léger enum gpio_dir (*get_direction)(struct gpio_chip *chip, 596dcd18c8SClément Léger unsigned int gpio_pin); 606dcd18c8SClément Léger void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin, 616dcd18c8SClément Léger enum gpio_dir direction); 626dcd18c8SClément Léger enum gpio_level (*get_value)(struct gpio_chip *chip, 636dcd18c8SClément Léger unsigned int gpio_pin); 646dcd18c8SClément Léger void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin, 656dcd18c8SClément Léger enum gpio_level value); 666dcd18c8SClément Léger enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip, 676dcd18c8SClément Léger unsigned int gpio_pin); 686dcd18c8SClément Léger void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin, 696dcd18c8SClément Léger enum gpio_interrupt enable_disable); 70*83f24981SEtienne Carriere /* Release GPIO resources */ 71*83f24981SEtienne Carriere void (*put)(struct gpio_chip *chip, struct gpio *gpio); 726dcd18c8SClément Léger }; 736dcd18c8SClément Léger 744fc179b6SThomas Perrot /* 754fc179b6SThomas Perrot * struct gpio - GPIO pin description 764fc179b6SThomas Perrot * @chip: GPIO controller chip reference 774fc179b6SThomas Perrot * @dt_flags: Pin boolean properties set from DT node 784fc179b6SThomas Perrot * @pin: Pin number in GPIO controller 794fc179b6SThomas Perrot */ 804fc179b6SThomas Perrot struct gpio { 814fc179b6SThomas Perrot struct gpio_chip *chip; 824fc179b6SThomas Perrot uint32_t dt_flags; 834fc179b6SThomas Perrot unsigned int pin; 844fc179b6SThomas Perrot }; 854fc179b6SThomas Perrot 864fc179b6SThomas Perrot static inline bool gpio_ops_is_valid(const struct gpio_ops *ops) 874fc179b6SThomas Perrot { 884fc179b6SThomas Perrot return ops->set_direction && ops->get_direction && ops->get_value && 894fc179b6SThomas Perrot ops->set_value; 904fc179b6SThomas Perrot } 914fc179b6SThomas Perrot 924fc179b6SThomas Perrot static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir) 934fc179b6SThomas Perrot { 944fc179b6SThomas Perrot gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir); 954fc179b6SThomas Perrot } 964fc179b6SThomas Perrot 974fc179b6SThomas Perrot static inline enum gpio_dir gpio_get_direction(struct gpio *gpio) 984fc179b6SThomas Perrot { 994fc179b6SThomas Perrot return gpio->chip->ops->get_direction(gpio->chip, gpio->pin); 1004fc179b6SThomas Perrot } 1014fc179b6SThomas Perrot 1024fc179b6SThomas Perrot static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value) 1034fc179b6SThomas Perrot { 1044fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW) 1054fc179b6SThomas Perrot value = !value; 1064fc179b6SThomas Perrot 1074fc179b6SThomas Perrot gpio->chip->ops->set_value(gpio->chip, gpio->pin, value); 1084fc179b6SThomas Perrot } 1094fc179b6SThomas Perrot 1104fc179b6SThomas Perrot static inline enum gpio_level gpio_get_value(struct gpio *gpio) 1114fc179b6SThomas Perrot { 1124fc179b6SThomas Perrot enum gpio_level value = GPIO_LEVEL_LOW; 1134fc179b6SThomas Perrot 1144fc179b6SThomas Perrot value = gpio->chip->ops->get_value(gpio->chip, gpio->pin); 1154fc179b6SThomas Perrot 1164fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW) 1174fc179b6SThomas Perrot value = !value; 1184fc179b6SThomas Perrot 1194fc179b6SThomas Perrot return value; 1204fc179b6SThomas Perrot } 1214fc179b6SThomas Perrot 122*83f24981SEtienne Carriere static inline void gpio_put(struct gpio *gpio) 123*83f24981SEtienne Carriere { 124*83f24981SEtienne Carriere assert(!gpio || (gpio->chip && gpio->chip->ops)); 125*83f24981SEtienne Carriere 126*83f24981SEtienne Carriere if (gpio && gpio->chip->ops->put) 127*83f24981SEtienne Carriere gpio->chip->ops->put(gpio->chip, gpio); 128*83f24981SEtienne Carriere } 129*83f24981SEtienne Carriere 1304fc179b6SThomas Perrot #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO) 1314fc179b6SThomas Perrot /** 1324fc179b6SThomas Perrot * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle 1334fc179b6SThomas Perrot * 1344fc179b6SThomas Perrot * @a: Pointer to devicetree description of the GPIO controller to parse 1354fc179b6SThomas Perrot * @res: Output result code of the operation: 1364fc179b6SThomas Perrot * TEE_SUCCESS in case of success 1374fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1384fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error. 1394fc179b6SThomas Perrot * 1404fc179b6SThomas Perrot * Returns a struct gpio pointer pointing to a GPIO instance matching 1414fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case 1424fc179b6SThomas Perrot * @res provides the error code. 1434fc179b6SThomas Perrot */ 1444fc179b6SThomas Perrot struct gpio *gpio_dt_alloc_pin(struct dt_driver_phandle_args *a, 1454fc179b6SThomas Perrot TEE_Result *res); 1464fc179b6SThomas Perrot 1474fc179b6SThomas Perrot /** 1484fc179b6SThomas Perrot * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in 1494fc179b6SThomas Perrot * 'gpios' property 1504fc179b6SThomas Perrot * 1514fc179b6SThomas Perrot * @fdt: Device tree to work on 1524fc179b6SThomas Perrot * @nodeoffset: Node offset of the subnode containing a 'gpios' property 1534fc179b6SThomas Perrot * @index: GPIO pin index in '*-gpios' property 1544fc179b6SThomas Perrot * @gpio_name: Name of the GPIO pin 1554fc179b6SThomas Perrot * @gpio: Output GPIO pin reference upon success 1564fc179b6SThomas Perrot * 1574fc179b6SThomas Perrot * Return TEE_SUCCESS in case of success 1584fc179b6SThomas Perrot * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1594fc179b6SThomas Perrot * Return a TEE_Result compliant code in case of error 1604fc179b6SThomas Perrot */ 1614fc179b6SThomas Perrot TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset, 1624fc179b6SThomas Perrot unsigned int index, const char *gpio_name, 1634fc179b6SThomas Perrot struct gpio **gpio); 1644fc179b6SThomas Perrot #else 1654fc179b6SThomas Perrot static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused, 1664fc179b6SThomas Perrot int nodeoffset __unused, 1674fc179b6SThomas Perrot unsigned int index __unused, 1684fc179b6SThomas Perrot const char *gpio_name __unused, 1694fc179b6SThomas Perrot struct gpio **gpio) 1704fc179b6SThomas Perrot { 1714fc179b6SThomas Perrot *gpio = NULL; 1724fc179b6SThomas Perrot return TEE_ERROR_NOT_SUPPORTED; 1734fc179b6SThomas Perrot } 1744fc179b6SThomas Perrot 1754fc179b6SThomas Perrot static inline 1764fc179b6SThomas Perrot struct gpio *gpio_dt_alloc_pin(struct dt_driver_phandle_args *a __unused, 1774fc179b6SThomas Perrot TEE_Result *res) 1784fc179b6SThomas Perrot { 1794fc179b6SThomas Perrot *res = TEE_ERROR_NOT_SUPPORTED; 1804fc179b6SThomas Perrot return NULL; 1814fc179b6SThomas Perrot } 1824fc179b6SThomas Perrot #endif /*CFG_DT*/ 1834fc179b6SThomas Perrot 1844fc179b6SThomas Perrot /** 1854fc179b6SThomas Perrot * gpio_dt_get_func - Typedef of function to get GPIO instance from 1864fc179b6SThomas Perrot * devicetree properties 1874fc179b6SThomas Perrot * 1884fc179b6SThomas Perrot * @a: Pointer to GPIO phandle and its argument in the FDT 1894fc179b6SThomas Perrot * @data: Pointer to the data given at gpio_dt_register_provider() call 1904fc179b6SThomas Perrot * @res: Output result code of the operation: 1914fc179b6SThomas Perrot * TEE_SUCCESS in case of success 1924fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized 1934fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error. 1944fc179b6SThomas Perrot * 1954fc179b6SThomas Perrot * Returns a struct GPIO pointer pointing to a GPIO instance matching 1964fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case 1974fc179b6SThomas Perrot * @res provides the error code. 1984fc179b6SThomas Perrot */ 1994fc179b6SThomas Perrot typedef struct gpio *(*gpio_dt_get_func)(struct dt_driver_phandle_args *a, 2004fc179b6SThomas Perrot void *data, TEE_Result *res); 2014fc179b6SThomas Perrot 2024fc179b6SThomas Perrot /** 2034fc179b6SThomas Perrot * gpio_dt_register_provider() - Register a GPIO controller provider 2044fc179b6SThomas Perrot * 2054fc179b6SThomas Perrot * @fdt: Device tree to work on 2064fc179b6SThomas Perrot * @nodeoffset: Node offset of the GPIO controller 2074fc179b6SThomas Perrot * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio 2084fc179b6SThomas Perrot * @data: Opaque reference which will be passed to the get_dt_gpio callback 2094fc179b6SThomas Perrot * Returns TEE_Result value 2104fc179b6SThomas Perrot */ 2114fc179b6SThomas Perrot static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset, 2124fc179b6SThomas Perrot gpio_dt_get_func get_dt_gpio, 2134fc179b6SThomas Perrot void *data) 2144fc179b6SThomas Perrot { 2154fc179b6SThomas Perrot return dt_driver_register_provider(fdt, nodeoffset, 2164fc179b6SThomas Perrot (get_of_device_func)get_dt_gpio, 2174fc179b6SThomas Perrot data, DT_DRIVER_GPIO); 2184fc179b6SThomas Perrot } 2194fc179b6SThomas Perrot 2206dcd18c8SClément Léger #endif /* DRIVERS_GPIO_H */ 221