xref: /optee_os/core/include/drivers/gpio.h (revision 39d1e320ec639a05e1c04b4fe1729904a0399f2b)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2016, Linaro Limited
4  */
5 
6 #ifndef __DRIVERS_GPIO_H
7 #define __DRIVERS_GPIO_H
8 
9 #include <assert.h>
10 #include <dt-bindings/gpio/gpio.h>
11 #include <kernel/dt_driver.h>
12 #include <stdint.h>
13 #include <tee_api_types.h>
14 
15 /**
16  * GPIO_DT_DECLARE - Declare a GPIO controller driver with a single
17  * device tree compatible string.
18  *
19  * @__name: GPIO controller driver name
20  * @__compat: Compatible string
21  * @__probe: GPIO controller probe function
22  */
23 #define GPIO_DT_DECLARE(__name, __compat, __probe) \
24 	static const struct dt_device_match __name ## _match_table[] = { \
25 		{ .compatible = __compat }, \
26 		{ } \
27 	}; \
28 	DEFINE_DT_DRIVER(__name ## _dt_driver) = { \
29 		.name = # __name, \
30 		.type = DT_DRIVER_GPIO, \
31 		.match_table = __name ## _match_table, \
32 		.probe = __probe, \
33 	}
34 
35 #define GPIO_FLAGS_BIT_DIR_SET		BIT(0)
36 #define GPIO_FLAGS_BIT_DIR_OUT		BIT(1)
37 #define GPIO_FLAGS_BIT_DIR_VAL		BIT(2)
38 
39 /**
40  * enum gpio_flags - Optional flags that are used to configure direction and
41  *                   output value. These values cannot be OR'd.
42  *
43  * @GPIOD_ASIS:		Don't change anything
44  * @GPIO_IN:		Set line to input mode
45  * @GPIO_OUT_LOW:	Set line to output and drive it low
46  * @GPIO_OUT_HIGH:	Set line to output and drive it high
47 
48  */
49 enum gpio_flags {
50 	GPIO_ASIS	= 0,
51 	GPIO_IN		= GPIO_FLAGS_BIT_DIR_SET,
52 	GPIO_OUT_LOW	= GPIO_FLAGS_BIT_DIR_SET | GPIO_FLAGS_BIT_DIR_OUT,
53 	GPIO_OUT_HIGH	= GPIO_FLAGS_BIT_DIR_SET | GPIO_FLAGS_BIT_DIR_OUT |
54 			  GPIO_FLAGS_BIT_DIR_VAL,
55 };
56 
57 enum gpio_dir {
58 	GPIO_DIR_OUT,
59 	GPIO_DIR_IN
60 };
61 
62 enum gpio_level {
63 	GPIO_LEVEL_LOW,
64 	GPIO_LEVEL_HIGH
65 };
66 
67 enum gpio_interrupt {
68 	GPIO_INTERRUPT_DISABLE,
69 	GPIO_INTERRUPT_ENABLE
70 };
71 
72 struct gpio;
73 struct gpio_ops;
74 
75 struct gpio_chip {
76 	const struct gpio_ops *ops;
77 };
78 
79 struct gpio_ops {
80 	/* Get GPIO direction current configuration */
81 	enum gpio_dir (*get_direction)(struct gpio_chip *chip,
82 				       unsigned int gpio_pin);
83 	/* Set GPIO direction configuration */
84 	void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin,
85 			      enum gpio_dir direction);
86 	/* Get GPIO current level */
87 	enum gpio_level (*get_value)(struct gpio_chip *chip,
88 				     unsigned int gpio_pin);
89 	/* Set GPIO level */
90 	void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin,
91 			  enum gpio_level value);
92 	/* Get GPIO interrupt state */
93 	enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip,
94 					     unsigned int gpio_pin);
95 	/* Enable or disable a GPIO interrupt */
96 	void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin,
97 			      enum gpio_interrupt enable_disable);
98 	/* Release GPIO resources */
99 	void (*put)(struct gpio_chip *chip, struct gpio *gpio);
100 };
101 
102 /*
103  * struct gpio - GPIO pin description
104  * @chip: GPIO controller chip reference
105  * @dt_flags: Pin boolean properties set from DT node
106  * @pin: Pin number in GPIO controller
107  */
108 struct gpio {
109 	struct gpio_chip *chip;
110 	uint32_t dt_flags;
111 	unsigned int pin;
112 };
113 
114 static inline bool gpio_ops_is_valid(const struct gpio_ops *ops)
115 {
116 	return ops->set_direction && ops->get_direction && ops->get_value &&
117 	       ops->set_value;
118 }
119 
120 static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir)
121 {
122 	gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir);
123 }
124 
125 static inline enum gpio_dir gpio_get_direction(struct gpio *gpio)
126 {
127 	return gpio->chip->ops->get_direction(gpio->chip, gpio->pin);
128 }
129 
130 static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value)
131 {
132 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
133 		value = !value;
134 
135 	gpio->chip->ops->set_value(gpio->chip, gpio->pin, value);
136 }
137 
138 static inline enum gpio_level gpio_get_value(struct gpio *gpio)
139 {
140 	enum gpio_level value = GPIO_LEVEL_LOW;
141 
142 	value = gpio->chip->ops->get_value(gpio->chip, gpio->pin);
143 
144 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
145 		value = !value;
146 
147 	return value;
148 }
149 
150 static inline void gpio_put(struct gpio *gpio)
151 {
152 	assert(!gpio || (gpio->chip && gpio->chip->ops));
153 
154 	if (gpio && gpio->chip->ops->put)
155 		gpio->chip->ops->put(gpio->chip, gpio);
156 }
157 
158 /**
159  * gpio_configure() - Configure a GPIO controller
160  *
161  * @gpio: GPIO pin
162  * @flags: requester flags of GPIO
163  *
164  * Return TEE_SUCCESS in case of success
165  * Return a TEE_Result compliant code in case of error
166  */
167 TEE_Result gpio_configure(struct gpio *gpio, enum gpio_flags flags);
168 
169 #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO)
170 /**
171  * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle
172  *
173  * @pargs: Pointer to devicetree description of the GPIO controller to parse
174  * @res: Output result code of the operation:
175  *	TEE_SUCCESS in case of success
176  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
177  *	Any TEE_Result compliant code in case of error.
178  *
179  * Returns a struct gpio pointer pointing to a GPIO instance matching
180  * the devicetree description or NULL if invalid description in which case
181  * @res provides the error code.
182  */
183 TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **gpio);
184 
185 /**
186  * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in
187  * 'gpios' or 'gpio' properties with or without prefixes.
188  *
189  * @fdt: Device tree to work on
190  * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio'
191  *		property.
192  * @index: GPIO pin index in 'gpios' property find in device tree.
193  * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree,
194  *	       can be NULL to search for 'gpios' or 'gpio' properties
195  * @gpio: Output GPIO pin reference upon success
196  *
197  * Return TEE_SUCCESS in case of success
198  * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
199  * Return a TEE_Result compliant code in case of error
200  */
201 TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset,
202 				unsigned int index, const char *gpio_name,
203 				struct gpio **gpio);
204 
205 /**
206  * gpio_dt_cfg_by_index() - Get a GPIO controller at a specific index in
207  * 'gpios' or 'gpio' properties (possibly prefixed) and configure it with
208  * flags.
209  *
210  * @fdt: Device tree to work on
211  * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio'
212  *		property.
213  * @index: GPIO pin index in 'gpios' property to get in device tree.
214  * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree,
215  *	       can be NULL to search for 'gpios' or 'gpio' properties
216  * @flags: Configuration flags for the GPIO
217  * @gpio: Output GPIO pin reference upon success
218  *
219  * Return TEE_SUCCESS in case of success
220  * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
221  * Return a TEE_Result compliant code in case of error
222  */
223 TEE_Result gpio_dt_cfg_by_index(const void *fdt, int nodeoffset,
224 				unsigned int index, const char *gpio_name,
225 				enum gpio_flags flags, struct gpio **gpio);
226 #else
227 static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused,
228 					      int nodeoffset __unused,
229 					      unsigned int index __unused,
230 					      const char *gpio_name __unused,
231 					      struct gpio **gpio __unused)
232 {
233 	return TEE_ERROR_NOT_SUPPORTED;
234 }
235 
236 static inline TEE_Result gpio_dt_cfg_by_index(const void *fdt __unused,
237 					      int nodeoffset __unused,
238 					      unsigned int index  __unused,
239 					      const char *gpio_name  __unused,
240 					      enum gpio_flags flags __unused,
241 					      struct gpio **gpio __unused)
242 {
243 	return TEE_ERROR_NOT_SUPPORTED;
244 }
245 
246 static inline TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs __unused,
247 					   struct gpio **gpio __unused)
248 {
249 	return TEE_ERROR_NOT_SUPPORTED;
250 }
251 #endif /*CFG_DT*/
252 
253 /**
254  * gpio_dt_get_func - Typedef of function to get GPIO instance from
255  * devicetree properties
256  *
257  * @pargs: Pointer to GPIO phandle and its argument in the FDT
258  * @data: Pointer to the data given at gpio_dt_register_provider() call
259  * @res: Output result code of the operation:
260  *	TEE_SUCCESS in case of success
261  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
262  *	Any TEE_Result compliant code in case of error.
263  *
264  * Returns a struct GPIO pointer pointing to a GPIO instance matching
265  * the devicetree description or NULL if invalid description in which case
266  * @res provides the error code.
267  */
268 typedef TEE_Result (*gpio_dt_get_func)(struct dt_pargs *pargs, void *data,
269 				       struct gpio **out_gpio);
270 
271 /**
272  * gpio_dt_register_provider() - Register a GPIO controller provider
273  *
274  * @fdt: Device tree to work on
275  * @nodeoffset: Node offset of the GPIO controller
276  * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio
277  * @data: Opaque reference which will be passed to the get_dt_gpio callback
278  * Returns TEE_Result value
279  */
280 static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset,
281 						gpio_dt_get_func get_dt_gpio,
282 						void *data)
283 {
284 	return dt_driver_register_provider(fdt, nodeoffset,
285 					   (get_of_device_func)get_dt_gpio,
286 					   data, DT_DRIVER_GPIO);
287 }
288 
289 #endif	/* __DRIVERS_GPIO_H */
290