]> git.ipfire.org Git - people/ms/u-boot.git/blame - arch/sparc/cpu/leon3/serial.c
Blackfin: Remove
[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
c2b37a0d
FR
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
898cc81d
DH
24#define CONFIG_SYS_GRLIB_APBUART_INDEX 0
25#endif
c2b37a0d 26#endif
898cc81d 27
ff0b9b77
DH
28static unsigned apbuart_calc_scaler(unsigned apbuart_freq, unsigned baud)
29{
30 return (((apbuart_freq * 10) / (baud * 8)) - 5) / 10;
31}
32
29b5ff7f 33static int leon3_serial_init(void)
1e9a164e 34{
a50adb7b 35 ambapp_dev_apbuart *uart;
1e9a164e
DH
36 ambapp_apbdev apbdev;
37 unsigned int tmp;
38
39 /* find UART */
898cc81d 40 if (ambapp_apb_find(&ambapp_plb, VENDOR_GAISLER, GAISLER_APBUART,
e43ce3fc 41 CONFIG_SYS_GRLIB_APBUART_INDEX, &apbdev) != 1) {
58e55856 42 gd->flags &= ~GD_FLG_SERIAL_READY;
e43ce3fc 43 panic("%s: apbuart not found!\n", __func__);
a50adb7b 44 return -1; /* didn't find hardware */
e43ce3fc 45 }
1e9a164e 46
a50adb7b
FR
47 /* found apbuart, let's init .. */
48 uart = (ambapp_dev_apbuart *) apbdev.address;
1e9a164e 49
ff0b9b77
DH
50 /* APBUART Frequency is equal to bus frequency */
51 gd->arch.uart_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
52
a50adb7b 53 /* Set scaler / baud rate */
ff0b9b77 54 tmp = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
a50adb7b 55 writel(tmp, &uart->scaler);
1e9a164e 56
a50adb7b 57 /* Let bit 11 be unchanged (debug bit for GRMON) */
f2879f59 58 tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
a50adb7b 59 /* Receiver & transmitter enable */
f2879f59 60 tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
a50adb7b 61 writel(tmp, &uart->ctrl);
1e9a164e 62
a50adb7b
FR
63 gd->arch.uart = uart;
64 return 0;
65}
1e9a164e 66
a50adb7b
FR
67static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
68{
69 ambapp_dev_apbuart *uart = gd->arch.uart;
70 return uart;
1e9a164e
DH
71}
72
29b5ff7f 73static void leon3_serial_putc_raw(const char c)
1e9a164e 74{
a50adb7b
FR
75 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
76
77 if (!uart)
1e9a164e
DH
78 return;
79
80 /* Wait for last character to go. */
f2879f59 81 while (!(readl(&uart->status) & APBUART_STATUS_THE))
a50adb7b 82 WATCHDOG_RESET();
1e9a164e
DH
83
84 /* Send data */
a50adb7b 85 writel(c, &uart->data);
1e9a164e
DH
86
87#ifdef LEON_DEBUG
88 /* Wait for data to be sent */
f2879f59 89 while (!(readl(&uart->status) & APBUART_STATUS_TSE))
a50adb7b 90 WATCHDOG_RESET();
1e9a164e
DH
91#endif
92}
93
29b5ff7f
MV
94static 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
29b5ff7f 102static int leon3_serial_getc(void)
1e9a164e 103{
a50adb7b
FR
104 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
105
106 if (!uart)
1e9a164e
DH
107 return 0;
108
109 /* Wait for a character to arrive. */
f2879f59 110 while (!(readl(&uart->status) & APBUART_STATUS_DR))
a50adb7b 111 WATCHDOG_RESET();
1e9a164e 112
a50adb7b
FR
113 /* Read character data */
114 return readl(&uart->data);
1e9a164e
DH
115}
116
29b5ff7f 117static int leon3_serial_tstc(void)
1e9a164e 118{
a50adb7b
FR
119 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
120
121 if (!uart)
122 return 0;
123
f2879f59 124 return readl(&uart->status) & APBUART_STATUS_DR;
1e9a164e
DH
125}
126
127/* set baud rate for uart */
29b5ff7f 128static void leon3_serial_setbrg(void)
1e9a164e 129{
a50adb7b 130 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
1e9a164e 131 unsigned int scaler;
a50adb7b
FR
132
133 if (!uart)
134 return;
135
136 if (!gd->baudrate)
137 gd->baudrate = CONFIG_BAUDRATE;
138
ff0b9b77
DH
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);
a50adb7b
FR
143
144 writel(scaler, &uart->scaler);
1e9a164e 145}
29b5ff7f 146
29b5ff7f
MV
147static 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,
ec3fd689 153 .puts = default_serial_puts,
29b5ff7f
MV
154 .getc = leon3_serial_getc,
155 .tstc = leon3_serial_tstc,
156};
157
158void 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}
e43ce3fc
FR
167
168#ifdef CONFIG_DEBUG_UART_APBUART
169
170#include <debug_uart.h>
171
172static inline void _debug_uart_init(void)
173{
174 ambapp_dev_apbuart *uart = (ambapp_dev_apbuart *)CONFIG_DEBUG_UART_BASE;
ff0b9b77 175 uart->scaler = apbuart_calc_scaler(CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
e43ce3fc
FR
176 uart->ctrl = APBUART_CTRL_RE | APBUART_CTRL_TE;
177}
178
179static 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
187DEBUG_UART_FUNCS
188
189#endif