1 /*
2  * Copyright 2023-2024, NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_imx_rgpio
8 
9 #include <errno.h>
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/drivers/pinctrl.h>
13 #include <zephyr/irq.h>
14 #include <fsl_common.h>
15 #include <fsl_rgpio.h>
16 
17 #include <zephyr/drivers/gpio/gpio_utils.h>
18 
19 /* Required by DEVICE_MMIO_NAMED_* macros */
20 #define DEV_CFG(_dev) \
21 	((const struct mcux_rgpio_config *)(_dev)->config)
22 #define DEV_DATA(_dev) ((struct mcux_rgpio_data *)(_dev)->data)
23 
24 struct mcux_rgpio_config {
25 	/* gpio_driver_config needs to be first */
26 	struct gpio_driver_config common;
27 
28 	DEVICE_MMIO_NAMED_ROM(reg_base);
29 
30 	const struct pinctrl_soc_pinmux *pin_muxes;
31 	uint8_t mux_count;
32 };
33 
34 struct mcux_rgpio_data {
35 	/* gpio_driver_data needs to be first */
36 	struct gpio_driver_data general;
37 
38 	DEVICE_MMIO_NAMED_RAM(reg_base);
39 
40 	/* port ISR callback routine address */
41 	sys_slist_t callbacks;
42 };
43 
mcux_rgpio_configure(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)44 static int mcux_rgpio_configure(const struct device *dev,
45 				gpio_pin_t pin, gpio_flags_t flags)
46 {
47 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
48 	const struct mcux_rgpio_config *config = dev->config;
49 
50 	struct pinctrl_soc_pin pin_cfg;
51 	int cfg_idx = pin, i;
52 
53 	/* Make sure pin is supported */
54 	if ((config->common.port_pin_mask & BIT(pin)) == 0) {
55 		return -ENOTSUP;
56 	}
57 
58 	/* Some SOCs have non-contiguous gpio pin layouts, account for this */
59 	for (i = 0; i < pin; i++) {
60 		if ((config->common.port_pin_mask & BIT(i)) == 0) {
61 			cfg_idx--;
62 		}
63 	}
64 
65 	/* Init pin configuration struct, and use pinctrl api to apply settings */
66 	if (cfg_idx >= config->mux_count) {
67 		/* Pin is not connected to a mux */
68 		return -ENOTSUP;
69 	}
70 
71 	/* Set appropriate bits in pin configuration register */
72 	volatile uint32_t *gpio_cfg_reg = (volatile uint32_t *)
73 			((size_t)config->pin_muxes[cfg_idx].config_register);
74 	uint32_t reg = *gpio_cfg_reg;
75 
76 #if defined(CONFIG_SOC_SERIES_IMXRT118X)
77 	/* PUE/PDRV types have the same ODE bit */
78 	if ((flags & GPIO_SINGLE_ENDED)) {
79 		/* Set ODE bit */
80 		reg |= IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
81 	} else {
82 		reg &= ~IOMUXC_SW_PAD_CTL_PAD_ODE_MASK;
83 	}
84 
85 	if (config->pin_muxes[pin].pue_mux) {
86 		if (flags & GPIO_PULL_UP) {
87 			reg |= (IOMUXC_SW_PAD_CTL_PAD_PUS_MASK | IOMUXC_SW_PAD_CTL_PAD_PUE_MASK);
88 		} else if (flags & GPIO_PULL_DOWN) {
89 			reg |= IOMUXC_SW_PAD_CTL_PAD_PUE_MASK;
90 			reg &= ~IOMUXC_SW_PAD_CTL_PAD_PUS_MASK;
91 		} else {
92 			/* Set pin to highz */
93 			reg &= ~IOMUXC_SW_PAD_CTL_PAD_PUE_MASK;
94 		}
95 	} else {
96 		/* PDRV type register layout */
97 		if (flags & GPIO_PULL_UP) {
98 			reg &= ~IOMUXC_SW_PAD_CTL_PAD_PULL_MASK;
99 			reg |= IOMUXC_SW_PAD_CTL_PAD_PULL(0x1U);
100 		} else if (flags & GPIO_PULL_DOWN) {
101 			reg &= ~IOMUXC_SW_PAD_CTL_PAD_PULL_MASK;
102 			reg |= IOMUXC_SW_PAD_CTL_PAD_PULL(0x2U);
103 		} else {
104 			/* Set pin to no pull */
105 			reg |= IOMUXC_SW_PAD_CTL_PAD_PULL_MASK;
106 		}
107 	}
108 #else
109 	/* TODO: Default flags, work for i.MX 9352 */
110 	if ((flags & GPIO_SINGLE_ENDED) != 0) {
111 		/* Set ODE bit */
112 		reg |= (0x1 << MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
113 	} else {
114 		reg &= ~(0x1 << MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
115 	}
116 	if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
117 		/* i.MX93 has no pull enable bit */
118 		if (((flags & GPIO_PULL_UP) != 0)) {
119 			reg |= (0x1 << MCUX_IMX_BIAS_PULL_UP_SHIFT);
120 			reg &= ~(0x1 << MCUX_IMX_BIAS_PULL_DOWN_SHIFT);
121 		} else {
122 			reg |= (0x1 << MCUX_IMX_BIAS_PULL_DOWN_SHIFT);
123 			reg &= ~(0x1 << MCUX_IMX_BIAS_PULL_UP_SHIFT);
124 		}
125 	} else {
126 		/* Set pin to highz */
127 		reg &= ~((0x1 << MCUX_IMX_BIAS_PULL_DOWN_SHIFT) |
128 				(0x1 << MCUX_IMX_BIAS_PULL_UP_SHIFT));
129 	}
130 #endif
131 
132 	memcpy(&pin_cfg.pinmux, &config->pin_muxes[cfg_idx], sizeof(pin_cfg));
133 	/* cfg register will be set by pinctrl_configure_pins */
134 	pin_cfg.pin_ctrl_flags = reg;
135 	pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE);
136 
137 	if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) {
138 		return -ENOTSUP;
139 	}
140 
141 	if (flags & GPIO_OUTPUT_INIT_HIGH) {
142 		RGPIO_WritePinOutput(base, pin, 1);
143 	}
144 
145 	if (flags & GPIO_OUTPUT_INIT_LOW) {
146 		RGPIO_WritePinOutput(base, pin, 0);
147 	}
148 
149 	WRITE_BIT(base->PDDR, pin, flags & GPIO_OUTPUT);
150 
151 	return 0;
152 }
153 
mcux_rgpio_port_get_raw(const struct device * dev,uint32_t * value)154 static int mcux_rgpio_port_get_raw(const struct device *dev, uint32_t *value)
155 {
156 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
157 
158 	*value = base->PDIR;
159 
160 	return 0;
161 }
162 
mcux_rgpio_port_set_masked_raw(const struct device * dev,uint32_t mask,uint32_t value)163 static int mcux_rgpio_port_set_masked_raw(const struct device *dev,
164 					  uint32_t mask,
165 					  uint32_t value)
166 {
167 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
168 
169 	base->PDOR = (base->PDOR & ~mask) | (mask & value);
170 
171 	return 0;
172 }
173 
mcux_rgpio_port_set_bits_raw(const struct device * dev,uint32_t mask)174 static int mcux_rgpio_port_set_bits_raw(const struct device *dev,
175 					uint32_t mask)
176 {
177 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
178 
179 	RGPIO_PortSet(base, mask);
180 
181 	return 0;
182 }
183 
mcux_rgpio_port_clear_bits_raw(const struct device * dev,uint32_t mask)184 static int mcux_rgpio_port_clear_bits_raw(const struct device *dev,
185 					  uint32_t mask)
186 {
187 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
188 
189 	RGPIO_PortClear(base, mask);
190 
191 	return 0;
192 }
193 
mcux_rgpio_port_toggle_bits(const struct device * dev,uint32_t mask)194 static int mcux_rgpio_port_toggle_bits(const struct device *dev,
195 					   uint32_t mask)
196 {
197 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
198 
199 	RGPIO_PortToggle(base, mask);
200 
201 	return 0;
202 }
203 
mcux_rgpio_pin_interrupt_configure(const struct device * dev,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)204 static int mcux_rgpio_pin_interrupt_configure(const struct device *dev,
205 						  gpio_pin_t pin,
206 						  enum gpio_int_mode mode,
207 						  enum gpio_int_trig trig)
208 {
209 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
210 	const struct mcux_rgpio_config *config = dev->config;
211 	unsigned int key;
212 	uint8_t irqs, irqc;
213 
214 	/* Make sure pin is supported */
215 	if ((config->common.port_pin_mask & BIT(pin)) == 0) {
216 		return -ENOTSUP;
217 	}
218 
219 	irqs = 0; /* only irq0 is used for irq */
220 
221 	if (mode == GPIO_INT_MODE_DISABLED) {
222 		irqc = kRGPIO_InterruptOrDMADisabled;
223 	} else if ((mode == GPIO_INT_MODE_EDGE) &&
224 		   (trig == GPIO_INT_TRIG_LOW)) {
225 		irqc = kRGPIO_InterruptFallingEdge;
226 	} else if ((mode == GPIO_INT_MODE_EDGE) &&
227 		   (trig == GPIO_INT_TRIG_HIGH)) {
228 		irqc = kRGPIO_InterruptRisingEdge;
229 	} else if ((mode == GPIO_INT_MODE_EDGE) &&
230 		   (trig == GPIO_INT_TRIG_BOTH)) {
231 		irqc = kRGPIO_InterruptEitherEdge;
232 	} else if ((mode == GPIO_INT_MODE_LEVEL) &&
233 		   (trig == GPIO_INT_TRIG_LOW)) {
234 		irqc = kRGPIO_InterruptLogicZero;
235 	} else if ((mode == GPIO_INT_MODE_LEVEL) &&
236 		   (trig == GPIO_INT_TRIG_HIGH)) {
237 		irqc = kRGPIO_InterruptLogicOne;
238 	} else {
239 		return -EINVAL; /* should never end up here */
240 	}
241 
242 	key = irq_lock();
243 	RGPIO_SetPinInterruptConfig(base, pin, irqs, irqc);
244 	irq_unlock(key);
245 
246 	return 0;
247 }
248 
mcux_rgpio_manage_callback(const struct device * dev,struct gpio_callback * callback,bool set)249 static int mcux_rgpio_manage_callback(const struct device *dev,
250 					  struct gpio_callback *callback,
251 					  bool set)
252 {
253 	struct mcux_rgpio_data *data = dev->data;
254 
255 	return gpio_manage_callback(&data->callbacks, callback, set);
256 }
257 
mcux_rgpio_port_isr(const struct device * dev)258 static void mcux_rgpio_port_isr(const struct device *dev)
259 {
260 	RGPIO_Type *base = (RGPIO_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base);
261 	struct mcux_rgpio_data *data = dev->data;
262 	uint32_t int_flags;
263 
264 	int_flags = base->ISFR[0]; /* Notice: only irq0 is used for now */
265 	base->ISFR[0] = int_flags;
266 
267 	gpio_fire_callbacks(&data->callbacks, dev, int_flags);
268 }
269 
270 static DEVICE_API(gpio, mcux_rgpio_driver_api) = {
271 	.pin_configure = mcux_rgpio_configure,
272 	.port_get_raw = mcux_rgpio_port_get_raw,
273 	.port_set_masked_raw = mcux_rgpio_port_set_masked_raw,
274 	.port_set_bits_raw = mcux_rgpio_port_set_bits_raw,
275 	.port_clear_bits_raw = mcux_rgpio_port_clear_bits_raw,
276 	.port_toggle_bits = mcux_rgpio_port_toggle_bits,
277 	.pin_interrupt_configure = mcux_rgpio_pin_interrupt_configure,
278 	.manage_callback = mcux_rgpio_manage_callback,
279 };
280 
281 /* These macros will declare an array of pinctrl_soc_pinmux types */
282 #define PINMUX_INIT(node, prop, idx) MCUX_IMX_PINMUX(DT_PROP_BY_IDX(node, prop, idx)),
283 #define MCUX_RGPIO_PIN_DECLARE(n)						\
284 	const struct pinctrl_soc_pinmux mcux_rgpio_pinmux_##n[] = {		\
285 		DT_FOREACH_PROP_ELEM(DT_DRV_INST(n), pinmux, PINMUX_INIT)	\
286 	};
287 #define MCUX_RGPIO_PIN_INIT(n)							\
288 	.pin_muxes = mcux_rgpio_pinmux_##n,					\
289 	.mux_count = DT_PROP_LEN(DT_DRV_INST(n), pinmux),
290 
291 #define MCUX_RGPIO_IRQ_INIT(n, i)					\
292 	do {								\
293 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, i, irq),		\
294 				DT_INST_IRQ_BY_IDX(n, i, priority),		\
295 				mcux_rgpio_port_isr,			\
296 				DEVICE_DT_INST_GET(n), 0);			\
297 									\
298 		irq_enable(DT_INST_IRQ_BY_IDX(n, i, irq));		\
299 	} while (false)
300 
301 #define MCUX_RGPIO_INIT(n)						\
302 	MCUX_RGPIO_PIN_DECLARE(n)					\
303 	static int mcux_rgpio_##n##_init(const struct device *dev);	\
304 									\
305 	static const struct mcux_rgpio_config mcux_rgpio_##n##_config = { \
306 		.common = {						\
307 			.port_pin_mask = GPIO_DT_INST_PORT_PIN_MASK_NGPIOS_EXC( \
308 					n, DT_INST_PROP(n, ngpios)) \
309 		},							\
310 		DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \
311 		MCUX_RGPIO_PIN_INIT(n)					\
312 	};								\
313 									\
314 	static struct mcux_rgpio_data mcux_rgpio_##n##_data;		\
315 									\
316 	DEVICE_DT_INST_DEFINE(n,					\
317 				mcux_rgpio_##n##_init,			\
318 				NULL,					\
319 				&mcux_rgpio_##n##_data,			\
320 				&mcux_rgpio_##n##_config,			\
321 				POST_KERNEL,				\
322 				CONFIG_GPIO_INIT_PRIORITY,			\
323 				&mcux_rgpio_driver_api);			\
324 									\
325 	static int mcux_rgpio_##n##_init(const struct device *dev)	\
326 	{								\
327 		DEVICE_MMIO_NAMED_MAP(dev, reg_base, \
328 			K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); \
329 		IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0),			\
330 		   (MCUX_RGPIO_IRQ_INIT(n, 0);))		\
331 									\
332 		IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 1),			\
333 			   (MCUX_RGPIO_IRQ_INIT(n, 1);))		\
334 									\
335 		return 0;						\
336 	}
337 
338 DT_INST_FOREACH_STATUS_OKAY(MCUX_RGPIO_INIT)
339