xref: /optee_os/core/include/drivers/gpio.h (revision 39d1e320ec639a05e1c04b4fe1729904a0399f2b)
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