1
2
3
4
5
6
7
8
9#include <common.h>
10#include <asm/io.h>
11#include <ambapp.h>
12#include <grlib/apbuart.h>
13#include <serial.h>
14#include <watchdog.h>
15
16DECLARE_GLOBAL_DATA_PTR;
17
18
19#ifndef CONFIG_SYS_GRLIB_APBUART_INDEX
20
21#ifdef CONFIG_CONS_INDEX
22#define CONFIG_SYS_GRLIB_APBUART_INDEX (CONFIG_CONS_INDEX - 1)
23#else
24#define CONFIG_SYS_GRLIB_APBUART_INDEX 0
25#endif
26#endif
27
28static unsigned apbuart_calc_scaler(unsigned apbuart_freq, unsigned baud)
29{
30 return (((apbuart_freq * 10) / (baud * 8)) - 5) / 10;
31}
32
33static int leon3_serial_init(void)
34{
35 ambapp_dev_apbuart *uart;
36 ambapp_apbdev apbdev;
37 unsigned int tmp;
38
39
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;
45 }
46
47
48 uart = (ambapp_dev_apbuart *) apbdev.address;
49
50
51 gd->arch.uart_freq = ambapp_bus_freq(&ambapp_plb, apbdev.ahb_bus_index);
52
53
54 tmp = apbuart_calc_scaler(gd->arch.uart_freq, CONFIG_BAUDRATE);
55 writel(tmp, &uart->scaler);
56
57
58 tmp = readl(&uart->ctrl) & APBUART_CTRL_DBG;
59
60 tmp |= APBUART_CTRL_RE | APBUART_CTRL_TE;
61 writel(tmp, &uart->ctrl);
62
63 gd->arch.uart = uart;
64 return 0;
65}
66
67static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
68{
69 ambapp_dev_apbuart *uart = gd->arch.uart;
70 return uart;
71}
72
73static void leon3_serial_putc_raw(const char c)
74{
75 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
76
77 if (!uart)
78 return;
79
80
81 while (!(readl(&uart->status) & APBUART_STATUS_THE))
82 WATCHDOG_RESET();
83
84
85 writel(c, &uart->data);
86
87#ifdef LEON_DEBUG
88
89 while (!(readl(&uart->status) & APBUART_STATUS_TSE))
90 WATCHDOG_RESET();
91#endif
92}
93
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
102static int leon3_serial_getc(void)
103{
104 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
105
106 if (!uart)
107 return 0;
108
109
110 while (!(readl(&uart->status) & APBUART_STATUS_DR))
111 WATCHDOG_RESET();
112
113
114 return readl(&uart->data);
115}
116
117static int leon3_serial_tstc(void)
118{
119 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
120
121 if (!uart)
122 return 0;
123
124 return readl(&uart->status) & APBUART_STATUS_DR;
125}
126
127
128static void leon3_serial_setbrg(void)
129{
130 ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
131 unsigned int scaler;
132
133 if (!uart)
134 return;
135
136 if (!gd->baudrate)
137 gd->baudrate = CONFIG_BAUDRATE;
138
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);
143
144 writel(scaler, &uart->scaler);
145}
146
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,
153 .puts = default_serial_puts,
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}
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;
175 uart->scaler = apbuart_calc_scaler(CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE);
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
190