xref: /openbmc/u-boot/drivers/serial/serial_arc.c (revision 22a240c32c1340183fce12867ae5f8736b92a638)
1*22a240c3SAlexey Brodkin /*
2*22a240c3SAlexey Brodkin  * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
3*22a240c3SAlexey Brodkin  *
4*22a240c3SAlexey Brodkin  * This program is free software; you can redistribute it and/or modify
5*22a240c3SAlexey Brodkin  * it under the terms of the GNU General Public License version 2 as
6*22a240c3SAlexey Brodkin  * published by the Free Software Foundation.
7*22a240c3SAlexey Brodkin  *
8*22a240c3SAlexey Brodkin  */
9*22a240c3SAlexey Brodkin 
10*22a240c3SAlexey Brodkin #include <common.h>
11*22a240c3SAlexey Brodkin #include <serial.h>
12*22a240c3SAlexey Brodkin 
13*22a240c3SAlexey Brodkin DECLARE_GLOBAL_DATA_PTR;
14*22a240c3SAlexey Brodkin 
15*22a240c3SAlexey Brodkin struct arc_serial_regs {
16*22a240c3SAlexey Brodkin 	unsigned int id0;
17*22a240c3SAlexey Brodkin 	unsigned int id1;
18*22a240c3SAlexey Brodkin 	unsigned int id2;
19*22a240c3SAlexey Brodkin 	unsigned int id3;
20*22a240c3SAlexey Brodkin 	unsigned int data;
21*22a240c3SAlexey Brodkin 	unsigned int status;
22*22a240c3SAlexey Brodkin 	unsigned int baudl;
23*22a240c3SAlexey Brodkin 	unsigned int baudh;
24*22a240c3SAlexey Brodkin };
25*22a240c3SAlexey Brodkin 
26*22a240c3SAlexey Brodkin /* Bit definitions of STATUS register */
27*22a240c3SAlexey Brodkin #define UART_RXEMPTY		(1 << 5)
28*22a240c3SAlexey Brodkin #define UART_OVERFLOW_ERR	(1 << 1)
29*22a240c3SAlexey Brodkin #define UART_TXEMPTY		(1 << 7)
30*22a240c3SAlexey Brodkin 
31*22a240c3SAlexey Brodkin struct arc_serial_regs *regs;
32*22a240c3SAlexey Brodkin 
33*22a240c3SAlexey Brodkin static void arc_serial_setbrg(void)
34*22a240c3SAlexey Brodkin {
35*22a240c3SAlexey Brodkin 	int arc_console_baud;
36*22a240c3SAlexey Brodkin 
37*22a240c3SAlexey Brodkin 	if (!gd->baudrate)
38*22a240c3SAlexey Brodkin 		gd->baudrate = CONFIG_BAUDRATE;
39*22a240c3SAlexey Brodkin 
40*22a240c3SAlexey Brodkin 	arc_console_baud = gd->cpu_clk / (gd->baudrate * 4) - 1;
41*22a240c3SAlexey Brodkin 	writel(arc_console_baud & 0xff, &regs->baudl);
42*22a240c3SAlexey Brodkin 	writel((arc_console_baud & 0xff00) >> 8, &regs->baudh);
43*22a240c3SAlexey Brodkin }
44*22a240c3SAlexey Brodkin 
45*22a240c3SAlexey Brodkin static int arc_serial_init(void)
46*22a240c3SAlexey Brodkin {
47*22a240c3SAlexey Brodkin 	regs = (struct arc_serial_regs *)CONFIG_ARC_UART_BASE;
48*22a240c3SAlexey Brodkin 	serial_setbrg();
49*22a240c3SAlexey Brodkin 	return 0;
50*22a240c3SAlexey Brodkin }
51*22a240c3SAlexey Brodkin 
52*22a240c3SAlexey Brodkin static void arc_serial_putc(const char c)
53*22a240c3SAlexey Brodkin {
54*22a240c3SAlexey Brodkin 	if (c == '\n')
55*22a240c3SAlexey Brodkin 		arc_serial_putc('\r');
56*22a240c3SAlexey Brodkin 
57*22a240c3SAlexey Brodkin 	while (!(readl(&regs->status) & UART_TXEMPTY))
58*22a240c3SAlexey Brodkin 		;
59*22a240c3SAlexey Brodkin 
60*22a240c3SAlexey Brodkin 	writel(c, &regs->data);
61*22a240c3SAlexey Brodkin }
62*22a240c3SAlexey Brodkin 
63*22a240c3SAlexey Brodkin static int arc_serial_tstc(void)
64*22a240c3SAlexey Brodkin {
65*22a240c3SAlexey Brodkin 	return !(readl(&regs->status) & UART_RXEMPTY);
66*22a240c3SAlexey Brodkin }
67*22a240c3SAlexey Brodkin 
68*22a240c3SAlexey Brodkin static int arc_serial_getc(void)
69*22a240c3SAlexey Brodkin {
70*22a240c3SAlexey Brodkin 	while (!arc_serial_tstc())
71*22a240c3SAlexey Brodkin 		;
72*22a240c3SAlexey Brodkin 
73*22a240c3SAlexey Brodkin 	/* Check for overflow errors */
74*22a240c3SAlexey Brodkin 	if (readl(&regs->status) & UART_OVERFLOW_ERR)
75*22a240c3SAlexey Brodkin 		return 0;
76*22a240c3SAlexey Brodkin 
77*22a240c3SAlexey Brodkin 	return readl(&regs->data) & 0xFF;
78*22a240c3SAlexey Brodkin }
79*22a240c3SAlexey Brodkin 
80*22a240c3SAlexey Brodkin static void arc_serial_puts(const char *s)
81*22a240c3SAlexey Brodkin {
82*22a240c3SAlexey Brodkin 	while (*s)
83*22a240c3SAlexey Brodkin 		arc_serial_putc(*s++);
84*22a240c3SAlexey Brodkin }
85*22a240c3SAlexey Brodkin 
86*22a240c3SAlexey Brodkin static struct serial_device arc_serial_drv = {
87*22a240c3SAlexey Brodkin 	.name	= "arc_serial",
88*22a240c3SAlexey Brodkin 	.start	= arc_serial_init,
89*22a240c3SAlexey Brodkin 	.stop	= NULL,
90*22a240c3SAlexey Brodkin 	.setbrg	= arc_serial_setbrg,
91*22a240c3SAlexey Brodkin 	.putc	= arc_serial_putc,
92*22a240c3SAlexey Brodkin 	.puts	= arc_serial_puts,
93*22a240c3SAlexey Brodkin 	.getc	= arc_serial_getc,
94*22a240c3SAlexey Brodkin 	.tstc	= arc_serial_tstc,
95*22a240c3SAlexey Brodkin };
96*22a240c3SAlexey Brodkin 
97*22a240c3SAlexey Brodkin void arc_serial_initialize(void)
98*22a240c3SAlexey Brodkin {
99*22a240c3SAlexey Brodkin 	serial_register(&arc_serial_drv);
100*22a240c3SAlexey Brodkin }
101*22a240c3SAlexey Brodkin 
102*22a240c3SAlexey Brodkin __weak struct serial_device *default_serial_console(void)
103*22a240c3SAlexey Brodkin {
104*22a240c3SAlexey Brodkin 	return &arc_serial_drv;
105*22a240c3SAlexey Brodkin }
106