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