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->vbatt_pins[0] != 0xFF) {
82 		uint32_t clear = 0;
83 
84 		for (int i = 0; config->vbatt_pins[i] != '\0'; i++) {
85 			if (config->vbatt_pins[i] == pin) {
86 				WRITE_BIT(clear, i, 1);
87 			}
88 		}
89 
90 		R_BSP_RegisterProtectDisable(BSP_REG_PROTECT_OM_LPC_BATT);
91 
92 		R_SYSTEM->VBTICTLR &= (uint8_t)~clear;
93 
94 		R_BSP_RegisterProtectEnable(BSP_REG_PROTECT_OM_LPC_BATT);
95 	}
96 
97 	pincfg.port_num = config->port_num;
98 	pincfg.pin_num = pin;
99 
100 	/* Initial pin settings when PFS is zeroed:
101 	 * - Low output, input mode
102 	 * - Pull-up disabled, CMOS output
103 	 * - Low drive strength
104 	 * - Not used for IRQ or analog
105 	 * - Configured as general I/O
106 	 */
107 	pfs_cfg = 0;
108 
109 	if ((flags & GPIO_OUTPUT) != 0U) {
110 		/* Set output pin initial value */
111 		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
112 			WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_PODR_Pos, 1);
113 		}
114 
115 		WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_PDR_Pos, 1);
116 	}
117 
118 	if ((flags & GPIO_LINE_OPEN_DRAIN) != 0) {
119 		WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_NCODR_Pos, 1);
120 	}
121 
122 	if ((flags & GPIO_PULL_UP) != 0) {
123 		WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_PCR_Pos, 1);
124 	}
125 
126 #if CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT
127 	if ((flags & GPIO_INT_ENABLE) != 0) {
128 		const struct gpio_ra_irq_info *irq_info = query_irq_info(dev, pin);
129 		int err = 0;
130 
131 		if (irq_info == NULL) {
132 			return -EINVAL;
133 		}
134 
135 		if (!device_is_ready(irq_info->port_irq)) {
136 			return -EWOULDBLOCK;
137 		}
138 
139 		struct gpio_ra_callback callback = {
140 			.port = (struct device *)dev,
141 			.port_num = config->port_num,
142 			.pin = pin,
143 			.mode = flags & (GPIO_INT_EDGE | GPIO_INT_DISABLE | GPIO_INT_ENABLE),
144 			.trigger = flags & (GPIO_INT_LOW_0 | GPIO_INT_HIGH_1),
145 			.isr = gpio_ra_callback_adapter,
146 		};
147 
148 		err = gpio_ra_interrupt_set(irq_info->port_irq, &callback);
149 		if (err < 0) {
150 			return err;
151 		}
152 
153 		WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_ISEL_Pos, 1);
154 	}
155 
156 	if ((flags & GPIO_INT_DISABLE) != 0) {
157 		const struct gpio_ra_irq_info *irq_info = query_irq_info(dev, pin);
158 
159 		if (irq_info == NULL) {
160 			return -EINVAL;
161 		}
162 
163 		if (!device_is_ready(irq_info->port_irq)) {
164 			return -EWOULDBLOCK;
165 		}
166 
167 		gpio_ra_interrupt_unset(irq_info->port_irq, config->port_num, pin);
168 		WRITE_BIT(pfs_cfg, R_PFS_PORT_PIN_PmnPFS_ISEL_Pos, 0);
169 	}
170 #endif
171 
172 	pincfg.cfg =
173 		pfs_cfg | (((flags & RENESAS_GPIO_DS_MSK) >> 8) << R_PFS_PORT_PIN_PmnPFS_DSCR_Pos);
174 
175 	return pinctrl_configure_pins(&pincfg, 1, PINCTRL_REG_NONE);
176 }
177 
gpio_ra_port_get_raw(const struct device * dev,uint32_t * value)178 static int gpio_ra_port_get_raw(const struct device *dev, uint32_t *value)
179 {
180 	const struct gpio_ra_config *config = dev->config;
181 	R_PORT0_Type *port = config->port;
182 
183 	*value = port->PIDR;
184 
185 	return 0;
186 }
187 
gpio_ra_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)188 static int gpio_ra_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask,
189 				       gpio_port_value_t value)
190 {
191 	const struct gpio_ra_config *config = dev->config;
192 	R_PORT0_Type *port = config->port;
193 
194 	port->PODR = ((port->PODR & ~mask) | (value & mask));
195 
196 	return 0;
197 }
198 
gpio_ra_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)199 static int gpio_ra_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins)
200 {
201 	const struct gpio_ra_config *config = dev->config;
202 	R_PORT0_Type *port = config->port;
203 
204 	port->PODR = (port->PODR | pins);
205 
206 	return 0;
207 }
208 
gpio_ra_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)209 static int gpio_ra_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins)
210 {
211 	const struct gpio_ra_config *config = dev->config;
212 	R_PORT0_Type *port = config->port;
213 
214 	port->PODR = (port->PODR & ~pins);
215 
216 	return 0;
217 }
218 
gpio_ra_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)219 static int gpio_ra_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins)
220 {
221 	const struct gpio_ra_config *config = dev->config;
222 	R_PORT0_Type *port = config->port;
223 
224 	port->PODR = (port->PODR ^ pins);
225 
226 	return 0;
227 }
228 
229 #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)230 static int gpio_ra_pin_interrupt_configure(const struct device *port, gpio_pin_t pin,
231 					   enum gpio_int_mode mode, enum gpio_int_trig trig)
232 {
233 	return gpio_ra_pin_configure(port, pin, (mode | trig));
234 }
235 
gpio_ra_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)236 static int gpio_ra_manage_callback(const struct device *dev, struct gpio_callback *callback,
237 				   bool set)
238 {
239 	struct gpio_ra_data *data = dev->data;
240 
241 	return gpio_manage_callback(&data->callbacks, callback, set);
242 }
243 #endif
244 
245 static DEVICE_API(gpio, gpio_ra_drv_api_funcs) = {
246 	.pin_configure = gpio_ra_pin_configure,
247 	.port_get_raw = gpio_ra_port_get_raw,
248 	.port_set_masked_raw = gpio_ra_port_set_masked_raw,
249 	.port_set_bits_raw = gpio_ra_port_set_bits_raw,
250 	.port_clear_bits_raw = gpio_ra_port_clear_bits_raw,
251 	.port_toggle_bits = gpio_ra_port_toggle_bits,
252 #if CONFIG_RENESAS_RA_EXTERNAL_INTERRUPT
253 	.pin_interrupt_configure = gpio_ra_pin_interrupt_configure,
254 	.manage_callback = gpio_ra_manage_callback,
255 #endif
256 };
257 
258 #define GPIO_RA_PINS_NAME(n, p, i) CONCAT(DT_STRING_TOKEN_BY_IDX(n, p, i), _pins)
259 
260 #define GPIO_RA_DECL_PINS(n, p, i)                                                                 \
261 	const uint8_t CONCAT(n, ___pins##i[]) = {                                                  \
262 		DT_FOREACH_PROP_ELEM_SEP(n, GPIO_RA_PINS_NAME(n, p, i), DT_PROP_BY_IDX, (,))};
263 
264 #define GPIO_RA_IRQ_INFO(n, p, i)                                                                  \
265 	{                                                                                          \
266 		.port_irq = DEVICE_DT_GET_OR_NULL(DT_PHANDLE_BY_IDX(n, port_irqs, i)),             \
267 		.pins = CONCAT(n, ___pins##i),                                                     \
268 		.num = ARRAY_SIZE(CONCAT(n, ___pins##i)),                                          \
269 	},
270 
271 #define GPIO_DEVICE_INIT(node, port_number, suffix, addr)                                          \
272 	DT_FOREACH_PROP_ELEM(node, port_irq_names, GPIO_RA_DECL_PINS);                             \
273 	struct gpio_ra_irq_info gpio_ra_irq_info_##suffix[] = {                                    \
274 		DT_FOREACH_PROP_ELEM(node, port_irq_names, GPIO_RA_IRQ_INFO)};                     \
275 	static const struct gpio_ra_config gpio_ra_config_##suffix = {                             \
276 		.common =                                                                          \
277 			{                                                                          \
278 				.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_NGPIOS(16U),              \
279 			},                                                                         \
280 		.port_num = port_number,                                                           \
281 		.port = (R_PORT0_Type *)addr,                                                      \
282 		.vbatt_pins = DT_PROP_OR(DT_NODELABEL(ioport##suffix), vbatts_pins, {0xFF}),       \
283 		.irq_info = gpio_ra_irq_info_##suffix,                                             \
284 		.irq_info_size = DT_PROP_LEN_OR(DT_NODELABEL(ioport##suffix), port_irq_names, 0),  \
285 	};                                                                                         \
286 	static struct gpio_ra_data gpio_ra_data_##suffix;                                          \
287 	DEVICE_DT_DEFINE(node, NULL, NULL, &gpio_ra_data_##suffix, &gpio_ra_config_##suffix,       \
288 			 PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, &gpio_ra_drv_api_funcs)
289 
290 #define GPIO_DEVICE_INIT_RA(suffix)                                                                \
291 	GPIO_DEVICE_INIT(DT_NODELABEL(ioport##suffix),                                             \
292 			 DT_PROP(DT_NODELABEL(ioport##suffix), port), suffix,                      \
293 			 DT_REG_ADDR(DT_NODELABEL(ioport##suffix)))
294 
295 #define GPIO_DEVICE_INIT_RA_IF_OKAY(suffix)                                                        \
296 	COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(ioport##suffix)),                         \
297 		    (GPIO_DEVICE_INIT_RA(suffix)),                                                 \
298 		    ())
299 
300 GPIO_DEVICE_INIT_RA_IF_OKAY(0);
301 GPIO_DEVICE_INIT_RA_IF_OKAY(1);
302 GPIO_DEVICE_INIT_RA_IF_OKAY(2);
303 GPIO_DEVICE_INIT_RA_IF_OKAY(3);
304 GPIO_DEVICE_INIT_RA_IF_OKAY(4);
305 GPIO_DEVICE_INIT_RA_IF_OKAY(5);
306 GPIO_DEVICE_INIT_RA_IF_OKAY(6);
307 GPIO_DEVICE_INIT_RA_IF_OKAY(7);
308 GPIO_DEVICE_INIT_RA_IF_OKAY(8);
309 GPIO_DEVICE_INIT_RA_IF_OKAY(9);
310 GPIO_DEVICE_INIT_RA_IF_OKAY(a);
311 GPIO_DEVICE_INIT_RA_IF_OKAY(b);
312