]> git.sur5r.net Git - u-boot/blob - arch/sparc/cpu/leon3/serial.c
sparc: leon3: Add debug_uart support to LEON3 serial driver.
[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                 panic("%s: apbuart not found!\n", __func__);
33                 return -1; /* didn't find hardware */
34         }
35
36         /* found apbuart, let's init .. */
37         uart = (ambapp_dev_apbuart *) apbdev.address;
38
39         /* Set scaler / baud rate */
40         tmp = (((CONFIG_SYS_CLK_FREQ*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
41         writel(tmp, &uart->scaler);
42
43         /* Let bit 11 be unchanged (debug bit for GRMON) */
44         tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
45         /* Receiver & transmitter enable */
46         tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
47         writel(tmp, &uart->ctrl);
48
49         gd->arch.uart = uart;
50         return 0;
51 }
52
53 static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
54 {
55         ambapp_dev_apbuart *uart = gd->arch.uart;
56         return uart;
57 }
58
59 static void leon3_serial_putc_raw(const char c)
60 {
61         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
62
63         if (!uart)
64                 return;
65
66         /* Wait for last character to go. */
67         while (!(readl(&uart->status) & APBUART_STATUS_THE))
68                 WATCHDOG_RESET();
69
70         /* Send data */
71         writel(c, &uart->data);
72
73 #ifdef LEON_DEBUG
74         /* Wait for data to be sent */
75         while (!(readl(&uart->status) & APBUART_STATUS_TSE))
76                 WATCHDOG_RESET();
77 #endif
78 }
79
80 static void leon3_serial_putc(const char c)
81 {
82         if (c == '\n')
83                 leon3_serial_putc_raw('\r');
84
85         leon3_serial_putc_raw(c);
86 }
87
88 static int leon3_serial_getc(void)
89 {
90         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
91
92         if (!uart)
93                 return 0;
94
95         /* Wait for a character to arrive. */
96         while (!(readl(&uart->status) & APBUART_STATUS_DR))
97                 WATCHDOG_RESET();
98
99         /* Read character data */
100         return readl(&uart->data);
101 }
102
103 static int leon3_serial_tstc(void)
104 {
105         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
106
107         if (!uart)
108                 return 0;
109
110         return readl(&uart->status) & APBUART_STATUS_DR;
111 }
112
113 /* set baud rate for uart */
114 static void leon3_serial_setbrg(void)
115 {
116         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
117         unsigned int scaler;
118
119         if (!uart)
120                 return;
121
122         if (!gd->baudrate)
123                 gd->baudrate = CONFIG_BAUDRATE;
124
125         scaler = (((CONFIG_SYS_CLK_FREQ*10) / (gd->baudrate*8)) - 5)/10;
126
127         writel(scaler, &uart->scaler);
128 }
129
130 static struct serial_device leon3_serial_drv = {
131         .name   = "leon3_serial",
132         .start  = leon3_serial_init,
133         .stop   = NULL,
134         .setbrg = leon3_serial_setbrg,
135         .putc   = leon3_serial_putc,
136         .puts   = default_serial_puts,
137         .getc   = leon3_serial_getc,
138         .tstc   = leon3_serial_tstc,
139 };
140
141 void leon3_serial_initialize(void)
142 {
143         serial_register(&leon3_serial_drv);
144 }
145
146 __weak struct serial_device *default_serial_console(void)
147 {
148         return &leon3_serial_drv;
149 }
150
151 #ifdef CONFIG_DEBUG_UART_APBUART
152
153 #include <debug_uart.h>
154
155 static inline void _debug_uart_init(void)
156 {
157         ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
158         uart->scaler = (((CONFIG_DEBUG_UART_CLOCK*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
159         uart->ctrl = APBUART_CTRL_RE | APBUART_CTRL_TE;
160 }
161
162 static inline void _debug_uart_putc(int ch)
163 {
164         ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
165         while (!(readl(&uart->status) & APBUART_STATUS_THE))
166                 WATCHDOG_RESET();
167         writel(ch, &uart->data);
168 }
169
170 DEBUG_UART_FUNCS
171
172 #endif