serial/serial_arc: set registers address during compilation
[people/ms/u-boot.git] / drivers / serial / serial_arc.c
1 /*
2  * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  *
8  */
9
10 #include <common.h>
11 #include <serial.h>
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 struct arc_serial_regs {
16         unsigned int id0;
17         unsigned int id1;
18         unsigned int id2;
19         unsigned int id3;
20         unsigned int data;
21         unsigned int status;
22         unsigned int baudl;
23         unsigned int baudh;
24 };
25
26 /* Bit definitions of STATUS register */
27 #define UART_RXEMPTY            (1 << 5)
28 #define UART_OVERFLOW_ERR       (1 << 1)
29 #define UART_TXEMPTY            (1 << 7)
30
31 struct arc_serial_regs *regs = (struct arc_serial_regs *)CONFIG_ARC_UART_BASE;
32
33 static void arc_serial_setbrg(void)
34 {
35         int arc_console_baud;
36
37         if (!gd->baudrate)
38                 gd->baudrate = CONFIG_BAUDRATE;
39
40         arc_console_baud = gd->cpu_clk / (gd->baudrate * 4) - 1;
41         writeb(arc_console_baud & 0xff, &regs->baudl);
42
43 #ifdef CONFIG_ARC
44         /*
45          * UART ISS(Instruction Set simulator) emulation has a subtle bug:
46          * A existing value of Baudh = 0 is used as a indication to startup
47          * it's internal state machine.
48          * Thus if baudh is set to 0, 2 times, it chokes.
49          * This happens with BAUD=115200 and the formaula above
50          * Until that is fixed, when running on ISS, we will set baudh to !0
51          */
52         if (gd->arch.running_on_hw)
53                 writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
54         else
55                 writeb(1, &regs->baudh);
56 #else
57         writeb((arc_console_baud & 0xff00) >> 8, &regs->baudh);
58 #endif
59 }
60
61 static int arc_serial_init(void)
62 {
63         serial_setbrg();
64         return 0;
65 }
66
67 static void arc_serial_putc(const char c)
68 {
69         if (c == '\n')
70                 arc_serial_putc('\r');
71
72         while (!(readb(&regs->status) & UART_TXEMPTY))
73                 ;
74
75         writeb(c, &regs->data);
76 }
77
78 static int arc_serial_tstc(void)
79 {
80         return !(readb(&regs->status) & UART_RXEMPTY);
81 }
82
83 static int arc_serial_getc(void)
84 {
85         while (!arc_serial_tstc())
86                 ;
87
88         /* Check for overflow errors */
89         if (readb(&regs->status) & UART_OVERFLOW_ERR)
90                 return 0;
91
92         return readb(&regs->data) & 0xFF;
93 }
94
95 static struct serial_device arc_serial_drv = {
96         .name   = "arc_serial",
97         .start  = arc_serial_init,
98         .stop   = NULL,
99         .setbrg = arc_serial_setbrg,
100         .putc   = arc_serial_putc,
101         .puts   = default_serial_puts,
102         .getc   = arc_serial_getc,
103         .tstc   = arc_serial_tstc,
104 };
105
106 void arc_serial_initialize(void)
107 {
108         serial_register(&arc_serial_drv);
109 }
110
111 __weak struct serial_device *default_serial_console(void)
112 {
113         return &arc_serial_drv;
114 }