]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/serial/serial_lpuart.c
Revert "ARM: SPL: do not set gd again"
[karo-tx-uboot.git] / drivers / serial / serial_lpuart.c
1 /*
2  * Copyright 2013 Freescale Semiconductor, Inc.
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <watchdog.h>
9 #include <asm/io.h>
10 #include <serial.h>
11 #include <linux/compiler.h>
12 #include <asm/arch/imx-regs.h>
13 #include <asm/arch/clock.h>
14
15 #define US1_TDRE        (1 << 7)
16 #define US1_RDRF        (1 << 5)
17 #define UC2_TE          (1 << 3)
18 #define UC2_RE          (1 << 2)
19
20 #define STAT_LBKDIF     (1 << 31)
21 #define STAT_RXEDGIF    (1 << 30)
22 #define STAT_TDRE       (1 << 23)
23 #define STAT_RDRF       (1 << 21)
24 #define STAT_IDLE       (1 << 20)
25 #define STAT_OR         (1 << 19)
26 #define STAT_NF         (1 << 18)
27 #define STAT_FE         (1 << 17)
28 #define STAT_PF         (1 << 16)
29 #define STAT_MA1F       (1 << 15)
30 #define STAT_MA2F       (1 << 14)
31 #define STAT_FLAGS      (STAT_LBKDIF | STAT_RXEDGIF | STAT_IDLE | STAT_OR | \
32                         STAT_NF | STAT_FE | STAT_PF | STAT_MA1F | STAT_MA2F)
33
34 #define CTRL_TE         (1 << 19)
35 #define CTRL_RE         (1 << 18)
36
37 #define FIFO_TXFE               0x80
38 #define FIFO_RXFE               0x40
39
40 #define WATER_TXWATER_OFF       1
41 #define WATER_RXWATER_OFF       16
42
43 DECLARE_GLOBAL_DATA_PTR;
44
45 struct lpuart_fsl *base = (struct lpuart_fsl *)LPUART_BASE;
46
47 #ifndef CONFIG_LPUART_32B_REG
48 static void lpuart_serial_setbrg(void)
49 {
50         u32 clk = mxc_get_clock(MXC_UART_CLK);
51         u16 sbr;
52
53         if (!gd->baudrate)
54                 gd->baudrate = CONFIG_BAUDRATE;
55
56         sbr = (u16)(clk / (16 * gd->baudrate));
57         /* place adjustment later - n/32 BRFA */
58
59         __raw_writeb(sbr >> 8, &base->ubdh);
60         __raw_writeb(sbr & 0xff, &base->ubdl);
61 }
62
63 static int lpuart_serial_getc(void)
64 {
65         u8 status;
66
67         while (!(__raw_readb(&base->us1) & US1_RDRF))
68                 WATCHDOG_RESET();
69
70         status = __raw_readb(&base->us1);
71         status |= US1_RDRF;
72         __raw_writeb(status, &base->us1);
73
74         return __raw_readb(&base->ud);
75 }
76
77 static void lpuart_serial_putc(const char c)
78 {
79         if (c == '\n')
80                 serial_putc('\r');
81
82         while (!(__raw_readb(&base->us1) & US1_TDRE))
83                 WATCHDOG_RESET();
84
85         __raw_writeb(c, &base->ud);
86 }
87
88 /*
89  * Test whether a character is in the RX buffer
90  */
91 static int lpuart_serial_tstc(void)
92 {
93         if (__raw_readb(&base->urcfifo) == 0)
94                 return 0;
95
96         return 1;
97 }
98
99 /*
100  * Initialise the serial port with the given baudrate. The settings
101  * are always 8 data bits, no parity, 1 stop bit, no start bits.
102  */
103 static int lpuart_serial_init(void)
104 {
105         u8 ctrl;
106
107         ctrl = __raw_readb(&base->uc2);
108         ctrl &= ~UC2_RE;
109         ctrl &= ~UC2_TE;
110         __raw_writeb(ctrl, &base->uc2);
111
112         __raw_writeb(0, &base->umodem);
113         __raw_writeb(0, &base->uc1);
114
115         /* provide data bits, parity, stop bit, etc */
116
117         serial_setbrg();
118
119         __raw_writeb(UC2_RE | UC2_TE, &base->uc2);
120
121         return 0;
122 }
123
124 static struct serial_device lpuart_serial_drv = {
125         .name = "lpuart_serial",
126         .start = lpuart_serial_init,
127         .stop = NULL,
128         .setbrg = lpuart_serial_setbrg,
129         .putc = lpuart_serial_putc,
130         .puts = default_serial_puts,
131         .getc = lpuart_serial_getc,
132         .tstc = lpuart_serial_tstc,
133 };
134 #else
135 static void lpuart32_serial_setbrg(void)
136 {
137         u32 clk = CONFIG_SYS_CLK_FREQ;
138         u32 sbr;
139
140         if (!gd->baudrate)
141                 gd->baudrate = CONFIG_BAUDRATE;
142
143         sbr = (clk / (16 * gd->baudrate));
144         /* place adjustment later - n/32 BRFA */
145
146         out_be32(&base->baud, sbr);
147 }
148
149 static int lpuart32_serial_getc(void)
150 {
151         u32 stat;
152
153         while (((stat = in_be32(&base->stat)) & STAT_RDRF) == 0) {
154                 out_be32(&base->stat, STAT_FLAGS);
155                 WATCHDOG_RESET();
156         }
157
158         return in_be32(&base->data) & 0x3ff;
159 }
160
161 static void lpuart32_serial_putc(const char c)
162 {
163         if (c == '\n')
164                 serial_putc('\r');
165
166         while (!(in_be32(&base->stat) & STAT_TDRE))
167                 WATCHDOG_RESET();
168
169         out_be32(&base->data, c);
170 }
171
172 /*
173  * Test whether a character is in the RX buffer
174  */
175 static int lpuart32_serial_tstc(void)
176 {
177         if ((in_be32(&base->water) >> 24) == 0)
178                 return 0;
179
180         return 1;
181 }
182
183 /*
184  * Initialise the serial port with the given baudrate. The settings
185  * are always 8 data bits, no parity, 1 stop bit, no start bits.
186  */
187 static int lpuart32_serial_init(void)
188 {
189         u8 ctrl;
190
191         ctrl = in_be32(&base->ctrl);
192         ctrl &= ~CTRL_RE;
193         ctrl &= ~CTRL_TE;
194         out_be32(&base->ctrl, ctrl);
195
196         out_be32(&base->modir, 0);
197         out_be32(&base->fifo, ~(FIFO_TXFE | FIFO_RXFE));
198
199         out_be32(&base->match, 0);
200         /* provide data bits, parity, stop bit, etc */
201
202         serial_setbrg();
203
204         out_be32(&base->ctrl, CTRL_RE | CTRL_TE);
205
206         return 0;
207 }
208
209 static struct serial_device lpuart32_serial_drv = {
210         .name = "lpuart32_serial",
211         .start = lpuart32_serial_init,
212         .stop = NULL,
213         .setbrg = lpuart32_serial_setbrg,
214         .putc = lpuart32_serial_putc,
215         .puts = default_serial_puts,
216         .getc = lpuart32_serial_getc,
217         .tstc = lpuart32_serial_tstc,
218 };
219 #endif
220
221 void lpuart_serial_initialize(void)
222 {
223 #ifdef CONFIG_LPUART_32B_REG
224         serial_register(&lpuart32_serial_drv);
225 #else
226         serial_register(&lpuart_serial_drv);
227 #endif
228 }
229
230 __weak struct serial_device *default_serial_console(void)
231 {
232 #ifdef CONFIG_LPUART_32B_REG
233         return &lpuart32_serial_drv;
234 #else
235         return &lpuart_serial_drv;
236 #endif
237 }