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