xref: /optee_os/core/include/drivers/gpio.h (revision d34de1de016972ad8fb4370ee353eafc1a69cbe3)
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 	/* Configure GPIO resources, based on dt_flags */
99 	TEE_Result (*configure)(struct gpio_chip *chip, struct gpio *gpio);
100 	/* Release GPIO resources */
101 	void (*put)(struct gpio_chip *chip, struct gpio *gpio);
102 };
103 
104 /*
105  * struct gpio - GPIO pin description
106  * @chip: GPIO controller chip reference
107  * @dt_flags: Pin boolean properties set from DT node
108  * @pin: Pin number in GPIO controller
109  */
110 struct gpio {
111 	struct gpio_chip *chip;
112 	uint32_t dt_flags;
113 	unsigned int pin;
114 };
115 
116 static inline bool gpio_ops_is_valid(const struct gpio_ops *ops)
117 {
118 	return ops->set_direction && ops->get_direction && ops->get_value &&
119 	       ops->set_value;
120 }
121 
122 static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir)
123 {
124 	gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir);
125 }
126 
127 static inline enum gpio_dir gpio_get_direction(struct gpio *gpio)
128 {
129 	return gpio->chip->ops->get_direction(gpio->chip, gpio->pin);
130 }
131 
132 static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value)
133 {
134 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
135 		value = !value;
136 
137 	gpio->chip->ops->set_value(gpio->chip, gpio->pin, value);
138 }
139 
140 static inline enum gpio_level gpio_get_value(struct gpio *gpio)
141 {
142 	enum gpio_level value = GPIO_LEVEL_LOW;
143 
144 	value = gpio->chip->ops->get_value(gpio->chip, gpio->pin);
145 
146 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
147 		value = !value;
148 
149 	return value;
150 }
151 
152 static inline void gpio_put(struct gpio *gpio)
153 {
154 	assert(!gpio || (gpio->chip && gpio->chip->ops));
155 
156 	if (gpio && gpio->chip->ops->put)
157 		gpio->chip->ops->put(gpio->chip, gpio);
158 }
159 
160 /**
161  * gpio_configure() - Configure a GPIO controller
162  *
163  * @gpio: GPIO pin
164  * @flags: requester flags of GPIO
165  *
166  * Return TEE_SUCCESS in case of success
167  * Return a TEE_Result compliant code in case of error
168  */
169 TEE_Result gpio_configure(struct gpio *gpio, enum gpio_flags flags);
170 
171 #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO)
172 /**
173  * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle
174  *
175  * @pargs: Pointer to devicetree description of the GPIO controller to parse
176  * @res: Output result code of the operation:
177  *	TEE_SUCCESS in case of success
178  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
179  *	Any TEE_Result compliant code in case of error.
180  *
181  * Returns a struct gpio pointer pointing to a GPIO instance matching
182  * the devicetree description or NULL if invalid description in which case
183  * @res provides the error code.
184  */
185 TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **gpio);
186 
187 /**
188  * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in
189  * 'gpios' or 'gpio' properties with or without prefixes.
190  *
191  * @fdt: Device tree to work on
192  * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio'
193  *		property.
194  * @index: GPIO pin index in 'gpios' property find in device tree.
195  * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree,
196  *	       can be NULL to search for 'gpios' or 'gpio' properties
197  * @gpio: Output GPIO pin reference upon success
198  *
199  * Return TEE_SUCCESS in case of success
200  * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
201  * Return a TEE_Result compliant code in case of error
202  */
203 TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset,
204 				unsigned int index, const char *gpio_name,
205 				struct gpio **gpio);
206 
207 /**
208  * gpio_dt_cfg_by_index() - Get a GPIO controller at a specific index in
209  * 'gpios' or 'gpio' properties (possibly prefixed) and configure it with
210  * flags.
211  *
212  * @fdt: Device tree to work on
213  * @nodeoffset: Node offset of the subnode containing a 'gpios' or 'gpio'
214  *		property.
215  * @index: GPIO pin index in 'gpios' property to get in device tree.
216  * @gpio_name: Prefix of a '-gpios' or '-gpio' properties in device tree,
217  *	       can be NULL to search for 'gpios' or 'gpio' properties
218  * @flags: Configuration flags for the GPIO
219  * @gpio: Output GPIO pin reference upon success
220  *
221  * Return TEE_SUCCESS in case of success
222  * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
223  * Return a TEE_Result compliant code in case of error
224  */
225 TEE_Result gpio_dt_cfg_by_index(const void *fdt, int nodeoffset,
226 				unsigned int index, const char *gpio_name,
227 				enum gpio_flags flags, struct gpio **gpio);
228 #else
229 static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused,
230 					      int nodeoffset __unused,
231 					      unsigned int index __unused,
232 					      const char *gpio_name __unused,
233 					      struct gpio **gpio __unused)
234 {
235 	return TEE_ERROR_NOT_SUPPORTED;
236 }
237 
238 static inline TEE_Result gpio_dt_cfg_by_index(const void *fdt __unused,
239 					      int nodeoffset __unused,
240 					      unsigned int index  __unused,
241 					      const char *gpio_name  __unused,
242 					      enum gpio_flags flags __unused,
243 					      struct gpio **gpio __unused)
244 {
245 	return TEE_ERROR_NOT_SUPPORTED;
246 }
247 
248 static inline TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs __unused,
249 					   struct gpio **gpio __unused)
250 {
251 	return TEE_ERROR_NOT_SUPPORTED;
252 }
253 #endif /*CFG_DT*/
254 
255 /**
256  * gpio_dt_get_func - Typedef of function to get GPIO instance from
257  * devicetree properties
258  *
259  * @pargs: Pointer to GPIO phandle and its argument in the FDT
260  * @data: Pointer to the data given at gpio_dt_register_provider() call
261  * @res: Output result code of the operation:
262  *	TEE_SUCCESS in case of success
263  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
264  *	Any TEE_Result compliant code in case of error.
265  *
266  * Returns a struct GPIO pointer pointing to a GPIO instance matching
267  * the devicetree description or NULL if invalid description in which case
268  * @res provides the error code.
269  */
270 typedef TEE_Result (*gpio_dt_get_func)(struct dt_pargs *pargs, void *data,
271 				       struct gpio **out_gpio);
272 
273 /**
274  * gpio_dt_register_provider() - Register a GPIO controller provider
275  *
276  * @fdt: Device tree to work on
277  * @nodeoffset: Node offset of the GPIO controller
278  * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio
279  * @data: Opaque reference which will be passed to the get_dt_gpio callback
280  * Returns TEE_Result value
281  */
282 static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset,
283 						gpio_dt_get_func get_dt_gpio,
284 						void *data)
285 {
286 	return dt_driver_register_provider(fdt, nodeoffset,
287 					   (get_of_device_func)get_dt_gpio,
288 					   data, DT_DRIVER_GPIO);
289 }
290 
291 #endif	/* __DRIVERS_GPIO_H */
292