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
gpio_ops_is_valid(const struct gpio_ops * ops)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
gpio_set_direction(struct gpio * gpio,enum gpio_dir dir)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
gpio_get_direction(struct gpio * gpio)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
gpio_set_value(struct gpio * gpio,enum gpio_level value)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
gpio_get_value(struct gpio * gpio)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
gpio_put(struct gpio * gpio)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
gpio_dt_get_by_index(const void * fdt __unused,int nodeoffset __unused,unsigned int index __unused,const char * gpio_name __unused,struct gpio ** gpio __unused)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
gpio_dt_cfg_by_index(const void * fdt __unused,int nodeoffset __unused,unsigned int index __unused,const char * gpio_name __unused,enum gpio_flags flags __unused,struct gpio ** gpio __unused)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
gpio_dt_alloc_pin(struct dt_pargs * pargs __unused,struct gpio ** gpio __unused)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 */
gpio_register_provider(const void * fdt,int nodeoffset,gpio_dt_get_func get_dt_gpio,void * data)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