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 enum gpio_dir {
36 	GPIO_DIR_OUT,
37 	GPIO_DIR_IN
38 };
39 
40 enum gpio_level {
41 	GPIO_LEVEL_LOW,
42 	GPIO_LEVEL_HIGH
43 };
44 
45 enum gpio_interrupt {
46 	GPIO_INTERRUPT_DISABLE,
47 	GPIO_INTERRUPT_ENABLE
48 };
49 
50 struct gpio;
51 struct gpio_ops;
52 
53 struct gpio_chip {
54 	const struct gpio_ops *ops;
55 };
56 
57 struct gpio_ops {
58 	/* Get GPIO direction current configuration */
59 	enum gpio_dir (*get_direction)(struct gpio_chip *chip,
60 				       unsigned int gpio_pin);
61 	/* Set GPIO direction configuration */
62 	void (*set_direction)(struct gpio_chip *chip, unsigned int gpio_pin,
63 			      enum gpio_dir direction);
64 	/* Get GPIO current level */
65 	enum gpio_level (*get_value)(struct gpio_chip *chip,
66 				     unsigned int gpio_pin);
67 	/* Set GPIO level */
68 	void (*set_value)(struct gpio_chip *chip, unsigned int gpio_pin,
69 			  enum gpio_level value);
70 	/* Get GPIO interrupt state */
71 	enum gpio_interrupt (*get_interrupt)(struct gpio_chip *chip,
72 					     unsigned int gpio_pin);
73 	/* Enable or disable a GPIO interrupt */
74 	void (*set_interrupt)(struct gpio_chip *chip, unsigned int gpio_pin,
75 			      enum gpio_interrupt enable_disable);
76 	/* Release GPIO resources */
77 	void (*put)(struct gpio_chip *chip, struct gpio *gpio);
78 };
79 
80 /*
81  * struct gpio - GPIO pin description
82  * @chip: GPIO controller chip reference
83  * @dt_flags: Pin boolean properties set from DT node
84  * @pin: Pin number in GPIO controller
85  */
86 struct gpio {
87 	struct gpio_chip *chip;
88 	uint32_t dt_flags;
89 	unsigned int pin;
90 };
91 
gpio_ops_is_valid(const struct gpio_ops * ops)92 static inline bool gpio_ops_is_valid(const struct gpio_ops *ops)
93 {
94 	return ops->set_direction && ops->get_direction && ops->get_value &&
95 	       ops->set_value;
96 }
97 
gpio_set_direction(struct gpio * gpio,enum gpio_dir dir)98 static inline void gpio_set_direction(struct gpio *gpio, enum gpio_dir dir)
99 {
100 	gpio->chip->ops->set_direction(gpio->chip, gpio->pin, dir);
101 }
102 
gpio_get_direction(struct gpio * gpio)103 static inline enum gpio_dir gpio_get_direction(struct gpio *gpio)
104 {
105 	return gpio->chip->ops->get_direction(gpio->chip, gpio->pin);
106 }
107 
gpio_set_value(struct gpio * gpio,enum gpio_level value)108 static inline void gpio_set_value(struct gpio *gpio, enum gpio_level value)
109 {
110 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
111 		value = !value;
112 
113 	gpio->chip->ops->set_value(gpio->chip, gpio->pin, value);
114 }
115 
gpio_get_value(struct gpio * gpio)116 static inline enum gpio_level gpio_get_value(struct gpio *gpio)
117 {
118 	enum gpio_level value = GPIO_LEVEL_LOW;
119 
120 	value = gpio->chip->ops->get_value(gpio->chip, gpio->pin);
121 
122 	if (gpio->dt_flags & GPIO_ACTIVE_LOW)
123 		value = !value;
124 
125 	return value;
126 }
127 
gpio_put(struct gpio * gpio)128 static inline void gpio_put(struct gpio *gpio)
129 {
130 	assert(!gpio || (gpio->chip && gpio->chip->ops));
131 
132 	if (gpio && gpio->chip->ops->put)
133 		gpio->chip->ops->put(gpio->chip, gpio);
134 }
135 
136 #if defined(CFG_DT) && defined(CFG_DRIVERS_GPIO)
137 /**
138  * gpio_dt_alloc_pin() - Get an allocated GPIO instance from its DT phandle
139  *
140  * @pargs: Pointer to devicetree description of the GPIO controller to parse
141  * @res: Output result code of the operation:
142  *	TEE_SUCCESS in case of success
143  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
144  *	Any TEE_Result compliant code in case of error.
145  *
146  * Returns a struct gpio pointer pointing to a GPIO instance matching
147  * the devicetree description or NULL if invalid description in which case
148  * @res provides the error code.
149  */
150 TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs, struct gpio **gpio);
151 
152 /**
153  * gpio_dt_get_by_index() - Get a GPIO controller at a specific index in
154  * 'gpios' property
155  *
156  * @fdt: Device tree to work on
157  * @nodeoffset: Node offset of the subnode containing a 'gpios' property
158  * @index: GPIO pin index in '*-gpios' property
159  * @gpio_name: Name of the GPIO pin
160  * @gpio: Output GPIO pin reference upon success
161  *
162  * Return TEE_SUCCESS in case of success
163  * Return TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
164  * Return a TEE_Result compliant code in case of error
165  */
166 TEE_Result gpio_dt_get_by_index(const void *fdt, int nodeoffset,
167 				unsigned int index, const char *gpio_name,
168 				struct gpio **gpio);
169 #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)170 static inline TEE_Result gpio_dt_get_by_index(const void *fdt __unused,
171 					      int nodeoffset __unused,
172 					      unsigned int index  __unused,
173 					      const char *gpio_name  __unused,
174 					      struct gpio **gpio __unused)
175 {
176 	return TEE_ERROR_NOT_SUPPORTED;
177 }
178 
gpio_dt_alloc_pin(struct dt_pargs * pargs __unused,struct gpio ** gpio __unused)179 static inline TEE_Result gpio_dt_alloc_pin(struct dt_pargs *pargs __unused,
180 					   struct gpio **gpio __unused)
181 {
182 	return TEE_ERROR_NOT_SUPPORTED;
183 }
184 #endif /*CFG_DT*/
185 
186 /**
187  * gpio_dt_get_func - Typedef of function to get GPIO instance from
188  * devicetree properties
189  *
190  * @pargs: Pointer to GPIO phandle and its argument in the FDT
191  * @data: Pointer to the data given at gpio_dt_register_provider() call
192  * @res: Output result code of the operation:
193  *	TEE_SUCCESS in case of success
194  *	TEE_ERROR_DEFER_DRIVER_INIT if GPIO controller is not initialized
195  *	Any TEE_Result compliant code in case of error.
196  *
197  * Returns a struct GPIO pointer pointing to a GPIO instance matching
198  * the devicetree description or NULL if invalid description in which case
199  * @res provides the error code.
200  */
201 typedef TEE_Result (*gpio_dt_get_func)(struct dt_pargs *pargs, void *data,
202 				       struct gpio **out_gpio);
203 
204 /**
205  * gpio_dt_register_provider() - Register a GPIO controller provider
206  *
207  * @fdt: Device tree to work on
208  * @nodeoffset: Node offset of the GPIO controller
209  * @get_dt_gpio: Callback to match the GPIO controller with a struct gpio
210  * @data: Opaque reference which will be passed to the get_dt_gpio callback
211  * Returns TEE_Result value
212  */
gpio_register_provider(const void * fdt,int nodeoffset,gpio_dt_get_func get_dt_gpio,void * data)213 static inline TEE_Result gpio_register_provider(const void *fdt, int nodeoffset,
214 						gpio_dt_get_func get_dt_gpio,
215 						void *data)
216 {
217 	return dt_driver_register_provider(fdt, nodeoffset,
218 					   (get_of_device_func)get_dt_gpio,
219 					   data, DT_DRIVER_GPIO);
220 }
221 
222 #endif	/* __DRIVERS_GPIO_H */
223