1 /*
2  * Copyright 2017, 2024 NXP
3  * Copyright (c) 2020 PHYTEC Messtechnik GmbH
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT nxp_kinetis_uart
9 
10 #include <errno.h>
11 #include <zephyr/device.h>
12 #include <zephyr/drivers/uart.h>
13 #include <zephyr/drivers/clock_control.h>
14 #include <zephyr/irq.h>
15 #include <fsl_uart.h>
16 #include <soc.h>
17 #include <zephyr/pm/device.h>
18 #include <zephyr/drivers/pinctrl.h>
19 
20 struct uart_mcux_config {
21 	UART_Type *base;
22 	const struct device *clock_dev;
23 	clock_control_subsys_t clock_subsys;
24 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
25 	void (*irq_config_func)(const struct device *dev);
26 #endif
27 	const struct pinctrl_dev_config *pincfg;
28 };
29 
30 struct uart_mcux_data {
31 	struct uart_config uart_cfg;
32 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
33 	uart_irq_callback_user_data_t callback;
34 	void *cb_data;
35 #endif
36 };
37 
uart_mcux_configure(const struct device * dev,const struct uart_config * cfg)38 static int uart_mcux_configure(const struct device *dev,
39 			       const struct uart_config *cfg)
40 {
41 	const struct uart_mcux_config *config = dev->config;
42 	struct uart_mcux_data *data = dev->data;
43 	uart_config_t uart_config;
44 	uint32_t clock_freq;
45 	status_t retval;
46 
47 	if (!device_is_ready(config->clock_dev)) {
48 		return -ENODEV;
49 	}
50 
51 	if (clock_control_get_rate(config->clock_dev, config->clock_subsys,
52 				   &clock_freq)) {
53 		return -EINVAL;
54 	}
55 
56 	UART_GetDefaultConfig(&uart_config);
57 
58 	uart_config.enableTx = true;
59 	uart_config.enableRx = true;
60 	uart_config.baudRate_Bps = cfg->baudrate;
61 
62 	switch (cfg->stop_bits) {
63 	case UART_CFG_STOP_BITS_1:
64 #if defined(FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT) && \
65 FSL_FEATURE_UART_HAS_STOP_BIT_CONFIG_SUPPORT
66 		uart_config.stopBitCount = kUART_OneStopBit;
67 		break;
68 	case UART_CFG_STOP_BITS_2:
69 		uart_config.stopBitCount = kUART_TwoStopBit;
70 #endif
71 		break;
72 	default:
73 		return -ENOTSUP;
74 	}
75 
76 #if defined(FSL_FEATURE_UART_HAS_MODEM_SUPPORT) && FSL_FEATURE_UART_HAS_MODEM_SUPPORT
77 	switch (cfg->flow_ctrl) {
78 	case UART_CFG_FLOW_CTRL_NONE:
79 		uart_config.enableRxRTS = false;
80 		uart_config.enableTxCTS = false;
81 		break;
82 	case UART_CFG_FLOW_CTRL_RTS_CTS:
83 		uart_config.enableRxRTS = true;
84 		uart_config.enableTxCTS = true;
85 		break;
86 	default:
87 		return -ENOTSUP;
88 	}
89 #endif
90 
91 	switch (cfg->parity) {
92 	case UART_CFG_PARITY_NONE:
93 		uart_config.parityMode = kUART_ParityDisabled;
94 		break;
95 	case UART_CFG_PARITY_EVEN:
96 		uart_config.parityMode = kUART_ParityEven;
97 		break;
98 	case UART_CFG_PARITY_ODD:
99 		uart_config.parityMode = kUART_ParityOdd;
100 		break;
101 	default:
102 		return -ENOTSUP;
103 	}
104 
105 	retval = UART_Init(config->base, &uart_config, clock_freq);
106 	if (retval != kStatus_Success) {
107 		return -EINVAL;
108 	}
109 
110 	data->uart_cfg = *cfg;
111 
112 	return 0;
113 }
114 
115 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
uart_mcux_config_get(const struct device * dev,struct uart_config * cfg)116 static int uart_mcux_config_get(const struct device *dev,
117 				struct uart_config *cfg)
118 {
119 	struct uart_mcux_data *data = dev->data;
120 
121 	*cfg = data->uart_cfg;
122 
123 	return 0;
124 }
125 #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
126 
uart_mcux_poll_in(const struct device * dev,unsigned char * c)127 static int uart_mcux_poll_in(const struct device *dev, unsigned char *c)
128 {
129 	const struct uart_mcux_config *config = dev->config;
130 	uint32_t flags = UART_GetStatusFlags(config->base);
131 	int ret = -1;
132 
133 	if (flags & kUART_RxDataRegFullFlag) {
134 		*c = UART_ReadByte(config->base);
135 		ret = 0;
136 	}
137 
138 	return ret;
139 }
140 
uart_mcux_poll_out(const struct device * dev,unsigned char c)141 static void uart_mcux_poll_out(const struct device *dev, unsigned char c)
142 {
143 	const struct uart_mcux_config *config = dev->config;
144 
145 	while (!(UART_GetStatusFlags(config->base) & kUART_TxDataRegEmptyFlag)) {
146 	}
147 
148 	UART_WriteByte(config->base, c);
149 }
150 
uart_mcux_err_check(const struct device * dev)151 static int uart_mcux_err_check(const struct device *dev)
152 {
153 	const struct uart_mcux_config *config = dev->config;
154 	uint32_t flags = UART_GetStatusFlags(config->base);
155 	int err = 0;
156 
157 	if (flags & kUART_RxOverrunFlag) {
158 		err |= UART_ERROR_OVERRUN;
159 	}
160 
161 	if (flags & kUART_ParityErrorFlag) {
162 		err |= UART_ERROR_PARITY;
163 	}
164 
165 	if (flags & kUART_FramingErrorFlag) {
166 		err |= UART_ERROR_FRAMING;
167 	}
168 
169 	UART_ClearStatusFlags(config->base, kUART_RxOverrunFlag |
170 					    kUART_ParityErrorFlag |
171 					    kUART_FramingErrorFlag);
172 
173 	return err;
174 }
175 
176 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_mcux_fifo_fill(const struct device * dev,const uint8_t * tx_data,int len)177 static int uart_mcux_fifo_fill(const struct device *dev,
178 			       const uint8_t *tx_data,
179 			       int len)
180 {
181 	const struct uart_mcux_config *config = dev->config;
182 	int num_tx = 0U;
183 
184 	while ((len - num_tx > 0) &&
185 	       (UART_GetStatusFlags(config->base) & kUART_TxDataRegEmptyFlag)) {
186 
187 		UART_WriteByte(config->base, tx_data[num_tx++]);
188 	}
189 
190 	return num_tx;
191 }
192 
uart_mcux_fifo_read(const struct device * dev,uint8_t * rx_data,const int len)193 static int uart_mcux_fifo_read(const struct device *dev, uint8_t *rx_data,
194 			       const int len)
195 {
196 	const struct uart_mcux_config *config = dev->config;
197 	int num_rx = 0U;
198 
199 	while ((len - num_rx > 0) &&
200 	       (UART_GetStatusFlags(config->base) & kUART_RxDataRegFullFlag)) {
201 
202 		rx_data[num_rx++] = UART_ReadByte(config->base);
203 	}
204 
205 	return num_rx;
206 }
207 
uart_mcux_irq_tx_enable(const struct device * dev)208 static void uart_mcux_irq_tx_enable(const struct device *dev)
209 {
210 	const struct uart_mcux_config *config = dev->config;
211 	uint32_t mask = kUART_TxDataRegEmptyInterruptEnable;
212 	pm_device_busy_set(dev);
213 	UART_EnableInterrupts(config->base, mask);
214 }
215 
uart_mcux_irq_tx_disable(const struct device * dev)216 static void uart_mcux_irq_tx_disable(const struct device *dev)
217 {
218 	const struct uart_mcux_config *config = dev->config;
219 	uint32_t mask = kUART_TxDataRegEmptyInterruptEnable;
220 	pm_device_busy_clear(dev);
221 	UART_DisableInterrupts(config->base, mask);
222 }
223 
uart_mcux_irq_tx_complete(const struct device * dev)224 static int uart_mcux_irq_tx_complete(const struct device *dev)
225 {
226 	const struct uart_mcux_config *config = dev->config;
227 	uint32_t flags = UART_GetStatusFlags(config->base);
228 
229 	return (flags & kUART_TransmissionCompleteFlag) != 0U;
230 }
231 
uart_mcux_irq_tx_ready(const struct device * dev)232 static int uart_mcux_irq_tx_ready(const struct device *dev)
233 {
234 	const struct uart_mcux_config *config = dev->config;
235 	uint32_t mask = kUART_TxDataRegEmptyInterruptEnable;
236 	uint32_t flags = UART_GetStatusFlags(config->base);
237 
238 	return (UART_GetEnabledInterrupts(config->base) & mask)
239 		&& (flags & kUART_TxDataRegEmptyFlag);
240 }
241 
uart_mcux_irq_rx_enable(const struct device * dev)242 static void uart_mcux_irq_rx_enable(const struct device *dev)
243 {
244 	const struct uart_mcux_config *config = dev->config;
245 	uint32_t mask = kUART_RxDataRegFullInterruptEnable;
246 
247 	UART_EnableInterrupts(config->base, mask);
248 }
249 
uart_mcux_irq_rx_disable(const struct device * dev)250 static void uart_mcux_irq_rx_disable(const struct device *dev)
251 {
252 	const struct uart_mcux_config *config = dev->config;
253 	uint32_t mask = kUART_RxDataRegFullInterruptEnable;
254 
255 	UART_DisableInterrupts(config->base, mask);
256 }
257 
uart_mcux_irq_rx_full(const struct device * dev)258 static int uart_mcux_irq_rx_full(const struct device *dev)
259 {
260 	const struct uart_mcux_config *config = dev->config;
261 	uint32_t flags = UART_GetStatusFlags(config->base);
262 
263 	return (flags & kUART_RxDataRegFullFlag) != 0U;
264 }
265 
uart_mcux_irq_rx_pending(const struct device * dev)266 static int uart_mcux_irq_rx_pending(const struct device *dev)
267 {
268 	const struct uart_mcux_config *config = dev->config;
269 	uint32_t mask = kUART_RxDataRegFullInterruptEnable;
270 
271 	return (UART_GetEnabledInterrupts(config->base) & mask)
272 		&& uart_mcux_irq_rx_full(dev);
273 }
274 
uart_mcux_irq_err_enable(const struct device * dev)275 static void uart_mcux_irq_err_enable(const struct device *dev)
276 {
277 	const struct uart_mcux_config *config = dev->config;
278 	uint32_t mask = kUART_NoiseErrorInterruptEnable |
279 			kUART_FramingErrorInterruptEnable |
280 			kUART_ParityErrorInterruptEnable;
281 
282 	UART_EnableInterrupts(config->base, mask);
283 }
284 
uart_mcux_irq_err_disable(const struct device * dev)285 static void uart_mcux_irq_err_disable(const struct device *dev)
286 {
287 	const struct uart_mcux_config *config = dev->config;
288 	uint32_t mask = kUART_NoiseErrorInterruptEnable |
289 			kUART_FramingErrorInterruptEnable |
290 			kUART_ParityErrorInterruptEnable;
291 
292 	UART_DisableInterrupts(config->base, mask);
293 }
294 
uart_mcux_irq_is_pending(const struct device * dev)295 static int uart_mcux_irq_is_pending(const struct device *dev)
296 {
297 	return uart_mcux_irq_tx_ready(dev) || uart_mcux_irq_rx_pending(dev);
298 }
299 
uart_mcux_irq_update(const struct device * dev)300 static int uart_mcux_irq_update(const struct device *dev)
301 {
302 	return 1;
303 }
304 
uart_mcux_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)305 static void uart_mcux_irq_callback_set(const struct device *dev,
306 				       uart_irq_callback_user_data_t cb,
307 				       void *cb_data)
308 {
309 	struct uart_mcux_data *data = dev->data;
310 
311 	data->callback = cb;
312 	data->cb_data = cb_data;
313 }
314 
uart_mcux_isr(const struct device * dev)315 static void uart_mcux_isr(const struct device *dev)
316 {
317 	struct uart_mcux_data *data = dev->data;
318 	if (data->callback) {
319 		data->callback(dev, data->cb_data);
320 	}
321 }
322 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
323 
uart_mcux_init(const struct device * dev)324 static int uart_mcux_init(const struct device *dev)
325 {
326 	const struct uart_mcux_config *config = dev->config;
327 	struct uart_mcux_data *data = dev->data;
328 	int err;
329 
330 	err = uart_mcux_configure(dev, &data->uart_cfg);
331 	if (err != 0) {
332 		return err;
333 	}
334 
335 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
336 	if (err != 0) {
337 		return err;
338 	}
339 
340 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
341 	config->irq_config_func(dev);
342 #endif
343 
344 	return 0;
345 }
346 
347 #ifdef CONFIG_PM_DEVICE
uart_mcux_pm_action(const struct device * dev,enum pm_device_action action)348 static int uart_mcux_pm_action(const struct device *dev, enum pm_device_action action)
349 {
350 	const struct uart_mcux_config *config = dev->config;
351 
352 	switch (action) {
353 	case PM_DEVICE_ACTION_RESUME:
354 		clock_control_on(config->clock_dev, config->clock_subsys);
355 		break;
356 	case PM_DEVICE_ACTION_SUSPEND:
357 		clock_control_off(config->clock_dev, config->clock_subsys);
358 		break;
359 	case PM_DEVICE_ACTION_TURN_OFF:
360 		return 0;
361 	case PM_DEVICE_ACTION_TURN_ON:
362 		return 0;
363 	default:
364 		return -ENOTSUP;
365 	}
366 	return 0;
367 }
368 #endif /*CONFIG_PM_DEVICE*/
369 
370 static DEVICE_API(uart, uart_mcux_driver_api) = {
371 	.poll_in = uart_mcux_poll_in,
372 	.poll_out = uart_mcux_poll_out,
373 	.err_check = uart_mcux_err_check,
374 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
375 	.configure = uart_mcux_configure,
376 	.config_get = uart_mcux_config_get,
377 #endif
378 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
379 	.fifo_fill = uart_mcux_fifo_fill,
380 	.fifo_read = uart_mcux_fifo_read,
381 	.irq_tx_enable = uart_mcux_irq_tx_enable,
382 	.irq_tx_disable = uart_mcux_irq_tx_disable,
383 	.irq_tx_complete = uart_mcux_irq_tx_complete,
384 	.irq_tx_ready = uart_mcux_irq_tx_ready,
385 	.irq_rx_enable = uart_mcux_irq_rx_enable,
386 	.irq_rx_disable = uart_mcux_irq_rx_disable,
387 	.irq_rx_ready = uart_mcux_irq_rx_full,
388 	.irq_err_enable = uart_mcux_irq_err_enable,
389 	.irq_err_disable = uart_mcux_irq_err_disable,
390 	.irq_is_pending = uart_mcux_irq_is_pending,
391 	.irq_update = uart_mcux_irq_update,
392 	.irq_callback_set = uart_mcux_irq_callback_set,
393 #endif
394 };
395 
396 #define UART_MCUX_DECLARE_CFG(n, IRQ_FUNC_INIT)				\
397 static const struct uart_mcux_config uart_mcux_##n##_config = {		\
398 	.base = (UART_Type *)DT_INST_REG_ADDR(n),			\
399 	.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)),		\
400 	.clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name),\
401 	.pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),			\
402 	IRQ_FUNC_INIT							\
403 }
404 
405 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
406 #define UART_MCUX_CONFIG_FUNC(n)					\
407 	static void uart_mcux_config_func_##n(const struct device *dev)	\
408 	{								\
409 		UART_MCUX_IRQ(n, status);	\
410 		UART_MCUX_IRQ(n, error);	\
411 	}
412 
413 #define UART_MCUX_IRQ_INIT(n, name)					\
414 	do {								\
415 		IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, name, irq),	\
416 			    DT_INST_IRQ_BY_NAME(n, name, priority),	\
417 			    uart_mcux_isr, DEVICE_DT_INST_GET(n), 0);	\
418 									\
419 		irq_enable(DT_INST_IRQ_BY_NAME(n, name, irq));	\
420 	} while (false)
421 
422 #define UART_MCUX_IRQ(n, name)						\
423 	COND_CODE_1(DT_INST_IRQ_HAS_NAME(n, name),		\
424 		    (UART_MCUX_IRQ_INIT(n, name)), ())
425 
426 #define UART_MCUX_IRQ_CFG_FUNC_INIT(n)					\
427 	.irq_config_func = uart_mcux_config_func_##n
428 #define UART_MCUX_INIT_CFG(n)						\
429 	UART_MCUX_DECLARE_CFG(n, UART_MCUX_IRQ_CFG_FUNC_INIT(n))
430 #else
431 #define UART_MCUX_CONFIG_FUNC(n)
432 #define UART_MCUX_IRQ_CFG_FUNC_INIT
433 #define UART_MCUX_INIT_CFG(n)						\
434 	UART_MCUX_DECLARE_CFG(n, UART_MCUX_IRQ_CFG_FUNC_INIT)
435 #endif
436 
437 #define UART_MCUX_INIT(n)						\
438 	PINCTRL_DT_INST_DEFINE(n);					\
439 									\
440 	static struct uart_mcux_data uart_mcux_##n##_data = {		\
441 		.uart_cfg = {						\
442 			.stop_bits = UART_CFG_STOP_BITS_1,		\
443 			.data_bits = UART_CFG_DATA_BITS_8,		\
444 			.baudrate  = DT_INST_PROP(n, current_speed),	\
445 			.parity    = UART_CFG_PARITY_NONE,		\
446 			.flow_ctrl = DT_INST_PROP(n, hw_flow_control) ?	\
447 				UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE,\
448 		},							\
449 	};								\
450 									\
451 	static const struct uart_mcux_config uart_mcux_##n##_config;	\
452 	PM_DEVICE_DT_INST_DEFINE(n, uart_mcux_pm_action);\
453 									\
454 	DEVICE_DT_INST_DEFINE(n,					\
455 			    uart_mcux_init,				\
456 			    PM_DEVICE_DT_INST_GET(n),			\
457 			    &uart_mcux_##n##_data,			\
458 			    &uart_mcux_##n##_config,			\
459 			    PRE_KERNEL_1,				\
460 			    CONFIG_SERIAL_INIT_PRIORITY,		\
461 			    &uart_mcux_driver_api);			\
462 									\
463 	UART_MCUX_CONFIG_FUNC(n)					\
464 									\
465 	UART_MCUX_INIT_CFG(n);
466 
467 DT_INST_FOREACH_STATUS_OKAY(UART_MCUX_INIT)
468