1
2
3
4
5
6
7
8
9#include <common.h>
10#include <asm/io.h>
11#include <serial.h>
12#include <watchdog.h>
13
14DECLARE_GLOBAL_DATA_PTR;
15
16static unsigned leon2_serial_calc_scaler(unsigned freq, unsigned baud)
17{
18 return (((freq*10) / (baud*8)) - 5) / 10;
19}
20
21static int leon2_serial_init(void)
22{
23 LEON2_regs *leon2 = (LEON2_regs *)LEON2_PREGS;
24 LEON2_Uart_regs *regs;
25 unsigned int tmp;
26
27#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
28 regs = (LEON2_Uart_regs *)&leon2->UART_Channel_1;
29#else
30 regs = (LEON2_Uart_regs *)&leon2->UART_Channel_2;
31#endif
32
33
34 tmp = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, CONFIG_BAUDRATE);
35 writel(tmp, ®s->UART_Scaler);
36
37
38 tmp = readl(®s->UART_Control) & LEON2_UART_CTRL_DBG;
39 tmp |= (LEON2_UART1_LOOPBACK_ENABLE << 7);
40 tmp |= (LEON2_UART1_FLOWCTRL_ENABLE << 6);
41 tmp |= (LEON2_UART1_PARITY_ENABLE << 5);
42 tmp |= (LEON2_UART1_ODDPAR_ENABLE << 4);
43
44 tmp |= (LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE);
45 writel(tmp, ®s->UART_Control);
46
47 gd->arch.uart = regs;
48 return 0;
49}
50
51static inline LEON2_Uart_regs *leon2_get_uart_regs(void)
52{
53 LEON2_Uart_regs *uart = gd->arch.uart;
54
55 return uart;
56}
57
58static void leon2_serial_putc_raw(const char c)
59{
60 LEON2_Uart_regs *uart = leon2_get_uart_regs();
61
62 if (!uart)
63 return;
64
65
66 while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_THE))
67 WATCHDOG_RESET();
68
69
70 writel(c, &uart->UART_Channel);
71
72#ifdef LEON_DEBUG
73
74 while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_TSE))
75 WATCHDOG_RESET();
76#endif
77}
78
79static void leon2_serial_putc(const char c)
80{
81 if (c == '\n')
82 leon2_serial_putc_raw('\r');
83
84 leon2_serial_putc_raw(c);
85}
86
87static int leon2_serial_getc(void)
88{
89 LEON2_Uart_regs *uart = leon2_get_uart_regs();
90
91 if (!uart)
92 return 0;
93
94
95 while (!(readl(&uart->UART_Status) & LEON2_UART_STAT_DR))
96 WATCHDOG_RESET();
97
98
99 return readl(&uart->UART_Channel);
100}
101
102static int leon2_serial_tstc(void)
103{
104 LEON2_Uart_regs *uart = leon2_get_uart_regs();
105
106 if (!uart)
107 return 0;
108
109 return readl(&uart->UART_Status) & LEON2_UART_STAT_DR;
110}
111
112static void leon2_serial_setbrg(void)
113{
114 LEON2_Uart_regs *uart = leon2_get_uart_regs();
115 unsigned int scaler;
116
117 if (!uart)
118 return;
119
120 if (!gd->baudrate)
121 gd->baudrate = CONFIG_BAUDRATE;
122
123 scaler = leon2_serial_calc_scaler(CONFIG_SYS_CLK_FREQ, gd->baudrate);
124
125 writel(scaler, &uart->UART_Scaler);
126}
127
128static struct serial_device leon2_serial_drv = {
129 .name = "leon2_serial",
130 .start = leon2_serial_init,
131 .stop = NULL,
132 .setbrg = leon2_serial_setbrg,
133 .putc = leon2_serial_putc,
134 .puts = default_serial_puts,
135 .getc = leon2_serial_getc,
136 .tstc = leon2_serial_tstc,
137};
138
139void leon2_serial_initialize(void)
140{
141 serial_register(&leon2_serial_drv);
142}
143
144__weak struct serial_device *default_serial_console(void)
145{
146 return &leon2_serial_drv;
147}
148