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 #define CONFIG_SYS_GRLIB_APBUART_INDEX 0
23 static unsigned apbuart_calc_scaler(unsigned apbuart_freq, unsigned baud)
25 return (((apbuart_freq * 10) / (baud * 8)) - 5) / 10;
28 static int leon3_serial_init(void)
30 ambapp_dev_apbuart *uart;
35 if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
36 CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1) {
37 gd->flags &= ~GD_FLG_SERIAL_READY;
38 panic("%s: apbuart not found!\n", __func__);
39 return -1; /* didn't find hardware */
42 /* found apbuart, let's init .. */
43 uart = (ambapp_dev_apbuart *) apbdev.address;
45 /* APBUART Frequency is equal to bus frequency */
46 gd->arch.uart_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
48 /* Set scaler / baud rate */
49 tmp = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
50 writel(tmp, &uart->scaler);
52 /* Let bit 11 be unchanged (debug bit for GRMON) */
53 tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
54 /* Receiver & transmitter enable */
55 tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
56 writel(tmp, &uart->ctrl);
62 static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
64 ambapp_dev_apbuart *uart = gd->arch.uart;
68 static void leon3_serial_putc_raw(const char c)
70 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
75 /* Wait for last character to go. */
76 while (!(readl(&uart->status) & APBUART_STATUS_THE))
80 writel(c, &uart->data);
83 /* Wait for data to be sent */
84 while (!(readl(&uart->status) & APBUART_STATUS_TSE))
89 static void leon3_serial_putc(const char c)
92 leon3_serial_putc_raw('\r');
94 leon3_serial_putc_raw(c);
97 static int leon3_serial_getc(void)
99 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
104 /* Wait for a character to arrive. */
105 while (!(readl(&uart->status) & APBUART_STATUS_DR))
108 /* Read character data */
109 return readl(&uart->data);
112 static int leon3_serial_tstc(void)
114 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
119 return readl(&uart->status) & APBUART_STATUS_DR;
122 /* set baud rate for uart */
123 static void leon3_serial_setbrg(void)
125 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
132 gd->baudrate = CONFIG_BAUDRATE;
134 if (!gd->arch.uart_freq)
135 gd->arch.uart_freq = CONFIG_SYS_CLK_FREQ;
137 scaler = apbuart_calc_scaler(gd->arch.uart_freq, gd->baudrate);
139 writel(scaler, &uart->scaler);
142 static struct serial_device leon3_serial_drv = {
143 .name = "leon3_serial",
144 .start = leon3_serial_init,
146 .setbrg = leon3_serial_setbrg,
147 .putc = leon3_serial_putc,
148 .puts = default_serial_puts,
149 .getc = leon3_serial_getc,
150 .tstc = leon3_serial_tstc,
153 void leon3_serial_initialize(void)
155 serial_register(&leon3_serial_drv);
158 __weak struct serial_device *default_serial_console(void)
160 return &leon3_serial_drv;
163 #ifdef CONFIG_DEBUG_UART_APBUART
165 #include <debug_uart.h>
167 static inline void _debug_uart_init(void)
169 ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
170 uart->scaler = apbuart_calc_scaler(CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
171 uart->ctrl = APBUART_CTRL_RE | APBUART_CTRL_TE;
174 static inline void _debug_uart_putc(int ch)
176 ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
177 while (!(readl(&uart->status) & APBUART_STATUS_THE))
179 writel(ch, &uart->data);