1 /*
2 * Copyright (c) 2020, Seagate Technology LLC
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #define DT_DRV_COMPAT nxp_lpc11u6x_uart
7
8 #include <cmsis_core.h>
9
10 #include <zephyr/drivers/uart.h>
11 #include <zephyr/drivers/clock_control.h>
12 #include <zephyr/irq.h>
13
14 #include "uart_lpc11u6x.h"
15
16 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart0))
lpc11u6x_uart0_poll_in(const struct device * dev,unsigned char * c)17 static int lpc11u6x_uart0_poll_in(const struct device *dev, unsigned char *c)
18 {
19 const struct lpc11u6x_uart0_config *cfg = dev->config;
20
21 if (!(cfg->uart0->lsr & LPC11U6X_UART0_LSR_RDR)) {
22 return -1;
23 }
24 *c = cfg->uart0->rbr;
25
26 return 0;
27 }
28
lpc11u6x_uart0_poll_out(const struct device * dev,unsigned char c)29 static void lpc11u6x_uart0_poll_out(const struct device *dev, unsigned char c)
30 {
31 const struct lpc11u6x_uart0_config *cfg = dev->config;
32
33 while (!(cfg->uart0->lsr & LPC11U6X_UART0_LSR_THRE)) {
34 }
35 cfg->uart0->thr = c;
36 }
37
lpc11u6x_uart0_err_check(const struct device * dev)38 static int lpc11u6x_uart0_err_check(const struct device *dev)
39 {
40 const struct lpc11u6x_uart0_config *cfg = dev->config;
41 uint32_t lsr;
42 int ret = 0;
43
44 lsr = cfg->uart0->lsr;
45 if (lsr & LPC11U6X_UART0_LSR_OE) {
46 ret |= UART_ERROR_OVERRUN;
47 }
48 if (lsr & LPC11U6X_UART0_LSR_PE) {
49 ret |= UART_ERROR_PARITY;
50 }
51 if (lsr & LPC11U6X_UART0_LSR_FE) {
52 ret |= UART_ERROR_FRAMING;
53 }
54 if (lsr & LPC11U6X_UART0_LSR_BI) {
55 ret |= UART_BREAK;
56 }
57
58 return ret;
59 }
60
lpc11u6x_uart0_write_divisor(struct lpc11u6x_uart0_regs * uart0,uint32_t div)61 static void lpc11u6x_uart0_write_divisor(struct lpc11u6x_uart0_regs *uart0,
62 uint32_t div)
63 {
64 /* Enable access to dll & dlm registers */
65 uart0->lcr |= LPC11U6X_UART0_LCR_DLAB;
66 uart0->dll = div & 0xFF;
67 uart0->dlm = (div >> 8) & 0xFF;
68 uart0->lcr &= ~LPC11U6X_UART0_LCR_DLAB;
69 }
70
lpc11u6x_uart0_write_fdr(struct lpc11u6x_uart0_regs * uart0,uint32_t div,uint32_t mul)71 static void lpc11u6x_uart0_write_fdr(struct lpc11u6x_uart0_regs *uart0,
72 uint32_t div, uint32_t mul)
73 {
74 uart0->fdr = (div & 0xF) | ((mul & 0xF) << 4);
75 }
76
lpc11u6x_uart0_config_baudrate(const struct device * clk_drv,const struct lpc11u6x_uart0_config * cfg,uint32_t baudrate)77 static void lpc11u6x_uart0_config_baudrate(const struct device *clk_drv,
78 const struct lpc11u6x_uart0_config *cfg,
79 uint32_t baudrate)
80 {
81 uint32_t div = 1, mul, dl;
82 uint32_t pclk;
83
84 /* Compute values for fractional baud rate generator. We need to have
85 * a clock that is as close as possible to a multiple of
86 * LPC11U6X_UART0_CLK so that we can have every baudrate that is
87 * a multiple of 9600
88 */
89 clock_control_get_rate(clk_drv, (clock_control_subsys_t) cfg->clkid,
90 &pclk);
91 mul = pclk / (pclk % LPC11U6X_UART0_CLK);
92
93 dl = pclk / (16 * baudrate + 16 * baudrate / mul);
94
95 /* Configure clock divisor and fractional baudrate generator */
96 lpc11u6x_uart0_write_divisor(cfg->uart0, dl);
97 lpc11u6x_uart0_write_fdr(cfg->uart0, div, mul);
98 }
99
100 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
lpc11u6x_uart0_configure(const struct device * dev,const struct uart_config * cfg)101 static int lpc11u6x_uart0_configure(const struct device *dev,
102 const struct uart_config *cfg)
103 {
104 const struct lpc11u6x_uart0_config *dev_cfg = dev->config;
105 struct lpc11u6x_uart0_data *data = dev->data;
106 uint32_t flags = 0;
107
108 /* Check that the baudrate is a multiple of 9600 */
109 if (cfg->baudrate % 9600) {
110 return -ENOTSUP;
111 }
112
113 switch (cfg->parity) {
114 case UART_CFG_PARITY_NONE:
115 break;
116 case UART_CFG_PARITY_ODD:
117 flags |= LPC11U6X_UART0_LCR_PARTIY_ENABLE |
118 LPC11U6X_UART0_LCR_PARTIY_ODD;
119 break;
120 case UART_CFG_PARITY_EVEN:
121 flags |= LPC11U6X_UART0_LCR_PARTIY_ENABLE |
122 LPC11U6X_UART0_LCR_PARTIY_EVEN;
123 break;
124 case UART_CFG_PARITY_MARK:
125 __fallthrough;
126 case UART_CFG_PARITY_SPACE:
127 return -ENOTSUP;
128 default:
129 return -EINVAL;
130 }
131
132 switch (cfg->stop_bits) {
133 case UART_CFG_STOP_BITS_0_5:
134 return -ENOTSUP;
135 case UART_CFG_STOP_BITS_1:
136 flags |= LPC11U6X_UART0_LCR_STOP_1BIT;
137 break;
138 case UART_CFG_STOP_BITS_1_5:
139 return -ENOTSUP;
140 case UART_CFG_STOP_BITS_2:
141 flags |= LPC11U6X_UART0_LCR_STOP_2BIT;
142 break;
143 default:
144 return -EINVAL;
145 }
146
147 switch (cfg->data_bits) {
148 case UART_CFG_DATA_BITS_5:
149 flags |= LPC11U6X_UART0_LCR_WLS_5BITS;
150 break;
151 case UART_CFG_DATA_BITS_6:
152 flags |= LPC11U6X_UART0_LCR_WLS_6BITS;
153 break;
154 case UART_CFG_DATA_BITS_7:
155 flags |= LPC11U6X_UART0_LCR_WLS_7BITS;
156 break;
157 case UART_CFG_DATA_BITS_8:
158 flags |= LPC11U6X_UART0_LCR_WLS_8BITS;
159 break;
160 case UART_CFG_DATA_BITS_9:
161 return -ENOTSUP;
162 default:
163 return -EINVAL;
164 }
165
166 if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) {
167 return -ENOTSUP;
168 }
169
170 lpc11u6x_uart0_config_baudrate(dev_cfg->clock_dev, dev_cfg, cfg->baudrate);
171 dev_cfg->uart0->lcr = flags;
172
173 data->baudrate = cfg->baudrate;
174 data->stop_bits = cfg->stop_bits;
175 data->data_bits = cfg->data_bits;
176 data->flow_ctrl = cfg->flow_ctrl;
177 data->parity = cfg->parity;
178
179 return 0;
180 }
181
lpc11u6x_uart0_config_get(const struct device * dev,struct uart_config * cfg)182 static int lpc11u6x_uart0_config_get(const struct device *dev,
183 struct uart_config *cfg)
184 {
185 struct lpc11u6x_uart0_data *data = dev->data;
186
187 cfg->baudrate = data->baudrate;
188 cfg->parity = data->parity;
189 cfg->stop_bits = data->stop_bits;
190 cfg->data_bits = data->data_bits;
191 cfg->flow_ctrl = data->flow_ctrl;
192
193 return 0;
194 }
195 #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
196
197 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
lpc11u6x_uart0_fifo_fill(const struct device * dev,const uint8_t * data,const int size)198 static int lpc11u6x_uart0_fifo_fill(const struct device *dev,
199 const uint8_t *data,
200 const int size)
201 {
202 const struct lpc11u6x_uart0_config *cfg = dev->config;
203 int nr_sent = 0;
204
205 while (nr_sent < size && (cfg->uart0->lsr & LPC11U6X_UART0_LSR_THRE)) {
206 cfg->uart0->thr = data[nr_sent++];
207 }
208
209 return nr_sent;
210 }
211
lpc11u6x_uart0_fifo_read(const struct device * dev,uint8_t * data,const int size)212 static int lpc11u6x_uart0_fifo_read(const struct device *dev, uint8_t *data,
213 const int size)
214 {
215 const struct lpc11u6x_uart0_config *cfg = dev->config;
216 int nr_rx = 0;
217
218 while (nr_rx < size && (cfg->uart0->lsr & LPC11U6X_UART0_LSR_RDR)) {
219 data[nr_rx++] = cfg->uart0->rbr;
220 }
221
222 return nr_rx;
223 }
224
lpc11u6x_uart0_irq_tx_enable(const struct device * dev)225 static void lpc11u6x_uart0_irq_tx_enable(const struct device *dev)
226 {
227 const struct lpc11u6x_uart0_config *cfg = dev->config;
228
229 cfg->uart0->ier = (cfg->uart0->ier & LPC11U6X_UART0_IER_MASK) |
230 LPC11U6X_UART0_IER_THREINTEN;
231
232 /* Due to hardware limitations, first TX interrupt is not triggered when
233 * enabling it in the IER register. We have to trigger it.
234 */
235 NVIC_SetPendingIRQ(DT_INST_IRQN(0));
236 }
237
lpc11u6x_uart0_irq_tx_disable(const struct device * dev)238 static void lpc11u6x_uart0_irq_tx_disable(const struct device *dev)
239 {
240 const struct lpc11u6x_uart0_config *cfg = dev->config;
241
242 cfg->uart0->ier = (cfg->uart0->ier & LPC11U6X_UART0_IER_MASK) &
243 ~LPC11U6X_UART0_IER_THREINTEN;
244 }
245
lpc11u6x_uart0_irq_tx_complete(const struct device * dev)246 static int lpc11u6x_uart0_irq_tx_complete(const struct device *dev)
247 {
248 const struct lpc11u6x_uart0_config *cfg = dev->config;
249
250 return (cfg->uart0->lsr & LPC11U6X_UART0_LSR_TEMT) != 0;
251 }
252
lpc11u6x_uart0_irq_tx_ready(const struct device * dev)253 static int lpc11u6x_uart0_irq_tx_ready(const struct device *dev)
254 {
255 const struct lpc11u6x_uart0_config *cfg = dev->config;
256
257 return (cfg->uart0->lsr & LPC11U6X_UART0_LSR_THRE) &&
258 (cfg->uart0->ier & LPC11U6X_UART0_IER_THREINTEN);
259 }
260
lpc11u6x_uart0_irq_rx_enable(const struct device * dev)261 static void lpc11u6x_uart0_irq_rx_enable(const struct device *dev)
262 {
263 const struct lpc11u6x_uart0_config *cfg = dev->config;
264
265 cfg->uart0->ier = (cfg->uart0->ier & LPC11U6X_UART0_IER_MASK) |
266 LPC11U6X_UART0_IER_RBRINTEN;
267 }
268
lpc11u6x_uart0_irq_rx_disable(const struct device * dev)269 static void lpc11u6x_uart0_irq_rx_disable(const struct device *dev)
270 {
271 const struct lpc11u6x_uart0_config *cfg = dev->config;
272
273 cfg->uart0->ier = (cfg->uart0->ier & LPC11U6X_UART0_IER_MASK) &
274 ~LPC11U6X_UART0_IER_RBRINTEN;
275 }
276
lpc11u6x_uart0_irq_rx_ready(const struct device * dev)277 static int lpc11u6x_uart0_irq_rx_ready(const struct device *dev)
278 {
279 struct lpc11u6x_uart0_data *data = dev->data;
280
281 return (LPC11U6X_UART0_IIR_INTID(data->cached_iir) ==
282 LPC11U6X_UART0_IIR_INTID_RDA) ||
283 (LPC11U6X_UART0_IIR_INTID(data->cached_iir) ==
284 LPC11U6X_UART0_IIR_INTID_CTI);
285 }
286
lpc11u6x_uart0_irq_err_enable(const struct device * dev)287 static void lpc11u6x_uart0_irq_err_enable(const struct device *dev)
288 {
289 const struct lpc11u6x_uart0_config *cfg = dev->config;
290
291 cfg->uart0->ier = (cfg->uart0->ier & LPC11U6X_UART0_IER_MASK) |
292 LPC11U6X_UART0_IER_RLSINTEN;
293 }
294
lpc11u6x_uart0_irq_err_disable(const struct device * dev)295 static void lpc11u6x_uart0_irq_err_disable(const struct device *dev)
296 {
297 const struct lpc11u6x_uart0_config *cfg = dev->config;
298
299 cfg->uart0->ier = (cfg->uart0->ier & LPC11U6X_UART0_IER_MASK) &
300 ~LPC11U6X_UART0_IER_RLSINTEN;
301 }
302
lpc11u6x_uart0_irq_is_pending(const struct device * dev)303 static int lpc11u6x_uart0_irq_is_pending(const struct device *dev)
304 {
305 struct lpc11u6x_uart0_data *data = dev->data;
306
307 return !(data->cached_iir & LPC11U6X_UART0_IIR_STATUS);
308 }
309
lpc11u6x_uart0_irq_update(const struct device * dev)310 static int lpc11u6x_uart0_irq_update(const struct device *dev)
311 {
312 const struct lpc11u6x_uart0_config *cfg = dev->config;
313 struct lpc11u6x_uart0_data *data = dev->data;
314
315 data->cached_iir = cfg->uart0->iir;
316 return 1;
317 }
318
lpc11u6x_uart0_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * user_data)319 static void lpc11u6x_uart0_irq_callback_set(const struct device *dev,
320 uart_irq_callback_user_data_t cb,
321 void *user_data)
322 {
323 struct lpc11u6x_uart0_data *data = dev->data;
324
325 data->cb = cb;
326 data->cb_data = user_data;
327 }
328
lpc11u6x_uart0_isr(const struct device * dev)329 static void lpc11u6x_uart0_isr(const struct device *dev)
330 {
331 struct lpc11u6x_uart0_data *data = dev->data;
332
333 if (data->cb) {
334 data->cb(dev, data->cb_data);
335 }
336 }
337 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
338
lpc11u6x_uart0_init(const struct device * dev)339 static int lpc11u6x_uart0_init(const struct device *dev)
340 {
341 const struct lpc11u6x_uart0_config *cfg = dev->config;
342 struct lpc11u6x_uart0_data *data = dev->data;
343 int err;
344
345 /* Apply default pin control state to select RX and TX pins */
346 err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
347 if (err) {
348 return err;
349 }
350
351 if (!device_is_ready(cfg->clock_dev)) {
352 return -ENODEV;
353 }
354
355 clock_control_on(cfg->clock_dev, (clock_control_subsys_t) cfg->clkid);
356
357 /* Configure baudrate, parity and stop bits */
358 lpc11u6x_uart0_config_baudrate(cfg->clock_dev, cfg, cfg->baudrate);
359
360 cfg->uart0->lcr |= LPC11U6X_UART0_LCR_WLS_8BITS; /* 8N1 */
361
362 data->baudrate = cfg->baudrate;
363 data->parity = UART_CFG_PARITY_NONE;
364 data->stop_bits = UART_CFG_STOP_BITS_1;
365 data->data_bits = UART_CFG_DATA_BITS_8;
366 data->flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
367
368 /* Configure FIFO */
369 cfg->uart0->fcr = LPC11U6X_UART0_FCR_FIFO_EN;
370
371 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
372 cfg->irq_config_func(dev);
373 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
374 return 0;
375 }
376
377 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
378 static void lpc11u6x_uart0_isr_config(const struct device *dev);
379 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
380
381 PINCTRL_DT_DEFINE(DT_NODELABEL(uart0));
382
383 BUILD_ASSERT(DT_PROP(DT_NODELABEL(uart0), rx_invert) == 0,
384 "rx-invert not supported for UART0");
385 BUILD_ASSERT(DT_PROP(DT_NODELABEL(uart0), tx_invert) == 0,
386 "tx-invert not supported for UART0");
387
388 static const struct lpc11u6x_uart0_config uart0_config = {
389 .uart0 = (struct lpc11u6x_uart0_regs *)
390 DT_REG_ADDR(DT_NODELABEL(uart0)),
391 .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_NODELABEL(uart0))),
392 .pincfg = PINCTRL_DT_DEV_CONFIG_GET(DT_NODELABEL(uart0)),
393 .clkid = DT_PHA_BY_IDX(DT_NODELABEL(uart0), clocks, 0, clkid),
394 .baudrate = DT_PROP(DT_NODELABEL(uart0), current_speed),
395 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
396 .irq_config_func = lpc11u6x_uart0_isr_config,
397 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
398 };
399
400 static DEVICE_API(uart, uart0_api) = {
401 .poll_in = lpc11u6x_uart0_poll_in,
402 .poll_out = lpc11u6x_uart0_poll_out,
403 .err_check = lpc11u6x_uart0_err_check,
404 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
405 .configure = lpc11u6x_uart0_configure,
406 .config_get = lpc11u6x_uart0_config_get,
407 #endif
408 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
409 .fifo_fill = lpc11u6x_uart0_fifo_fill,
410 .fifo_read = lpc11u6x_uart0_fifo_read,
411 .irq_tx_enable = lpc11u6x_uart0_irq_tx_enable,
412 .irq_tx_disable = lpc11u6x_uart0_irq_tx_disable,
413 .irq_tx_ready = lpc11u6x_uart0_irq_tx_ready,
414 .irq_tx_complete = lpc11u6x_uart0_irq_tx_complete,
415 .irq_rx_enable = lpc11u6x_uart0_irq_rx_enable,
416 .irq_rx_disable = lpc11u6x_uart0_irq_rx_disable,
417 .irq_rx_ready = lpc11u6x_uart0_irq_rx_ready,
418 .irq_err_enable = lpc11u6x_uart0_irq_err_enable,
419 .irq_err_disable = lpc11u6x_uart0_irq_err_disable,
420 .irq_is_pending = lpc11u6x_uart0_irq_is_pending,
421 .irq_update = lpc11u6x_uart0_irq_update,
422 .irq_callback_set = lpc11u6x_uart0_irq_callback_set,
423 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
424 };
425
426 static struct lpc11u6x_uart0_data uart0_data;
427
428 DEVICE_DT_DEFINE(DT_NODELABEL(uart0),
429 &lpc11u6x_uart0_init,
430 NULL,
431 &uart0_data, &uart0_config,
432 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY,
433 &uart0_api);
434
435 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
lpc11u6x_uart0_isr_config(const struct device * dev)436 static void lpc11u6x_uart0_isr_config(const struct device *dev)
437 {
438 IRQ_CONNECT(DT_IRQN(DT_NODELABEL(uart0)),
439 DT_IRQ(DT_NODELABEL(uart0), priority),
440 lpc11u6x_uart0_isr, DEVICE_DT_GET(DT_NODELABEL(uart0)), 0);
441
442 irq_enable(DT_IRQN(DT_NODELABEL(uart0)));
443 }
444 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
445
446 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart0)) */
447
448 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) || \
449 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) || \
450 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3)) || \
451 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
452
lpc11u6x_uartx_poll_in(const struct device * dev,unsigned char * c)453 static int lpc11u6x_uartx_poll_in(const struct device *dev, unsigned char *c)
454 {
455 const struct lpc11u6x_uartx_config *cfg = dev->config;
456
457 if (!(cfg->base->stat & LPC11U6X_UARTX_STAT_RXRDY)) {
458 return -1;
459 }
460 *c = cfg->base->rx_dat;
461 return 0;
462 }
463
lpc11u6x_uartx_poll_out(const struct device * dev,unsigned char c)464 static void lpc11u6x_uartx_poll_out(const struct device *dev, unsigned char c)
465 {
466 const struct lpc11u6x_uartx_config *cfg = dev->config;
467
468 while (!(cfg->base->stat & LPC11U6X_UARTX_STAT_TXRDY)) {
469 }
470 cfg->base->tx_dat = c;
471 }
472
lpc11u6x_uartx_err_check(const struct device * dev)473 static int lpc11u6x_uartx_err_check(const struct device *dev)
474 {
475 const struct lpc11u6x_uartx_config *cfg = dev->config;
476 int ret = 0;
477
478 if (cfg->base->stat & LPC11U6X_UARTX_STAT_OVERRUNINT) {
479 ret |= UART_ERROR_OVERRUN;
480 }
481 if (cfg->base->stat & LPC11U6X_UARTX_STAT_FRAMERRINT) {
482 ret |= UART_ERROR_FRAMING;
483 }
484 if (cfg->base->stat & LPC11U6X_UARTX_STAT_PARITYERRINT) {
485 ret |= UART_ERROR_PARITY;
486 }
487
488 return ret;
489 }
490
lpc11u6x_uartx_config_baud(const struct lpc11u6x_uartx_config * cfg,uint32_t baudrate)491 static void lpc11u6x_uartx_config_baud(const struct lpc11u6x_uartx_config *cfg,
492 uint32_t baudrate)
493 {
494 uint32_t clk_rate;
495 uint32_t div;
496 const struct device *clk_drv = cfg->clock_dev;
497
498 clock_control_get_rate(clk_drv, (clock_control_subsys_t) cfg->clkid,
499 &clk_rate);
500
501 div = clk_rate / (16 * baudrate);
502 if (div != 0) {
503 div -= 1;
504 }
505 cfg->base->brg = div & LPC11U6X_UARTX_BRG_MASK;
506 }
507
508 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
lpc11u6x_uartx_configure(const struct device * dev,const struct uart_config * cfg)509 static int lpc11u6x_uartx_configure(const struct device *dev,
510 const struct uart_config *cfg)
511 {
512 const struct lpc11u6x_uartx_config *dev_cfg = dev->config;
513 struct lpc11u6x_uartx_data *data = dev->data;
514 uint32_t flags = 0;
515
516 /* We only support baudrates that are multiple of 9600 */
517 if (cfg->baudrate % 9600) {
518 return -ENOTSUP;
519 }
520
521 switch (cfg->parity) {
522 case UART_CFG_PARITY_NONE:
523 flags |= LPC11U6X_UARTX_CFG_PARITY_NONE;
524 break;
525 case UART_CFG_PARITY_ODD:
526 flags |= LPC11U6X_UARTX_CFG_PARITY_ODD;
527 break;
528 case UART_CFG_PARITY_EVEN:
529 flags |= LPC11U6X_UARTX_CFG_PARITY_EVEN;
530 break;
531 case UART_CFG_PARITY_MARK:
532 __fallthrough;
533 case UART_CFG_PARITY_SPACE:
534 return -ENOTSUP;
535 default:
536 return -EINVAL;
537 }
538
539 switch (cfg->stop_bits) {
540 case UART_CFG_STOP_BITS_0_5:
541 return -ENOTSUP;
542 case UART_CFG_STOP_BITS_1:
543 flags |= LPC11U6X_UARTX_CFG_STOP_1BIT;
544 break;
545 case UART_CFG_STOP_BITS_1_5:
546 return -ENOTSUP;
547 case UART_CFG_STOP_BITS_2:
548 flags |= LPC11U6X_UARTX_CFG_STOP_2BIT;
549 break;
550 default:
551 return -EINVAL;
552 }
553
554 switch (cfg->data_bits) {
555 case UART_CFG_DATA_BITS_5:
556 __fallthrough;
557 case UART_CFG_DATA_BITS_6:
558 return -ENOTSUP;
559 case UART_CFG_DATA_BITS_7:
560 flags |= LPC11U6X_UARTX_CFG_DATALEN_7BIT;
561 break;
562 case UART_CFG_DATA_BITS_8:
563 flags |= LPC11U6X_UARTX_CFG_DATALEN_8BIT;
564 break;
565 case UART_CFG_DATA_BITS_9:
566 flags |= LPC11U6X_UARTX_CFG_DATALEN_9BIT;
567 break;
568 default:
569 return -EINVAL;
570 }
571
572 if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) {
573 return -ENOTSUP;
574 }
575
576 if (dev_cfg->rx_invert) {
577 flags |= LPC11U6X_UARTX_CFG_RXPOL(1);
578 }
579 if (dev_cfg->tx_invert) {
580 flags |= LPC11U6X_UARTX_CFG_TXPOL(1);
581 }
582
583 /* Disable UART */
584 dev_cfg->base->cfg = 0;
585
586 /* Update baudrate */
587 lpc11u6x_uartx_config_baud(dev_cfg, cfg->baudrate);
588
589 /* Set parity, data bits, stop bits and re-enable UART interface */
590 dev_cfg->base->cfg = flags | LPC11U6X_UARTX_CFG_ENABLE;
591
592 data->baudrate = cfg->baudrate;
593 data->parity = cfg->parity;
594 data->stop_bits = cfg->stop_bits;
595 data->data_bits = cfg->data_bits;
596 data->flow_ctrl = cfg->flow_ctrl;
597
598 return 0;
599 }
600
lpc11u6x_uartx_config_get(const struct device * dev,struct uart_config * cfg)601 static int lpc11u6x_uartx_config_get(const struct device *dev,
602 struct uart_config *cfg)
603 {
604 const struct lpc11u6x_uartx_data *data = dev->data;
605
606 cfg->baudrate = data->baudrate;
607 cfg->parity = data->parity;
608 cfg->stop_bits = data->stop_bits;
609 cfg->data_bits = data->data_bits;
610 cfg->flow_ctrl = data->flow_ctrl;
611
612 return 0;
613 }
614 #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
615
616 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
lpc11u6x_uartx_fifo_fill(const struct device * dev,const uint8_t * data,int size)617 static int lpc11u6x_uartx_fifo_fill(const struct device *dev,
618 const uint8_t *data,
619 int size)
620 {
621 const struct lpc11u6x_uartx_config *cfg = dev->config;
622 int tx_size = 0;
623
624 while (tx_size < size &&
625 (cfg->base->stat & LPC11U6X_UARTX_STAT_TXRDY)) {
626 cfg->base->tx_dat = data[tx_size++];
627 }
628 return tx_size;
629 }
630
lpc11u6x_uartx_fifo_read(const struct device * dev,uint8_t * data,int size)631 static int lpc11u6x_uartx_fifo_read(const struct device *dev, uint8_t *data,
632 int size)
633 {
634 const struct lpc11u6x_uartx_config *cfg = dev->config;
635 int rx_size = 0;
636
637 while (rx_size < size &&
638 (cfg->base->stat & LPC11U6X_UARTX_STAT_RXRDY)) {
639 data[rx_size++] = cfg->base->rx_dat;
640 }
641 return rx_size;
642 }
643
lpc11u6x_uartx_irq_tx_enable(const struct device * dev)644 static void lpc11u6x_uartx_irq_tx_enable(const struct device *dev)
645 {
646 const struct lpc11u6x_uartx_config *cfg = dev->config;
647
648 cfg->base->int_en_set = (cfg->base->int_en_set &
649 LPC11U6X_UARTX_INT_EN_SET_MASK) |
650 LPC11U6X_UARTX_INT_EN_SET_TXRDYEN;
651 }
652
lpc11u6x_uartx_irq_tx_disable(const struct device * dev)653 static void lpc11u6x_uartx_irq_tx_disable(const struct device *dev)
654 {
655 const struct lpc11u6x_uartx_config *cfg = dev->config;
656
657 cfg->base->int_en_clr = LPC11U6X_UARTX_INT_EN_CLR_TXRDYCLR;
658 }
659
lpc11u6x_uartx_irq_tx_ready(const struct device * dev)660 static int lpc11u6x_uartx_irq_tx_ready(const struct device *dev)
661 {
662 const struct lpc11u6x_uartx_config *cfg = dev->config;
663
664 return (cfg->base->stat & LPC11U6X_UARTX_STAT_TXRDY) &&
665 (cfg->base->int_en_set & LPC11U6X_UARTX_INT_EN_SET_TXRDYEN);
666 }
667
lpc11u6x_uartx_irq_tx_complete(const struct device * dev)668 static int lpc11u6x_uartx_irq_tx_complete(const struct device *dev)
669 {
670 const struct lpc11u6x_uartx_config *cfg = dev->config;
671
672 return (cfg->base->stat & LPC11U6X_UARTX_STAT_TXIDLE) != 0;
673 }
674
lpc11u6x_uartx_irq_rx_enable(const struct device * dev)675 static void lpc11u6x_uartx_irq_rx_enable(const struct device *dev)
676 {
677 const struct lpc11u6x_uartx_config *cfg = dev->config;
678
679 cfg->base->int_en_set = (cfg->base->int_en_set &
680 LPC11U6X_UARTX_INT_EN_SET_MASK) |
681 LPC11U6X_UARTX_INT_EN_SET_RXRDYEN;
682 }
683
lpc11u6x_uartx_irq_rx_disable(const struct device * dev)684 static void lpc11u6x_uartx_irq_rx_disable(const struct device *dev)
685 {
686 const struct lpc11u6x_uartx_config *cfg = dev->config;
687
688 cfg->base->int_en_clr = LPC11U6X_UARTX_INT_EN_CLR_RXRDYCLR;
689 }
690
lpc11u6x_uartx_irq_rx_ready(const struct device * dev)691 static int lpc11u6x_uartx_irq_rx_ready(const struct device *dev)
692 {
693 const struct lpc11u6x_uartx_config *cfg = dev->config;
694
695 return (cfg->base->stat & LPC11U6X_UARTX_STAT_RXRDY) &&
696 (cfg->base->int_en_set & LPC11U6X_UARTX_INT_EN_SET_RXRDYEN);
697 }
698
lpc11u6x_uartx_irq_err_enable(const struct device * dev)699 static void lpc11u6x_uartx_irq_err_enable(const struct device *dev)
700 {
701 const struct lpc11u6x_uartx_config *cfg = dev->config;
702
703 cfg->base->int_en_set = (cfg->base->int_en_set &
704 LPC11U6X_UARTX_INT_EN_SET_MASK) |
705 (LPC11U6X_UARTX_INT_EN_SET_RXRDYEN |
706 LPC11U6X_UARTX_INT_EN_SET_FRAMERREN |
707 LPC11U6X_UARTX_INT_EN_SET_PARITYERREN);
708 }
709
lpc11u6x_uartx_irq_err_disable(const struct device * dev)710 static void lpc11u6x_uartx_irq_err_disable(const struct device *dev)
711 {
712 const struct lpc11u6x_uartx_config *cfg = dev->config;
713
714 cfg->base->int_en_clr = LPC11U6X_UARTX_INT_EN_CLR_OVERRUNCLR |
715 LPC11U6X_UARTX_INT_EN_CLR_FRAMERRCLR |
716 LPC11U6X_UARTX_INT_EN_CLR_PARITYERRCLR;
717 }
718
lpc11u6x_uartx_irq_is_pending(const struct device * dev)719 static int lpc11u6x_uartx_irq_is_pending(const struct device *dev)
720 {
721 const struct lpc11u6x_uartx_config *cfg = dev->config;
722
723 if ((cfg->base->stat & LPC11U6X_UARTX_STAT_RXRDY) &&
724 (cfg->base->int_stat & LPC11U6X_UARTX_INT_STAT_RXRDY)) {
725 return 1;
726 }
727 if ((cfg->base->stat & LPC11U6X_UARTX_STAT_TXRDY) &&
728 cfg->base->int_stat & LPC11U6X_UARTX_INT_STAT_TXRDY) {
729 return 1;
730 }
731 if (cfg->base->stat & (LPC11U6X_UARTX_STAT_OVERRUNINT |
732 LPC11U6X_UARTX_STAT_FRAMERRINT |
733 LPC11U6X_UARTX_STAT_PARITYERRINT)) {
734 return 1;
735 }
736 return 0;
737 }
738
lpc11u6x_uartx_irq_update(const struct device * dev)739 static int lpc11u6x_uartx_irq_update(const struct device *dev)
740 {
741 return 1;
742 }
743
lpc11u6x_uartx_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * user_data)744 static void lpc11u6x_uartx_irq_callback_set(const struct device *dev,
745 uart_irq_callback_user_data_t cb,
746 void *user_data)
747 {
748 struct lpc11u6x_uartx_data *data = dev->data;
749
750 data->cb = cb;
751 data->cb_data = user_data;
752 }
753
lpc11u6x_uartx_isr(const struct device * dev)754 static void lpc11u6x_uartx_isr(const struct device *dev)
755 {
756 struct lpc11u6x_uartx_data *data = dev->data;
757
758 if (data->cb) {
759 data->cb(dev, data->cb_data);
760 }
761 }
762
lpc11u6x_uartx_shared_isr(const void * arg)763 static void lpc11u6x_uartx_shared_isr(const void *arg)
764 {
765 struct lpc11u6x_uartx_shared_irq *shared_irq =
766 (struct lpc11u6x_uartx_shared_irq *)arg;
767 int i;
768
769 for (i = 0; i < ARRAY_SIZE(shared_irq->devices); i++) {
770 if (shared_irq->devices[i]) {
771 lpc11u6x_uartx_isr(shared_irq->devices[i]);
772 }
773 }
774 }
775 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
776
lpc11u6x_uartx_init(const struct device * dev)777 static int lpc11u6x_uartx_init(const struct device *dev)
778 {
779 const struct lpc11u6x_uartx_config *cfg = dev->config;
780 struct lpc11u6x_uartx_data *data = dev->data;
781 int err;
782
783 /* Apply default pin control state to select RX and TX pins */
784 err = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT);
785 if (err) {
786 return err;
787 }
788
789 clock_control_on(cfg->clock_dev, (clock_control_subsys_t) cfg->clkid);
790
791 /* Configure baudrate, parity and stop bits */
792 lpc11u6x_uartx_config_baud(cfg, cfg->baudrate);
793 cfg->base->cfg = LPC11U6X_UARTX_CFG_DATALEN_8BIT; /* 8N1 */
794
795 data->baudrate = cfg->baudrate;
796 data->parity = UART_CFG_PARITY_NONE;
797 data->stop_bits = UART_CFG_STOP_BITS_1;
798 data->data_bits = UART_CFG_DATA_BITS_8;
799 data->flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
800
801 if (cfg->rx_invert) {
802 cfg->base->cfg |= LPC11U6X_UARTX_CFG_RXPOL(1);
803 }
804 if (cfg->tx_invert) {
805 cfg->base->cfg |= LPC11U6X_UARTX_CFG_TXPOL(1);
806 }
807
808 /* Enable UART */
809 cfg->base->cfg = (cfg->base->cfg & LPC11U6X_UARTX_CFG_MASK) |
810 LPC11U6X_UARTX_CFG_ENABLE;
811
812 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
813 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) || \
814 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
815 lpc11u6x_uartx_isr_config_1(dev);
816 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) ||
817 * DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
818 */
819
820 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) || \
821 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3))
822 lpc11u6x_uartx_isr_config_2(dev);
823 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) ||
824 * DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3))
825 */
826 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
827 return 0;
828 }
829
830 static DEVICE_API(uart, uartx_api) = {
831 .poll_in = lpc11u6x_uartx_poll_in,
832 .poll_out = lpc11u6x_uartx_poll_out,
833 .err_check = lpc11u6x_uartx_err_check,
834 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
835 .configure = lpc11u6x_uartx_configure,
836 .config_get = lpc11u6x_uartx_config_get,
837 #endif
838 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
839 .fifo_fill = lpc11u6x_uartx_fifo_fill,
840 .fifo_read = lpc11u6x_uartx_fifo_read,
841 .irq_tx_enable = lpc11u6x_uartx_irq_tx_enable,
842 .irq_tx_disable = lpc11u6x_uartx_irq_tx_disable,
843 .irq_tx_ready = lpc11u6x_uartx_irq_tx_ready,
844 .irq_tx_complete = lpc11u6x_uartx_irq_tx_complete,
845 .irq_rx_enable = lpc11u6x_uartx_irq_rx_enable,
846 .irq_rx_disable = lpc11u6x_uartx_irq_rx_disable,
847 .irq_rx_ready = lpc11u6x_uartx_irq_rx_ready,
848 .irq_err_enable = lpc11u6x_uartx_irq_err_enable,
849 .irq_err_disable = lpc11u6x_uartx_irq_err_disable,
850 .irq_is_pending = lpc11u6x_uartx_irq_is_pending,
851 .irq_update = lpc11u6x_uartx_irq_update,
852 .irq_callback_set = lpc11u6x_uartx_irq_callback_set,
853 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
854 };
855
856
857 #define LPC11U6X_UARTX_INIT(idx) \
858 PINCTRL_DT_DEFINE(DT_NODELABEL(uart##idx)); \
859 \
860 static const struct lpc11u6x_uartx_config uart_cfg_##idx = { \
861 .base = (struct lpc11u6x_uartx_regs *) \
862 DT_REG_ADDR(DT_NODELABEL(uart##idx)), \
863 .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_NODELABEL(uart##idx))), \
864 .clkid = DT_PHA_BY_IDX(DT_NODELABEL(uart##idx), clocks, 0, clkid), \
865 .pincfg = PINCTRL_DT_DEV_CONFIG_GET(DT_NODELABEL(uart##idx)), \
866 .baudrate = DT_PROP(DT_NODELABEL(uart##idx), current_speed), \
867 .rx_invert = DT_PROP(DT_NODELABEL(uart##idx), rx_invert), \
868 .tx_invert = DT_PROP(DT_NODELABEL(uart##idx), tx_invert), \
869 }; \
870 \
871 static struct lpc11u6x_uartx_data uart_data_##idx; \
872 \
873 DEVICE_DT_DEFINE(DT_NODELABEL(uart##idx), \
874 &lpc11u6x_uartx_init, NULL, \
875 &uart_data_##idx, &uart_cfg_##idx, \
876 PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
877 &uartx_api)
878
879 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1))
880 LPC11U6X_UARTX_INIT(1);
881 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) */
882
883 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2))
884 LPC11U6X_UARTX_INIT(2);
885 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) */
886
887 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3))
888 LPC11U6X_UARTX_INIT(3);
889 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3)) */
890
891 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
892 LPC11U6X_UARTX_INIT(4);
893 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4)) */
894
895 #if CONFIG_UART_INTERRUPT_DRIVEN && \
896 (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) || \
897 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4)))
898
899 struct lpc11u6x_uartx_shared_irq lpc11u6x_uartx_shared_irq_info_1 = {
900 .devices = {
901 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1))
902 DEVICE_DT_GET(DT_NODELABEL(uart1)),
903 #else
904 NULL,
905 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) */
906 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4))
907 DEVICE_DT_GET(DT_NODELABEL(uart4)),
908 #else
909 NULL,
910 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4)) */
911 },
912 };
913
lpc11u6x_uartx_isr_config_1(const struct device * dev)914 static void lpc11u6x_uartx_isr_config_1(const struct device *dev)
915 {
916 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1))
917 IRQ_CONNECT(DT_IRQN(DT_NODELABEL(uart1)),
918 DT_IRQ(DT_NODELABEL(uart1), priority),
919 lpc11u6x_uartx_shared_isr,
920 &lpc11u6x_uartx_shared_irq_info_1,
921 0);
922 irq_enable(DT_IRQN(DT_NODELABEL(uart1)));
923 #else
924 IRQ_CONNECT(DT_IRQN(DT_NODELABEL(uart4)),
925 DT_IRQ(DT_NODELABEL(uart4), priority),
926 lpc11u6x_uartx_shared_isr,
927 &lpc11u6x_uartx_shared_irq_info_1,
928 0);
929 irq_enable(DT_IRQN(DT_NODELABEL(uart4)));
930 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) */
931 }
932 #endif /* CONFIG_UART_INTERRUPT_DRIVEN &&
933 * (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart1)) ||
934 * DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart4)))
935 */
936
937 #if CONFIG_UART_INTERRUPT_DRIVEN && \
938 (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) || \
939 DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3)))
940 struct lpc11u6x_uartx_shared_irq lpc11u6x_uartx_shared_irq_info_2 = {
941 .devices = {
942 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2))
943 DEVICE_DT_GET(DT_NODELABEL(uart2)),
944 #else
945 NULL,
946 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) */
947 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3))
948 DEVICE_DT_GET(DT_NODELABEL(uart3)),
949 #else
950 NULL,
951 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3)) */
952 },
953 };
954
lpc11u6x_uartx_isr_config_2(const struct device * dev)955 static void lpc11u6x_uartx_isr_config_2(const struct device *dev)
956 {
957 #if DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2))
958 IRQ_CONNECT(DT_IRQN(DT_NODELABEL(uart2)),
959 DT_IRQ(DT_NODELABEL(uart2), priority),
960 lpc11u6x_uartx_shared_isr,
961 &lpc11u6x_uartx_shared_irq_info_2,
962 0);
963 irq_enable(DT_IRQN(DT_NODELABEL(uart2)));
964 #else
965 IRQ_CONNECT(DT_IRQN(DT_NODELABEL(uart3)),
966 DT_IRQ(DT_NODELABEL(uart3), priority),
967 lpc11u6x_uartx_shared_isr,
968 &lpc11u6x_uartx_shared_irq_info_2,
969 0);
970 irq_enable(DT_IRQN(DT_NODELABEL(uart3)));
971 #endif /* DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) */
972 }
973 #endif /* CONFIG_UART_INTERRUPT_DRIVEN &&
974 * (DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart2)) ||
975 * DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(uart3)))
976 */
977 #endif /* DT_NODE_EXISTS(DT_NODELABEL(uart1) ||
978 * DT_NODE_EXISTS(DT_NODELABEL(uart2) ||
979 * DT_NODE_EXISTS(DT_NODELABEL(uart3) ||
980 * DT_NODE_EXISTS(DT_NODELABEL(uart4)
981 */
982