]> git.sur5r.net Git - u-boot/blob - arch/sparc/cpu/leon3/serial.c
sparc: leon3: Moved GRLIB core header files to common include/grlib directory
[u-boot] / arch / sparc / cpu / leon3 / serial.c
1 /* GRLIB APBUART Serial controller driver
2  *
3  * (C) Copyright 2007, 2015
4  * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <asm/io.h>
11 #include <ambapp.h>
12 #include <grlib/apbuart.h>
13 #include <serial.h>
14 #include <watchdog.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 /* Select which UART that will become u-boot console */
19 #ifndef CONFIG_SYS_GRLIB_APBUART_INDEX
20 #define CONFIG_SYS_GRLIB_APBUART_INDEX 0
21 #endif
22
23 static int leon3_serial_init(void)
24 {
25         ambapp_dev_apbuart *uart;
26         ambapp_apbdev apbdev;
27         unsigned int tmp;
28
29         /* find UART */
30         if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
31                 CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1)
32                 return -1; /* didn't find hardware */
33
34         /* found apbuart, let's init .. */
35         uart = (ambapp_dev_apbuart *) apbdev.address;
36
37         /* Set scaler / baud rate */
38         tmp = (((CONFIG_SYS_CLK_FREQ*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
39         writel(tmp, &uart->scaler);
40
41         /* Let bit 11 be unchanged (debug bit for GRMON) */
42         tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
43         /* Receiver & transmitter enable */
44         tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
45         writel(tmp, &uart->ctrl);
46
47         gd->arch.uart = uart;
48         return 0;
49 }
50
51 static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
52 {
53         ambapp_dev_apbuart *uart = gd->arch.uart;
54         return uart;
55 }
56
57 static void leon3_serial_putc_raw(const char c)
58 {
59         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
60
61         if (!uart)
62                 return;
63
64         /* Wait for last character to go. */
65         while (!(readl(&uart->status) & APBUART_STATUS_THE))
66                 WATCHDOG_RESET();
67
68         /* Send data */
69         writel(c, &uart->data);
70
71 #ifdef LEON_DEBUG
72         /* Wait for data to be sent */
73         while (!(readl(&uart->status) & APBUART_STATUS_TSE))
74                 WATCHDOG_RESET();
75 #endif
76 }
77
78 static void leon3_serial_putc(const char c)
79 {
80         if (c == '\n')
81                 leon3_serial_putc_raw('\r');
82
83         leon3_serial_putc_raw(c);
84 }
85
86 static int leon3_serial_getc(void)
87 {
88         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
89
90         if (!uart)
91                 return 0;
92
93         /* Wait for a character to arrive. */
94         while (!(readl(&uart->status) & APBUART_STATUS_DR))
95                 WATCHDOG_RESET();
96
97         /* Read character data */
98         return readl(&uart->data);
99 }
100
101 static int leon3_serial_tstc(void)
102 {
103         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
104
105         if (!uart)
106                 return 0;
107
108         return readl(&uart->status) & APBUART_STATUS_DR;
109 }
110
111 /* set baud rate for uart */
112 static void leon3_serial_setbrg(void)
113 {
114         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
115         unsigned int scaler;
116
117         if (!uart)
118                 return;
119
120         if (!gd->baudrate)
121                 gd->baudrate = CONFIG_BAUDRATE;
122
123         scaler = (((CONFIG_SYS_CLK_FREQ*10) / (gd->baudrate*8)) - 5)/10;
124
125         writel(scaler, &uart->scaler);
126 }
127
128 static struct serial_device leon3_serial_drv = {
129         .name   = "leon3_serial",
130         .start  = leon3_serial_init,
131         .stop   = NULL,
132         .setbrg = leon3_serial_setbrg,
133         .putc   = leon3_serial_putc,
134         .puts   = default_serial_puts,
135         .getc   = leon3_serial_getc,
136         .tstc   = leon3_serial_tstc,
137 };
138
139 void leon3_serial_initialize(void)
140 {
141         serial_register(&leon3_serial_drv);
142 }
143
144 __weak struct serial_device *default_serial_console(void)
145 {
146         return &leon3_serial_drv;
147 }