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