Blackfin: Remove
[oweals/u-boot.git] / 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 /* Try to use CONFIG_CONS_INDEX, if available, it is numbered from 1 */
21 #ifdef CONFIG_CONS_INDEX
22 #define CONFIG_SYS_GRLIB_APBUART_INDEX (CONFIG_CONS_INDEX - 1)
23 #else
24 #define CONFIG_SYS_GRLIB_APBUART_INDEX 0
25 #endif
26 #endif
27
28 static unsigned apbuart_calc_scaler(unsigned apbuart_freq, unsigned baud)
29 {
30         return (((apbuart_freq * 10) / (baud * 8)) - 5) / 10;
31 }
32
33 static int leon3_serial_init(void)
34 {
35         ambapp_dev_apbuart *uart;
36         ambapp_apbdev apbdev;
37         unsigned int tmp;
38
39         /* find UART */
40         if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
41                 CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1) {
42                 gd->flags &= ~GD_FLG_SERIAL_READY;
43                 panic("%s: apbuart not found!\n", __func__);
44                 return -1; /* didn't find hardware */
45         }
46
47         /* found apbuart, let's init .. */
48         uart = (ambapp_dev_apbuart *) apbdev.address;
49
50         /* APBUART Frequency is equal to bus frequency */
51         gd->arch.uart_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
52
53         /* Set scaler / baud rate */
54         tmp = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
55         writel(tmp, &uart->scaler);
56
57         /* Let bit 11 be unchanged (debug bit for GRMON) */
58         tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
59         /* Receiver & transmitter enable */
60         tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
61         writel(tmp, &uart->ctrl);
62
63         gd->arch.uart = uart;
64         return 0;
65 }
66
67 static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
68 {
69         ambapp_dev_apbuart *uart = gd->arch.uart;
70         return uart;
71 }
72
73 static void leon3_serial_putc_raw(const char c)
74 {
75         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
76
77         if (!uart)
78                 return;
79
80         /* Wait for last character to go. */
81         while (!(readl(&uart->status) & APBUART_STATUS_THE))
82                 WATCHDOG_RESET();
83
84         /* Send data */
85         writel(c, &uart->data);
86
87 #ifdef LEON_DEBUG
88         /* Wait for data to be sent */
89         while (!(readl(&uart->status) & APBUART_STATUS_TSE))
90                 WATCHDOG_RESET();
91 #endif
92 }
93
94 static void leon3_serial_putc(const char c)
95 {
96         if (c == '\n')
97                 leon3_serial_putc_raw('\r');
98
99         leon3_serial_putc_raw(c);
100 }
101
102 static int leon3_serial_getc(void)
103 {
104         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
105
106         if (!uart)
107                 return 0;
108
109         /* Wait for a character to arrive. */
110         while (!(readl(&uart->status) & APBUART_STATUS_DR))
111                 WATCHDOG_RESET();
112
113         /* Read character data */
114         return readl(&uart->data);
115 }
116
117 static int leon3_serial_tstc(void)
118 {
119         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
120
121         if (!uart)
122                 return 0;
123
124         return readl(&uart->status) & APBUART_STATUS_DR;
125 }
126
127 /* set baud rate for uart */
128 static void leon3_serial_setbrg(void)
129 {
130         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
131         unsigned int scaler;
132
133         if (!uart)
134                 return;
135
136         if (!gd->baudrate)
137                 gd->baudrate = CONFIG_BAUDRATE;
138
139         if (!gd->arch.uart_freq)
140                 gd->arch.uart_freq = CONFIG_SYS_CLK_FREQ;
141
142         scaler = apbuart_calc_scaler(gd->arch.uart_freq, gd->baudrate);
143
144         writel(scaler, &uart->scaler);
145 }
146
147 static struct serial_device leon3_serial_drv = {
148         .name   = "leon3_serial",
149         .start  = leon3_serial_init,
150         .stop   = NULL,
151         .setbrg = leon3_serial_setbrg,
152         .putc   = leon3_serial_putc,
153         .puts   = default_serial_puts,
154         .getc   = leon3_serial_getc,
155         .tstc   = leon3_serial_tstc,
156 };
157
158 void leon3_serial_initialize(void)
159 {
160         serial_register(&leon3_serial_drv);
161 }
162
163 __weak struct serial_device *default_serial_console(void)
164 {
165         return &leon3_serial_drv;
166 }
167
168 #ifdef CONFIG_DEBUG_UART_APBUART
169
170 #include <debug_uart.h>
171
172 static inline void _debug_uart_init(void)
173 {
174         ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
175         uart->scaler = apbuart_calc_scaler(CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
176         uart->ctrl = APBUART_CTRL_RE | APBUART_CTRL_TE;
177 }
178
179 static inline void _debug_uart_putc(int ch)
180 {
181         ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
182         while (!(readl(&uart->status) & APBUART_STATUS_THE))
183                 WATCHDOG_RESET();
184         writel(ch, &uart->data);
185 }
186
187 DEBUG_UART_FUNCS
188
189 #endif