blob: 5cfbb9ed15951ef7d6189ce20f401fdfac7d555f [file] [log] [blame]
Daniel Hellstrom207e6952008-03-28 10:00:33 +01001/* GRLIB APBUART Serial controller driver
2 *
3 * (C) Copyright 2008
4 * Daniel Hellstrom, Gaisler Research, daniel@gaisler.com.
5 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
Daniel Hellstrom207e6952008-03-28 10:00:33 +01007 */
8
9#include <common.h>
10#include <asm/processor.h>
11#include <asm/leon.h>
Marek Vasut8330d1e2012-09-13 12:25:07 +020012#include <serial.h>
13#include <linux/compiler.h>
Daniel Hellstrom207e6952008-03-28 10:00:33 +010014
15DECLARE_GLOBAL_DATA_PTR;
16
Marek Vasut8330d1e2012-09-13 12:25:07 +020017static int leon2_serial_init(void)
Daniel Hellstrom207e6952008-03-28 10:00:33 +010018{
19 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
20 LEON2_Uart_regs *regs;
21 unsigned int tmp;
22
23 /* Init LEON2 UART
24 *
25 * Set scaler / baud rate
26 *
27 * Receiver & transmitter enable
28 */
29#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
30 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
31#else
32 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
33#endif
34
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020035 regs->UART_Scaler = CONFIG_SYS_LEON2_UART1_SCALER;
Daniel Hellstrom207e6952008-03-28 10:00:33 +010036
37 /* Let bit 11 be unchanged (debug bit for GRMON) */
38 tmp = READ_WORD(regs->UART_Control);
39
40 regs->UART_Control = ((tmp & LEON2_UART_CTRL_DBG) |
41 (LEON2_UART1_LOOPBACK_ENABLE << 7) |
42 (LEON2_UART1_FLOWCTRL_ENABLE << 6) |
43 (LEON2_UART1_PARITY_ENABLE << 5) |
44 (LEON2_UART1_ODDPAR_ENABLE << 4) |
45 LEON2_UART_CTRL_RE | LEON2_UART_CTRL_TE);
46
47 return 0;
48}
49
Marek Vasut8330d1e2012-09-13 12:25:07 +020050static void leon2_serial_putc_raw(const char c)
Daniel Hellstrom207e6952008-03-28 10:00:33 +010051{
52 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
53 LEON2_Uart_regs *regs;
54
55#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
56 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
57#else
58 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
59#endif
60
61 /* Wait for last character to go. */
62 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_THE)) ;
63
64 /* Send data */
65 regs->UART_Channel = c;
66
67#ifdef LEON_DEBUG
68 /* Wait for data to be sent */
69 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_TSE)) ;
70#endif
71}
72
Marek Vasut8330d1e2012-09-13 12:25:07 +020073static void leon2_serial_putc(const char c)
74{
75 if (c == '\n')
76 leon2_serial_putc_raw('\r');
77
78 leon2_serial_putc_raw(c);
79}
80
Marek Vasut8330d1e2012-09-13 12:25:07 +020081static int leon2_serial_getc(void)
Daniel Hellstrom207e6952008-03-28 10:00:33 +010082{
83 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
84 LEON2_Uart_regs *regs;
85
86#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
87 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
88#else
89 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
90#endif
91
92 /* Wait for a character to arrive. */
93 while (!(READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR)) ;
94
95 /* read data */
96 return READ_WORD(regs->UART_Channel);
97}
98
Marek Vasut8330d1e2012-09-13 12:25:07 +020099static int leon2_serial_tstc(void)
Daniel Hellstrom207e6952008-03-28 10:00:33 +0100100{
101 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
102 LEON2_Uart_regs *regs;
103
104#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
105 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
106#else
107 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
108#endif
109
110 return (READ_WORD(regs->UART_Status) & LEON2_UART_STAT_DR);
111}
112
113/* set baud rate for uart */
Marek Vasut8330d1e2012-09-13 12:25:07 +0200114static void leon2_serial_setbrg(void)
Daniel Hellstrom207e6952008-03-28 10:00:33 +0100115{
116 /* update baud rate settings, read it from gd->baudrate */
117 unsigned int scaler;
118 LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;
119 LEON2_Uart_regs *regs;
120
121#if LEON2_CONSOLE_SELECT == LEON_CONSOLE_UART1
122 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_1;
123#else
124 regs = (LEON2_Uart_regs *) & leon2->UART_Channel_2;
125#endif
126
127 if (gd->baudrate > 0) {
128 scaler =
129 (((CONFIG_SYS_CLK_FREQ * 10) / (gd->baudrate * 8)) -
130 5) / 10;
131 regs->UART_Scaler = scaler;
132 }
133}
Marek Vasut8330d1e2012-09-13 12:25:07 +0200134
Marek Vasut8330d1e2012-09-13 12:25:07 +0200135static struct serial_device leon2_serial_drv = {
136 .name = "leon2_serial",
137 .start = leon2_serial_init,
138 .stop = NULL,
139 .setbrg = leon2_serial_setbrg,
140 .putc = leon2_serial_putc,
Marek Vasutd9c64492012-10-06 14:07:02 +0000141 .puts = default_serial_puts,
Marek Vasut8330d1e2012-09-13 12:25:07 +0200142 .getc = leon2_serial_getc,
143 .tstc = leon2_serial_tstc,
144};
145
146void leon2_serial_initialize(void)
147{
148 serial_register(&leon2_serial_drv);
149}
150
151__weak struct serial_device *default_serial_console(void)
152{
153 return &leon2_serial_drv;
154}