1 /*
2  * Copyright (c) 2016 Freescale Semiconductor, Inc.
3  * Copyright (c) 2017, NXP
4  * Copyright (c) 2018 Foundries.io
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #define DT_DRV_COMPAT openisa_rv32m1_gpio
10 
11 #include <errno.h>
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/irq.h>
15 #include <soc.h>
16 #include <fsl_common.h>
17 #include <fsl_port.h>
18 #include <zephyr/drivers/clock_control.h>
19 
20 #include <zephyr/drivers/gpio/gpio_utils.h>
21 
22 struct gpio_rv32m1_config {
23 	/* gpio_driver_config needs to be first */
24 	struct gpio_driver_config common;
25 	GPIO_Type *gpio_base;
26 	PORT_Type *port_base;
27 	unsigned int flags;
28 	const struct device *clock_dev;
29 	clock_control_subsys_t clock_subsys;
30 	int (*irq_config_func)(const struct device *dev);
31 };
32 
33 struct gpio_rv32m1_data {
34 	/* gpio_driver_data needs to be first */
35 	struct gpio_driver_data common;
36 	/* port ISR callback routine address */
37 	sys_slist_t callbacks;
38 };
39 
get_port_pcr_irqc_value_from_flags(const struct device * dev,uint32_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)40 static uint32_t get_port_pcr_irqc_value_from_flags(const struct device *dev,
41 						   uint32_t pin,
42 						   enum gpio_int_mode mode,
43 						   enum gpio_int_trig trig)
44 {
45 	port_interrupt_t port_interrupt = 0;
46 
47 	if (mode == GPIO_INT_MODE_DISABLED) {
48 		port_interrupt = kPORT_InterruptOrDMADisabled;
49 	} else {
50 		if (mode == GPIO_INT_MODE_LEVEL) {
51 			if (trig == GPIO_INT_TRIG_LOW) {
52 				port_interrupt = kPORT_InterruptLogicZero;
53 			} else {
54 				port_interrupt = kPORT_InterruptLogicOne;
55 			}
56 		} else {
57 			switch (trig) {
58 			case GPIO_INT_TRIG_LOW:
59 				port_interrupt = kPORT_InterruptFallingEdge;
60 				break;
61 			case GPIO_INT_TRIG_HIGH:
62 				port_interrupt = kPORT_InterruptRisingEdge;
63 				break;
64 			case GPIO_INT_TRIG_BOTH:
65 				port_interrupt = kPORT_InterruptEitherEdge;
66 				break;
67 			default:
68 				return -EINVAL;
69 			}
70 		}
71 	}
72 
73 	return PORT_PCR_IRQC(port_interrupt);
74 }
75 
gpio_rv32m1_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)76 static int gpio_rv32m1_configure(const struct device *dev,
77 				 gpio_pin_t pin, gpio_flags_t flags)
78 {
79 	const struct gpio_rv32m1_config *config = dev->config;
80 	GPIO_Type *gpio_base = config->gpio_base;
81 	PORT_Type *port_base = config->port_base;
82 	uint32_t mask = 0U;
83 	uint32_t pcr = 0U;
84 
85 	/* Check for an invalid pin number */
86 	if (pin >= ARRAY_SIZE(port_base->PCR)) {
87 		return -EINVAL;
88 	}
89 
90 	/* Check for an invalid pin configuration */
91 	if ((flags & GPIO_INT_ENABLE) && ((flags & GPIO_INPUT) == 0)) {
92 		return -EINVAL;
93 	}
94 
95 	if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
96 		return -ENOTSUP;
97 	}
98 
99 	if ((flags & GPIO_SINGLE_ENDED) != 0) {
100 		return -ENOTSUP;
101 	}
102 
103 	/* Check if GPIO port supports interrupts */
104 	if ((flags & GPIO_INT_ENABLE) &&
105 	    ((config->flags & GPIO_INT_ENABLE) == 0U)) {
106 		return -ENOTSUP;
107 	}
108 
109 	/* The flags contain options that require touching registers in the
110 	 * GPIO module and the corresponding PORT module.
111 	 *
112 	 * Start with the GPIO module and set up the pin direction register.
113 	 * 0 - pin is input, 1 - pin is output
114 	 */
115 
116 	switch (flags & GPIO_DIR_MASK) {
117 	case GPIO_INPUT:
118 		gpio_base->PDDR &= ~BIT(pin);
119 		break;
120 	case GPIO_OUTPUT:
121 		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
122 			gpio_base->PSOR = BIT(pin);
123 		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
124 			gpio_base->PCOR = BIT(pin);
125 		}
126 		gpio_base->PDDR |= BIT(pin);
127 		break;
128 	default:
129 		return -ENOTSUP;
130 	}
131 
132 	/* Set PCR mux to GPIO for the pin we are configuring */
133 	mask |= PORT_PCR_MUX_MASK;
134 	pcr |= PORT_PCR_MUX(kPORT_MuxAsGpio);
135 
136 	/* Now do the PORT module. Figure out the pullup/pulldown
137 	 * configuration, but don't write it to the PCR register yet.
138 	 */
139 	mask |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
140 
141 	if ((flags & GPIO_PULL_UP) != 0) {
142 		/* Enable the pull and select the pullup resistor. */
143 		pcr |= PORT_PCR_PE_MASK | PORT_PCR_PS_MASK;
144 
145 	} else if ((flags & GPIO_PULL_DOWN) != 0) {
146 		/* Enable the pull and select the pulldown resistor (deselect
147 		 * the pullup resistor.
148 		 */
149 		pcr |= PORT_PCR_PE_MASK;
150 	}
151 
152 	/* Still in the PORT module. Figure out the interrupt configuration,
153 	 * but don't write it to the PCR register yet.
154 	 */
155 	mask |= PORT_PCR_IRQC_MASK;
156 
157 	/* Accessing by pin, we only need to write one PCR register. */
158 	port_base->PCR[pin] = (port_base->PCR[pin] & ~mask) | pcr;
159 
160 	return 0;
161 }
162 
gpio_rv32m1_port_get_raw(const struct device * dev,uint32_t * value)163 static int gpio_rv32m1_port_get_raw(const struct device *dev, uint32_t *value)
164 {
165 	const struct gpio_rv32m1_config *config = dev->config;
166 	GPIO_Type *gpio_base = config->gpio_base;
167 
168 	*value = gpio_base->PDIR;
169 
170 	return 0;
171 }
172 
gpio_rv32m1_port_set_masked_raw(const struct device * dev,uint32_t mask,uint32_t value)173 static int gpio_rv32m1_port_set_masked_raw(const struct device *dev,
174 					   uint32_t mask,
175 					   uint32_t value)
176 {
177 	const struct gpio_rv32m1_config *config = dev->config;
178 	GPIO_Type *gpio_base = config->gpio_base;
179 
180 	gpio_base->PDOR = (gpio_base->PDOR & ~mask) | (mask & value);
181 
182 	return 0;
183 }
184 
gpio_rv32m1_port_set_bits_raw(const struct device * dev,uint32_t mask)185 static int gpio_rv32m1_port_set_bits_raw(const struct device *dev,
186 					 uint32_t mask)
187 {
188 	const struct gpio_rv32m1_config *config = dev->config;
189 	GPIO_Type *gpio_base = config->gpio_base;
190 
191 	gpio_base->PSOR = mask;
192 
193 	return 0;
194 }
195 
gpio_rv32m1_port_clear_bits_raw(const struct device * dev,uint32_t mask)196 static int gpio_rv32m1_port_clear_bits_raw(const struct device *dev,
197 					   uint32_t mask)
198 {
199 	const struct gpio_rv32m1_config *config = dev->config;
200 	GPIO_Type *gpio_base = config->gpio_base;
201 
202 	gpio_base->PCOR = mask;
203 
204 	return 0;
205 }
206 
gpio_rv32m1_port_toggle_bits(const struct device * dev,uint32_t mask)207 static int gpio_rv32m1_port_toggle_bits(const struct device *dev,
208 					uint32_t mask)
209 {
210 	const struct gpio_rv32m1_config *config = dev->config;
211 	GPIO_Type *gpio_base = config->gpio_base;
212 
213 	gpio_base->PTOR = mask;
214 
215 	return 0;
216 }
217 
gpio_rv32m1_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)218 static int gpio_rv32m1_pin_interrupt_configure(const struct device *dev,
219 					       gpio_pin_t pin,
220 					       enum gpio_int_mode mode,
221 					       enum gpio_int_trig trig)
222 {
223 	const struct gpio_rv32m1_config *config = dev->config;
224 	PORT_Type *port_base = config->port_base;
225 
226 	/* Check for an invalid pin number */
227 	if (pin >= ARRAY_SIZE(port_base->PCR)) {
228 		return -EINVAL;
229 	}
230 
231 	/* Check if GPIO port supports interrupts */
232 	if ((mode != GPIO_INT_MODE_DISABLED) &&
233 	    ((config->flags & GPIO_INT_ENABLE) == 0U)) {
234 		return -ENOTSUP;
235 	}
236 
237 	uint32_t pcr = get_port_pcr_irqc_value_from_flags(dev, pin, mode, trig);
238 
239 	port_base->PCR[pin] = (port_base->PCR[pin] & ~PORT_PCR_IRQC_MASK) | pcr;
240 
241 	return 0;
242 }
243 
244 
gpio_rv32m1_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)245 static int gpio_rv32m1_manage_callback(const struct device *dev,
246 				       struct gpio_callback *callback,
247 				       bool set)
248 {
249 	struct gpio_rv32m1_data *data = dev->data;
250 
251 	gpio_manage_callback(&data->callbacks, callback, set);
252 
253 	return 0;
254 }
255 
gpio_rv32m1_port_isr(const struct device * dev)256 static void gpio_rv32m1_port_isr(const struct device *dev)
257 {
258 	const struct gpio_rv32m1_config *config = dev->config;
259 	struct gpio_rv32m1_data *data = dev->data;
260 	uint32_t int_status;
261 
262 	int_status = config->port_base->ISFR;
263 
264 	/* Clear the port interrupts before invoking callbacks */
265 	config->port_base->ISFR = int_status;
266 
267 	gpio_fire_callbacks(&data->callbacks, dev, int_status);
268 }
269 
gpio_rv32m1_init(const struct device * dev)270 static int gpio_rv32m1_init(const struct device *dev)
271 {
272 	const struct gpio_rv32m1_config *config = dev->config;
273 	int ret;
274 
275 	if (config->clock_dev) {
276 		if (!device_is_ready(config->clock_dev)) {
277 			return -ENODEV;
278 		}
279 
280 		ret = clock_control_on(config->clock_dev, config->clock_subsys);
281 		if (ret < 0) {
282 			return ret;
283 		}
284 	}
285 
286 	return config->irq_config_func(dev);
287 }
288 
289 static DEVICE_API(gpio, gpio_rv32m1_driver_api) = {
290 	.pin_configure = gpio_rv32m1_configure,
291 	.port_get_raw = gpio_rv32m1_port_get_raw,
292 	.port_set_masked_raw = gpio_rv32m1_port_set_masked_raw,
293 	.port_set_bits_raw = gpio_rv32m1_port_set_bits_raw,
294 	.port_clear_bits_raw = gpio_rv32m1_port_clear_bits_raw,
295 	.port_toggle_bits = gpio_rv32m1_port_toggle_bits,
296 	.pin_interrupt_configure = gpio_rv32m1_pin_interrupt_configure,
297 	.manage_callback = gpio_rv32m1_manage_callback,
298 };
299 
300 #define INST_DT_PORT_ADDR(n) \
301 	DT_REG_ADDR(DT_INST_PHANDLE(n, openisa_rv32m1_port))
302 #define INST_DT_CLK_CTRL_DEV(n) \
303 	UTIL_AND(DT_INST_NODE_HAS_PROP(n, clocks), DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)))
304 #define INST_DT_CLK_CELL_NAME(n) \
305 	UTIL_AND(DT_INST_NODE_HAS_PROP(n, clocks), DT_INST_CLOCKS_CELL(n, name))
306 
307 #define GPIO_RV32M1_INIT(n) \
308 	static int gpio_rv32m1_##n##_init(const struct device *dev);	\
309 									\
310 	static const struct gpio_rv32m1_config gpio_rv32m1_##n##_config = {\
311 		.common = {						\
312 			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n),\
313 		},							\
314 		.gpio_base = (GPIO_Type *) DT_INST_REG_ADDR(n),		\
315 		.port_base = (PORT_Type *) INST_DT_PORT_ADDR(n),	\
316 		.flags = GPIO_INT_ENABLE,				\
317 		.irq_config_func = gpio_rv32m1_##n##_init,		\
318 		.clock_dev = INST_DT_CLK_CTRL_DEV(n),			\
319 		.clock_subsys = (clock_control_subsys_t)		\
320 				INST_DT_CLK_CELL_NAME(n)		\
321 	};								\
322 									\
323 	static struct gpio_rv32m1_data gpio_rv32m1_##n##_data;		\
324 									\
325 	DEVICE_DT_INST_DEFINE(n,					\
326 			    gpio_rv32m1_init,				\
327 			    NULL,					\
328 			    &gpio_rv32m1_##n##_data,			\
329 			    &gpio_rv32m1_##n##_config,			\
330 			    PRE_KERNEL_1,				\
331 			    CONFIG_GPIO_INIT_PRIORITY,			\
332 			    &gpio_rv32m1_driver_api);			\
333 									\
334 	static int gpio_rv32m1_##n##_init(const struct device *dev)	\
335 	{								\
336 		IRQ_CONNECT(DT_INST_IRQN(n),				\
337 			    0,						\
338 			    gpio_rv32m1_port_isr,			\
339 			    DEVICE_DT_INST_GET(n), 0);			\
340 									\
341 		irq_enable(DT_INST_IRQN(0));				\
342 									\
343 		return 0;						\
344 	}
345 
346 DT_INST_FOREACH_STATUS_OKAY(GPIO_RV32M1_INIT)
347