]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/sparc/cpu/leon3/serial.c
sparc: leon3: Add debug_uart support to LEON3 serial driver.
[people/ms/u-boot.git] / arch / sparc / cpu / leon3 / serial.c
CommitLineData
1e9a164e
DH
1/* GRLIB APBUART Serial controller driver
2 *
a50adb7b
FR
3 * (C) Copyright 2007, 2015
4 * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
1e9a164e 5 *
1a459660 6 * SPDX-License-Identifier: GPL-2.0+
1e9a164e
DH
7 */
8
9#include <common.h>
a50adb7b 10#include <asm/io.h>
1e9a164e 11#include <ambapp.h>
f2879f59 12#include <grlib/apbuart.h>
29b5ff7f 13#include <serial.h>
a50adb7b 14#include <watchdog.h>
1e9a164e
DH
15
16DECLARE_GLOBAL_DATA_PTR;
17
898cc81d
DH
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
29b5ff7f 23static int leon3_serial_init(void)
1e9a164e 24{
a50adb7b 25 ambapp_dev_apbuart *uart;
1e9a164e
DH
26 ambapp_apbdev apbdev;
27 unsigned int tmp;
28
29 /* find UART */
898cc81d 30 if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
e43ce3fc
FR
31 CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1) {
32 panic("%s: apbuart not found!\n", __func__);
a50adb7b 33 return -1; /* didn't find hardware */
e43ce3fc 34 }
1e9a164e 35
a50adb7b
FR
36 /* found apbuart, let's init .. */
37 uart = (ambapp_dev_apbuart *) apbdev.address;
1e9a164e 38
a50adb7b
FR
39 /* Set scaler / baud rate */
40 tmp = (((CONFIG_SYS_CLK_FREQ*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
41 writel(tmp, &uart->scaler);
1e9a164e 42
a50adb7b 43 /* Let bit 11 be unchanged (debug bit for GRMON) */
f2879f59 44 tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
a50adb7b 45 /* Receiver & transmitter enable */
f2879f59 46 tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
a50adb7b 47 writel(tmp, &uart->ctrl);
1e9a164e 48
a50adb7b
FR
49 gd->arch.uart = uart;
50 return 0;
51}
1e9a164e 52
a50adb7b
FR
53static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
54{
55 ambapp_dev_apbuart *uart = gd->arch.uart;
56 return uart;
1e9a164e
DH
57}
58
29b5ff7f 59static void leon3_serial_putc_raw(const char c)
1e9a164e 60{
a50adb7b
FR
61 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
62
63 if (!uart)
1e9a164e
DH
64 return;
65
66 /* Wait for last character to go. */
f2879f59 67 while (!(readl(&uart->status) & APBUART_STATUS_THE))
a50adb7b 68 WATCHDOG_RESET();
1e9a164e
DH
69
70 /* Send data */
a50adb7b 71 writel(c, &uart->data);
1e9a164e
DH
72
73#ifdef LEON_DEBUG
74 /* Wait for data to be sent */
f2879f59 75 while (!(readl(&uart->status) & APBUART_STATUS_TSE))
a50adb7b 76 WATCHDOG_RESET();
1e9a164e
DH
77#endif
78}
79
29b5ff7f
MV
80static 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
29b5ff7f 88static int leon3_serial_getc(void)
1e9a164e 89{
a50adb7b
FR
90 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
91
92 if (!uart)
1e9a164e
DH
93 return 0;
94
95 /* Wait for a character to arrive. */
f2879f59 96 while (!(readl(&uart->status) & APBUART_STATUS_DR))
a50adb7b 97 WATCHDOG_RESET();
1e9a164e 98
a50adb7b
FR
99 /* Read character data */
100 return readl(&uart->data);
1e9a164e
DH
101}
102
29b5ff7f 103static int leon3_serial_tstc(void)
1e9a164e 104{
a50adb7b
FR
105 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
106
107 if (!uart)
108 return 0;
109
f2879f59 110 return readl(&uart->status) & APBUART_STATUS_DR;
1e9a164e
DH
111}
112
113/* set baud rate for uart */
29b5ff7f 114static void leon3_serial_setbrg(void)
1e9a164e 115{
a50adb7b 116 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
1e9a164e 117 unsigned int scaler;
a50adb7b
FR
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);
1e9a164e 128}
29b5ff7f 129
29b5ff7f
MV
130static 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,
ec3fd689 136 .puts = default_serial_puts,
29b5ff7f
MV
137 .getc = leon3_serial_getc,
138 .tstc = leon3_serial_tstc,
139};
140
141void 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}
e43ce3fc
FR
150
151#ifdef CONFIG_DEBUG_UART_APBUART
152
153#include <debug_uart.h>
154
155static 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
162static 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
170DEBUG_UART_FUNCS
171
172#endif