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
3539d1e320SPatrick Delaunay #define GPIO_FLAGS_BIT_DIR_SET BIT(0)
3639d1e320SPatrick Delaunay #define GPIO_FLAGS_BIT_DIR_OUT BIT(1)
3739d1e320SPatrick Delaunay #define GPIO_FLAGS_BIT_DIR_VAL BIT(2)
3839d1e320SPatrick Delaunay
3939d1e320SPatrick Delaunay /**
4039d1e320SPatrick Delaunay * enum gpio_flags - Optional flags that are used to configure direction and
4139d1e320SPatrick Delaunay * output value. These values cannot be OR'd.
4239d1e320SPatrick Delaunay *
4339d1e320SPatrick Delaunay * @GPIOD_ASIS: Don't change anything
4439d1e320SPatrick Delaunay * @GPIO_IN: Set line to input mode
4539d1e320SPatrick Delaunay * @GPIO_OUT_LOW: Set line to output and drive it low
4639d1e320SPatrick Delaunay * @GPIO_OUT_HIGH: Set line to output and drive it high
4739d1e320SPatrick Delaunay
4839d1e320SPatrick Delaunay */
4939d1e320SPatrick Delaunay enum gpio_flags {
5039d1e320SPatrick Delaunay GPIO_ASIS = 0,
5139d1e320SPatrick Delaunay GPIO_IN = GPIO_FLAGS_BIT_DIR_SET,
5239d1e320SPatrick Delaunay GPIO_OUT_LOW = GPIO_FLAGS_BIT_DIR_SET | GPIO_FLAGS_BIT_DIR_OUT,
5339d1e320SPatrick Delaunay GPIO_OUT_HIGH = GPIO_FLAGS_BIT_DIR_SET | GPIO_FLAGS_BIT_DIR_OUT |
5439d1e320SPatrick Delaunay GPIO_FLAGS_BIT_DIR_VAL,
5539d1e320SPatrick Delaunay };
5639d1e320SPatrick 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);
98*396e1f07SPatrick Delaunay /* Configure GPIO resources, based on dt_flags */
99*396e1f07SPatrick Delaunay TEE_Result (*configure)(struct gpio_chip *chip, struct gpio *gpio);
10083f24981SEtienne Carriere /* Release GPIO resources */
10183f24981SEtienne Carriere void (*put)(struct gpio_chip *chip, struct gpio *gpio);
1026dcd18c8SClément Léger };
1036dcd18c8SClément Léger
1044fc179b6SThomas Perrot /*
1054fc179b6SThomas Perrot * struct gpio - GPIO pin description
1064fc179b6SThomas Perrot * @chip: GPIO controller chip reference
1074fc179b6SThomas Perrot * @dt_flags: Pin boolean properties set from DT node
1084fc179b6SThomas Perrot * @pin: Pin number in GPIO controller
1094fc179b6SThomas Perrot */
1104fc179b6SThomas Perrot struct gpio {
1114fc179b6SThomas Perrot struct gpio_chip *chip;
1124fc179b6SThomas Perrot uint32_t dt_flags;
1134fc179b6SThomas Perrot unsigned int pin;
1144fc179b6SThomas Perrot };
1154fc179b6SThomas Perrot
gpio_ops_is_valid(const struct gpio_ops * ops)1164fc179b6SThomas Perrot static inline bool gpio_ops_is_valid(const struct gpio_ops *ops)
1174fc179b6SThomas Perrot {
1184fc179b6SThomas Perrot return ops->set_direction && ops->get_direction && ops->get_value &&
1194fc179b6SThomas Perrot ops->set_value;
1204fc179b6SThomas Perrot }
1214fc179b6SThomas Perrot
gpio_set_direction(struct gpio * gpio,enum gpio_dir dir)1224fc179b6SThomas Perrot static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir)
1234fc179b6SThomas Perrot {
1244fc179b6SThomas Perrot gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir);
1254fc179b6SThomas Perrot }
1264fc179b6SThomas Perrot
gpio_get_direction(struct gpio * gpio)1274fc179b6SThomas Perrot static inline enum gpio_dir gpio_get_direction(struct gpio *gpio)
1284fc179b6SThomas Perrot {
1294fc179b6SThomas Perrot return gpio->chip->ops->get_direction(gpio->chip, gpio->pin);
1304fc179b6SThomas Perrot }
1314fc179b6SThomas Perrot
gpio_set_value(struct gpio * gpio,enum gpio_level value)1324fc179b6SThomas Perrot static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value)
1334fc179b6SThomas Perrot {
1344fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW)
1354fc179b6SThomas Perrot value = !value;
1364fc179b6SThomas Perrot
1374fc179b6SThomas Perrot gpio->chip->ops->set_value(gpio->chip, gpio->pin, value);
1384fc179b6SThomas Perrot }
1394fc179b6SThomas Perrot
gpio_get_value(struct gpio * gpio)1404fc179b6SThomas Perrot static inline enum gpio_level gpio_get_value(struct gpio *gpio)
1414fc179b6SThomas Perrot {
1424fc179b6SThomas Perrot enum gpio_level value = GPIO_LEVEL_LOW;
1434fc179b6SThomas Perrot
1444fc179b6SThomas Perrot value = gpio->chip->ops->get_value(gpio->chip, gpio->pin);
1454fc179b6SThomas Perrot
1464fc179b6SThomas Perrot if (gpio->dt_flags & GPIO_ACTIVE_LOW)
1474fc179b6SThomas Perrot value = !value;
1484fc179b6SThomas Perrot
1494fc179b6SThomas Perrot return value;
1504fc179b6SThomas Perrot }
1514fc179b6SThomas Perrot
gpio_put(struct gpio * gpio)15283f24981SEtienne Carriere static inline void gpio_put(struct gpio *gpio)
15383f24981SEtienne Carriere {
15483f24981SEtienne Carriere assert(!gpio || (gpio->chip && gpio->chip->ops));
15583f24981SEtienne Carriere
15683f24981SEtienne Carriere if (gpio && gpio->chip->ops->put)
15783f24981SEtienne Carriere gpio->chip->ops->put(gpio->chip, gpio);
15883f24981SEtienne Carriere }
15983f24981SEtienne Carriere
16039d1e320SPatrick Delaunay /**
16139d1e320SPatrick Delaunay * gpio_configure() - Configure a GPIO controller
16239d1e320SPatrick Delaunay *
16339d1e320SPatrick Delaunay * @gpio: GPIO pin
16439d1e320SPatrick Delaunay * @flags: requester flags of GPIO
16539d1e320SPatrick Delaunay *
16639d1e320SPatrick Delaunay * Return TEE_SUCCESS in case of success
16739d1e320SPatrick Delaunay * Return a TEE_Result compliant code in case of error
16839d1e320SPatrick Delaunay */
16939d1e320SPatrick Delaunay TEE_Result gpio_configure(struct gpio *gpio, enum gpio_flags flags);
17039d1e320SPatrick Delaunay
1714fc179b6SThomas Perrot #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO)
1724fc179b6SThomas Perrot /**
1734fc179b6SThomas Perrot * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle
1744fc179b6SThomas Perrot *
1758fd620f7SEtienne Carriere * @pargs: Pointer to devicetree description of the GPIO controller to parse
1764fc179b6SThomas Perrot * @res: Output result code of the operation:
1774fc179b6SThomas Perrot * TEE_SUCCESS in case of success
1784fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
1794fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error.
1804fc179b6SThomas Perrot *
1814fc179b6SThomas Perrot * Returns a struct gpio pointer pointing to a GPIO instance matching
1824fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case
1834fc179b6SThomas Perrot * @res provides the error code.
1844fc179b6SThomas Perrot */
185b357d34fSEtienne Carriere TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **gpio);
1864fc179b6SThomas Perrot
1874fc179b6SThomas Perrot /**
1884fc179b6SThomas Perrot * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in
189a37f67edSPatrick Delaunay * 'gpios' or 'gpio' properties with or without prefixes.
1904fc179b6SThomas Perrot *
1914fc179b6SThomas Perrot * @fdt: Device tree to work on
192a37f67edSPatrick Delaunay * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio'
193a37f67edSPatrick Delaunay * property.
194a37f67edSPatrick Delaunay * @index: GPIO pin index in 'gpios' property find in device tree.
195a37f67edSPatrick Delaunay * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree,
196a37f67edSPatrick Delaunay * can be NULL to search for 'gpios' or 'gpio' properties
1974fc179b6SThomas Perrot * @gpio: Output GPIO pin reference upon success
1984fc179b6SThomas Perrot *
1994fc179b6SThomas Perrot * Return TEE_SUCCESS in case of success
2004fc179b6SThomas Perrot * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
2014fc179b6SThomas Perrot * Return a TEE_Result compliant code in case of error
2024fc179b6SThomas Perrot */
2034fc179b6SThomas Perrot TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset,
2044fc179b6SThomas Perrot unsigned int index, const char *gpio_name,
2054fc179b6SThomas Perrot struct gpio **gpio);
20639d1e320SPatrick Delaunay
20739d1e320SPatrick Delaunay /**
20839d1e320SPatrick Delaunay * gpio_dt_cfg_by_index() - Get a GPIO controller at a specific index in
20939d1e320SPatrick Delaunay * 'gpios' or 'gpio' properties (possibly prefixed) and configure it with
21039d1e320SPatrick Delaunay * flags.
21139d1e320SPatrick Delaunay *
21239d1e320SPatrick Delaunay * @fdt: Device tree to work on
21339d1e320SPatrick Delaunay * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio'
21439d1e320SPatrick Delaunay * property.
21539d1e320SPatrick Delaunay * @index: GPIO pin index in 'gpios' property to get in device tree.
21639d1e320SPatrick Delaunay * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree,
21739d1e320SPatrick Delaunay * can be NULL to search for 'gpios' or 'gpio' properties
21839d1e320SPatrick Delaunay * @flags: Configuration flags for the GPIO
21939d1e320SPatrick Delaunay * @gpio: Output GPIO pin reference upon success
22039d1e320SPatrick Delaunay *
22139d1e320SPatrick Delaunay * Return TEE_SUCCESS in case of success
22239d1e320SPatrick Delaunay * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
22339d1e320SPatrick Delaunay * Return a TEE_Result compliant code in case of error
22439d1e320SPatrick Delaunay */
22539d1e320SPatrick Delaunay TEE_Result gpio_dt_cfg_by_index(const void *fdt, int nodeoffset,
22639d1e320SPatrick Delaunay unsigned int index, const char *gpio_name,
22739d1e320SPatrick Delaunay enum gpio_flags flags, struct gpio **gpio);
2284fc179b6SThomas Perrot #else
gpio_dt_get_by_index(const void * fdt __unused,int nodeoffset __unused,unsigned int index __unused,const char * gpio_name __unused,struct gpio ** gpio __unused)2294fc179b6SThomas Perrot static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused,
2304fc179b6SThomas Perrot int nodeoffset __unused,
2314fc179b6SThomas Perrot unsigned int index __unused,
2324fc179b6SThomas Perrot const char *gpio_name __unused,
233b357d34fSEtienne Carriere struct gpio **gpio __unused)
2344fc179b6SThomas Perrot {
2354fc179b6SThomas Perrot return TEE_ERROR_NOT_SUPPORTED;
2364fc179b6SThomas Perrot }
2374fc179b6SThomas Perrot
gpio_dt_cfg_by_index(const void * fdt __unused,int nodeoffset __unused,unsigned int index __unused,const char * gpio_name __unused,enum gpio_flags flags __unused,struct gpio ** gpio __unused)23839d1e320SPatrick Delaunay static inline TEE_Result gpio_dt_cfg_by_index(const void *fdt __unused,
23939d1e320SPatrick Delaunay int nodeoffset __unused,
24039d1e320SPatrick Delaunay unsigned int index __unused,
24139d1e320SPatrick Delaunay const char *gpio_name __unused,
24239d1e320SPatrick Delaunay enum gpio_flags flags __unused,
24339d1e320SPatrick Delaunay struct gpio **gpio __unused)
24439d1e320SPatrick Delaunay {
24539d1e320SPatrick Delaunay return TEE_ERROR_NOT_SUPPORTED;
24639d1e320SPatrick Delaunay }
24739d1e320SPatrick Delaunay
gpio_dt_alloc_pin(struct dt_pargs * pargs __unused,struct gpio ** gpio __unused)248b357d34fSEtienne Carriere static inline TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs __unused,
249b357d34fSEtienne Carriere struct gpio **gpio __unused)
2504fc179b6SThomas Perrot {
251b357d34fSEtienne Carriere return TEE_ERROR_NOT_SUPPORTED;
2524fc179b6SThomas Perrot }
2534fc179b6SThomas Perrot #endif /*CFG_DT*/
2544fc179b6SThomas Perrot
2554fc179b6SThomas Perrot /**
2564fc179b6SThomas Perrot * gpio_dt_get_func - Typedef of function to get GPIO instance from
2574fc179b6SThomas Perrot * devicetree properties
2584fc179b6SThomas Perrot *
2598fd620f7SEtienne Carriere * @pargs: Pointer to GPIO phandle and its argument in the FDT
2604fc179b6SThomas Perrot * @data: Pointer to the data given at gpio_dt_register_provider() call
2614fc179b6SThomas Perrot * @res: Output result code of the operation:
2624fc179b6SThomas Perrot * TEE_SUCCESS in case of success
2634fc179b6SThomas Perrot * TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
2644fc179b6SThomas Perrot * Any TEE_Result compliant code in case of error.
2654fc179b6SThomas Perrot *
2664fc179b6SThomas Perrot * Returns a struct GPIO pointer pointing to a GPIO instance matching
2674fc179b6SThomas Perrot * the devicetree description or NULL if invalid description in which case
2684fc179b6SThomas Perrot * @res provides the error code.
2694fc179b6SThomas Perrot */
270b357d34fSEtienne Carriere typedef TEE_Result (*gpio_dt_get_func)(struct dt_pargs *pargs, void *data,
271b357d34fSEtienne Carriere struct gpio **out_gpio);
2724fc179b6SThomas Perrot
2734fc179b6SThomas Perrot /**
2744fc179b6SThomas Perrot * gpio_dt_register_provider() - Register a GPIO controller provider
2754fc179b6SThomas Perrot *
2764fc179b6SThomas Perrot * @fdt: Device tree to work on
2774fc179b6SThomas Perrot * @nodeoffset: Node offset of the GPIO controller
2784fc179b6SThomas Perrot * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio
2794fc179b6SThomas Perrot * @data: Opaque reference which will be passed to the get_dt_gpio callback
2804fc179b6SThomas Perrot * Returns TEE_Result value
2814fc179b6SThomas Perrot */
gpio_register_provider(const void * fdt,int nodeoffset,gpio_dt_get_func get_dt_gpio,void * data)2824fc179b6SThomas Perrot static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset,
2834fc179b6SThomas Perrot gpio_dt_get_func get_dt_gpio,
2844fc179b6SThomas Perrot void *data)
2854fc179b6SThomas Perrot {
2864fc179b6SThomas Perrot return dt_driver_register_provider(fdt, nodeoffset,
2874fc179b6SThomas Perrot (get_of_device_func)get_dt_gpio,
2884fc179b6SThomas Perrot data, DT_DRIVER_GPIO);
2894fc179b6SThomas Perrot }
2904fc179b6SThomas Perrot
291d50fee03SEtienne Carriere #endif /* __DRIVERS_GPIO_H */
292