]>
Commit | Line | Data |
---|---|---|
2fb28dcf GL |
1 | /* |
2 | * (C) Copyright 2002 | |
3 | * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> | |
4 | * | |
5 | * (C) Copyright 2008 | |
6 | * Guennadi Liakhovetki, DENX Software Engineering, <lg@denx.de> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
10 | * the Free Software Foundation; either version 2 of the License, or | |
11 | * (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
21 | * | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | ||
26 | #include <s3c6400.h> | |
27 | ||
28 | #ifdef CONFIG_SERIAL1 | |
29 | #define UART_NR S3C64XX_UART0 | |
30 | ||
31 | #elif defined(CONFIG_SERIAL2) | |
32 | #define UART_NR S3C64XX_UART1 | |
33 | ||
34 | #elif defined(CONFIG_SERIAL3) | |
35 | #define UART_NR S3C64XX_UART2 | |
36 | ||
37 | #else | |
38 | #error "Bad: you didn't configure serial ..." | |
39 | #endif | |
40 | ||
41 | #define barrier() asm volatile("" ::: "memory") | |
42 | ||
43 | /* | |
44 | * The coefficient, used to calculate the baudrate on S3C6400 UARTs is | |
45 | * calculated as | |
46 | * C = UBRDIV * 16 + number_of_set_bits_in_UDIVSLOT | |
47 | * however, section 31.6.11 of the datasheet doesn't recomment using 1 for 1, | |
48 | * 3 for 2, ... (2^n - 1) for n, instead, they suggest using these constants: | |
49 | */ | |
50 | static const int udivslot[] = { | |
51 | 0, | |
52 | 0x0080, | |
53 | 0x0808, | |
54 | 0x0888, | |
55 | 0x2222, | |
56 | 0x4924, | |
57 | 0x4a52, | |
58 | 0x54aa, | |
59 | 0x5555, | |
60 | 0xd555, | |
61 | 0xd5d5, | |
62 | 0xddd5, | |
63 | 0xdddd, | |
64 | 0xdfdd, | |
65 | 0xdfdf, | |
66 | 0xffdf, | |
67 | }; | |
68 | ||
69 | void serial_setbrg(void) | |
70 | { | |
71 | DECLARE_GLOBAL_DATA_PTR; | |
72 | s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); | |
73 | u32 pclk = get_PCLK(); | |
74 | u32 baudrate = gd->baudrate; | |
75 | int i; | |
76 | ||
77 | i = (pclk / baudrate) % 16; | |
78 | ||
79 | uart->UBRDIV = pclk / baudrate / 16 - 1; | |
80 | uart->UDIVSLOT = udivslot[i]; | |
81 | ||
82 | for (i = 0; i < 100; i++) | |
83 | barrier(); | |
84 | } | |
85 | ||
86 | /* | |
87 | * Initialise the serial port with the given baudrate. The settings | |
88 | * are always 8 data bits, no parity, 1 stop bit, no start bits. | |
89 | */ | |
90 | int serial_init(void) | |
91 | { | |
92 | s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); | |
93 | ||
94 | /* reset and enable FIFOs, set triggers to the maximum */ | |
95 | uart->UFCON = 0xff; | |
96 | uart->UMCON = 0; | |
97 | /* 8N1 */ | |
98 | uart->ULCON = 3; | |
99 | /* No interrupts, no DMA, pure polling */ | |
100 | uart->UCON = 5; | |
101 | ||
102 | serial_setbrg(); | |
103 | ||
104 | return 0; | |
105 | } | |
106 | ||
107 | /* | |
108 | * Read a single byte from the serial port. Returns 1 on success, 0 | |
109 | * otherwise. When the function is succesfull, the character read is | |
110 | * written into its argument c. | |
111 | */ | |
112 | int serial_getc(void) | |
113 | { | |
114 | s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); | |
115 | ||
116 | /* wait for character to arrive */ | |
117 | while (!(uart->UTRSTAT & 0x1)); | |
118 | ||
119 | return uart->URXH & 0xff; | |
120 | } | |
121 | ||
2fb28dcf GL |
122 | #ifdef CONFIG_MODEM_SUPPORT |
123 | static int be_quiet; | |
124 | void disable_putc(void) | |
125 | { | |
126 | be_quiet = 1; | |
127 | } | |
128 | ||
129 | void enable_putc(void) | |
130 | { | |
131 | be_quiet = 0; | |
132 | } | |
133 | #endif | |
134 | ||
135 | ||
136 | /* | |
137 | * Output a single byte to the serial port. | |
138 | */ | |
139 | void serial_putc(const char c) | |
140 | { | |
141 | s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); | |
142 | ||
143 | #ifdef CONFIG_MODEM_SUPPORT | |
144 | if (be_quiet) | |
145 | return; | |
146 | #endif | |
147 | ||
148 | /* wait for room in the tx FIFO */ | |
149 | while (!(uart->UTRSTAT & 0x2)); | |
150 | ||
2fb28dcf GL |
151 | uart->UTXH = c; |
152 | ||
153 | /* If \n, also do \r */ | |
154 | if (c == '\n') | |
155 | serial_putc('\r'); | |
156 | } | |
157 | ||
158 | /* | |
159 | * Test whether a character is in the RX buffer | |
160 | */ | |
161 | int serial_tstc(void) | |
162 | { | |
163 | s3c64xx_uart *const uart = s3c64xx_get_base_uart(UART_NR); | |
164 | ||
165 | return uart->UTRSTAT & 0x1; | |
166 | } | |
167 | ||
168 | void serial_puts(const char *s) | |
169 | { | |
170 | while (*s) | |
171 | serial_putc(*s++); | |
172 | } |