1 /*
2  * Copyright (c) 2016, Texas Instruments Incorporated
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ti_cc32xx_gpio
8 #include <errno.h>
9 
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/init.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/sys/sys_io.h>
15 
16 /* Driverlib includes */
17 #include <inc/hw_types.h>
18 #include <inc/hw_memmap.h>
19 #include <inc/hw_ints.h>
20 #include <inc/hw_gpio.h>
21 #include <driverlib/rom.h>
22 #include <driverlib/pin.h>
23 #undef __GPIO_H__  /* Zephyr and CC32XX SDK gpio.h conflict */
24 #include <driverlib/gpio.h>
25 #include <driverlib/rom_map.h>
26 #include <driverlib/interrupt.h>
27 #include <zephyr/irq.h>
28 
29 #include <zephyr/drivers/gpio/gpio_utils.h>
30 
31 /* Reserved */
32 #define PIN_XX  0xFF
33 
34 static const uint8_t pinTable[] = {
35 	/* 00     01      02      03      04      05      06      07  */
36 	PIN_50, PIN_55, PIN_57, PIN_58, PIN_59, PIN_60, PIN_61, PIN_62,
37 	/* 08     09      10      11      12      13      14      15  */
38 	PIN_63, PIN_64, PIN_01, PIN_02, PIN_03, PIN_04, PIN_05, PIN_06,
39 	/* 16     17      18      19      20      21      22      23  */
40 	PIN_07, PIN_08, PIN_XX, PIN_XX, PIN_XX, PIN_XX, PIN_15, PIN_16,
41 	/* 24     25      26      27      28      29      30      31  */
42 	PIN_17, PIN_21, PIN_29, PIN_30, PIN_18, PIN_20, PIN_53, PIN_45,
43 	/* 32 */
44 	PIN_52
45 };
46 
47 struct gpio_cc32xx_config {
48 	/* gpio_driver_config needs to be first */
49 	struct gpio_driver_config common;
50 	/* base address of GPIO port */
51 	unsigned long port_base;
52 	/* GPIO port number */
53 	uint8_t port_num;
54 };
55 
56 struct gpio_cc32xx_data {
57 	/* gpio_driver_data needs to be first */
58 	struct gpio_driver_data common;
59 	/* list of registered callbacks */
60 	sys_slist_t callbacks;
61 };
62 
63 static int gpio_cc32xx_port_set_bits_raw(const struct device *port,
64 					 uint32_t mask);
65 static int gpio_cc32xx_port_clear_bits_raw(const struct device *port,
66 					   uint32_t mask);
67 
gpio_cc32xx_config(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)68 static inline int gpio_cc32xx_config(const struct device *port,
69 				     gpio_pin_t pin,
70 				     gpio_flags_t flags)
71 {
72 	const struct gpio_cc32xx_config *gpio_config = port->config;
73 	unsigned long port_base = gpio_config->port_base;
74 
75 	if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
76 		return -ENOTSUP;
77 	}
78 
79 	if ((flags & (GPIO_INPUT | GPIO_OUTPUT)) == 0) {
80 		return -ENOTSUP;
81 	}
82 
83 	if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) {
84 		return -ENOTSUP;
85 	}
86 
87 	MAP_PinTypeGPIO(pinTable[gpio_config->port_num * 8 + pin],
88 		PIN_MODE_0, false);
89 	if (flags & GPIO_OUTPUT) {
90 		MAP_GPIODirModeSet(port_base, (1 << pin), GPIO_DIR_MODE_OUT);
91 		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
92 			gpio_cc32xx_port_set_bits_raw(port, BIT(pin));
93 		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
94 			gpio_cc32xx_port_clear_bits_raw(port, BIT(pin));
95 		}
96 	} else {
97 		MAP_GPIODirModeSet(port_base, (1 << pin), GPIO_DIR_MODE_IN);
98 	}
99 
100 	return 0;
101 }
102 
gpio_cc32xx_port_get_raw(const struct device * port,uint32_t * value)103 static int gpio_cc32xx_port_get_raw(const struct device *port,
104 				    uint32_t *value)
105 {
106 	const struct gpio_cc32xx_config *gpio_config = port->config;
107 	unsigned long port_base = gpio_config->port_base;
108 	unsigned char pin_packed = 0xFF;
109 
110 	*value = MAP_GPIOPinRead(port_base, pin_packed);
111 
112 	return 0;
113 }
114 
gpio_cc32xx_port_set_masked_raw(const struct device * port,uint32_t mask,uint32_t value)115 static int gpio_cc32xx_port_set_masked_raw(const struct device *port,
116 					   uint32_t mask,
117 					   uint32_t value)
118 {
119 	const struct gpio_cc32xx_config *gpio_config = port->config;
120 	unsigned long port_base = gpio_config->port_base;
121 
122 	MAP_GPIOPinWrite(port_base, (unsigned char)mask, (unsigned char)value);
123 
124 	return 0;
125 }
126 
gpio_cc32xx_port_set_bits_raw(const struct device * port,uint32_t mask)127 static int gpio_cc32xx_port_set_bits_raw(const struct device *port,
128 					 uint32_t mask)
129 {
130 	const struct gpio_cc32xx_config *gpio_config = port->config;
131 	unsigned long port_base = gpio_config->port_base;
132 
133 	MAP_GPIOPinWrite(port_base, (unsigned char)mask, (unsigned char)mask);
134 
135 	return 0;
136 }
137 
gpio_cc32xx_port_clear_bits_raw(const struct device * port,uint32_t mask)138 static int gpio_cc32xx_port_clear_bits_raw(const struct device *port,
139 					   uint32_t mask)
140 {
141 	const struct gpio_cc32xx_config *gpio_config = port->config;
142 	unsigned long port_base = gpio_config->port_base;
143 
144 	MAP_GPIOPinWrite(port_base, (unsigned char)mask, (unsigned char)~mask);
145 
146 	return 0;
147 }
148 
gpio_cc32xx_port_toggle_bits(const struct device * port,uint32_t mask)149 static int gpio_cc32xx_port_toggle_bits(const struct device *port,
150 					uint32_t mask)
151 {
152 	const struct gpio_cc32xx_config *gpio_config = port->config;
153 	unsigned long port_base = gpio_config->port_base;
154 	long value;
155 
156 	value = MAP_GPIOPinRead(port_base, mask);
157 
158 	MAP_GPIOPinWrite(port_base, (unsigned char)mask,
159 		(unsigned char)~value);
160 
161 	return 0;
162 }
163 
gpio_cc32xx_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)164 static int gpio_cc32xx_pin_interrupt_configure(const struct device *port,
165 					       gpio_pin_t pin,
166 					       enum gpio_int_mode mode,
167 					       enum gpio_int_trig trig)
168 {
169 	const struct gpio_cc32xx_config *gpio_config = port->config;
170 	unsigned long port_base = gpio_config->port_base;
171 	unsigned long int_type;
172 
173 	__ASSERT(pin < 8, "Invalid pin number - only 8 pins per port");
174 
175 	/*
176 	 * disable interrupt prior to changing int type helps
177 	 * prevent spurious interrupts observed when switching
178 	 * to level-based
179 	 */
180 	MAP_GPIOIntDisable(port_base, (1 << pin));
181 
182 	if (mode != GPIO_INT_MODE_DISABLED) {
183 		if (mode == GPIO_INT_MODE_EDGE) {
184 			if (trig == GPIO_INT_TRIG_BOTH) {
185 				int_type = GPIO_BOTH_EDGES;
186 			} else if (trig == GPIO_INT_TRIG_HIGH) {
187 				int_type = GPIO_RISING_EDGE;
188 			} else {
189 				int_type = GPIO_FALLING_EDGE;
190 			}
191 		} else { /* GPIO_INT_MODE_LEVEL */
192 			if (trig == GPIO_INT_TRIG_HIGH) {
193 				int_type = GPIO_HIGH_LEVEL;
194 			} else {
195 				int_type = GPIO_LOW_LEVEL;
196 			}
197 		}
198 
199 		MAP_GPIOIntTypeSet(port_base, (1 << pin), int_type);
200 		MAP_GPIOIntClear(port_base, (1 << pin));
201 		MAP_GPIOIntEnable(port_base, (1 << pin));
202 	}
203 
204 	return 0;
205 }
206 
gpio_cc32xx_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)207 static int gpio_cc32xx_manage_callback(const struct device *dev,
208 				       struct gpio_callback *callback,
209 				       bool set)
210 {
211 	struct gpio_cc32xx_data *data = dev->data;
212 
213 	return gpio_manage_callback(&data->callbacks, callback, set);
214 }
215 
gpio_cc32xx_port_isr(const struct device * dev)216 static void gpio_cc32xx_port_isr(const struct device *dev)
217 {
218 	const struct gpio_cc32xx_config *config = dev->config;
219 	struct gpio_cc32xx_data *data = dev->data;
220 	uint32_t int_status;
221 
222 	/* See which interrupts triggered: */
223 	int_status = (uint32_t)MAP_GPIOIntStatus(config->port_base, 1);
224 
225 	/* Clear GPIO Interrupt */
226 	MAP_GPIOIntClear(config->port_base, int_status);
227 
228 	/* Call the registered callbacks */
229 	gpio_fire_callbacks(&data->callbacks, dev, int_status);
230 }
231 
232 static const struct gpio_driver_api api_funcs = {
233 	.pin_configure = gpio_cc32xx_config,
234 	.port_get_raw = gpio_cc32xx_port_get_raw,
235 	.port_set_masked_raw = gpio_cc32xx_port_set_masked_raw,
236 	.port_set_bits_raw = gpio_cc32xx_port_set_bits_raw,
237 	.port_clear_bits_raw = gpio_cc32xx_port_clear_bits_raw,
238 	.port_toggle_bits = gpio_cc32xx_port_toggle_bits,
239 	.pin_interrupt_configure = gpio_cc32xx_pin_interrupt_configure,
240 	.manage_callback = gpio_cc32xx_manage_callback,
241 };
242 
243 #define GPIO_CC32XX_INIT_FUNC(n)					     \
244 	static int gpio_cc32xx_a##n##_init(const struct device *dev)		     \
245 	{								     \
246 		ARG_UNUSED(dev);					     \
247 									     \
248 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority),	     \
249 			gpio_cc32xx_port_isr, DEVICE_DT_INST_GET(n),         \
250 			0);						     \
251 									     \
252 		MAP_IntPendClear(DT_INST_IRQN(n) + 16);			     \
253 		irq_enable(DT_INST_IRQN(n));				     \
254 									     \
255 		return 0;						     \
256 	}
257 
258 #define GPIO_CC32XX_DEVICE_INIT(n)					     \
259 	DEVICE_DT_INST_DEFINE(n, &gpio_cc32xx_a##n##_init,		     \
260 			NULL, &gpio_cc32xx_a##n##_data,			     \
261 			&gpio_cc32xx_a##n##_config,			     \
262 			POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY,		     \
263 			&api_funcs)
264 
265 #define GPIO_CC32XX_INIT(n)						     \
266 	static const struct gpio_cc32xx_config gpio_cc32xx_a##n##_config = { \
267 		.common = {						     \
268 			.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
269 		},							     \
270 		.port_base = DT_INST_REG_ADDR(n),			     \
271 		.port_num = n						     \
272 	};								     \
273 									     \
274 	static struct gpio_cc32xx_data gpio_cc32xx_a##n##_data;		     \
275 									     \
276 	GPIO_CC32XX_INIT_FUNC(n)					     \
277 									     \
278 	GPIO_CC32XX_DEVICE_INIT(n);
279 
280 DT_INST_FOREACH_STATUS_OKAY(GPIO_CC32XX_INIT)
281