]>
Commit | Line | Data |
---|---|---|
0b135cfc NI |
1 | /* |
2 | * SuperH SCIF device driver. | |
ac331da0 | 3 | * Copyright (c) 2007,2008 Nobuhiro Iwamatsu |
61fb15c5 | 4 | * |
0b135cfc NI |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program; if not, write to the Free Software | |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | */ | |
19 | ||
20 | #include <common.h> | |
21 | #include <asm/processor.h> | |
22 | ||
ab09f433 NI |
23 | #if defined(CONFIG_CONS_SCIF0) |
24 | # define SCIF_BASE SCIF0_BASE | |
25 | #elif defined(CONFIG_CONS_SCIF1) | |
26 | # define SCIF_BASE SCIF1_BASE | |
27 | #elif defined(CONFIG_CONS_SCIF2) | |
28 | # define SCIF_BASE SCIF2_BASE | |
29 | #elif defined(CONFIG_CONS_SCIF3) | |
30 | # define SCIF_BASE SCIF3_BASE | |
31 | #elif defined(CONFIG_CONS_SCIF4) | |
32 | # define SCIF_BASE SCIF4_BASE | |
33 | #elif defined(CONFIG_CONS_SCIF5) | |
34 | # define SCIF_BASE SCIF5_BASE | |
0b135cfc | 35 | #else |
ab09f433 | 36 | # error "Default SCIF doesn't set....." |
0b135cfc NI |
37 | #endif |
38 | ||
76e49aa7 NI |
39 | /* Base register */ |
40 | #define SCSMR (vu_short *)(SCIF_BASE + 0x0) | |
41 | #define SCBRR (vu_char *)(SCIF_BASE + 0x4) | |
42 | #define SCSCR (vu_short *)(SCIF_BASE + 0x8) | |
43 | #define SCFCR (vu_short *)(SCIF_BASE + 0x18) | |
44 | #define SCFDR (vu_short *)(SCIF_BASE + 0x1C) | |
ab09f433 NI |
45 | #if defined(CONFIG_CPU_SH7720) || \ |
46 | (defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A)) | |
08c5fabe | 47 | # define SCFSR (vu_short *)(SCIF_BASE + 0x14) /* SCSSR */ |
3ecff1d7 NI |
48 | # define SCFTDR (vu_char *)(SCIF_BASE + 0x20) |
49 | # define SCFRDR (vu_char *)(SCIF_BASE + 0x24) | |
7c10c572 | 50 | #else |
3ecff1d7 | 51 | # define SCFTDR (vu_char *)(SCIF_BASE + 0xC) |
08c5fabe | 52 | # define SCFSR (vu_short *)(SCIF_BASE + 0x10) |
3ecff1d7 | 53 | # define SCFRDR (vu_char *)(SCIF_BASE + 0x14) |
7c10c572 YS |
54 | #endif |
55 | ||
08c5fabe | 56 | #if defined(CONFIG_CPU_SH7780) || \ |
b55523ef | 57 | defined(CONFIG_CPU_SH7785) |
3ecff1d7 NI |
58 | # define SCRFDR (vu_short *)(SCIF_BASE + 0x20) |
59 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x24) | |
53677ef1 | 60 | # define SCLSR (vu_short *)(SCIF_BASE + 0x28) |
3ecff1d7 NI |
61 | # define SCRER (vu_short *)(SCIF_BASE + 0x2C) |
62 | # define LSR_ORER 1 | |
63 | # define FIFOLEVEL_MASK 0xFF | |
08c5fabe | 64 | #elif defined(CONFIG_CPU_SH7763) |
ab09f433 | 65 | # if defined(CONFIG_CONS_SCIF2) |
08c5fabe NI |
66 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x20) |
67 | # define SCLSR (vu_short *)(SCIF_BASE + 0x24) | |
68 | # define LSR_ORER 1 | |
69 | # define FIFOLEVEL_MASK 0x1F | |
70 | # else | |
71 | # define SCRFDR (vu_short *)(SCIF_BASE + 0x20) | |
72 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x24) | |
73 | # define SCLSR (vu_short *)(SCIF_BASE + 0x28) | |
74 | # define SCRER (vu_short *)(SCIF_BASE + 0x2C) | |
75 | # define LSR_ORER 1 | |
76 | # define FIFOLEVEL_MASK 0xFF | |
77 | # endif | |
ab09f433 | 78 | #elif defined(CONFIG_CPU_SH7723) |
a03c09c5 | 79 | # if defined(CONFIG_SCIF_A) |
ab09f433 NI |
80 | # define SCLSR SCFSR |
81 | # define LSR_ORER 0x0200 | |
82 | # define FIFOLEVEL_MASK 0x3F | |
83 | #else | |
84 | # define SCLSR (vu_short *)(SCIF_BASE + 0x24) | |
85 | # define LSR_ORER 1 | |
86 | # define FIFOLEVEL_MASK 0x1F | |
87 | #endif | |
b55523ef | 88 | #elif defined(CONFIG_CPU_SH7750) || \ |
56693327 | 89 | defined(CONFIG_CPU_SH7751) || \ |
6ede753d NI |
90 | defined(CONFIG_CPU_SH7722) || \ |
91 | defined(CONFIG_CPU_SH7203) | |
53677ef1 | 92 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x20) |
08c5fabe | 93 | # define SCLSR (vu_short *)(SCIF_BASE + 0x24) |
3ecff1d7 NI |
94 | # define LSR_ORER 1 |
95 | # define FIFOLEVEL_MASK 0x1F | |
b55523ef | 96 | #elif defined(CONFIG_CPU_SH7720) |
15e2697c | 97 | # define SCLSR SCFSR |
3ecff1d7 NI |
98 | # define LSR_ORER 0x0200 |
99 | # define FIFOLEVEL_MASK 0x1F | |
08c5fabe | 100 | #elif defined(CONFIG_CPU_SH7710) || \ |
b55523ef | 101 | defined(CONFIG_CPU_SH7712) |
08c5fabe | 102 | # define SCLSR SCFSR /* SCSSR */ |
3ecff1d7 NI |
103 | # define LSR_ORER 1 |
104 | # define FIFOLEVEL_MASK 0x1F | |
76e49aa7 | 105 | #endif |
ac331da0 | 106 | |
b55523ef | 107 | /* SCBRR register value setting */ |
ac331da0 | 108 | #if defined(CONFIG_CPU_SH7720) |
3ecff1d7 | 109 | # define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) |
ab09f433 NI |
110 | #elif defined(CONFIG_CPU_SH7723) && defined(CONFIG_SCIF_A) |
111 | /* SH7723 SCIFA use bus clock. So clock *2 */ | |
112 | # define SCBRR_VALUE(bps, clk) (((clk*2*2)+16*bps)/(32*bps)-1) | |
08c5fabe | 113 | #else /* Generic SuperH */ |
3ecff1d7 | 114 | # define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) |
0b135cfc NI |
115 | #endif |
116 | ||
08c5fabe NI |
117 | #define SCR_RE (1 << 4) |
118 | #define SCR_TE (1 << 5) | |
119 | #define FCR_RFRST (1 << 1) /* RFCL */ | |
120 | #define FCR_TFRST (1 << 2) /* TFCL */ | |
121 | #define FSR_DR (1 << 0) | |
122 | #define FSR_RDF (1 << 1) | |
123 | #define FSR_FER (1 << 3) | |
124 | #define FSR_BRK (1 << 4) | |
125 | #define FSR_FER (1 << 3) | |
126 | #define FSR_TEND (1 << 6) | |
127 | #define FSR_ER (1 << 7) | |
0b135cfc NI |
128 | |
129 | /*----------------------------------------------------------------------*/ | |
130 | ||
08c5fabe | 131 | void serial_setbrg(void) |
0b135cfc NI |
132 | { |
133 | DECLARE_GLOBAL_DATA_PTR; | |
08c5fabe | 134 | *SCBRR = SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ); |
0b135cfc NI |
135 | } |
136 | ||
08c5fabe | 137 | int serial_init(void) |
0b135cfc NI |
138 | { |
139 | *SCSCR = (SCR_RE | SCR_TE); | |
08c5fabe | 140 | *SCSMR = 0; |
0b135cfc NI |
141 | *SCSMR = 0; |
142 | *SCFCR = (FCR_RFRST | FCR_TFRST); | |
143 | *SCFCR; | |
144 | *SCFCR = 0; | |
145 | ||
146 | serial_setbrg(); | |
147 | return 0; | |
148 | } | |
149 | ||
08c5fabe | 150 | static int serial_rx_fifo_level(void) |
0b135cfc | 151 | { |
08c5fabe | 152 | #if defined(SCRFDR) |
3ecff1d7 NI |
153 | return (*SCRFDR >> 0) & FIFOLEVEL_MASK; |
154 | #else | |
155 | return (*SCFDR >> 0) & FIFOLEVEL_MASK; | |
156 | #endif | |
0b135cfc NI |
157 | } |
158 | ||
08c5fabe | 159 | void serial_raw_putc(const char c) |
0b135cfc NI |
160 | { |
161 | unsigned int fsr_bits_to_clear; | |
162 | ||
163 | while (1) { | |
08c5fabe | 164 | if (*SCFSR & FSR_TEND) { /* Tx fifo is empty */ |
0b135cfc NI |
165 | fsr_bits_to_clear = FSR_TEND; |
166 | break; | |
167 | } | |
168 | } | |
169 | ||
170 | *SCFTDR = c; | |
171 | if (fsr_bits_to_clear != 0) | |
172 | *SCFSR &= ~fsr_bits_to_clear; | |
173 | } | |
174 | ||
08c5fabe | 175 | void serial_putc(const char c) |
0b135cfc NI |
176 | { |
177 | if (c == '\n') | |
08c5fabe NI |
178 | serial_raw_putc('\r'); |
179 | serial_raw_putc(c); | |
0b135cfc NI |
180 | } |
181 | ||
08c5fabe | 182 | void serial_puts(const char *s) |
0b135cfc NI |
183 | { |
184 | char c; | |
185 | while ((c = *s++) != 0) | |
08c5fabe | 186 | serial_putc(c); |
0b135cfc NI |
187 | } |
188 | ||
08c5fabe | 189 | int serial_tstc(void) |
0b135cfc | 190 | { |
ab09f433 | 191 | return serial_rx_fifo_level() ? 1 : 0; |
0b135cfc NI |
192 | } |
193 | ||
08c5fabe NI |
194 | #define FSR_ERR_CLEAR 0x0063 |
195 | #define RDRF_CLEAR 0x00fc | |
196 | void handle_error(void) | |
197 | { | |
0b135cfc | 198 | |
08c5fabe NI |
199 | (void)*SCFSR; |
200 | *SCFSR = FSR_ERR_CLEAR; | |
201 | (void)*SCLSR; | |
202 | *SCLSR = 0x00; | |
0b135cfc NI |
203 | } |
204 | ||
08c5fabe NI |
205 | int serial_getc_check(void) |
206 | { | |
0b135cfc NI |
207 | unsigned short status; |
208 | ||
08c5fabe | 209 | status = *SCFSR; |
0b135cfc | 210 | |
08c5fabe | 211 | if (status & (FSR_FER | FSR_ER | FSR_BRK)) |
0b135cfc | 212 | handle_error(); |
08c5fabe | 213 | if (*SCLSR & LSR_ORER) |
0b135cfc | 214 | handle_error(); |
ab09f433 | 215 | return status & (FSR_DR | FSR_RDF); |
0b135cfc NI |
216 | } |
217 | ||
08c5fabe | 218 | int serial_getc(void) |
0b135cfc | 219 | { |
08c5fabe | 220 | unsigned short status; |
0b135cfc | 221 | char ch; |
ab09f433 NI |
222 | |
223 | while (!serial_getc_check()) | |
224 | ; | |
0b135cfc NI |
225 | |
226 | ch = *SCFRDR; | |
08c5fabe | 227 | status = *SCFSR; |
0b135cfc | 228 | |
08c5fabe | 229 | *SCFSR = RDRF_CLEAR; |
0b135cfc NI |
230 | |
231 | if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK)) | |
232 | handle_error(); | |
233 | ||
08c5fabe | 234 | if (*SCLSR & LSR_ORER) |
0b135cfc NI |
235 | handle_error(); |
236 | ||
08c5fabe | 237 | return ch; |
0b135cfc | 238 | } |