1 /*
2 * Copyright (c) 2019-2020 Cobham Gaisler AB
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT gaisler_apbuart
8
9 #include <zephyr/drivers/uart.h>
10 #include <zephyr/irq.h>
11 #include <zephyr/sys/time_units.h>
12 #include <errno.h>
13
14 /* APBUART registers
15 *
16 * Offset | Name | Description
17 * ------ | ------ | ----------------------------------------
18 * 0x0000 | data | UART data register
19 * 0x0004 | status | UART status register
20 * 0x0008 | ctrl | UART control register
21 * 0x000c | scaler | UART scaler register
22 * 0x0010 | debug | UART FIFO debug register
23 */
24
25 struct apbuart_regs {
26 /** @brief UART data register
27 *
28 * Bit | Name | Description
29 * ------ | ------ | ----------------------------------------
30 * 7-0 | data | Holding register or FIFO
31 */
32 uint32_t data; /* 0x0000 */
33
34 /** @brief UART status register
35 *
36 * Bit | Name | Description
37 * ------ | ------ | ----------------------------------------
38 * 31-26 | RCNT | Receiver FIFO count
39 * 25-20 | TCNT | Transmitter FIFO count
40 * 10 | RF | Receiver FIFO full
41 * 9 | TF | Transmitter FIFO full
42 * 8 | RH | Receiver FIFO half-full
43 * 7 | TH | Transmitter FIFO half-full
44 * 6 | FE | Framing error
45 * 5 | PE | Parity error
46 * 4 | OV | Overrun
47 * 3 | BR | Break received
48 * 2 | TE | Transmitter FIFO empty
49 * 1 | TS | Transmitter shift register empty
50 * 0 | DR | Data ready
51 */
52 uint32_t status; /* 0x0004 */
53
54 /** @brief UART control register
55 *
56 * Bit | Name | Description
57 * ------ | ------ | ----------------------------------------
58 * 31 | FA | FIFOs available
59 * 14 | SI | Transmitter shift register empty interrupt enable
60 * 13 | DI | Delayed interrupt enable
61 * 12 | BI | Break interrupt enable
62 * 11 | DB | FIFO debug mode enable
63 * 10 | RF | Receiver FIFO interrupt enable
64 * 9 | TF | Transmitter FIFO interrupt enable
65 * 8 | EC | External clock
66 * 7 | LB | Loop back
67 * 6 | FL | Flow control
68 * 5 | PE | Parity enable
69 * 4 | PS | Parity select
70 * 3 | TI | Transmitter interrupt enable
71 * 2 | RI | Receiver interrupt enable
72 * 1 | TE | Transmitter enable
73 * 0 | RE | Receiver enable
74 */
75 uint32_t ctrl; /* 0x0008 */
76
77 /** @brief UART scaler register
78 *
79 * Bit | Name | Description
80 * ------ | ------ | ----------------------------------------
81 * 11-0 | RELOAD | Scaler reload value
82 */
83 uint32_t scaler; /* 0x000c */
84
85 /** @brief UART FIFO debug register
86 *
87 * Bit | Name | Description
88 * ------ | ------ | ----------------------------------------
89 * 7-0 | data | Holding register or FIFO
90 */
91 uint32_t debug; /* 0x0010 */
92 };
93
94 /* APBUART register bits. */
95
96 /* Control register */
97 #define APBUART_CTRL_FA (1 << 31)
98 #define APBUART_CTRL_DB (1 << 11)
99 #define APBUART_CTRL_RF (1 << 10)
100 #define APBUART_CTRL_TF (1 << 9)
101 #define APBUART_CTRL_LB (1 << 7)
102 #define APBUART_CTRL_FL (1 << 6)
103 #define APBUART_CTRL_PE (1 << 5)
104 #define APBUART_CTRL_PS (1 << 4)
105 #define APBUART_CTRL_TI (1 << 3)
106 #define APBUART_CTRL_RI (1 << 2)
107 #define APBUART_CTRL_TE (1 << 1)
108 #define APBUART_CTRL_RE (1 << 0)
109
110 /* Status register */
111 #define APBUART_STATUS_RF (1 << 10)
112 #define APBUART_STATUS_TF (1 << 9)
113 #define APBUART_STATUS_RH (1 << 8)
114 #define APBUART_STATUS_TH (1 << 7)
115 #define APBUART_STATUS_FE (1 << 6)
116 #define APBUART_STATUS_PE (1 << 5)
117 #define APBUART_STATUS_OV (1 << 4)
118 #define APBUART_STATUS_BR (1 << 3)
119 #define APBUART_STATUS_TE (1 << 2)
120 #define APBUART_STATUS_TS (1 << 1)
121 #define APBUART_STATUS_DR (1 << 0)
122
123 /* For APBUART implemented without FIFO */
124 #define APBUART_STATUS_HOLD_REGISTER_EMPTY (1 << 2)
125
126 struct apbuart_dev_cfg {
127 struct apbuart_regs *regs;
128 int interrupt;
129 };
130
131 struct apbuart_dev_data {
132 int usefifo;
133 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
134 uart_irq_callback_user_data_t cb;
135 void *cb_data;
136 #endif
137 };
138
139 /*
140 * This routine waits for the TX holding register or TX FIFO to be ready and
141 * then it writes a character to the data register.
142 */
apbuart_poll_out(const struct device * dev,unsigned char x)143 static void apbuart_poll_out(const struct device *dev, unsigned char x)
144 {
145 const struct apbuart_dev_cfg *config = dev->config;
146 struct apbuart_dev_data *data = dev->data;
147 volatile struct apbuart_regs *regs = (void *) config->regs;
148
149 if (data->usefifo) {
150 /* Transmitter FIFO full flag is available. */
151 while (regs->status & APBUART_STATUS_TF) {
152 ;
153 }
154 } else {
155 /*
156 * Transmitter "hold register empty" AKA "FIFO empty" flag is
157 * available.
158 */
159 while (!(regs->status & APBUART_STATUS_HOLD_REGISTER_EMPTY)) {
160 ;
161 }
162 }
163
164 regs->data = x & 0xff;
165 }
166
apbuart_poll_in(const struct device * dev,unsigned char * c)167 static int apbuart_poll_in(const struct device *dev, unsigned char *c)
168 {
169 const struct apbuart_dev_cfg *config = dev->config;
170 volatile struct apbuart_regs *regs = (void *) config->regs;
171
172 if ((regs->status & APBUART_STATUS_DR) == 0) {
173 return -1;
174 }
175 *c = regs->data & 0xff;
176
177 return 0;
178 }
179
apbuart_err_check(const struct device * dev)180 static int apbuart_err_check(const struct device *dev)
181 {
182 const struct apbuart_dev_cfg *config = dev->config;
183 volatile struct apbuart_regs *regs = (void *) config->regs;
184 const uint32_t status = regs->status;
185 int err = 0;
186
187 if (status & APBUART_STATUS_FE) {
188 err |= UART_ERROR_FRAMING;
189 }
190 if (status & APBUART_STATUS_PE) {
191 err |= UART_ERROR_PARITY;
192 }
193 if (status & APBUART_STATUS_OV) {
194 err |= UART_ERROR_OVERRUN;
195 }
196 if (status & APBUART_STATUS_BR) {
197 err |= UART_BREAK;
198 }
199
200 return err;
201 }
202
203 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
get_baud(volatile struct apbuart_regs * const regs)204 static int get_baud(volatile struct apbuart_regs *const regs)
205 {
206 unsigned int core_clk_hz;
207 unsigned int scaler;
208
209 scaler = regs->scaler;
210 core_clk_hz = sys_clock_hw_cycles_per_sec();
211
212 /* Calculate baud rate from generator "scaler" number */
213 return core_clk_hz / ((scaler + 1) * 8);
214 }
215
set_baud(volatile struct apbuart_regs * const regs,uint32_t baud)216 static void set_baud(volatile struct apbuart_regs *const regs, uint32_t baud)
217 {
218 unsigned int core_clk_hz;
219 unsigned int scaler;
220
221 if (baud == 0) {
222 return;
223 }
224
225 core_clk_hz = sys_clock_hw_cycles_per_sec();
226
227 /* Calculate Baud rate generator "scaler" number */
228 scaler = (core_clk_hz / (baud * 8)) - 1;
229
230 /* Set new baud rate by setting scaler */
231 regs->scaler = scaler;
232 }
233
apbuart_configure(const struct device * dev,const struct uart_config * cfg)234 static int apbuart_configure(const struct device *dev,
235 const struct uart_config *cfg)
236 {
237 const struct apbuart_dev_cfg *config = dev->config;
238 volatile struct apbuart_regs *regs = (void *) config->regs;
239 uint32_t ctrl = 0;
240 uint32_t newctrl = 0;
241
242 switch (cfg->parity) {
243 case UART_CFG_PARITY_NONE:
244 break;
245 case UART_CFG_PARITY_EVEN:
246 newctrl |= APBUART_CTRL_PE;
247 break;
248 case UART_CFG_PARITY_ODD:
249 newctrl |= APBUART_CTRL_PE | APBUART_CTRL_PS;
250 break;
251 default:
252 return -ENOTSUP;
253 }
254
255 if (cfg->stop_bits != UART_CFG_STOP_BITS_1) {
256 return -ENOTSUP;
257 }
258
259 if (cfg->data_bits != UART_CFG_DATA_BITS_8) {
260 return -ENOTSUP;
261 }
262
263 switch (cfg->flow_ctrl) {
264 case UART_CFG_FLOW_CTRL_NONE:
265 break;
266 case UART_CFG_FLOW_CTRL_RTS_CTS:
267 newctrl |= APBUART_CTRL_FL;
268 break;
269 default:
270 return -ENOTSUP;
271 }
272
273 set_baud(regs, cfg->baudrate);
274
275 ctrl = regs->ctrl;
276 ctrl &= ~(APBUART_CTRL_PE | APBUART_CTRL_PS | APBUART_CTRL_FL);
277 regs->ctrl = ctrl | newctrl;
278
279 return 0;
280 }
281
apbuart_config_get(const struct device * dev,struct uart_config * cfg)282 static int apbuart_config_get(const struct device *dev, struct uart_config *cfg)
283 {
284 const struct apbuart_dev_cfg *config = dev->config;
285 volatile struct apbuart_regs *regs = (void *) config->regs;
286 const uint32_t ctrl = regs->ctrl;
287
288 cfg->parity = UART_CFG_PARITY_NONE;
289 if (ctrl & APBUART_CTRL_PE) {
290 if (ctrl & APBUART_CTRL_PS) {
291 cfg->parity = UART_CFG_PARITY_ODD;
292 } else {
293 cfg->parity = UART_CFG_PARITY_EVEN;
294 }
295 }
296
297 cfg->flow_ctrl = UART_CFG_FLOW_CTRL_NONE;
298 if (ctrl & APBUART_CTRL_FL) {
299 cfg->flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS;
300 }
301
302 cfg->baudrate = get_baud(regs);
303
304 cfg->data_bits = UART_CFG_DATA_BITS_8;
305 cfg->stop_bits = UART_CFG_STOP_BITS_1;
306
307 return 0;
308 }
309 #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
310
311 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
312 static void apbuart_isr(const struct device *dev);
313
apbuart_fifo_fill(const struct device * dev,const uint8_t * tx_data,int size)314 static int apbuart_fifo_fill(const struct device *dev, const uint8_t *tx_data,
315 int size)
316 {
317 const struct apbuart_dev_cfg *config = dev->config;
318 struct apbuart_dev_data *data = dev->data;
319 volatile struct apbuart_regs *regs = (void *) config->regs;
320 int i;
321
322 if (data->usefifo) {
323 /* Transmitter FIFO full flag is available. */
324 for (
325 i = 0;
326 (i < size) && !(regs->status & APBUART_STATUS_TF);
327 i++
328 ) {
329 regs->data = tx_data[i];
330 }
331 return i;
332 }
333 for (i = 0; (i < size) && (regs->status & APBUART_STATUS_TE); i++) {
334 regs->data = tx_data[i];
335 }
336
337 return i;
338 }
339
apbuart_fifo_read(const struct device * dev,uint8_t * rx_data,const int size)340 static int apbuart_fifo_read(const struct device *dev, uint8_t *rx_data,
341 const int size)
342 {
343 const struct apbuart_dev_cfg *config = dev->config;
344 volatile struct apbuart_regs *regs = (void *) config->regs;
345 int i;
346
347 for (i = 0; (i < size) && (regs->status & APBUART_STATUS_DR); i++) {
348 rx_data[i] = regs->data & 0xff;
349 }
350
351 return i;
352 }
353
apbuart_irq_tx_enable(const struct device * dev)354 static void apbuart_irq_tx_enable(const struct device *dev)
355 {
356 const struct apbuart_dev_cfg *config = dev->config;
357 struct apbuart_dev_data *data = dev->data;
358 volatile struct apbuart_regs *regs = (void *) config->regs;
359 unsigned int key;
360
361 if (data->usefifo) {
362 /* Enable the FIFO level interrupt */
363 regs->ctrl |= APBUART_CTRL_TF;
364 return;
365 }
366
367 regs->ctrl |= APBUART_CTRL_TI;
368 /*
369 * The "TI" interrupt is an edge interrupt. It fires each time the TX
370 * holding register (or FIFO if implemented) moves from non-empty to
371 * empty.
372 *
373 * When the APBUART is implemented _without_ FIFO, the TI interrupt is
374 * the only TX interrupt we have. When the APBUART is implemented
375 * _with_ FIFO, the TI will fire on each TX byte.
376 */
377 regs->ctrl |= APBUART_CTRL_TI;
378 /* Fire the first "TI" edge interrupt to get things going. */
379 key = irq_lock();
380 apbuart_isr(dev);
381 irq_unlock(key);
382 }
383
apbuart_irq_tx_disable(const struct device * dev)384 static void apbuart_irq_tx_disable(const struct device *dev)
385 {
386 const struct apbuart_dev_cfg *config = dev->config;
387 volatile struct apbuart_regs *regs = (void *) config->regs;
388
389 regs->ctrl &= ~(APBUART_CTRL_TF | APBUART_CTRL_TI);
390 }
391
apbuart_irq_tx_ready(const struct device * dev)392 static int apbuart_irq_tx_ready(const struct device *dev)
393 {
394 const struct apbuart_dev_cfg *config = dev->config;
395 struct apbuart_dev_data *data = dev->data;
396 volatile struct apbuart_regs *regs = (void *) config->regs;
397
398 if (data->usefifo) {
399 return !(regs->status & APBUART_STATUS_TF);
400 }
401 return !!(regs->status & APBUART_STATUS_TE);
402 }
403
apbuart_irq_tx_complete(const struct device * dev)404 static int apbuart_irq_tx_complete(const struct device *dev)
405 {
406 const struct apbuart_dev_cfg *config = dev->config;
407 volatile struct apbuart_regs *regs = (void *) config->regs;
408
409 return !!(regs->status & APBUART_STATUS_TS);
410 }
411
apbuart_irq_rx_enable(const struct device * dev)412 static void apbuart_irq_rx_enable(const struct device *dev)
413 {
414 const struct apbuart_dev_cfg *config = dev->config;
415 volatile struct apbuart_regs *regs = (void *) config->regs;
416
417 regs->ctrl |= APBUART_CTRL_RI;
418 }
419
apbuart_irq_rx_disable(const struct device * dev)420 static void apbuart_irq_rx_disable(const struct device *dev)
421 {
422 const struct apbuart_dev_cfg *config = dev->config;
423 volatile struct apbuart_regs *regs = (void *) config->regs;
424
425 regs->ctrl &= ~APBUART_CTRL_RI;
426 }
427
apbuart_irq_rx_ready(const struct device * dev)428 static int apbuart_irq_rx_ready(const struct device *dev)
429 {
430 const struct apbuart_dev_cfg *config = dev->config;
431 volatile struct apbuart_regs *regs = (void *) config->regs;
432
433 return !!(regs->status & APBUART_STATUS_DR);
434 }
435
apbuart_irq_is_pending(const struct device * dev)436 static int apbuart_irq_is_pending(const struct device *dev)
437 {
438 const struct apbuart_dev_cfg *config = dev->config;
439 struct apbuart_dev_data *data = dev->data;
440 volatile struct apbuart_regs *regs = (void *) config->regs;
441 uint32_t status = regs->status;
442 uint32_t ctrl = regs->ctrl;
443
444 if ((ctrl & APBUART_CTRL_RI) && (status & APBUART_STATUS_DR)) {
445 return 1;
446 }
447
448 if (data->usefifo) {
449 /* TH is the TX FIFO half-empty flag */
450 if (status & APBUART_STATUS_TH) {
451 return 1;
452 }
453 } else {
454 if ((ctrl & APBUART_CTRL_TI) && (status & APBUART_STATUS_TE)) {
455 return 1;
456 }
457 }
458
459 return 0;
460 }
461
apbuart_irq_update(const struct device * dev)462 static int apbuart_irq_update(const struct device *dev)
463 {
464 return 1;
465 }
466
apbuart_irq_callback_set(const struct device * dev,uart_irq_callback_user_data_t cb,void * cb_data)467 static void apbuart_irq_callback_set(const struct device *dev,
468 uart_irq_callback_user_data_t cb,
469 void *cb_data)
470 {
471 struct apbuart_dev_data *const dev_data = dev->data;
472
473 dev_data->cb = cb;
474 dev_data->cb_data = cb_data;
475 }
476
apbuart_isr(const struct device * dev)477 static void apbuart_isr(const struct device *dev)
478 {
479 struct apbuart_dev_data *const dev_data = dev->data;
480
481 if (dev_data->cb) {
482 dev_data->cb(dev, dev_data->cb_data);
483 }
484 }
485 #endif /* CONFIG_UART_INTERRUPT_DRIVEN */
486
apbuart_init(const struct device * dev)487 static int apbuart_init(const struct device *dev)
488 {
489 const struct apbuart_dev_cfg *config = dev->config;
490 struct apbuart_dev_data *data = dev->data;
491 volatile struct apbuart_regs *regs = (void *) config->regs;
492 const uint32_t APBUART_DEBUG_MASK = APBUART_CTRL_DB | APBUART_CTRL_FL;
493 uint32_t dm;
494 uint32_t ctrl;
495
496 ctrl = regs->ctrl;
497 data->usefifo = !!(ctrl & APBUART_CTRL_FA);
498 /* NOTE: CTRL_FL has reset value 0. CTRL_DB has no reset value. */
499 dm = ctrl & APBUART_DEBUG_MASK;
500 if (dm == APBUART_DEBUG_MASK) {
501 /* Debug mode enabled so assume APBUART already initialized. */
502 ;
503 } else {
504 regs->ctrl = APBUART_CTRL_TE | APBUART_CTRL_RE;
505 }
506
507 regs->status = 0;
508
509 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
510 irq_connect_dynamic(config->interrupt,
511 0, (void (*)(const void *))apbuart_isr, dev, 0);
512 irq_enable(config->interrupt);
513 #endif
514
515 return 0;
516 }
517
518 /* Driver API defined in uart.h */
519 static DEVICE_API(uart, apbuart_driver_api) = {
520 .poll_in = apbuart_poll_in,
521 .poll_out = apbuart_poll_out,
522 .err_check = apbuart_err_check,
523 #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
524 .configure = apbuart_configure,
525 .config_get = apbuart_config_get,
526 #endif
527 #ifdef CONFIG_UART_INTERRUPT_DRIVEN
528 .fifo_fill = apbuart_fifo_fill,
529 .fifo_read = apbuart_fifo_read,
530 .irq_tx_enable = apbuart_irq_tx_enable,
531 .irq_tx_disable = apbuart_irq_tx_disable,
532 .irq_tx_ready = apbuart_irq_tx_ready,
533 .irq_rx_enable = apbuart_irq_rx_enable,
534 .irq_rx_disable = apbuart_irq_rx_disable,
535 .irq_tx_complete = apbuart_irq_tx_complete,
536 .irq_rx_ready = apbuart_irq_rx_ready,
537 .irq_is_pending = apbuart_irq_is_pending,
538 .irq_update = apbuart_irq_update,
539 .irq_callback_set = apbuart_irq_callback_set,
540 #endif
541 };
542
543 #define APBUART_INIT(index) \
544 static const struct apbuart_dev_cfg apbuart##index##_config = { \
545 .regs = (struct apbuart_regs *) \
546 DT_INST_REG_ADDR(index), \
547 IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \
548 (.interrupt = DT_INST_IRQN(index),)) \
549 }; \
550 \
551 static struct apbuart_dev_data apbuart##index##_data = { \
552 .usefifo = 0, \
553 }; \
554 \
555 DEVICE_DT_INST_DEFINE(index, \
556 &apbuart_init, \
557 NULL, \
558 &apbuart##index##_data, \
559 &apbuart##index##_config, \
560 PRE_KERNEL_1, \
561 CONFIG_SERIAL_INIT_PRIORITY, \
562 &apbuart_driver_api);
563
564 DT_INST_FOREACH_STATUS_OKAY(APBUART_INIT)
565