]> git.sur5r.net Git - u-boot/blob - drivers/serial/serial_arc.c
Merge branch 'u-boot-samsung/master' into 'u-boot-arm/master'
[u-boot] / 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;
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         regs = (struct arc_serial_regs *)CONFIG_ARC_UART_BASE;
64         serial_setbrg();
65         return 0;
66 }
67
68 static void arc_serial_putc(const char c)
69 {
70         if (c == '\n')
71                 arc_serial_putc('\r');
72
73         while (!(readb(&regs->status) & UART_TXEMPTY))
74                 ;
75
76         writeb(c, &regs->data);
77 }
78
79 static int arc_serial_tstc(void)
80 {
81         return !(readb(&regs->status) & UART_RXEMPTY);
82 }
83
84 static int arc_serial_getc(void)
85 {
86         while (!arc_serial_tstc())
87                 ;
88
89         /* Check for overflow errors */
90         if (readb(&regs->status) & UART_OVERFLOW_ERR)
91                 return 0;
92
93         return readb(&regs->data) & 0xFF;
94 }
95
96 static struct serial_device arc_serial_drv = {
97         .name   = "arc_serial",
98         .start  = arc_serial_init,
99         .stop   = NULL,
100         .setbrg = arc_serial_setbrg,
101         .putc   = arc_serial_putc,
102         .puts   = default_serial_puts,
103         .getc   = arc_serial_getc,
104         .tstc   = arc_serial_tstc,
105 };
106
107 void arc_serial_initialize(void)
108 {
109         serial_register(&arc_serial_drv);
110 }
111
112 __weak struct serial_device *default_serial_console(void)
113 {
114         return &arc_serial_drv;
115 }