xref: /openbmc/u-boot/drivers/serial/atmel_usart.c (revision 3765b3e7)
1 /*
2  * Copyright (C) 2004-2006 Atmel Corporation
3  *
4  * Modified to support C structur SoC access by
5  * Andreas Bießmann <biessmann@corscience.de>
6  *
7  * SPDX-License-Identifier:	GPL-2.0+
8  */
9 #include <common.h>
10 #include <watchdog.h>
11 #include <serial.h>
12 #include <linux/compiler.h>
13 
14 #include <asm/io.h>
15 #include <asm/arch/clk.h>
16 #include <asm/arch/hardware.h>
17 
18 #include "atmel_usart.h"
19 
20 DECLARE_GLOBAL_DATA_PTR;
21 
22 static void atmel_serial_setbrg(void)
23 {
24 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
25 	unsigned long divisor;
26 	unsigned long usart_hz;
27 
28 	/*
29 	 *              Master Clock
30 	 * Baud Rate = --------------
31 	 *                16 * CD
32 	 */
33 	usart_hz = get_usart_clk_rate(CONFIG_USART_ID);
34 	divisor = (usart_hz / 16 + gd->baudrate / 2) / gd->baudrate;
35 	writel(USART3_BF(CD, divisor), &usart->brgr);
36 }
37 
38 static int atmel_serial_init(void)
39 {
40 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
41 
42 	/*
43 	 * Just in case: drain transmitter register
44 	 * 1000us is enough for baudrate >= 9600
45 	 */
46 	if (!(readl(&usart->csr) & USART3_BIT(TXEMPTY)))
47 		__udelay(1000);
48 
49 	writel(USART3_BIT(RSTRX) | USART3_BIT(RSTTX), &usart->cr);
50 
51 	serial_setbrg();
52 
53 	writel((USART3_BF(USART_MODE, USART3_USART_MODE_NORMAL)
54 			   | USART3_BF(USCLKS, USART3_USCLKS_MCK)
55 			   | USART3_BF(CHRL, USART3_CHRL_8)
56 			   | USART3_BF(PAR, USART3_PAR_NONE)
57 			   | USART3_BF(NBSTOP, USART3_NBSTOP_1)),
58 			   &usart->mr);
59 	writel(USART3_BIT(RXEN) | USART3_BIT(TXEN), &usart->cr);
60 	/* 100us is enough for the new settings to be settled */
61 	__udelay(100);
62 
63 	return 0;
64 }
65 
66 static void atmel_serial_putc(char c)
67 {
68 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
69 
70 	if (c == '\n')
71 		serial_putc('\r');
72 
73 	while (!(readl(&usart->csr) & USART3_BIT(TXRDY)));
74 	writel(c, &usart->thr);
75 }
76 
77 static int atmel_serial_getc(void)
78 {
79 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
80 
81 	while (!(readl(&usart->csr) & USART3_BIT(RXRDY)))
82 		 WATCHDOG_RESET();
83 	return readl(&usart->rhr);
84 }
85 
86 static int atmel_serial_tstc(void)
87 {
88 	atmel_usart3_t *usart = (atmel_usart3_t *)CONFIG_USART_BASE;
89 	return (readl(&usart->csr) & USART3_BIT(RXRDY)) != 0;
90 }
91 
92 static struct serial_device atmel_serial_drv = {
93 	.name	= "atmel_serial",
94 	.start	= atmel_serial_init,
95 	.stop	= NULL,
96 	.setbrg	= atmel_serial_setbrg,
97 	.putc	= atmel_serial_putc,
98 	.puts	= default_serial_puts,
99 	.getc	= atmel_serial_getc,
100 	.tstc	= atmel_serial_tstc,
101 };
102 
103 void atmel_serial_initialize(void)
104 {
105 	serial_register(&atmel_serial_drv);
106 }
107 
108 __weak struct serial_device *default_serial_console(void)
109 {
110 	return &atmel_serial_drv;
111 }
112