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 <device.h>
11 #include <drivers/gpio.h>
12 #include <soc.h>
13 #include <sys/util.h>
14 #include <gpio_imx.h>
15 
16 #include "gpio_utils.h"
17 
18 struct imx_gpio_config {
19 	/* gpio_driver_config needs to be first */
20 	struct gpio_driver_config common;
21 	GPIO_Type *base;
22 };
23 
24 struct imx_gpio_data {
25 	/* gpio_driver_data needs to be first */
26 	struct gpio_driver_data common;
27 	/* port ISR callback routine address */
28 	sys_slist_t callbacks;
29 };
30 
imx_gpio_configure(const struct device * port,gpio_pin_t pin,gpio_flags_t flags)31 static int imx_gpio_configure(const struct device *port, gpio_pin_t pin,
32 			      gpio_flags_t flags)
33 {
34 	const struct imx_gpio_config *config = port->config;
35 	GPIO_Type *base = config->base;
36 
37 	if (((flags & GPIO_INPUT) != 0U) && ((flags & GPIO_OUTPUT) != 0U)) {
38 		return -ENOTSUP;
39 	}
40 
41 	if ((flags & (GPIO_SINGLE_ENDED
42 		      | GPIO_PULL_UP
43 		      | GPIO_PULL_DOWN)) != 0U) {
44 		return -ENOTSUP;
45 	}
46 
47 	/* Disable interrupts for pin */
48 	GPIO_SetPinIntMode(base, pin, false);
49 	GPIO_SetIntEdgeSelect(base, pin, false);
50 
51 	if ((flags & GPIO_OUTPUT) != 0U) {
52 		/* Set output pin initial value */
53 		if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
54 			GPIO_WritePinOutput(base, pin, gpioPinClear);
55 		} else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
56 			GPIO_WritePinOutput(base, pin, gpioPinSet);
57 		}
58 
59 		/* Set pin as output */
60 		WRITE_BIT(base->GDIR, pin, 1U);
61 	} else {
62 		/* Set pin as input */
63 		WRITE_BIT(base->GDIR, pin, 0U);
64 	}
65 
66 	return 0;
67 }
68 
imx_gpio_port_get_raw(const struct device * port,uint32_t * value)69 static int imx_gpio_port_get_raw(const struct device *port, uint32_t *value)
70 {
71 	const struct imx_gpio_config *config = port->config;
72 	GPIO_Type *base = config->base;
73 
74 	*value = GPIO_ReadPortInput(base);
75 
76 	return 0;
77 }
78 
imx_gpio_port_set_masked_raw(const struct device * port,gpio_port_pins_t mask,gpio_port_value_t value)79 static int imx_gpio_port_set_masked_raw(const struct device *port,
80 					gpio_port_pins_t mask,
81 					gpio_port_value_t value)
82 {
83 	const struct imx_gpio_config *config = port->config;
84 	GPIO_Type *base = config->base;
85 
86 	GPIO_WritePortOutput(base,
87 			(GPIO_ReadPortInput(base) & ~mask) | (value & mask));
88 
89 	return 0;
90 }
91 
imx_gpio_port_set_bits_raw(const struct device * port,gpio_port_pins_t pins)92 static int imx_gpio_port_set_bits_raw(const struct device *port,
93 				      gpio_port_pins_t pins)
94 {
95 	const struct imx_gpio_config *config = port->config;
96 	GPIO_Type *base = config->base;
97 
98 	GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) | pins);
99 
100 	return 0;
101 }
102 
imx_gpio_port_clear_bits_raw(const struct device * port,gpio_port_pins_t pins)103 static int imx_gpio_port_clear_bits_raw(const struct device *port,
104 					gpio_port_pins_t pins)
105 {
106 	const struct imx_gpio_config *config = port->config;
107 	GPIO_Type *base = config->base;
108 
109 	GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) & ~pins);
110 
111 	return 0;
112 }
113 
imx_gpio_port_toggle_bits(const struct device * port,gpio_port_pins_t pins)114 static int imx_gpio_port_toggle_bits(const struct device *port,
115 				     gpio_port_pins_t pins)
116 {
117 	const struct imx_gpio_config *config = port->config;
118 	GPIO_Type *base = config->base;
119 
120 	GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) ^ pins);
121 
122 	return 0;
123 }
124 
imx_gpio_pin_interrupt_configure(const struct device * port,gpio_pin_t pin,enum gpio_int_mode mode,enum gpio_int_trig trig)125 static int imx_gpio_pin_interrupt_configure(const struct device *port,
126 					    gpio_pin_t pin,
127 					    enum gpio_int_mode mode,
128 					    enum gpio_int_trig trig)
129 {
130 	const struct imx_gpio_config *config = port->config;
131 	GPIO_Type *base = config->base;
132 	volatile uint32_t *icr_reg;
133 	unsigned int key;
134 	uint32_t icr_val;
135 	uint8_t shift;
136 
137 	if (((base->GDIR & BIT(pin)) != 0U)
138 	    && (mode != GPIO_INT_MODE_DISABLED)) {
139 		/* Interrupt on output pin not supported */
140 		return -ENOTSUP;
141 	}
142 
143 	if ((mode == GPIO_INT_MODE_EDGE) && (trig == GPIO_INT_TRIG_LOW)) {
144 		icr_val = 3U;
145 	} else if ((mode == GPIO_INT_MODE_EDGE) &&
146 		   (trig == GPIO_INT_TRIG_HIGH)) {
147 		icr_val = 2U;
148 	} else if ((mode == GPIO_INT_MODE_LEVEL) &&
149 		   (trig == GPIO_INT_TRIG_HIGH)) {
150 		icr_val = 1U;
151 	} else {
152 		icr_val = 0U;
153 	}
154 
155 	if (pin < 16U) {
156 		shift = 2U * pin;
157 		icr_reg = &(base->ICR1);
158 	} else if (pin < 32U) {
159 		shift = 2U * (pin - 16U);
160 		icr_reg = &(base->ICR2);
161 	} else {
162 		return -EINVAL;
163 	}
164 
165 	key = irq_lock();
166 
167 	*icr_reg = (*icr_reg & ~(3U << shift)) | (icr_val << shift);
168 
169 	WRITE_BIT(base->EDGE_SEL, pin, trig == GPIO_INT_TRIG_BOTH);
170 	WRITE_BIT(base->ISR, pin, mode != GPIO_INT_MODE_DISABLED);
171 	WRITE_BIT(base->IMR, pin, mode != GPIO_INT_MODE_DISABLED);
172 
173 	irq_unlock(key);
174 
175 	return 0;
176 }
177 
imx_gpio_manage_callback(const struct device * port,struct gpio_callback * cb,bool set)178 static int imx_gpio_manage_callback(const struct device *port,
179 				    struct gpio_callback *cb, bool set)
180 {
181 	struct imx_gpio_data *data = port->data;
182 
183 	return gpio_manage_callback(&data->callbacks, cb, set);
184 }
185 
imx_gpio_port_isr(const struct device * port)186 static void imx_gpio_port_isr(const struct device *port)
187 {
188 	const struct imx_gpio_config *config = port->config;
189 	struct imx_gpio_data *data = port->data;
190 	uint32_t int_status;
191 
192 	int_status = config->base->ISR;
193 
194 	config->base->ISR = int_status;
195 
196 	gpio_fire_callbacks(&data->callbacks, port, int_status);
197 }
198 
199 static const struct gpio_driver_api imx_gpio_driver_api = {
200 	.pin_configure = imx_gpio_configure,
201 	.port_get_raw = imx_gpio_port_get_raw,
202 	.port_set_masked_raw = imx_gpio_port_set_masked_raw,
203 	.port_set_bits_raw = imx_gpio_port_set_bits_raw,
204 	.port_clear_bits_raw = imx_gpio_port_clear_bits_raw,
205 	.port_toggle_bits = imx_gpio_port_toggle_bits,
206 	.pin_interrupt_configure = imx_gpio_pin_interrupt_configure,
207 	.manage_callback = imx_gpio_manage_callback,
208 };
209 
210 #define GPIO_IMX_INIT(n)						\
211 	static int imx_gpio_##n##_init(const struct device *port);	\
212 									\
213 	static const struct imx_gpio_config imx_gpio_##n##_config = {	\
214 		.common = {						\
215 			.port_pin_mask =				\
216 				GPIO_PORT_PIN_MASK_FROM_DT_INST(n),	\
217 		},							\
218 		.base = (GPIO_Type *)DT_INST_REG_ADDR(n),		\
219 	};								\
220 									\
221 	static struct imx_gpio_data imx_gpio_##n##_data;		\
222 									\
223 	DEVICE_DT_INST_DEFINE(n,					\
224 			    imx_gpio_##n##_init,			\
225 			    NULL,					\
226 			    &imx_gpio_##n##_data,			\
227 			    &imx_gpio_##n##_config,			\
228 			    POST_KERNEL,				\
229 			    CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,	\
230 			    &imx_gpio_driver_api);			\
231 									\
232 	static int imx_gpio_##n##_init(const struct device *port)	\
233 	{								\
234 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 0, irq),		\
235 			    DT_INST_IRQ_BY_IDX(n, 0, priority),		\
236 			    imx_gpio_port_isr,				\
237 			    DEVICE_DT_INST_GET(n), 0);			\
238 									\
239 		irq_enable(DT_INST_IRQ_BY_IDX(n, 0, irq));		\
240 									\
241 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, 1, irq),		\
242 			    DT_INST_IRQ_BY_IDX(n, 1, priority),		\
243 			    imx_gpio_port_isr,				\
244 			    DEVICE_DT_INST_GET(n), 0);			\
245 									\
246 		irq_enable(DT_INST_IRQ_BY_IDX(n, 1, irq));		\
247 									\
248 		return 0;						\
249 	}
250 
251 DT_INST_FOREACH_STATUS_OKAY(GPIO_IMX_INIT)
252