xref: /optee_os/core/include/drivers/gpio.h (revision 4fc179b6919181df142772f53cc26cd107fed69f)
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*4fc179b6SThomas Perrot #include <dt-bindings/gpio/gpio.h>
10*4fc179b6SThomas Perrot #include <kernel/dt_driver.h>
11*4fc179b6SThomas Perrot #include <stdint.h>
12*4fc179b6SThomas Perrot #include <tee_api_types.h>
13*4fc179b6SThomas Perrot 
14*4fc179b6SThomas Perrot /**
15*4fc179b6SThomas Perrot  * GPIO_DT_DECLARE - Declare a GPIO controller driver with a single
16*4fc179b6SThomas Perrot  * device tree compatible string.
17*4fc179b6SThomas Perrot  *
18*4fc179b6SThomas Perrot  * @__name: GPIO controller driver name
19*4fc179b6SThomas Perrot  * @__compat: Compatible string
20*4fc179b6SThomas Perrot  * @__probe: GPIO controller probe function
21*4fc179b6SThomas Perrot  */
22*4fc179b6SThomas Perrot #define GPIO_DT_DECLARE(__name, __compat, __probe) \
23*4fc179b6SThomas Perrot 	static const struct dt_device_match __name ## _match_table[] = { \
24*4fc179b6SThomas Perrot 		{ .compatible = __compat }, \
25*4fc179b6SThomas Perrot 		{ } \
26*4fc179b6SThomas Perrot 	}; \
27*4fc179b6SThomas Perrot 	DEFINE_DT_DRIVER(__name ## _dt_driver) = { \
28*4fc179b6SThomas Perrot 		.name = # __name, \
29*4fc179b6SThomas Perrot 		.type = DT_DRIVER_GPIO, \
30*4fc179b6SThomas Perrot 		.match_table = __name ## _match_table, \
31*4fc179b6SThomas Perrot 		.probe = __probe, \
32*4fc179b6SThomas Perrot 	}
33*4fc179b6SThomas Perrot 
346dcd18c8SClément Léger enum gpio_dir {
356dcd18c8SClément Léger 	GPIO_DIR_OUT,
366dcd18c8SClément Léger 	GPIO_DIR_IN
376dcd18c8SClément Léger };
386dcd18c8SClément Léger 
396dcd18c8SClément Léger enum gpio_level {
406dcd18c8SClément Léger 	GPIO_LEVEL_LOW,
416dcd18c8SClément Léger 	GPIO_LEVEL_HIGH
426dcd18c8SClément Léger };
436dcd18c8SClément Léger 
446dcd18c8SClément Léger enum gpio_interrupt {
456dcd18c8SClément Léger 	GPIO_INTERRUPT_DISABLE,
466dcd18c8SClément Léger 	GPIO_INTERRUPT_ENABLE
476dcd18c8SClément Léger };
486dcd18c8SClément Léger 
496dcd18c8SClément Léger struct gpio_chip {
506dcd18c8SClément Léger 	const struct gpio_ops *ops;
516dcd18c8SClément Léger };
526dcd18c8SClément Léger 
536dcd18c8SClément Léger struct gpio_ops {
546dcd18c8SClément Léger 	enum gpio_dir (*get_direction)(struct gpio_chip *chip,
556dcd18c8SClément Léger 				       unsigned int gpio_pin);
566dcd18c8SClément Léger 	void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin,
576dcd18c8SClément Léger 			      enum gpio_dir direction);
586dcd18c8SClément Léger 	enum gpio_level (*get_value)(struct gpio_chip *chip,
596dcd18c8SClément Léger 				     unsigned int gpio_pin);
606dcd18c8SClément Léger 	void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin,
616dcd18c8SClément Léger 			  enum gpio_level value);
626dcd18c8SClément Léger 	enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip,
636dcd18c8SClément Léger 					     unsigned int gpio_pin);
646dcd18c8SClément Léger 	void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin,
656dcd18c8SClément Léger 			      enum gpio_interrupt enable_disable);
666dcd18c8SClément Léger };
676dcd18c8SClément Léger 
68*4fc179b6SThomas Perrot /*
69*4fc179b6SThomas Perrot  * struct gpio - GPIO pin description
70*4fc179b6SThomas Perrot  * @chip: GPIO controller chip reference
71*4fc179b6SThomas Perrot  * @dt_flags: Pin boolean properties set from DT node
72*4fc179b6SThomas Perrot  * @pin: Pin number in GPIO controller
73*4fc179b6SThomas Perrot  */
74*4fc179b6SThomas Perrot struct gpio {
75*4fc179b6SThomas Perrot 	struct gpio_chip *chip;
76*4fc179b6SThomas Perrot 	uint32_t dt_flags;
77*4fc179b6SThomas Perrot 	unsigned int pin;
78*4fc179b6SThomas Perrot };
79*4fc179b6SThomas Perrot 
80*4fc179b6SThomas Perrot static inline bool gpio_ops_is_valid(const struct gpio_ops *ops)
81*4fc179b6SThomas Perrot {
82*4fc179b6SThomas Perrot 	return ops->set_direction && ops->get_direction && ops->get_value &&
83*4fc179b6SThomas Perrot 	       ops->set_value;
84*4fc179b6SThomas Perrot }
85*4fc179b6SThomas Perrot 
86*4fc179b6SThomas Perrot static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir)
87*4fc179b6SThomas Perrot {
88*4fc179b6SThomas Perrot 	gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir);
89*4fc179b6SThomas Perrot }
90*4fc179b6SThomas Perrot 
91*4fc179b6SThomas Perrot static inline enum gpio_dir gpio_get_direction(struct gpio *gpio)
92*4fc179b6SThomas Perrot {
93*4fc179b6SThomas Perrot 	return gpio->chip->ops->get_direction(gpio->chip, gpio->pin);
94*4fc179b6SThomas Perrot }
95*4fc179b6SThomas Perrot 
96*4fc179b6SThomas Perrot static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value)
97*4fc179b6SThomas Perrot {
98*4fc179b6SThomas Perrot 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
99*4fc179b6SThomas Perrot 		value = !value;
100*4fc179b6SThomas Perrot 
101*4fc179b6SThomas Perrot 	gpio->chip->ops->set_value(gpio->chip, gpio->pin, value);
102*4fc179b6SThomas Perrot }
103*4fc179b6SThomas Perrot 
104*4fc179b6SThomas Perrot static inline enum gpio_level gpio_get_value(struct gpio *gpio)
105*4fc179b6SThomas Perrot {
106*4fc179b6SThomas Perrot 	enum gpio_level value = GPIO_LEVEL_LOW;
107*4fc179b6SThomas Perrot 
108*4fc179b6SThomas Perrot 	value = gpio->chip->ops->get_value(gpio->chip, gpio->pin);
109*4fc179b6SThomas Perrot 
110*4fc179b6SThomas Perrot 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
111*4fc179b6SThomas Perrot 		value = !value;
112*4fc179b6SThomas Perrot 
113*4fc179b6SThomas Perrot 	return value;
114*4fc179b6SThomas Perrot }
115*4fc179b6SThomas Perrot 
116*4fc179b6SThomas Perrot #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO)
117*4fc179b6SThomas Perrot /**
118*4fc179b6SThomas Perrot  * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle
119*4fc179b6SThomas Perrot  *
120*4fc179b6SThomas Perrot  * @a: Pointer to devicetree description of the GPIO controller to parse
121*4fc179b6SThomas Perrot  * @res: Output result code of the operation:
122*4fc179b6SThomas Perrot  *	TEE_SUCCESS in case of success
123*4fc179b6SThomas Perrot  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
124*4fc179b6SThomas Perrot  *	Any TEE_Result compliant code in case of error.
125*4fc179b6SThomas Perrot  *
126*4fc179b6SThomas Perrot  * Returns a struct gpio pointer pointing to a GPIO instance matching
127*4fc179b6SThomas Perrot  * the devicetree description or NULL if invalid description in which case
128*4fc179b6SThomas Perrot  * @res provides the error code.
129*4fc179b6SThomas Perrot  */
130*4fc179b6SThomas Perrot struct gpio *gpio_dt_alloc_pin(struct dt_driver_phandle_args *a,
131*4fc179b6SThomas Perrot 			       TEE_Result *res);
132*4fc179b6SThomas Perrot 
133*4fc179b6SThomas Perrot /**
134*4fc179b6SThomas Perrot  * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in
135*4fc179b6SThomas Perrot  * 'gpios' property
136*4fc179b6SThomas Perrot  *
137*4fc179b6SThomas Perrot  * @fdt: Device tree to work on
138*4fc179b6SThomas Perrot  * @nodeoffset: Node offset of the subnode containing a 'gpios' property
139*4fc179b6SThomas Perrot  * @index: GPIO pin index in '*-gpios' property
140*4fc179b6SThomas Perrot  * @gpio_name: Name of the GPIO pin
141*4fc179b6SThomas Perrot  * @gpio: Output GPIO pin reference upon success
142*4fc179b6SThomas Perrot  *
143*4fc179b6SThomas Perrot  * Return TEE_SUCCESS in case of success
144*4fc179b6SThomas Perrot  * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
145*4fc179b6SThomas Perrot  * Return a TEE_Result compliant code in case of error
146*4fc179b6SThomas Perrot  */
147*4fc179b6SThomas Perrot TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset,
148*4fc179b6SThomas Perrot 				unsigned int index, const char *gpio_name,
149*4fc179b6SThomas Perrot 				struct gpio **gpio);
150*4fc179b6SThomas Perrot #else
151*4fc179b6SThomas Perrot static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused,
152*4fc179b6SThomas Perrot 					      int nodeoffset __unused,
153*4fc179b6SThomas Perrot 					      unsigned int index  __unused,
154*4fc179b6SThomas Perrot 					      const char *gpio_name  __unused,
155*4fc179b6SThomas Perrot 					      struct gpio **gpio)
156*4fc179b6SThomas Perrot {
157*4fc179b6SThomas Perrot 	*gpio = NULL;
158*4fc179b6SThomas Perrot 	return TEE_ERROR_NOT_SUPPORTED;
159*4fc179b6SThomas Perrot }
160*4fc179b6SThomas Perrot 
161*4fc179b6SThomas Perrot static inline
162*4fc179b6SThomas Perrot struct gpio *gpio_dt_alloc_pin(struct dt_driver_phandle_args *a __unused,
163*4fc179b6SThomas Perrot 			       TEE_Result *res)
164*4fc179b6SThomas Perrot {
165*4fc179b6SThomas Perrot 	*res = TEE_ERROR_NOT_SUPPORTED;
166*4fc179b6SThomas Perrot 	return NULL;
167*4fc179b6SThomas Perrot }
168*4fc179b6SThomas Perrot #endif /*CFG_DT*/
169*4fc179b6SThomas Perrot 
170*4fc179b6SThomas Perrot /**
171*4fc179b6SThomas Perrot  * gpio_dt_get_func - Typedef of function to get GPIO instance from
172*4fc179b6SThomas Perrot  * devicetree properties
173*4fc179b6SThomas Perrot  *
174*4fc179b6SThomas Perrot  * @a: Pointer to GPIO phandle and its argument in the FDT
175*4fc179b6SThomas Perrot  * @data: Pointer to the data given at gpio_dt_register_provider() call
176*4fc179b6SThomas Perrot  * @res: Output result code of the operation:
177*4fc179b6SThomas Perrot  *	TEE_SUCCESS in case of success
178*4fc179b6SThomas Perrot  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
179*4fc179b6SThomas Perrot  *	Any TEE_Result compliant code in case of error.
180*4fc179b6SThomas Perrot  *
181*4fc179b6SThomas Perrot  * Returns a struct GPIO pointer pointing to a GPIO instance matching
182*4fc179b6SThomas Perrot  * the devicetree description or NULL if invalid description in which case
183*4fc179b6SThomas Perrot  * @res provides the error code.
184*4fc179b6SThomas Perrot  */
185*4fc179b6SThomas Perrot typedef struct gpio *(*gpio_dt_get_func)(struct dt_driver_phandle_args *a,
186*4fc179b6SThomas Perrot 					 void *data, TEE_Result *res);
187*4fc179b6SThomas Perrot 
188*4fc179b6SThomas Perrot /**
189*4fc179b6SThomas Perrot  * gpio_dt_register_provider() - Register a GPIO controller provider
190*4fc179b6SThomas Perrot  *
191*4fc179b6SThomas Perrot  * @fdt: Device tree to work on
192*4fc179b6SThomas Perrot  * @nodeoffset: Node offset of the GPIO controller
193*4fc179b6SThomas Perrot  * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio
194*4fc179b6SThomas Perrot  * @data: Opaque reference which will be passed to the get_dt_gpio callback
195*4fc179b6SThomas Perrot  * Returns TEE_Result value
196*4fc179b6SThomas Perrot  */
197*4fc179b6SThomas Perrot static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset,
198*4fc179b6SThomas Perrot 						gpio_dt_get_func get_dt_gpio,
199*4fc179b6SThomas Perrot 						void *data)
200*4fc179b6SThomas Perrot {
201*4fc179b6SThomas Perrot 	return dt_driver_register_provider(fdt, nodeoffset,
202*4fc179b6SThomas Perrot 					   (get_of_device_func)get_dt_gpio,
203*4fc179b6SThomas Perrot 					   data, DT_DRIVER_GPIO);
204*4fc179b6SThomas Perrot }
205*4fc179b6SThomas Perrot 
2066dcd18c8SClément Léger #endif	/* DRIVERS_GPIO_H */
207