1 /*
2  * Copyright (c) 2019, Manivannan Sadhasivam <mani@kernel.org>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_imx_iuart
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/uart.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/irq.h>
13 #include <errno.h>
14 #include <fsl_uart.h>
15 #include <zephyr/drivers/pinctrl.h>
16 
17 struct mcux_iuart_config {
18 	UART_Type *base;
19 	const struct device *clock_dev;
20 	clock_control_subsys_t clock_subsys;
21 	uint32_t baud_rate;
22 	/* initial parity, 0 for none, 1 for odd, 2 for even */
23 	uint8_t parity;
24 	const struct pinctrl_dev_config *pincfg;
25 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
26 	void (*irq_config_func)(const struct device *dev);
27 #endif
28 };
29 
30 struct mcux_iuart_data {
31 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
32 	uart_irq_callback_user_data_t callback;
33 	void *cb_data;
34 #endif
35 };
36 
mcux_iuart_poll_in(const struct device * dev,unsigned char * c)37 static int mcux_iuart_poll_in(const struct device *dev, unsigned char *c)
38 {
39 	const struct mcux_iuart_config *config = dev->config;
40 	int ret = -1;
41 
42 	if (UART_GetStatusFlag(config->base, kUART_RxDataReadyFlag)) {
43 		*c = UART_ReadByte(config->base);
44 		ret = 0;
45 	}
46 
47 	return ret;
48 }
49 
mcux_iuart_poll_out(const struct device * dev,unsigned char c)50 static void mcux_iuart_poll_out(const struct device *dev, unsigned char c)
51 {
52 	const struct mcux_iuart_config *config = dev->config;
53 
54 	while (!(UART_GetStatusFlag(config->base, kUART_TxReadyFlag))) {
55 	}
56 
57 	UART_WriteByte(config->base, c);
58 }
59 
mcux_iuart_err_check(const struct device * dev)60 static int mcux_iuart_err_check(const struct device *dev)
61 {
62 	const struct mcux_iuart_config *config = dev->config;
63 	int err = 0;
64 
65 	if (UART_GetStatusFlag(config->base, kUART_RxOverrunFlag)) {
66 		err |= UART_ERROR_OVERRUN;
67 		UART_ClearStatusFlag(config->base, kUART_RxOverrunFlag);
68 	}
69 
70 	if (UART_GetStatusFlag(config->base, kUART_ParityErrorFlag)) {
71 		err |= UART_ERROR_PARITY;
72 		UART_ClearStatusFlag(config->base, kUART_ParityErrorFlag);
73 	}
74 
75 	if (UART_GetStatusFlag(config->base, kUART_FrameErrorFlag)) {
76 		err |= UART_ERROR_FRAMING;
77 		UART_ClearStatusFlag(config->base, kUART_FrameErrorFlag);
78 	}
79 
80 	return err;
81 }
82 
83 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
mcux_iuart_fifo_fill(const struct device * dev,const uint8_t * tx_data,int len)84 static int mcux_iuart_fifo_fill(const struct device *dev,
85 				const uint8_t *tx_data,
86 				int len)
87 {
88 	const struct mcux_iuart_config *config = dev->config;
89 	uint8_t num_tx = 0U;
90 
91 	while ((len - num_tx > 0) &&
92 	       (UART_GetStatusFlag(config->base, kUART_TxEmptyFlag))) {
93 
94 		UART_WriteByte(config->base, tx_data[num_tx++]);
95 	}
96 
97 	return num_tx;
98 }
99 
mcux_iuart_fifo_read(const struct device * dev,uint8_t * rx_data,const int len)100 static int mcux_iuart_fifo_read(const struct device *dev, uint8_t *rx_data,
101 				const int len)
102 {
103 	const struct mcux_iuart_config *config = dev->config;
104 	uint8_t num_rx = 0U;
105 
106 	while ((len - num_rx > 0) &&
107 	       (UART_GetStatusFlag(config->base, kUART_RxDataReadyFlag))) {
108 
109 		rx_data[num_rx++] = UART_ReadByte(config->base);
110 	}
111 
112 	return num_rx;
113 }
114 
mcux_iuart_irq_tx_enable(const struct device * dev)115 static void mcux_iuart_irq_tx_enable(const struct device *dev)
116 {
117 	const struct mcux_iuart_config *config = dev->config;
118 
119 	UART_EnableInterrupts(config->base, kUART_TxEmptyEnable);
120 }
121 
mcux_iuart_irq_tx_disable(const struct device * dev)122 static void mcux_iuart_irq_tx_disable(const struct device *dev)
123 {
124 	const struct mcux_iuart_config *config = dev->config;
125 
126 	UART_DisableInterrupts(config->base, kUART_TxEmptyEnable);
127 }
128 
mcux_iuart_irq_tx_complete(const struct device * dev)129 static int mcux_iuart_irq_tx_complete(const struct device *dev)
130 {
131 	const struct mcux_iuart_config *config = dev->config;
132 
133 	return (UART_GetStatusFlag(config->base, kUART_TxEmptyFlag)) != 0U;
134 }
135 
mcux_iuart_irq_tx_ready(const struct device * dev)136 static int mcux_iuart_irq_tx_ready(const struct device *dev)
137 {
138 	const struct mcux_iuart_config *config = dev->config;
139 	uint32_t mask = kUART_TxEmptyEnable;
140 
141 	return (UART_GetEnabledInterrupts(config->base) & mask)
142 		&& mcux_iuart_irq_tx_complete(dev);
143 }
144 
mcux_iuart_irq_rx_enable(const struct device * dev)145 static void mcux_iuart_irq_rx_enable(const struct device *dev)
146 {
147 	const struct mcux_iuart_config *config = dev->config;
148 	uint32_t mask = kUART_RxDataReadyEnable;
149 
150 	UART_EnableInterrupts(config->base, mask);
151 }
152 
mcux_iuart_irq_rx_disable(const struct device * dev)153 static void mcux_iuart_irq_rx_disable(const struct device *dev)
154 {
155 	const struct mcux_iuart_config *config = dev->config;
156 	uint32_t mask = kUART_RxDataReadyEnable;
157 
158 	UART_DisableInterrupts(config->base, mask);
159 }
160 
mcux_iuart_irq_rx_full(const struct device * dev)161 static int mcux_iuart_irq_rx_full(const struct device *dev)
162 {
163 	const struct mcux_iuart_config *config = dev->config;
164 
165 	return (UART_GetStatusFlag(config->base, kUART_RxDataReadyFlag)) != 0U;
166 }
167 
mcux_iuart_irq_rx_pending(const struct device * dev)168 static int mcux_iuart_irq_rx_pending(const struct device *dev)
169 {
170 	const struct mcux_iuart_config *config = dev->config;
171 	uint32_t mask = kUART_RxDataReadyEnable;
172 
173 	return (UART_GetEnabledInterrupts(config->base) & mask)
174 		&& mcux_iuart_irq_rx_full(dev);
175 }
176 
mcux_iuart_irq_err_enable(const struct device * dev)177 static void mcux_iuart_irq_err_enable(const struct device *dev)
178 {
179 	const struct mcux_iuart_config *config = dev->config;
180 	uint32_t mask = kUART_RxOverrunEnable | kUART_ParityErrorEnable |
181 			kUART_FrameErrorEnable;
182 
183 	UART_EnableInterrupts(config->base, mask);
184 }
185 
mcux_iuart_irq_err_disable(const struct device * dev)186 static void mcux_iuart_irq_err_disable(const struct device *dev)
187 {
188 	const struct mcux_iuart_config *config = dev->config;
189 	uint32_t mask = kUART_RxOverrunEnable | kUART_ParityErrorEnable |
190 			kUART_FrameErrorEnable;
191 
192 	UART_DisableInterrupts(config->base, mask);
193 }
194 
mcux_iuart_irq_is_pending(const struct device * dev)195 static int mcux_iuart_irq_is_pending(const struct device *dev)
196 {
197 	return mcux_iuart_irq_tx_ready(dev) || mcux_iuart_irq_rx_pending(dev);
198 }
199 
mcux_iuart_irq_update(const struct device * dev)200 static int mcux_iuart_irq_update(const struct device *dev)
201 {
202 	return 1;
203 }
204 
mcux_iuart_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)205 static void mcux_iuart_irq_callback_set(const struct device *dev,
206 					uart_irq_callback_user_data_t cb,
207 					void *cb_data)
208 {
209 	struct mcux_iuart_data *data = dev->data;
210 
211 	data->callback = cb;
212 	data->cb_data = cb_data;
213 }
214 
mcux_iuart_isr(const struct device * dev)215 static void mcux_iuart_isr(const struct device *dev)
216 {
217 	struct mcux_iuart_data *data = dev->data;
218 
219 	if (data->callback) {
220 		data->callback(dev, data->cb_data);
221 	}
222 }
223 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
224 
mcux_iuart_init(const struct device * dev)225 static int mcux_iuart_init(const struct device *dev)
226 {
227 	const struct mcux_iuart_config *config = dev->config;
228 	uart_config_t uart_config;
229 	uint32_t clock_freq;
230 	int err;
231 
232 	if (!device_is_ready(config->clock_dev)) {
233 		return -ENODEV;
234 	}
235 
236 	if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
237 				   &clock_freq)) {
238 		return -EINVAL;
239 	}
240 
241 	UART_GetDefaultConfig(&uart_config);
242 	uart_config.enableTx = true;
243 	uart_config.enableRx = true;
244 	uart_config.baudRate_Bps = config->baud_rate;
245 
246 	clock_control_on(config->clock_dev, config->clock_subsys);
247 	switch (config->parity) {
248 	case UART_CFG_PARITY_NONE:
249 		uart_config.parityMode = kUART_ParityDisabled;
250 		break;
251 	case UART_CFG_PARITY_EVEN:
252 		uart_config.parityMode = kUART_ParityEven;
253 		break;
254 	case UART_CFG_PARITY_ODD:
255 		uart_config.parityMode = kUART_ParityOdd;
256 		break;
257 	default:
258 		return -ENOTSUP;
259 	}
260 
261 	UART_Init(config->base, &uart_config, clock_freq);
262 
263 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
264 	if (err) {
265 		clock_control_off(config->clock_dev, config->clock_subsys);
266 		return err;
267 	}
268 
269 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
270 	config->irq_config_func(dev);
271 #endif
272 
273 	return 0;
274 }
275 
276 static const struct uart_driver_api mcux_iuart_driver_api = {
277 	.poll_in = mcux_iuart_poll_in,
278 	.poll_out = mcux_iuart_poll_out,
279 	.err_check = mcux_iuart_err_check,
280 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
281 	.fifo_fill = mcux_iuart_fifo_fill,
282 	.fifo_read = mcux_iuart_fifo_read,
283 	.irq_tx_enable = mcux_iuart_irq_tx_enable,
284 	.irq_tx_disable = mcux_iuart_irq_tx_disable,
285 	.irq_tx_complete = mcux_iuart_irq_tx_complete,
286 	.irq_tx_ready = mcux_iuart_irq_tx_ready,
287 	.irq_rx_enable = mcux_iuart_irq_rx_enable,
288 	.irq_rx_disable = mcux_iuart_irq_rx_disable,
289 	.irq_rx_ready = mcux_iuart_irq_rx_full,
290 	.irq_err_enable = mcux_iuart_irq_err_enable,
291 	.irq_err_disable = mcux_iuart_irq_err_disable,
292 	.irq_is_pending = mcux_iuart_irq_is_pending,
293 	.irq_update = mcux_iuart_irq_update,
294 	.irq_callback_set = mcux_iuart_irq_callback_set,
295 #endif
296 };
297 
298 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
299 #define MCUX_IUART_IRQ_INIT(n, i)					\
300 	do {								\
301 		IRQ_CONNECT(DT_INST_IRQ_BY_IDX(n, i, irq),		\
302 			    DT_INST_IRQ_BY_IDX(n, i, priority),		\
303 			    mcux_iuart_isr, DEVICE_DT_INST_GET(n), 0);	\
304 									\
305 		irq_enable(DT_INST_IRQ_BY_IDX(n, i, irq));		\
306 	} while (false)
307 #define IUART_MCUX_CONFIG_FUNC(n)					\
308 	static void mcux_iuart_config_func_##n(const struct device *dev) \
309 	{								\
310 		MCUX_IUART_IRQ_INIT(n, 0);				\
311 									\
312 		IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 1),			\
313 			   (MCUX_IUART_IRQ_INIT(n, 1);))		\
314 	}
315 #define IUART_MCUX_IRQ_CFG_FUNC_INIT(n)				\
316 	.irq_config_func = mcux_iuart_config_func_##n
317 #define IUART_MCUX_INIT_CFG(n)						\
318 	IUART_MCUX_DECLARE_CFG(n, IUART_MCUX_IRQ_CFG_FUNC_INIT(n))
319 #else
320 #define IUART_MCUX_CONFIG_FUNC(n)
321 #define IUART_MCUX_IRQ_CFG_FUNC_INIT
322 #define IUART_MCUX_INIT_CFG(n)						\
323 	IUART_MCUX_DECLARE_CFG(n, IUART_MCUX_IRQ_CFG_FUNC_INIT)
324 #endif
325 
326 #define IUART_MCUX_DECLARE_CFG(n, IRQ_FUNC_INIT)			\
327 static const struct mcux_iuart_config mcux_iuart_##n##_config = {	\
328 	.base = (UART_Type *) DT_INST_REG_ADDR(n),			\
329 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),		\
330 	.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\
331 	.baud_rate = DT_INST_PROP(n, current_speed),			\
332 	.parity = DT_INST_ENUM_IDX_OR(n, parity, UART_CFG_PARITY_NONE),	\
333 	.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),			\
334 	IRQ_FUNC_INIT							\
335 }
336 
337 #define IUART_MCUX_INIT(n)						\
338 									\
339 	static struct mcux_iuart_data mcux_iuart_##n##_data;		\
340 									\
341 	static const struct mcux_iuart_config mcux_iuart_##n##_config;\
342 									\
343 	DEVICE_DT_INST_DEFINE(n,					\
344 			    mcux_iuart_init,				\
345 			    NULL,					\
346 			    &mcux_iuart_##n##_data,			\
347 			    &mcux_iuart_##n##_config,			\
348 			    PRE_KERNEL_1,				\
349 			    CONFIG_SERIAL_INIT_PRIORITY,		\
350 			    &mcux_iuart_driver_api);			\
351 									\
352 	PINCTRL_DT_INST_DEFINE(n);					\
353 									\
354 	IUART_MCUX_CONFIG_FUNC(n)					\
355 									\
356 	IUART_MCUX_INIT_CFG(n);
357 
358 DT_INST_FOREACH_STATUS_OKAY(IUART_MCUX_INIT)
359