]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/serial/serial_sh.c
nand: Add verification functions
[people/ms/u-boot.git] / drivers / serial / serial_sh.c
CommitLineData
0b135cfc
NI
1/*
2 * SuperH SCIF device driver.
48ca882c 3 * Copyright (C) 2013 Renesas Electronics Corporation
59088e4a 4 * Copyright (C) 2007,2008,2010, 2014 Nobuhiro Iwamatsu
3f6c8e36 5 * Copyright (C) 2002 - 2008 Paul Mundt
61fb15c5 6 *
1a459660 7 * SPDX-License-Identifier: GPL-2.0+
0b135cfc
NI
8 */
9
10#include <common.h>
59088e4a
NI
11#include <errno.h>
12#include <dm.h>
fc83c927 13#include <asm/io.h>
0b135cfc 14#include <asm/processor.h>
8bdd7efa
MV
15#include <serial.h>
16#include <linux/compiler.h>
59088e4a
NI
17#include <dm/platform_data/serial_sh.h>
18#include "serial_sh.h"
0b135cfc 19
3f6c8e36
NI
20#if defined(CONFIG_CPU_SH7760) || \
21 defined(CONFIG_CPU_SH7780) || \
22 defined(CONFIG_CPU_SH7785) || \
23 defined(CONFIG_CPU_SH7786)
24static int scif_rxfill(struct uart_port *port)
25{
26 return sci_in(port, SCRFDR) & 0xff;
27}
28#elif defined(CONFIG_CPU_SH7763)
29static int scif_rxfill(struct uart_port *port)
0b135cfc 30{
3f6c8e36 31 if ((port->mapbase == 0xffe00000) ||
59088e4a 32 (port->mapbase == 0xffe08000)) {
3f6c8e36
NI
33 /* SCIF0/1*/
34 return sci_in(port, SCRFDR) & 0xff;
35 } else {
36 /* SCIF2 */
37 return sci_in(port, SCFDR) & SCIF2_RFDC_MASK;
38 }
39}
40#elif defined(CONFIG_ARCH_SH7372)
41static int scif_rxfill(struct uart_port *port)
42{
43 if (port->type == PORT_SCIFA)
44 return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
45 else
46 return sci_in(port, SCRFDR);
47}
3ecff1d7 48#else
3f6c8e36
NI
49static int scif_rxfill(struct uart_port *port)
50{
51 return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
52}
3ecff1d7 53#endif
3f6c8e36 54
59088e4a 55static void sh_serial_init_generic(struct uart_port *port)
3f6c8e36 56{
59088e4a
NI
57 sci_out(port, SCSCR , SCSCR_INIT(port));
58 sci_out(port, SCSCR , SCSCR_INIT(port));
59 sci_out(port, SCSMR, 0);
60 sci_out(port, SCSMR, 0);
61 sci_out(port, SCFCR, SCFCR_RFRST|SCFCR_TFRST);
62 sci_in(port, SCFCR);
63 sci_out(port, SCFCR, 0);
0b135cfc
NI
64}
65
59088e4a
NI
66static void
67sh_serial_setbrg_generic(struct uart_port *port, int clk, int baudrate)
7c791b3f 68{
59088e4a
NI
69 if (port->clk_mode == EXT_CLK) {
70 unsigned short dl = DL_VALUE(baudrate, clk);
71 sci_out(port, DL, dl);
89f99a62 72 /* Need wait: Clock * 1/dl * 1/16 */
59088e4a
NI
73 udelay((1000000 * dl * 16 / clk) * 1000 + 1);
74 } else {
75 sci_out(port, SCBRR, SCBRR_VALUE(baudrate, clk));
76 }
7c791b3f
TK
77}
78
59088e4a 79static void handle_error(struct uart_port *port)
0b135cfc 80{
59088e4a
NI
81 sci_in(port, SCxSR);
82 sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
83 sci_in(port, SCLSR);
84 sci_out(port, SCLSR, 0x00);
85}
86
87static int serial_raw_putc(struct uart_port *port, const char c)
88{
89 /* Tx fifo is empty */
90 if (!(sci_in(port, SCxSR) & SCxSR_TEND(port)))
91 return -EAGAIN;
0b135cfc 92
59088e4a
NI
93 sci_out(port, SCxTDR, c);
94 sci_out(port, SCxSR, sci_in(port, SCxSR) & ~SCxSR_TEND(port));
95
96 return 0;
0b135cfc
NI
97}
98
59088e4a 99static int serial_rx_fifo_level(struct uart_port *port)
0b135cfc 100{
59088e4a 101 return scif_rxfill(port);
0b135cfc
NI
102}
103
59088e4a 104static int sh_serial_tstc_generic(struct uart_port *port)
0b135cfc 105{
59088e4a
NI
106 if (sci_in(port, SCxSR) & SCIF_ERRORS) {
107 handle_error(port);
7c791b3f
TK
108 return 0;
109 }
110
59088e4a 111 return serial_rx_fifo_level(port) ? 1 : 0;
0b135cfc
NI
112}
113
59088e4a 114static int serial_getc_check(struct uart_port *port)
08c5fabe 115{
0b135cfc
NI
116 unsigned short status;
117
59088e4a 118 status = sci_in(port, SCxSR);
0b135cfc 119
3f6c8e36 120 if (status & SCIF_ERRORS)
59088e4a
NI
121 handle_error(port);
122 if (sci_in(port, SCLSR) & SCxSR_ORER(port))
123 handle_error(port);
124 return status & (SCIF_DR | SCxSR_RDxF(port));
0b135cfc
NI
125}
126
59088e4a 127static int sh_serial_getc_generic(struct uart_port *port)
0b135cfc 128{
08c5fabe 129 unsigned short status;
0b135cfc 130 char ch;
ab09f433 131
59088e4a
NI
132 if (!serial_getc_check(port))
133 return -EAGAIN;
0b135cfc 134
59088e4a
NI
135 ch = sci_in(port, SCxRDR);
136 status = sci_in(port, SCxSR);
0b135cfc 137
59088e4a 138 sci_out(port, SCxSR, SCxSR_RDxF_CLEAR(port));
0b135cfc 139
3f6c8e36 140 if (status & SCIF_ERRORS)
59088e4a
NI
141 handle_error(port);
142
143 if (sci_in(port, SCLSR) & SCxSR_ORER(port))
144 handle_error(port);
145
146 return ch;
147}
148
149#ifdef CONFIG_DM_SERIAL
150
151static int sh_serial_pending(struct udevice *dev, bool input)
152{
153 struct uart_port *priv = dev_get_priv(dev);
154
155 return sh_serial_tstc_generic(priv);
156}
157
158static int sh_serial_putc(struct udevice *dev, const char ch)
159{
160 struct uart_port *priv = dev_get_priv(dev);
161
162 return serial_raw_putc(priv, ch);
163}
164
165static int sh_serial_getc(struct udevice *dev)
166{
167 struct uart_port *priv = dev_get_priv(dev);
168
169 return sh_serial_getc_generic(priv);
170}
171
172static int sh_serial_setbrg(struct udevice *dev, int baudrate)
173{
174 struct sh_serial_platdata *plat = dev_get_platdata(dev);
175 struct uart_port *priv = dev_get_priv(dev);
176
177 sh_serial_setbrg_generic(priv, plat->clk, baudrate);
178
179 return 0;
180}
181
182static int sh_serial_probe(struct udevice *dev)
183{
184 struct sh_serial_platdata *plat = dev_get_platdata(dev);
185 struct uart_port *priv = dev_get_priv(dev);
186
187 priv->membase = (unsigned char *)plat->base;
188 priv->mapbase = plat->base;
189 priv->type = plat->type;
190 priv->clk_mode = plat->clk_mode;
191
192 sh_serial_init_generic(priv);
193
194 return 0;
195}
196
197static const struct dm_serial_ops sh_serial_ops = {
198 .putc = sh_serial_putc,
199 .pending = sh_serial_pending,
200 .getc = sh_serial_getc,
201 .setbrg = sh_serial_setbrg,
202};
203
204U_BOOT_DRIVER(serial_sh) = {
205 .name = "serial_sh",
206 .id = UCLASS_SERIAL,
207 .probe = sh_serial_probe,
208 .ops = &sh_serial_ops,
209 .flags = DM_FLAG_PRE_RELOC,
210 .priv_auto_alloc_size = sizeof(struct uart_port),
211};
212
213#else /* CONFIG_DM_SERIAL */
214
215#if defined(CONFIG_CONS_SCIF0)
216# define SCIF_BASE SCIF0_BASE
217#elif defined(CONFIG_CONS_SCIF1)
218# define SCIF_BASE SCIF1_BASE
219#elif defined(CONFIG_CONS_SCIF2)
220# define SCIF_BASE SCIF2_BASE
221#elif defined(CONFIG_CONS_SCIF3)
222# define SCIF_BASE SCIF3_BASE
223#elif defined(CONFIG_CONS_SCIF4)
224# define SCIF_BASE SCIF4_BASE
225#elif defined(CONFIG_CONS_SCIF5)
226# define SCIF_BASE SCIF5_BASE
227#elif defined(CONFIG_CONS_SCIF6)
228# define SCIF_BASE SCIF6_BASE
229#elif defined(CONFIG_CONS_SCIF7)
230# define SCIF_BASE SCIF7_BASE
231#else
232# error "Default SCIF doesn't set....."
233#endif
234
235#if defined(CONFIG_SCIF_A)
236 #define SCIF_BASE_PORT PORT_SCIFA
237#else
238 #define SCIF_BASE_PORT PORT_SCIF
239#endif
240
241static struct uart_port sh_sci = {
242 .membase = (unsigned char *)SCIF_BASE,
243 .mapbase = SCIF_BASE,
244 .type = SCIF_BASE_PORT,
245#ifdef CONFIG_SCIF_USE_EXT_CLK
246 .clk_mode = EXT_CLK,
247#endif
248};
249
250static void sh_serial_setbrg(void)
251{
252 DECLARE_GLOBAL_DATA_PTR;
253 struct uart_port *port = &sh_sci;
254
255 sh_serial_setbrg_generic(port, CONFIG_SH_SCIF_CLK_FREQ, gd->baudrate);
256}
257
258static int sh_serial_init(void)
259{
260 struct uart_port *port = &sh_sci;
261
262 sh_serial_init_generic(port);
263 serial_setbrg();
264
265 return 0;
266}
267
268static void sh_serial_putc(const char c)
269{
270 struct uart_port *port = &sh_sci;
271
272 if (c == '\n') {
273 while (1) {
274 if (serial_raw_putc(port, '\r') != -EAGAIN)
275 break;
276 }
277 }
278 while (1) {
279 if (serial_raw_putc(port, c) != -EAGAIN)
280 break;
281 }
282}
283
284static int sh_serial_tstc(void)
285{
286 struct uart_port *port = &sh_sci;
287
288 return sh_serial_tstc_generic(port);
289}
290
291static int sh_serial_getc(void)
292{
293 struct uart_port *port = &sh_sci;
294 int ch;
295
296 while (1) {
297 ch = sh_serial_getc_generic(port);
298 if (ch != -EAGAIN)
299 break;
300 }
0b135cfc 301
08c5fabe 302 return ch;
0b135cfc 303}
8bdd7efa 304
8bdd7efa
MV
305static struct serial_device sh_serial_drv = {
306 .name = "sh_serial",
307 .start = sh_serial_init,
308 .stop = NULL,
309 .setbrg = sh_serial_setbrg,
310 .putc = sh_serial_putc,
ec3fd689 311 .puts = default_serial_puts,
8bdd7efa
MV
312 .getc = sh_serial_getc,
313 .tstc = sh_serial_tstc,
314};
315
316void sh_serial_initialize(void)
317{
318 serial_register(&sh_serial_drv);
319}
320
321__weak struct serial_device *default_serial_console(void)
322{
323 return &sh_serial_drv;
324}
59088e4a 325#endif /* CONFIG_DM_SERIAL */