1 /*
2 * Copyright (c) 2024 Renesas Electronics Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT renesas_ra_gpio_ioport
8
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/drivers/pinctrl.h>
11 #include <zephyr/dt-bindings/gpio/renesas-ra-gpio-ioport.h>
12 #include <zephyr/drivers/misc/renesas_ra_external_interrupt/renesas_ra_external_interrupt.h>
13 #include <zephyr/drivers/gpio/gpio_utils.h>
14 #include <soc.h>
15
16 struct gpio_ra_irq_info {
17 const struct device *port_irq;
18 const uint8_t *const pins;
19 size_t num;
20 };
21
22 struct gpio_ra_config {
23 struct gpio_driver_config common;
24 uint8_t port_num;
25 R_PORT0_Type *port;
26 const struct gpio_ra_irq_info *irq_info;
27 const size_t irq_info_size;
28 gpio_pin_t vbatt_pins[];
29 };
30
31 struct gpio_ra_data {
32 struct gpio_driver_data common;
33 sys_slist_t callbacks;
34 };
35
36 #if CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT
query_irq_info(const struct device * dev,uint32_t pin)37 static const struct gpio_ra_irq_info *query_irq_info(const struct device *dev, uint32_t pin)
38 {
39 const struct gpio_ra_config *config = dev->config;
40
41 for (int i = 0; i < config->irq_info_size; i++) {
42 const struct gpio_ra_irq_info *info = &config->irq_info[i];
43
44 for (int j = 0; j < info->num; j++) {
45 if (info->pins[j] == pin) {
46 return info;
47 }
48 }
49 }
50
51 return NULL;
52 }
53
gpio_ra_callback_adapter(const struct device * dev,gpio_pin_t pin)54 static void gpio_ra_callback_adapter(const struct device *dev, gpio_pin_t pin)
55 {
56 struct gpio_ra_data *data = dev->data;
57
58 gpio_fire_callbacks(&data->callbacks, dev, BIT(pin));
59 }
60 #endif
61
gpio_ra_pin_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)62 static int gpio_ra_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags)
63 {
64 const struct gpio_ra_config *config = dev->config;
65
66 struct ra_pinctrl_soc_pin pincfg;
67 uint32_t pfs_cfg;
68
69 if (((flags & GPIO_INPUT) != 0U) && ((flags & GPIO_OUTPUT) != 0U)) {
70 return -ENOTSUP;
71 }
72
73 if ((flags & GPIO_PULL_DOWN) != 0U) {
74 return -ENOTSUP;
75 }
76
77 if (!IS_ENABLED(CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT) && ((flags & GPIO_INT_ENABLE) != 0)) {
78 return -ENOTSUP;
79 }
80
81 #if CONFIG_GPIO_RA_HAS_VBTICTLR
82 if (config->vbatt_pins[0] != 0xFF) {
83 uint32_t clear = 0;
84
85 for (int i = 0; config->vbatt_pins[i] != '\0'; i++) {
86 if (config->vbatt_pins[i] == pin) {
87 WRITE_BIT(clear, i, 1);
88 }
89 }
90
91 R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_OM_LPC_BATT);
92
93 R_SYSTEM->VBTICTLR &= (uint8_t)~clear;
94
95 R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_OM_LPC_BATT);
96 }
97 #endif
98
99 pincfg.port_num = config->port_num;
100 pincfg.pin_num = pin;
101
102 /* Initial pin settings when PFS is zeroed:
103 * - Low output, input mode
104 * - Pull-up disabled, CMOS output
105 * - Low drive strength
106 * - Not used for IRQ or analog
107 * - Configured as general I/O
108 */
109 pfs_cfg = 0;
110
111 if ((flags & GPIO_OUTPUT) != 0U) {
112 /* Set output pin initial value */
113 if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
114 WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_PODR_Pos, 1);
115 }
116
117 WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_PDR_Pos, 1);
118 }
119
120 if ((flags & GPIO_LINE_OPEN_DRAIN) != 0) {
121 WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_NCODR_Pos, 1);
122 }
123
124 if ((flags & GPIO_PULL_UP) != 0) {
125 WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_PCR_Pos, 1);
126 }
127
128 #if CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT
129 if ((flags & GPIO_INT_ENABLE) != 0) {
130 const struct gpio_ra_irq_info *irq_info = query_irq_info(dev, pin);
131 int err = 0;
132
133 if (irq_info == NULL) {
134 return -EINVAL;
135 }
136
137 if (!device_is_ready(irq_info->port_irq)) {
138 return -EWOULDBLOCK;
139 }
140
141 struct gpio_ra_callback callback = {
142 .port = (struct device *)dev,
143 .port_num = config->port_num,
144 .pin = pin,
145 .mode = flags & (GPIO_INT_EDGE | GPIO_INT_DISABLE | GPIO_INT_ENABLE),
146 .trigger = flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1),
147 .isr = gpio_ra_callback_adapter,
148 };
149
150 err = gpio_ra_interrupt_set(irq_info->port_irq, &callback);
151 if (err < 0) {
152 return err;
153 }
154
155 WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_ISEL_Pos, 1);
156 }
157
158 if ((flags & GPIO_INT_DISABLE) != 0) {
159 const struct gpio_ra_irq_info *irq_info = query_irq_info(dev, pin);
160
161 if (irq_info == NULL) {
162 return -EINVAL;
163 }
164
165 if (!device_is_ready(irq_info->port_irq)) {
166 return -EWOULDBLOCK;
167 }
168
169 gpio_ra_interrupt_unset(irq_info->port_irq, config->port_num, pin);
170 WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_ISEL_Pos, 0);
171 }
172 #endif
173
174 pincfg.cfg =
175 pfs_cfg | (((flags & RENESAS_GPIO_DS_MSK) >> 8) << R_PFS_PORT_PIN_PmnPFS_DSCR_Pos);
176
177 return pinctrl_configure_pins(&pincfg, 1, PINCTRL_REG_NONE);
178 }
179
gpio_ra_pin_get_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t * flags)180 __maybe_unused static int gpio_ra_pin_get_config(const struct device *dev, gpio_pin_t pin,
181 gpio_flags_t *flags)
182 {
183 const struct gpio_ra_config *config = dev->config;
184 uint32_t pincfg;
185
186 if (pin >= RA_PINCTRL_PIN_NUM) {
187 return -EINVAL;
188 }
189
190 memset(flags, 0, sizeof(gpio_flags_t));
191
192 pincfg = R_PFS->PORT[config->port_num].PIN[pin].PmnPFS;
193
194 if (pincfg & BIT(R_PFS_PORT_PIN_PmnPFS_PDR_Pos)) {
195 *flags |= GPIO_OUTPUT;
196 } else {
197 *flags |= GPIO_INPUT;
198 }
199
200 if (pincfg & BIT(R_PFS_PORT_PIN_PmnPFS_NCODR_Pos)) {
201 *flags |= GPIO_LINE_OPEN_DRAIN;
202 }
203
204 if (pincfg & BIT(R_PFS_PORT_PIN_PmnPFS_PCR_Pos)) {
205 *flags |= GPIO_PULL_UP;
206 }
207
208 return 0;
209 }
210
gpio_ra_port_get_raw(const struct device * dev,uint32_t * value)211 static int gpio_ra_port_get_raw(const struct device *dev, uint32_t *value)
212 {
213 const struct gpio_ra_config *config = dev->config;
214 R_PORT0_Type *port = config->port;
215
216 *value = port->PIDR;
217
218 return 0;
219 }
220
gpio_ra_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)221 static int gpio_ra_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
222 gpio_port_value_t value)
223 {
224 const struct gpio_ra_config *config = dev->config;
225 R_PORT0_Type *port = config->port;
226
227 port->PODR = ((port->PODR & ~mask) | (value & mask));
228
229 return 0;
230 }
231
gpio_ra_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)232 static int gpio_ra_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
233 {
234 const struct gpio_ra_config *config = dev->config;
235 R_PORT0_Type *port = config->port;
236
237 port->PODR = (port->PODR | pins);
238
239 return 0;
240 }
241
gpio_ra_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)242 static int gpio_ra_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
243 {
244 const struct gpio_ra_config *config = dev->config;
245 R_PORT0_Type *port = config->port;
246
247 port->PODR = (port->PODR & ~pins);
248
249 return 0;
250 }
251
gpio_ra_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)252 static int gpio_ra_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
253 {
254 const struct gpio_ra_config *config = dev->config;
255 R_PORT0_Type *port = config->port;
256
257 port->PODR = (port->PODR ^ pins);
258
259 return 0;
260 }
261
262 #if CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT
gpio_ra_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)263 static int gpio_ra_pin_interrupt_configure(const struct device *port, gpio_pin_t pin,
264 enum gpio_int_mode mode, enum gpio_int_trig trig)
265 {
266 gpio_flags_t flags;
267 int err;
268
269 err = gpio_ra_pin_get_config(port, pin, &flags);
270 if (err) {
271 return err;
272 }
273
274 return gpio_ra_pin_configure(port, pin, (flags | mode | trig));
275 }
276
gpio_ra_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)277 static int gpio_ra_manage_callback(const struct device *dev, struct gpio_callback *callback,
278 bool set)
279 {
280 struct gpio_ra_data *data = dev->data;
281
282 return gpio_manage_callback(&data->callbacks, callback, set);
283 }
284 #endif
285
286 static DEVICE_API(gpio, gpio_ra_drv_api_funcs) = {
287 .pin_configure = gpio_ra_pin_configure,
288 #ifdef CONFIG_GPIO_GET_CONFIG
289 .pin_get_config = gpio_ra_pin_get_config,
290 #endif
291 .port_get_raw = gpio_ra_port_get_raw,
292 .port_set_masked_raw = gpio_ra_port_set_masked_raw,
293 .port_set_bits_raw = gpio_ra_port_set_bits_raw,
294 .port_clear_bits_raw = gpio_ra_port_clear_bits_raw,
295 .port_toggle_bits = gpio_ra_port_toggle_bits,
296 #if CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT
297 .pin_interrupt_configure = gpio_ra_pin_interrupt_configure,
298 .manage_callback = gpio_ra_manage_callback,
299 #endif
300 };
301
302 #define GPIO_RA_PINS_NAME(n, p, i) CONCAT(DT_STRING_TOKEN_BY_IDX(n, p, i), _pins)
303
304 #define GPIO_RA_DECL_PINS(n, p, i) \
305 const uint8_t CONCAT(n, ___pins##i[]) = { \
306 DT_FOREACH_PROP_ELEM_SEP(n, GPIO_RA_PINS_NAME(n, p, i), DT_PROP_BY_IDX, (,))};
307
308 #define GPIO_RA_IRQ_INFO(n, p, i) \
309 { \
310 .port_irq = DEVICE_DT_GET_OR_NULL(DT_PHANDLE_BY_IDX(n, port_irqs, i)), \
311 .pins = CONCAT(n, ___pins##i), \
312 .num = ARRAY_SIZE(CONCAT(n, ___pins##i)), \
313 },
314
315 #define DECL_PINS_PARAMETER(node) \
316 COND_CODE_1(DT_NODE_HAS_PROP(node, port_irq_names), \
317 (DT_FOREACH_PROP_ELEM(node, port_irq_names, GPIO_RA_DECL_PINS)), ())
318 #define IRQ_INFO_PARAMETER(node) \
319 COND_CODE_1(DT_NODE_HAS_PROP(node, port_irq_names), \
320 (DT_FOREACH_PROP_ELEM(node, port_irq_names, GPIO_RA_IRQ_INFO)), ())
321
322 #define GPIO_DEVICE_INIT(node, port_number, suffix, addr) \
323 DECL_PINS_PARAMETER(node); \
324 struct gpio_ra_irq_info gpio_ra_irq_info_##suffix[] = {IRQ_INFO_PARAMETER(node)}; \
325 static const struct gpio_ra_config gpio_ra_config_##suffix = { \
326 .common = \
327 { \
328 .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_NGPIOS(16U), \
329 }, \
330 .port_num = port_number, \
331 .port = (R_PORT0_Type *)addr, \
332 .vbatt_pins = DT_PROP_OR(DT_NODELABEL(ioport##suffix), vbatts_pins, {0xFF}), \
333 .irq_info = gpio_ra_irq_info_##suffix, \
334 .irq_info_size = DT_PROP_LEN_OR(DT_NODELABEL(ioport##suffix), port_irq_names, 0), \
335 }; \
336 static struct gpio_ra_data gpio_ra_data_##suffix; \
337 DEVICE_DT_DEFINE(node, NULL, NULL, &gpio_ra_data_##suffix, &gpio_ra_config_##suffix, \
338 PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, &gpio_ra_drv_api_funcs)
339
340 #define GPIO_DEVICE_INIT_RA(suffix) \
341 GPIO_DEVICE_INIT(DT_NODELABEL(ioport##suffix), \
342 DT_PROP(DT_NODELABEL(ioport##suffix), port), suffix, \
343 DT_REG_ADDR(DT_NODELABEL(ioport##suffix)))
344
345 #define GPIO_DEVICE_INIT_RA_IF_OKAY(suffix) \
346 COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ioport##suffix)), \
347 (GPIO_DEVICE_INIT_RA(suffix)), \
348 ())
349
350 GPIO_DEVICE_INIT_RA_IF_OKAY(0);
351 GPIO_DEVICE_INIT_RA_IF_OKAY(1);
352 GPIO_DEVICE_INIT_RA_IF_OKAY(2);
353 GPIO_DEVICE_INIT_RA_IF_OKAY(3);
354 GPIO_DEVICE_INIT_RA_IF_OKAY(4);
355 GPIO_DEVICE_INIT_RA_IF_OKAY(5);
356 GPIO_DEVICE_INIT_RA_IF_OKAY(6);
357 GPIO_DEVICE_INIT_RA_IF_OKAY(7);
358 GPIO_DEVICE_INIT_RA_IF_OKAY(8);
359 GPIO_DEVICE_INIT_RA_IF_OKAY(9);
360 GPIO_DEVICE_INIT_RA_IF_OKAY(a);
361 GPIO_DEVICE_INIT_RA_IF_OKAY(b);
362