]> git.sur5r.net Git - u-boot/blob - arch/sparc/cpu/leon3/serial.c
sparc: Update startup code to take PIC mode into account
[u-boot] / arch / sparc / cpu / leon3 / serial.c
1 /* GRLIB APBUART Serial controller driver
2  *
3  * (C) Copyright 2007, 2015
4  * Daniel Hellstrom, Cobham Gaisler, daniel@gaisler.com.
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <asm/io.h>
11 #include <ambapp.h>
12 #include <serial.h>
13 #include <watchdog.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 static int leon3_serial_init(void)
18 {
19         ambapp_dev_apbuart *uart;
20         ambapp_apbdev apbdev;
21         unsigned int tmp;
22
23         /* find UART */
24         if (ambapp_apb_first(VENDOR_GAISLER, GAISLER_APBUART, &apbdev) != 1)
25                 return -1; /* didn't find hardware */
26
27         /* found apbuart, let's init .. */
28         uart = (ambapp_dev_apbuart *) apbdev.address;
29
30         /* Set scaler / baud rate */
31         tmp = (((CONFIG_SYS_CLK_FREQ*10) / (CONFIG_BAUDRATE*8)) - 5)/10;
32         writel(tmp, &uart->scaler);
33
34         /* Let bit 11 be unchanged (debug bit for GRMON) */
35         tmp = readl(&uart->ctrl) & LEON_REG_UART_CTRL_DBG;
36         /* Receiver & transmitter enable */
37         tmp |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
38         writel(tmp, &uart->ctrl);
39
40         gd->arch.uart = uart;
41         return 0;
42 }
43
44 static inline ambapp_dev_apbuart *leon3_get_uart_regs(void)
45 {
46         ambapp_dev_apbuart *uart = gd->arch.uart;
47         return uart;
48 }
49
50 static void leon3_serial_putc_raw(const char c)
51 {
52         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
53
54         if (!uart)
55                 return;
56
57         /* Wait for last character to go. */
58         while (!(readl(&uart->status) & LEON_REG_UART_STATUS_THE))
59                 WATCHDOG_RESET();
60
61         /* Send data */
62         writel(c, &uart->data);
63
64 #ifdef LEON_DEBUG
65         /* Wait for data to be sent */
66         while (!(readl(&uart->status) & LEON_REG_UART_STATUS_TSE))
67                 WATCHDOG_RESET();
68 #endif
69 }
70
71 static void leon3_serial_putc(const char c)
72 {
73         if (c == '\n')
74                 leon3_serial_putc_raw('\r');
75
76         leon3_serial_putc_raw(c);
77 }
78
79 static int leon3_serial_getc(void)
80 {
81         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
82
83         if (!uart)
84                 return 0;
85
86         /* Wait for a character to arrive. */
87         while (!(readl(&uart->status) & LEON_REG_UART_STATUS_DR))
88                 WATCHDOG_RESET();
89
90         /* Read character data */
91         return readl(&uart->data);
92 }
93
94 static int leon3_serial_tstc(void)
95 {
96         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
97
98         if (!uart)
99                 return 0;
100
101         return readl(&uart->status) & LEON_REG_UART_STATUS_DR;
102 }
103
104 /* set baud rate for uart */
105 static void leon3_serial_setbrg(void)
106 {
107         ambapp_dev_apbuart * const uart = leon3_get_uart_regs();
108         unsigned int scaler;
109
110         if (!uart)
111                 return;
112
113         if (!gd->baudrate)
114                 gd->baudrate = CONFIG_BAUDRATE;
115
116         scaler = (((CONFIG_SYS_CLK_FREQ*10) / (gd->baudrate*8)) - 5)/10;
117
118         writel(scaler, &uart->scaler);
119 }
120
121 static struct serial_device leon3_serial_drv = {
122         .name   = "leon3_serial",
123         .start  = leon3_serial_init,
124         .stop   = NULL,
125         .setbrg = leon3_serial_setbrg,
126         .putc   = leon3_serial_putc,
127         .puts   = default_serial_puts,
128         .getc   = leon3_serial_getc,
129         .tstc   = leon3_serial_tstc,
130 };
131
132 void leon3_serial_initialize(void)
133 {
134         serial_register(&leon3_serial_drv);
135 }
136
137 __weak struct serial_device *default_serial_console(void)
138 {
139         return &leon3_serial_drv;
140 }