1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  *  Copyright (c) 2023 Nuvoton Technology Corporation.
5  */
6 
7 #define DT_DRV_COMPAT nuvoton_numaker_uart
8 
9 #include <string.h>
10 #include <zephyr/drivers/uart.h>
11 #include <zephyr/drivers/reset.h>
12 #include <zephyr/irq.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/drivers/clock_control.h>
15 #include <zephyr/drivers/clock_control/clock_control_numaker.h>
16 #include <zephyr/drivers/pinctrl.h>
17 #include <NuMicro.h>
18 
19 LOG_MODULE_REGISTER(numaker_uart, LOG_LEVEL_ERR);
20 
21 struct uart_numaker_config {
22 	UART_T *uart;
23 	const struct reset_dt_spec reset;
24 	uint32_t clk_modidx;
25 	uint32_t clk_src;
26 	uint32_t clk_div;
27 	const struct device *clk_dev;
28 	uint32_t irq_n;
29 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
30 	void (*irq_config_func)(const struct device *dev);
31 #endif
32 	const struct pinctrl_dev_config *pincfg;
33 };
34 
35 struct uart_numaker_data {
36 	const struct device *clock;
37 	struct uart_config ucfg;
38 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
39 	uart_irq_callback_user_data_t user_cb;
40 	void *user_data;
41 #endif
42 };
43 
uart_numaker_poll_in(const struct device * dev,unsigned char * c)44 static int uart_numaker_poll_in(const struct device *dev, unsigned char *c)
45 {
46 	const struct uart_numaker_config *config = dev->config;
47 	uint32_t count;
48 
49 	count = UART_Read(config->uart, c, 1);
50 	if (!count) {
51 		return -1;
52 	}
53 
54 	return 0;
55 }
56 
uart_numaker_poll_out(const struct device * dev,unsigned char c)57 static void uart_numaker_poll_out(const struct device *dev, unsigned char c)
58 {
59 	const struct uart_numaker_config *config = dev->config;
60 
61 	UART_Write(config->uart, &c, 1);
62 }
63 
uart_numaker_err_check(const struct device * dev)64 static int uart_numaker_err_check(const struct device *dev)
65 {
66 	const struct uart_numaker_config *config = dev->config;
67 	UART_T *uart = config->uart;
68 	uint32_t flags = uart->FIFOSTS;
69 	int err = 0;
70 
71 	if (flags & UART_FIFOSTS_RXOVIF_Msk) {
72 		err |= UART_ERROR_OVERRUN;
73 	}
74 
75 	if (flags & UART_FIFOSTS_PEF_Msk) {
76 		err |= UART_ERROR_PARITY;
77 	}
78 
79 	if (flags & UART_FIFOSTS_FEF_Msk) {
80 		err |= UART_ERROR_FRAMING;
81 	}
82 
83 	if (flags & UART_FIFOSTS_BIF_Msk) {
84 		err |= UART_BREAK;
85 	}
86 
87 	if (flags & (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk |
88 		     UART_FIFOSTS_RXOVIF_Msk)) {
89 		uart->FIFOSTS = (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk |
90 				 UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk);
91 	}
92 	return err;
93 }
94 
uart_numaker_convert_stopbit(enum uart_config_stop_bits sb)95 static inline int32_t uart_numaker_convert_stopbit(enum uart_config_stop_bits sb)
96 {
97 	switch (sb) {
98 	case UART_CFG_STOP_BITS_1:
99 		return UART_STOP_BIT_1;
100 	case UART_CFG_STOP_BITS_1_5:
101 		return UART_STOP_BIT_1_5;
102 	case UART_CFG_STOP_BITS_2:
103 		return UART_STOP_BIT_2;
104 	default:
105 		return -ENOTSUP;
106 	}
107 };
108 
uart_numaker_convert_datalen(enum uart_config_data_bits db)109 static inline int32_t uart_numaker_convert_datalen(enum uart_config_data_bits db)
110 {
111 	switch (db) {
112 	case UART_CFG_DATA_BITS_5:
113 		return UART_WORD_LEN_5;
114 	case UART_CFG_DATA_BITS_6:
115 		return UART_WORD_LEN_6;
116 	case UART_CFG_DATA_BITS_7:
117 		return UART_WORD_LEN_7;
118 	case UART_CFG_DATA_BITS_8:
119 		return UART_WORD_LEN_8;
120 	default:
121 		return -ENOTSUP;
122 	}
123 }
124 
uart_numaker_convert_parity(enum uart_config_parity parity)125 static inline uint32_t uart_numaker_convert_parity(enum uart_config_parity parity)
126 {
127 	switch (parity) {
128 	case UART_CFG_PARITY_ODD:
129 		return UART_PARITY_ODD;
130 	case UART_CFG_PARITY_EVEN:
131 		return UART_PARITY_EVEN;
132 	case UART_CFG_PARITY_MARK:
133 		return UART_PARITY_MARK;
134 	case UART_CFG_PARITY_SPACE:
135 		return UART_PARITY_SPACE;
136 	case UART_CFG_PARITY_NONE:
137 	default:
138 		return UART_PARITY_NONE;
139 	}
140 }
141 
142 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
uart_numaker_configure(const struct device * dev,const struct uart_config * cfg)143 static int uart_numaker_configure(const struct device *dev, const struct uart_config *cfg)
144 {
145 	const struct uart_numaker_config *config = dev->config;
146 	struct uart_numaker_data *pData = dev->data;
147 	int32_t databits, stopbits;
148 	uint32_t parity;
149 
150 	databits = uart_numaker_convert_datalen(cfg->data_bits);
151 	if (databits < 0) {
152 		return databits;
153 	}
154 
155 	stopbits = uart_numaker_convert_stopbit(cfg->stop_bits);
156 	if (stopbits < 0) {
157 		return stopbits;
158 	}
159 
160 	if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_NONE) {
161 		UART_DisableFlowCtrl(config->uart);
162 	} else if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS) {
163 		UART_EnableFlowCtrl(config->uart);
164 	} else {
165 		return -ENOTSUP;
166 	}
167 
168 	parity = uart_numaker_convert_parity(cfg->parity);
169 
170 	UART_SetLineConfig(config->uart, cfg->baudrate, databits, parity, stopbits);
171 
172 	memcpy(&pData->ucfg, cfg, sizeof(*cfg));
173 
174 	return 0;
175 }
176 
uart_numaker_config_get(const struct device * dev,struct uart_config * cfg)177 static int uart_numaker_config_get(const struct device *dev, struct uart_config *cfg)
178 {
179 	struct uart_numaker_data *pData = dev->data;
180 
181 	memcpy(cfg, &pData->ucfg, sizeof(*cfg));
182 
183 	return 0;
184 }
185 #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
186 
uart_numaker_init(const struct device * dev)187 static int uart_numaker_init(const struct device *dev)
188 {
189 	const struct uart_numaker_config *config = dev->config;
190 	struct uart_numaker_data *pData = dev->data;
191 	int err = 0;
192 
193 	SYS_UnlockReg();
194 
195 	struct numaker_scc_subsys scc_subsys;
196 
197 	memset(&scc_subsys, 0x00, sizeof(scc_subsys));
198 	scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC;
199 	scc_subsys.pcc.clk_modidx = config->clk_modidx;
200 	scc_subsys.pcc.clk_src = config->clk_src;
201 	scc_subsys.pcc.clk_div = config->clk_div;
202 
203 	/* Equivalent to CLK_EnableModuleClock(clk_modidx) */
204 	err = clock_control_on(config->clk_dev, (clock_control_subsys_t)&scc_subsys);
205 	if (err != 0) {
206 		goto move_exit;
207 	}
208 	/* Equivalent to CLK_SetModuleClock(clk_modidx, clk_src, clk_div) */
209 	err = clock_control_configure(config->clk_dev, (clock_control_subsys_t)&scc_subsys, NULL);
210 	if (err != 0) {
211 		goto move_exit;
212 	}
213 
214 	/*
215 	 * Set pinctrl for UART0 RXD and TXD
216 	 * Set multi-function pins for UART0 RXD and TXD
217 	 */
218 	err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT);
219 	if (err != 0) {
220 		goto move_exit;
221 	}
222 
223 	/* Same as BSP's SYS_ResetModule(id_rst) */
224 	if (!device_is_ready(config->reset.dev)) {
225 		LOG_ERR("reset controller not ready");
226 		return -ENODEV;
227 	}
228 
229 	/* Reset UART to default state */
230 	reset_line_toggle_dt(&config->reset);
231 
232 	UART_Open(config->uart, pData->ucfg.baudrate);
233 
234 	if (pData->ucfg.flow_ctrl == UART_CFG_FLOW_CTRL_NONE) {
235 		UART_DisableFlowCtrl(config->uart);
236 	} else if (pData->ucfg.flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS) {
237 		UART_EnableFlowCtrl(config->uart);
238 	} else {
239 		LOG_ERR("H/W flow control (%d) not support", pData->ucfg.flow_ctrl);
240 		return -ENOTSUP;
241 	}
242 
243 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
244 	config->irq_config_func(dev);
245 #endif
246 
247 move_exit:
248 	SYS_LockReg();
249 	return err;
250 }
251 
252 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_numaker_fifo_fill(const struct device * dev,const uint8_t * tx_data,int size)253 static int uart_numaker_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size)
254 {
255 	const struct uart_numaker_config *config = dev->config;
256 	UART_T *uart = config->uart;
257 	int tx_bytes = 0;
258 
259 	/* Check TX FIFO not full, then fill */
260 	while (((size - tx_bytes) > 0) && (!(uart->FIFOSTS & UART_FIFOSTS_TXFULL_Msk))) {
261 		/* Fill one byte into TX FIFO */
262 		uart->DAT = tx_data[tx_bytes++];
263 	}
264 
265 	return tx_bytes;
266 }
267 
uart_numaker_fifo_read(const struct device * dev,uint8_t * rx_data,const int size)268 static int uart_numaker_fifo_read(const struct device *dev, uint8_t *rx_data, const int size)
269 {
270 	const struct uart_numaker_config *config = dev->config;
271 	UART_T *uart = config->uart;
272 	int rx_bytes = 0;
273 
274 	/* Check RX FIFO not empty, then read */
275 	while (((size - rx_bytes) > 0) && (!(uart->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk))) {
276 		/* Read one byte from UART RX FIFO */
277 		rx_data[rx_bytes++] = (uint8_t)uart->DAT;
278 	}
279 
280 	return rx_bytes;
281 }
282 
uart_numaker_irq_tx_enable(const struct device * dev)283 static void uart_numaker_irq_tx_enable(const struct device *dev)
284 {
285 	const struct uart_numaker_config *config = dev->config;
286 	UART_T *uart = config->uart;
287 
288 	UART_EnableInt(uart, UART_INTEN_THREIEN_Msk);
289 }
290 
uart_numaker_irq_tx_disable(const struct device * dev)291 static void uart_numaker_irq_tx_disable(const struct device *dev)
292 {
293 	const struct uart_numaker_config *config = dev->config;
294 	UART_T *uart = config->uart;
295 
296 	UART_DisableInt(uart, UART_INTEN_THREIEN_Msk);
297 }
298 
uart_numaker_irq_tx_ready(const struct device * dev)299 static int uart_numaker_irq_tx_ready(const struct device *dev)
300 {
301 	const struct uart_numaker_config *config = dev->config;
302 	UART_T *uart = config->uart;
303 
304 	return ((!UART_IS_TX_FULL(uart)) && (uart->INTEN & UART_INTEN_THREIEN_Msk));
305 }
306 
uart_numaker_irq_tx_complete(const struct device * dev)307 static int uart_numaker_irq_tx_complete(const struct device *dev)
308 {
309 	const struct uart_numaker_config *config = dev->config;
310 	UART_T *uart = config->uart;
311 
312 	return (uart->INTSTS & UART_INTSTS_THREINT_Msk);
313 }
314 
uart_numaker_irq_rx_enable(const struct device * dev)315 static void uart_numaker_irq_rx_enable(const struct device *dev)
316 {
317 	const struct uart_numaker_config *config = dev->config;
318 	UART_T *uart = config->uart;
319 
320 	UART_EnableInt(uart, UART_INTEN_RDAIEN_Msk);
321 }
322 
uart_numaker_irq_rx_disable(const struct device * dev)323 static void uart_numaker_irq_rx_disable(const struct device *dev)
324 {
325 	const struct uart_numaker_config *config = dev->config;
326 	UART_T *uart = config->uart;
327 
328 	UART_DisableInt(uart, UART_INTEN_RDAIEN_Msk);
329 }
330 
uart_numaker_irq_rx_ready(const struct device * dev)331 static int uart_numaker_irq_rx_ready(const struct device *dev)
332 {
333 	const struct uart_numaker_config *config = dev->config;
334 	UART_T *uart = config->uart;
335 
336 	return ((!UART_GET_RX_EMPTY(uart)) && (uart->INTEN & UART_INTEN_RDAIEN_Msk));
337 }
338 
uart_numaker_irq_err_enable(const struct device * dev)339 static void uart_numaker_irq_err_enable(const struct device *dev)
340 {
341 	const struct uart_numaker_config *config = dev->config;
342 	UART_T *uart = config->uart;
343 
344 	UART_EnableInt(uart, UART_INTEN_BUFERRIEN_Msk | UART_INTEN_SWBEIEN_Msk);
345 }
346 
uart_numaker_irq_err_disable(const struct device * dev)347 static void uart_numaker_irq_err_disable(const struct device *dev)
348 {
349 	const struct uart_numaker_config *config = dev->config;
350 	UART_T *uart = config->uart;
351 
352 	UART_DisableInt(uart, UART_INTEN_BUFERRIEN_Msk | UART_INTEN_SWBEIEN_Msk);
353 }
354 
uart_numaker_irq_is_pending(const struct device * dev)355 static int uart_numaker_irq_is_pending(const struct device *dev)
356 {
357 
358 	return (uart_numaker_irq_tx_ready(dev) || (uart_numaker_irq_rx_ready(dev)));
359 }
360 
uart_numaker_irq_update(const struct device * dev)361 static int uart_numaker_irq_update(const struct device *dev)
362 {
363 	ARG_UNUSED(dev);
364 
365 	/* nothing to be done */
366 	return 1;
367 }
368 
uart_numaker_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)369 static void uart_numaker_irq_callback_set(const struct device *dev,
370 					  uart_irq_callback_user_data_t cb, void *cb_data)
371 {
372 	struct uart_numaker_data *pData = dev->data;
373 
374 	pData->user_cb = cb;
375 	pData->user_data = cb_data;
376 }
377 
uart_numaker_isr(const struct device * dev)378 static void uart_numaker_isr(const struct device *dev)
379 {
380 	struct uart_numaker_data *pData = dev->data;
381 
382 	if (pData->user_cb) {
383 		pData->user_cb(dev, pData->user_data);
384 	}
385 }
386 
387 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
388 
389 static DEVICE_API(uart, uart_numaker_driver_api) = {
390 	.poll_in = uart_numaker_poll_in,
391 	.poll_out = uart_numaker_poll_out,
392 	.err_check = uart_numaker_err_check,
393 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
394 	.configure = uart_numaker_configure,
395 	.config_get = uart_numaker_config_get,
396 #endif
397 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
398 	.fifo_fill = uart_numaker_fifo_fill,
399 	.fifo_read = uart_numaker_fifo_read,
400 	.irq_tx_enable = uart_numaker_irq_tx_enable,
401 	.irq_tx_disable = uart_numaker_irq_tx_disable,
402 	.irq_tx_ready = uart_numaker_irq_tx_ready,
403 	.irq_tx_complete = uart_numaker_irq_tx_complete,
404 	.irq_rx_enable = uart_numaker_irq_rx_enable,
405 	.irq_rx_disable = uart_numaker_irq_rx_disable,
406 	.irq_rx_ready = uart_numaker_irq_rx_ready,
407 	.irq_err_enable = uart_numaker_irq_err_enable,
408 	.irq_err_disable = uart_numaker_irq_err_disable,
409 	.irq_is_pending = uart_numaker_irq_is_pending,
410 	.irq_update = uart_numaker_irq_update,
411 	.irq_callback_set = uart_numaker_irq_callback_set,
412 #endif
413 };
414 
415 #define CLOCK_CTRL_INIT(n) .clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(n))),
416 
417 #define PINCTRL_DEFINE(n) PINCTRL_DT_INST_DEFINE(n);
418 #define PINCTRL_INIT(n)	  .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n),
419 
420 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
421 #define NUMAKER_UART_IRQ_CONFIG_FUNC(n)                                                            \
422 	static void uart_numaker_irq_config_##n(const struct device *dev)                          \
423 	{                                                                                          \
424 		IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), uart_numaker_isr,           \
425 			    DEVICE_DT_INST_GET(n), 0);                                             \
426 		irq_enable(DT_INST_IRQN(n));                                                       \
427 	}
428 #define IRQ_FUNC_INIT(n) .irq_config_func = uart_numaker_irq_config_##n
429 #else
430 #define NUMAKER_UART_IRQ_CONFIG_FUNC(n)
431 #define IRQ_FUNC_INIT(n)
432 #endif
433 
434 #define NUMAKER_UART_INIT(inst)                                                                    \
435 	PINCTRL_DEFINE(inst)                                                                       \
436 	NUMAKER_UART_IRQ_CONFIG_FUNC(inst)                                                         \
437                                                                                                    \
438 	static const struct uart_numaker_config uart_numaker_cfg_##inst = {                        \
439 		.uart = (UART_T *)DT_INST_REG_ADDR(inst),                                          \
440 		.reset = RESET_DT_SPEC_INST_GET(inst),                                             \
441 		.clk_modidx = DT_INST_CLOCKS_CELL(inst, clock_module_index),                       \
442 		.clk_src = DT_INST_CLOCKS_CELL(inst, clock_source),                                \
443 		.clk_div = DT_INST_CLOCKS_CELL(inst, clock_divider),                               \
444 		CLOCK_CTRL_INIT(inst).irq_n = DT_INST_IRQN(inst),                                  \
445 		PINCTRL_INIT(inst) IRQ_FUNC_INIT(inst)};                                           \
446                                                                                                    \
447 	static struct uart_numaker_data uart_numaker_data_##inst = {                               \
448 		.ucfg =                                                                            \
449 			{                                                                          \
450 				.baudrate = DT_INST_PROP(inst, current_speed),                     \
451 				.flow_ctrl = COND_CODE_1(DT_INST_PROP_OR(inst, hw_flow_control, 0),\
452 							 (UART_CFG_FLOW_CTRL_RTS_CTS),             \
453 							 (UART_CFG_FLOW_CTRL_NONE)),               \
454 			},                                                                         \
455 	};                                                                                         \
456                                                                                                    \
457 	DEVICE_DT_INST_DEFINE(inst, uart_numaker_init, NULL, &uart_numaker_data_##inst,            \
458 			      &uart_numaker_cfg_##inst, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
459 			      &uart_numaker_driver_api);
460 
461 DT_INST_FOREACH_STATUS_OKAY(NUMAKER_UART_INIT)
462