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