1 /* GRLIB APBUART Serial controller driver
3 * (C) Copyright 2007, 2015
4 * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
6 * SPDX-License-Identifier: GPL-2.0+
12 #include <grlib/apbuart.h>
16 DECLARE_GLOBAL_DATA_PTR;
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)
24 #define CONFIG_SYS_GRLIB_APBUART_INDEX 0
28 static unsigned apbuart_calc_scaler(unsigned apbuart_freq, unsigned baud)
30 return (((apbuart_freq * 10) / (baud * 8)) - 5) / 10;
33 static int leon3_serial_init(void)
35 ambapp_dev_apbuart *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 */
47 /* found apbuart, let's init .. */
48 uart = (ambapp_dev_apbuart *) apbdev.address;
50 /* APBUART Frequency is equal to bus frequency */
51 gd->arch.uart_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
53 /* Set scaler / baud rate */
54 tmp = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
55 writel(tmp, &uart->scaler);
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);
67 static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
69 ambapp_dev_apbuart *uart = gd->arch.uart;
73 static void leon3_serial_putc_raw(const char c)
75 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
80 /* Wait for last character to go. */
81 while (!(readl(&uart->status) & APBUART_STATUS_THE))
85 writel(c, &uart->data);
88 /* Wait for data to be sent */
89 while (!(readl(&uart->status) & APBUART_STATUS_TSE))
94 static void leon3_serial_putc(const char c)
97 leon3_serial_putc_raw('\r');
99 leon3_serial_putc_raw(c);
102 static int leon3_serial_getc(void)
104 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
109 /* Wait for a character to arrive. */
110 while (!(readl(&uart->status) & APBUART_STATUS_DR))
113 /* Read character data */
114 return readl(&uart->data);
117 static int leon3_serial_tstc(void)
119 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
124 return readl(&uart->status) & APBUART_STATUS_DR;
127 /* set baud rate for uart */
128 static void leon3_serial_setbrg(void)
130 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
137 gd->baudrate = CONFIG_BAUDRATE;
139 if (!gd->arch.uart_freq)
140 gd->arch.uart_freq = CONFIG_SYS_CLK_FREQ;
142 scaler = apbuart_calc_scaler(gd->arch.uart_freq, gd->baudrate);
144 writel(scaler, &uart->scaler);
147 static struct serial_device leon3_serial_drv = {
148 .name = "leon3_serial",
149 .start = leon3_serial_init,
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,
158 void leon3_serial_initialize(void)
160 serial_register(&leon3_serial_drv);
163 __weak struct serial_device *default_serial_console(void)
165 return &leon3_serial_drv;
168 #ifdef CONFIG_DEBUG_UART_APBUART
170 #include <debug_uart.h>
172 static inline void _debug_uart_init(void)
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;
179 static inline void _debug_uart_putc(int ch)
181 ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
182 while (!(readl(&uart->status) & APBUART_STATUS_THE))
184 writel(ch, &uart->data);