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