1 /*
2 * Copyright (c) 2006-2025, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-07-29 KyleChan first version
9 * 2022-01-19 Sherman add PIN2IRQX_TABLE
10 * 2025-01-13 newflydd pin_get for RZ
11 */
12
13 #include <drv_gpio.h>
14
15 #ifdef RT_USING_PIN
16
17 #define DBG_TAG "drv.gpio"
18 #ifdef DRV_DEBUG
19 #define DBG_LVL DBG_LOG
20 #else
21 #define DBG_LVL DBG_INFO
22 #endif /* DRV_DEBUG */
23
24 #ifdef R_ICU_H
25 #include "gpio_cfg.h"
26
ra_pin_get_irqx(rt_uint32_t pin)27 static rt_base_t ra_pin_get_irqx(rt_uint32_t pin)
28 {
29 PIN2IRQX_TABLE(pin)
30 }
31
32 static struct rt_pin_irq_hdr pin_irq_hdr_tab[RA_IRQ_MAX] = {0};
33 struct ra_pin_irq_map pin_irq_map[RA_IRQ_MAX] = {0};
34
ra_irq_tab_init(void)35 static void ra_irq_tab_init(void)
36 {
37 for (int i = 0; i < RA_IRQ_MAX; ++i)
38 {
39 pin_irq_hdr_tab[i].pin = -1;
40 pin_irq_hdr_tab[i].mode = 0;
41 pin_irq_hdr_tab[i].args = RT_NULL;
42 pin_irq_hdr_tab[i].hdr = RT_NULL;
43 }
44 }
45
ra_pin_map_init(void)46 static void ra_pin_map_init(void)
47 {
48 #if defined(VECTOR_NUMBER_ICU_IRQ0) || (VECTOR_NUMBER_IRQ0)
49 pin_irq_map[0].irq_ctrl = &g_external_irq0_ctrl;
50 pin_irq_map[0].irq_cfg = &g_external_irq0_cfg;
51 #endif
52 #if defined(VECTOR_NUMBER_ICU_IRQ1) || (VECTOR_NUMBER_IRQ1)
53 pin_irq_map[1].irq_ctrl = &g_external_irq1_ctrl;
54 pin_irq_map[1].irq_cfg = &g_external_irq1_cfg;
55 #endif
56 #if defined(VECTOR_NUMBER_ICU_IRQ2) || (VECTOR_NUMBER_IRQ2)
57 pin_irq_map[2].irq_ctrl = &g_external_irq2_ctrl;
58 pin_irq_map[2].irq_cfg = &g_external_irq2_cfg;
59 #endif
60 #if defined(VECTOR_NUMBER_ICU_IRQ3) || (VECTOR_NUMBER_IRQ3)
61 pin_irq_map[3].irq_ctrl = &g_external_irq3_ctrl;
62 pin_irq_map[3].irq_cfg = &g_external_irq3_cfg;
63 #endif
64 #if defined(VECTOR_NUMBER_ICU_IRQ4) || (VECTOR_NUMBER_IRQ4)
65 pin_irq_map[4].irq_ctrl = &g_external_irq4_ctrl;
66 pin_irq_map[4].irq_cfg = &g_external_irq4_cfg;
67 #endif
68 #if defined(VECTOR_NUMBER_ICU_IRQ5) || (VECTOR_NUMBER_IRQ5)
69 pin_irq_map[5].irq_ctrl = &g_external_irq5_ctrl;
70 pin_irq_map[5].irq_cfg = &g_external_irq5_cfg;
71 #endif
72 #if defined(VECTOR_NUMBER_ICU_IRQ6) || (VECTOR_NUMBER_IRQ6)
73 pin_irq_map[6].irq_ctrl = &g_external_irq6_ctrl;
74 pin_irq_map[6].irq_cfg = &g_external_irq6_cfg;
75 #endif
76 #if defined(VECTOR_NUMBER_ICU_IRQ7) || (VECTOR_NUMBER_IRQ7)
77 pin_irq_map[7].irq_ctrl = &g_external_irq7_ctrl;
78 pin_irq_map[7].irq_cfg = &g_external_irq7_cfg;
79 #endif
80 #if defined(VECTOR_NUMBER_ICU_IRQ8) || (VECTOR_NUMBER_IRQ8)
81 pin_irq_map[8].irq_ctrl = &g_external_irq8_ctrl;
82 pin_irq_map[8].irq_cfg = &g_external_irq8_cfg;
83 #endif
84 #if defined(VECTOR_NUMBER_ICU_IRQ9) || (VECTOR_NUMBER_IRQ9)
85 pin_irq_map[9].irq_ctrl = &g_external_irq9_ctrl;
86 pin_irq_map[9].irq_cfg = &g_external_irq9_cfg;
87 #endif
88 #if defined(VECTOR_NUMBER_ICU_IRQ10) || (VECTOR_NUMBER_IRQ10)
89 pin_irq_map[10].irq_ctrl = &g_external_irq10_ctrl;
90 pin_irq_map[10].irq_cfg = &g_external_irq10_cfg;
91 #endif
92 #if defined(VECTOR_NUMBER_ICU_IRQ11) || (VECTOR_NUMBER_IRQ11)
93 pin_irq_map[11].irq_ctrl = &g_external_irq11_ctrl;
94 pin_irq_map[11].irq_cfg = &g_external_irq11_cfg;
95 #endif
96 #if defined(VECTOR_NUMBER_ICU_IRQ12) || (VECTOR_NUMBER_IRQ12)
97 pin_irq_map[12].irq_ctrl = &g_external_irq12_ctrl;
98 pin_irq_map[12].irq_cfg = &g_external_irq12_cfg;
99 #endif
100 #if defined(VECTOR_NUMBER_ICU_IRQ13) || (VECTOR_NUMBER_IRQ13)
101 pin_irq_map[13].irq_ctrl = &g_external_irq13_ctrl;
102 pin_irq_map[13].irq_cfg = &g_external_irq13_cfg;
103 #endif
104 #if defined(VECTOR_NUMBER_ICU_IRQ14) || (VECTOR_NUMBER_IRQ014)
105 pin_irq_map[14].irq_ctrl = &g_external_irq14_ctrl;
106 pin_irq_map[14].irq_cfg = &g_external_irq14_cfg;
107 #endif
108 #if defined(VECTOR_NUMBER_ICU_IRQ15) || (VECTOR_NUMBER_IRQ015)
109 pin_irq_map[15].irq_ctrl = &g_external_irq15_ctrl;
110 pin_irq_map[15].irq_cfg = &g_external_irq15_cfg;
111 #endif
112 }
113 #endif /* R_ICU_H */
114
ra_pin_mode(rt_device_t dev,rt_base_t pin,rt_uint8_t mode)115 static void ra_pin_mode(rt_device_t dev, rt_base_t pin, rt_uint8_t mode)
116 {
117 fsp_err_t err;
118
119 /* Initialize the IOPORT module and configure the pins */
120 err = R_IOPORT_Open(&g_ioport_ctrl, &g_bsp_pin_cfg);
121
122 if (err != FSP_SUCCESS)
123 {
124 LOG_E("GPIO open failed");
125 return;
126 }
127
128 switch (mode)
129 {
130 case PIN_MODE_OUTPUT:
131 err = R_IOPORT_PinCfg(&g_ioport_ctrl, (bsp_io_port_pin_t)pin, BSP_IO_DIRECTION_OUTPUT);
132 if (err != FSP_SUCCESS)
133 {
134 LOG_E("PIN_MODE_OUTPUT configuration failed");
135 return;
136 }
137 break;
138
139 case PIN_MODE_INPUT:
140 err = R_IOPORT_PinCfg(&g_ioport_ctrl, (bsp_io_port_pin_t)pin, BSP_IO_DIRECTION_INPUT);
141 if (err != FSP_SUCCESS)
142 {
143 LOG_E("PIN_MODE_INPUT configuration failed");
144 return;
145 }
146 break;
147
148 case PIN_MODE_OUTPUT_OD:
149 err = R_IOPORT_PinCfg(&g_ioport_ctrl, (bsp_io_port_pin_t)pin, IOPORT_CFG_NMOS_ENABLE);
150 if (err != FSP_SUCCESS)
151 {
152 LOG_E("PIN_MODE_OUTPUT_OD configuration failed");
153 return;
154 }
155 break;
156 }
157 }
158
ra_pin_write(rt_device_t dev,rt_base_t pin,rt_uint8_t value)159 static void ra_pin_write(rt_device_t dev, rt_base_t pin, rt_uint8_t value)
160 {
161 bsp_io_level_t level = BSP_IO_LEVEL_HIGH;
162
163 if (value != level)
164 {
165 level = BSP_IO_LEVEL_LOW;
166 }
167
168 R_BSP_PinAccessEnable();
169 #ifdef SOC_SERIES_R9A07G0
170 R_IOPORT_PinWrite(&g_ioport_ctrl, (bsp_io_port_pin_t)pin, (bsp_io_level_t)level);
171 #else
172 R_BSP_PinWrite(pin, level);
173 #endif
174 R_BSP_PinAccessDisable();
175 }
176
ra_pin_read(rt_device_t dev,rt_base_t pin)177 static rt_ssize_t ra_pin_read(rt_device_t dev, rt_base_t pin)
178 {
179 if ((pin > RA_MAX_PIN_VALUE) || (pin < RA_MIN_PIN_VALUE))
180 {
181 return -RT_EINVAL;
182 }
183 #ifdef SOC_SERIES_R9A07G0
184 bsp_io_level_t io_level;
185 R_IOPORT_PinRead(&g_ioport_ctrl, (bsp_io_port_pin_t)pin, &io_level);
186 return io_level;
187 #else
188 return R_BSP_PinRead(pin);
189 #endif
190 }
191
ra_pin_irq_enable(struct rt_device * device,rt_base_t pin,rt_uint8_t enabled)192 static rt_err_t ra_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
193 {
194 #ifdef R_ICU_H
195 rt_err_t err;
196 rt_int32_t irqx = ra_pin_get_irqx(pin);
197 if (PIN_IRQ_ENABLE == enabled)
198 {
199 if (0 <= irqx && irqx < sizeof(pin_irq_map) / sizeof(pin_irq_map[0]))
200 {
201 err = R_ICU_ExternalIrqOpen((external_irq_ctrl_t *const)pin_irq_map[irqx].irq_ctrl,
202 (external_irq_cfg_t const * const)pin_irq_map[irqx].irq_cfg);
203 /* Handle error */
204 if (FSP_SUCCESS != err)
205 {
206 /* ICU Open failure message */
207 LOG_E("\r\n**R_ICU_ExternalIrqOpen API FAILED**\r\n");
208 return -RT_ERROR;
209 }
210
211 err = R_ICU_ExternalIrqEnable((external_irq_ctrl_t *const)pin_irq_map[irqx].irq_ctrl);
212 /* Handle error */
213 if (FSP_SUCCESS != err)
214 {
215 /* ICU Enable failure message */
216 LOG_E("\r\n**R_ICU_ExternalIrqEnable API FAILED**\r\n");
217 return -RT_ERROR;
218 }
219 }
220 }
221 else if (PIN_IRQ_DISABLE == enabled)
222 {
223 err = R_ICU_ExternalIrqDisable((external_irq_ctrl_t *const)pin_irq_map[irqx].irq_ctrl);
224 if (FSP_SUCCESS != err)
225 {
226 /* ICU Disable failure message */
227 LOG_E("\r\n**R_ICU_ExternalIrqDisable API FAILED**\r\n");
228 return -RT_ERROR;
229 }
230 err = R_ICU_ExternalIrqClose((external_irq_ctrl_t *const)pin_irq_map[irqx].irq_ctrl);
231 if (FSP_SUCCESS != err)
232 {
233 /* ICU Close failure message */
234 LOG_E("\r\n**R_ICU_ExternalIrqClose API FAILED**\r\n");
235 return -RT_ERROR;
236 }
237 }
238 return RT_EOK;
239 #else
240 return -RT_ERROR;
241 #endif
242 }
243
ra_pin_attach_irq(struct rt_device * device,rt_base_t pin,rt_uint8_t mode,void (* hdr)(void * args),void * args)244 static rt_err_t ra_pin_attach_irq(struct rt_device *device, rt_base_t pin,
245 rt_uint8_t mode, void (*hdr)(void *args), void *args)
246 {
247 #ifdef R_ICU_H
248 rt_int32_t irqx = ra_pin_get_irqx(pin);
249 if (0 <= irqx && irqx < (sizeof(pin_irq_map) / sizeof(pin_irq_map[0])))
250 {
251 int level = rt_hw_interrupt_disable();
252 if (pin_irq_hdr_tab[irqx].pin == irqx &&
253 pin_irq_hdr_tab[irqx].hdr == hdr &&
254 pin_irq_hdr_tab[irqx].mode == mode &&
255 pin_irq_hdr_tab[irqx].args == args)
256 {
257 rt_hw_interrupt_enable(level);
258 return RT_EOK;
259 }
260 if (pin_irq_hdr_tab[irqx].pin != -1)
261 {
262 rt_hw_interrupt_enable(level);
263 return -RT_EBUSY;
264 }
265 pin_irq_hdr_tab[irqx].pin = irqx;
266 pin_irq_hdr_tab[irqx].hdr = hdr;
267 pin_irq_hdr_tab[irqx].mode = mode;
268 pin_irq_hdr_tab[irqx].args = args;
269 rt_hw_interrupt_enable(level);
270 }
271 else return -RT_ERROR;
272 return RT_EOK;
273 #else
274 return -RT_ERROR;
275 #endif
276 }
277
ra_pin_dettach_irq(struct rt_device * device,rt_base_t pin)278 static rt_err_t ra_pin_dettach_irq(struct rt_device *device, rt_base_t pin)
279 {
280 #ifdef R_ICU_H
281 rt_int32_t irqx = ra_pin_get_irqx(pin);
282 if (0 <= irqx && irqx < sizeof(pin_irq_map) / sizeof(pin_irq_map[0]))
283 {
284 int level = rt_hw_interrupt_disable();
285 if (pin_irq_hdr_tab[irqx].pin == -1)
286 {
287 rt_hw_interrupt_enable(level);
288 return RT_EOK;
289 }
290 pin_irq_hdr_tab[irqx].pin = -1;
291 pin_irq_hdr_tab[irqx].hdr = RT_NULL;
292 pin_irq_hdr_tab[irqx].mode = 0;
293 pin_irq_hdr_tab[irqx].args = RT_NULL;
294 rt_hw_interrupt_enable(level);
295 }
296 else
297 {
298 return -RT_ERROR;
299 }
300 return RT_EOK;
301 #else
302 return -RT_ERROR;
303 #endif
304 }
305
ra_pin_get(const char * name)306 static rt_base_t ra_pin_get(const char *name)
307 {
308 #ifdef SOC_FAMILY_RENESAS_RZ
309 /* RZ series: use "PXX_X" format, like "P01_1" */
310 if ((rt_strlen(name) == 5) &&
311 ((name[0] == 'P') || (name[0] == 'p')) &&
312 (name[3] == '_') &&
313 ('0' <= (int) name[1] && (int) name[1] <= '1') &&
314 ('0' <= (int) name[2] && (int) name[2] <= '9') &&
315 ('0' <= (int) name[4] && (int) name[4] <= '7'))
316 {
317 return (((int) name[1] - '0') * 10 + ((int) name[2] - '0')) * 0x100 + ((int) name[4] - '0');
318 }
319 LOG_W("Invalid pin expression, use `PXX_X` format like `P01_1`");
320 #else
321 /* RA series: use "PXXX" format, like "P101"*/
322 if ((rt_strlen(name) == 4) &&
323 (name[0] == 'P' || name[0] == 'p') &&
324 (name[1] >= '0' && name[1] <= '9') &&
325 (name[2] >= '0' && name[1] <= '9') &&
326 (name[3] >= '0' && name[1] <= '9'))
327 {
328 return (name[1] - '0') * 0x100 + (name[2] - '0') * 10 + (name[3] - '0');
329 }
330 LOG_W("Invalid pin expression, use `PXXX` format like `P101`");
331 #endif
332 return -RT_ERROR;
333 }
334
335 const static struct rt_pin_ops _ra_pin_ops =
336 {
337 .pin_mode = ra_pin_mode,
338 .pin_write = ra_pin_write,
339 .pin_read = ra_pin_read,
340 .pin_attach_irq = ra_pin_attach_irq,
341 .pin_detach_irq = ra_pin_dettach_irq,
342 .pin_irq_enable = ra_pin_irq_enable,
343 .pin_get = ra_pin_get,
344 };
345
rt_hw_pin_init(void)346 int rt_hw_pin_init(void)
347 {
348 #ifdef R_ICU_H
349 ra_irq_tab_init();
350 ra_pin_map_init();
351 #endif
352
353 return rt_device_pin_register("pin", &_ra_pin_ops, RT_NULL);
354 }
355
356 #ifdef R_ICU_H
irq_callback(external_irq_callback_args_t * p_args)357 void irq_callback(external_irq_callback_args_t *p_args)
358 {
359 rt_interrupt_enter();
360 if (p_args->channel == pin_irq_hdr_tab[p_args->channel].pin)
361 {
362 pin_irq_hdr_tab[p_args->channel].hdr(pin_irq_hdr_tab[p_args->channel].args);
363 }
364 rt_interrupt_leave();
365 };
366 #endif /* R_ICU_H */
367
368 #endif /* RT_USING_PIN */
369