1 /*
2  * Copyright (c) 2018-2019, NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_imx_gpio
8 
9 #include <errno.h>
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/gpio.h>
12 #include <zephyr/irq.h>
13 #include <soc.h>
14 #include <zephyr/sys/util.h>
15 #include <gpio_imx.h>
16 #include <string.h>
17 #include <zephyr/drivers/pinctrl.h>
18 
19 #include <zephyr/drivers/gpio/gpio_utils.h>
20 
21 struct imx_gpio_config {
22 	/* gpio_driver_config needs to be first */
23 	struct gpio_driver_config common;
24 	GPIO_Type *base;
25 	const struct pinctrl_soc_pinmux *pin_muxes;
26 	uint8_t mux_count;
27 };
28 
29 struct imx_gpio_data {
30 	/* gpio_driver_data needs to be first */
31 	struct gpio_driver_data common;
32 	/* port ISR callback routine address */
33 	sys_slist_t callbacks;
34 };
35 
imx_gpio_configure(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)36 static int imx_gpio_configure(const struct device *port, gpio_pin_t pin,
37 			      gpio_flags_t flags)
38 {
39 	const struct imx_gpio_config *config = port->config;
40 	GPIO_Type *base = config->base;
41 
42 	if (((flags & GPIO_INPUT) != 0U) && ((flags & GPIO_OUTPUT) != 0U)) {
43 		return -ENOTSUP;
44 	}
45 	__ASSERT_NO_MSG(pin < config->mux_count);
46 
47 	struct pinctrl_soc_pin pin_cfg;
48 	/* Set appropriate bits in pin configuration register */
49 	volatile uint32_t *gpio_cfg_reg =
50 		(volatile uint32_t *)config->pin_muxes[pin].config_register;
51 	uint32_t reg = *gpio_cfg_reg;
52 
53 #ifdef MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT
54 	if ((flags & GPIO_SINGLE_ENDED) != 0) {
55 		/* Set ODE bit */
56 		reg |= BIT(MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
57 	} else {
58 		reg &= ~BIT(MCUX_IMX_DRIVE_OPEN_DRAIN_SHIFT);
59 	}
60 #else
61 	if ((flags & GPIO_SINGLE_ENDED) != 0) {
62 		return -ENOTSUP;
63 	}
64 #endif
65 	if (((flags & GPIO_PULL_UP) != 0) || ((flags & GPIO_PULL_DOWN) != 0)) {
66 		reg |= BIT(MCUX_IMX_PULL_ENABLE_SHIFT);
67 #ifdef CONFIG_SOC_MCIMX6X_M4
68 		reg |= BIT(MCUX_IMX_BIAS_BUS_HOLD_SHIFT);
69 #endif
70 		if (((flags & GPIO_PULL_UP) != 0)) {
71 			reg |= BIT(MCUX_IMX_BIAS_PULL_UP_SHIFT);
72 		} else {
73 			reg &= ~BIT(MCUX_IMX_BIAS_PULL_UP_SHIFT);
74 		}
75 	} else {
76 		/* Set pin to highz */
77 		reg &= ~BIT(MCUX_IMX_PULL_ENABLE_SHIFT);
78 #ifdef CONFIG_SOC_MCIMX6X_M4
79 		reg &= ~BIT(MCUX_IMX_BIAS_BUS_HOLD_SHIFT);
80 #endif
81 	}
82 
83 	/* Init pin configuration struct, and use pinctrl api to apply settings */
84 	__ASSERT_NO_MSG(pin < config->mux_count);
85 
86 	memcpy(&pin_cfg.pinmux, &config->pin_muxes[pin], sizeof(pin_cfg.pinmux));
87 
88 	unsigned int key = irq_lock();
89 
90 	/* cfg register will be set by pinctrl_configure_pins */
91 	pin_cfg.pin_ctrl_flags = reg;
92 	pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE);
93 
94 	/* Disable interrupts for pin */
95 	GPIO_SetPinIntMode(base, pin, false);
96 	GPIO_SetIntEdgeSelect(base, pin, false);
97 
98 	if ((flags & GPIO_OUTPUT) != 0U) {
99 		/* Set output pin initial value */
100 		if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
101 			GPIO_WritePinOutput(base, pin, gpioPinClear);
102 		} else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
103 			GPIO_WritePinOutput(base, pin, gpioPinSet);
104 		}
105 
106 		/* Set pin as output */
107 		WRITE_BIT(base->GDIR, pin, 1U);
108 	} else {
109 		/* Set pin as input */
110 		WRITE_BIT(base->GDIR, pin, 0U);
111 	}
112 
113 	irq_unlock(key);
114 
115 	return 0;
116 }
117 
imx_gpio_port_get_raw(const struct device * port,uint32_t * value)118 static int imx_gpio_port_get_raw(const struct device *port, uint32_t *value)
119 {
120 	const struct imx_gpio_config *config = port->config;
121 	GPIO_Type *base = config->base;
122 
123 	*value = GPIO_ReadPortInput(base);
124 
125 	return 0;
126 }
127 
imx_gpio_port_set_masked_raw(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t value)128 static int imx_gpio_port_set_masked_raw(const struct device *port,
129 					gpio_port_pins_t mask,
130 					gpio_port_value_t value)
131 {
132 	const struct imx_gpio_config *config = port->config;
133 	GPIO_Type *base = config->base;
134 
135 	unsigned int key = irq_lock();
136 	GPIO_WritePortOutput(base,
137 			(GPIO_ReadPortInput(base) & ~mask) | (value & mask));
138 	irq_unlock(key);
139 
140 	return 0;
141 }
142 
imx_gpio_port_set_bits_raw(const struct device * port,gpio_port_pins_t pins)143 static int imx_gpio_port_set_bits_raw(const struct device *port,
144 				      gpio_port_pins_t pins)
145 {
146 	const struct imx_gpio_config *config = port->config;
147 	GPIO_Type *base = config->base;
148 
149 	unsigned int key = irq_lock();
150 	GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) | pins);
151 	irq_unlock(key);
152 
153 	return 0;
154 }
155 
imx_gpio_port_clear_bits_raw(const struct device * port,gpio_port_pins_t pins)156 static int imx_gpio_port_clear_bits_raw(const struct device *port,
157 					gpio_port_pins_t pins)
158 {
159 	const struct imx_gpio_config *config = port->config;
160 	GPIO_Type *base = config->base;
161 
162 	unsigned int key = irq_lock();
163 	GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) & ~pins);
164 	irq_unlock(key);
165 
166 	return 0;
167 }
168 
imx_gpio_port_toggle_bits(const struct device * port,gpio_port_pins_t pins)169 static int imx_gpio_port_toggle_bits(const struct device *port,
170 				     gpio_port_pins_t pins)
171 {
172 	const struct imx_gpio_config *config = port->config;
173 	GPIO_Type *base = config->base;
174 
175 	unsigned int key = irq_lock();
176 	GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) ^ pins);
177 	irq_unlock(key);
178 
179 	return 0;
180 }
181 
imx_gpio_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)182 static int imx_gpio_pin_interrupt_configure(const struct device *port,
183 					    gpio_pin_t pin,
184 					    enum gpio_int_mode mode,
185 					    enum gpio_int_trig trig)
186 {
187 	const struct imx_gpio_config *config = port->config;
188 	GPIO_Type *base = config->base;
189 	volatile uint32_t *icr_reg;
190 	unsigned int key;
191 	uint32_t icr_val;
192 	uint8_t shift;
193 
194 	if (((base->GDIR & BIT(pin)) != 0U)
195 	    && (mode != GPIO_INT_MODE_DISABLED)) {
196 		/* Interrupt on output pin not supported */
197 		return -ENOTSUP;
198 	}
199 
200 	if ((mode == GPIO_INT_MODE_EDGE) && (trig == GPIO_INT_TRIG_LOW)) {
201 		icr_val = 3U;
202 	} else if ((mode == GPIO_INT_MODE_EDGE) &&
203 		   (trig == GPIO_INT_TRIG_HIGH)) {
204 		icr_val = 2U;
205 	} else if ((mode == GPIO_INT_MODE_LEVEL) &&
206 		   (trig == GPIO_INT_TRIG_HIGH)) {
207 		icr_val = 1U;
208 	} else {
209 		icr_val = 0U;
210 	}
211 
212 	if (pin < 16U) {
213 		shift = 2U * pin;
214 		icr_reg = &(base->ICR1);
215 	} else if (pin < 32U) {
216 		shift = 2U * (pin - 16U);
217 		icr_reg = &(base->ICR2);
218 	} else {
219 		return -EINVAL;
220 	}
221 
222 	key = irq_lock();
223 
224 	*icr_reg = (*icr_reg & ~(3U << shift)) | (icr_val << shift);
225 
226 	WRITE_BIT(base->EDGE_SEL, pin, trig == GPIO_INT_TRIG_BOTH);
227 	WRITE_BIT(base->ISR, pin, mode != GPIO_INT_MODE_DISABLED);
228 	WRITE_BIT(base->IMR, pin, mode != GPIO_INT_MODE_DISABLED);
229 
230 	irq_unlock(key);
231 
232 	return 0;
233 }
234 
imx_gpio_manage_callback(const struct device * port,struct gpio_callback * cb,bool set)235 static int imx_gpio_manage_callback(const struct device *port,
236 				    struct gpio_callback *cb, bool set)
237 {
238 	struct imx_gpio_data *data = port->data;
239 
240 	return gpio_manage_callback(&data->callbacks, cb, set);
241 }
242 
imx_gpio_port_isr(const struct device * port)243 static void imx_gpio_port_isr(const struct device *port)
244 {
245 	const struct imx_gpio_config *config = port->config;
246 	struct imx_gpio_data *data = port->data;
247 	uint32_t int_status;
248 
249 	int_status = config->base->ISR & config->base->IMR;
250 
251 	config->base->ISR = int_status;
252 
253 	gpio_fire_callbacks(&data->callbacks, port, int_status);
254 }
255 
256 static DEVICE_API(gpio, imx_gpio_driver_api) = {
257 	.pin_configure = imx_gpio_configure,
258 	.port_get_raw = imx_gpio_port_get_raw,
259 	.port_set_masked_raw = imx_gpio_port_set_masked_raw,
260 	.port_set_bits_raw = imx_gpio_port_set_bits_raw,
261 	.port_clear_bits_raw = imx_gpio_port_clear_bits_raw,
262 	.port_toggle_bits = imx_gpio_port_toggle_bits,
263 	.pin_interrupt_configure = imx_gpio_pin_interrupt_configure,
264 	.manage_callback = imx_gpio_manage_callback,
265 };
266 
267 /* These macros will declare an array of pinctrl_soc_pinmux types */
268 #define PINMUX_INIT(node, prop, idx) MCUX_IMX_PINMUX(DT_PROP_BY_IDX(node, prop, idx)),
269 #define IMX_IGPIO_PIN_DECLARE(n)						\
270 	const struct pinctrl_soc_pinmux mcux_igpio_pinmux_##n[] = {		\
271 		DT_INST_FOREACH_PROP_ELEM(n, pinmux, PINMUX_INIT)	\
272 	};
273 #define IMX_IGPIO_PIN_INIT(n)							\
274 	.pin_muxes = mcux_igpio_pinmux_##n,					\
275 	.mux_count = DT_INST_PROP_LEN(n, pinmux),
276 
277 #define GPIO_IMX_INIT(n)						\
278 	IMX_IGPIO_PIN_DECLARE(n)					\
279 	static int imx_gpio_##n##_init(const struct device *port);	\
280 									\
281 	static const struct imx_gpio_config imx_gpio_##n##_config = {	\
282 		.common = {						\
283 			.port_pin_mask =				\
284 				GPIO_PORT_PIN_MASK_FROM_DT_INST(n),	\
285 		},							\
286 		.base = (GPIO_Type *)DT_INST_REG_ADDR(n),		\
287 		IMX_IGPIO_PIN_INIT(n)					\
288 	};								\
289 									\
290 	static struct imx_gpio_data imx_gpio_##n##_data;		\
291 									\
292 	DEVICE_DT_INST_DEFINE(n,					\
293 			    imx_gpio_##n##_init,			\
294 			    NULL,					\
295 			    &imx_gpio_##n##_data,			\
296 			    &imx_gpio_##n##_config,			\
297 			    PRE_KERNEL_1,				\
298 			    CONFIG_GPIO_INIT_PRIORITY,			\
299 			    &imx_gpio_driver_api);			\
300 									\
301 	static int imx_gpio_##n##_init(const struct device *port)	\
302 	{								\
303 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 0, irq),		\
304 			    DT_INST_IRQ_BY_IDX(n, 0, priority),		\
305 			    imx_gpio_port_isr,				\
306 			    DEVICE_DT_INST_GET(n), 0);			\
307 									\
308 		irq_enable(DT_INST_IRQ_BY_IDX(n, 0, irq));		\
309 									\
310 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 1, irq),		\
311 			    DT_INST_IRQ_BY_IDX(n, 1, priority),		\
312 			    imx_gpio_port_isr,				\
313 			    DEVICE_DT_INST_GET(n), 0);			\
314 									\
315 		irq_enable(DT_INST_IRQ_BY_IDX(n, 1, irq));		\
316 									\
317 		return 0;						\
318 	}
319 
320 DT_INST_FOREACH_STATUS_OKAY(GPIO_IMX_INIT)
321