]>
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 | ||
0b135cfc 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 | |
08c5fabe NI |
27 | #elif defined (CONFIG_CONS_SCIF2) |
28 | #define SCIF_BASE SCIF2_BASE | |
0b135cfc NI |
29 | #else |
30 | #error "Default SCIF doesn't set....." | |
31 | #endif | |
32 | ||
76e49aa7 NI |
33 | /* Base register */ |
34 | #define SCSMR (vu_short *)(SCIF_BASE + 0x0) | |
35 | #define SCBRR (vu_char *)(SCIF_BASE + 0x4) | |
36 | #define SCSCR (vu_short *)(SCIF_BASE + 0x8) | |
37 | #define SCFCR (vu_short *)(SCIF_BASE + 0x18) | |
38 | #define SCFDR (vu_short *)(SCIF_BASE + 0x1C) | |
08c5fabe NI |
39 | #ifdef CONFIG_CPU_SH7720 /* SH7720 specific */ |
40 | # define SCFSR (vu_short *)(SCIF_BASE + 0x14) /* SCSSR */ | |
3ecff1d7 NI |
41 | # define SCFTDR (vu_char *)(SCIF_BASE + 0x20) |
42 | # define SCFRDR (vu_char *)(SCIF_BASE + 0x24) | |
7c10c572 | 43 | #else |
3ecff1d7 | 44 | # define SCFTDR (vu_char *)(SCIF_BASE + 0xC) |
08c5fabe | 45 | # define SCFSR (vu_short *)(SCIF_BASE + 0x10) |
3ecff1d7 | 46 | # define SCFRDR (vu_char *)(SCIF_BASE + 0x14) |
7c10c572 YS |
47 | #endif |
48 | ||
08c5fabe | 49 | #if defined(CONFIG_CPU_SH7780) || \ |
b55523ef | 50 | defined(CONFIG_CPU_SH7785) |
3ecff1d7 NI |
51 | # define SCRFDR (vu_short *)(SCIF_BASE + 0x20) |
52 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x24) | |
53677ef1 | 53 | # define SCLSR (vu_short *)(SCIF_BASE + 0x28) |
3ecff1d7 NI |
54 | # define SCRER (vu_short *)(SCIF_BASE + 0x2C) |
55 | # define LSR_ORER 1 | |
56 | # define FIFOLEVEL_MASK 0xFF | |
08c5fabe NI |
57 | #elif defined(CONFIG_CPU_SH7763) |
58 | # if defined (CONFIG_CONS_SCIF2) | |
59 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x20) | |
60 | # define SCLSR (vu_short *)(SCIF_BASE + 0x24) | |
61 | # define LSR_ORER 1 | |
62 | # define FIFOLEVEL_MASK 0x1F | |
63 | # else | |
64 | # define SCRFDR (vu_short *)(SCIF_BASE + 0x20) | |
65 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x24) | |
66 | # define SCLSR (vu_short *)(SCIF_BASE + 0x28) | |
67 | # define SCRER (vu_short *)(SCIF_BASE + 0x2C) | |
68 | # define LSR_ORER 1 | |
69 | # define FIFOLEVEL_MASK 0xFF | |
70 | # endif | |
b55523ef | 71 | #elif defined(CONFIG_CPU_SH7750) || \ |
56693327 | 72 | defined(CONFIG_CPU_SH7751) || \ |
b55523ef | 73 | defined(CONFIG_CPU_SH7722) |
53677ef1 | 74 | # define SCSPTR (vu_short *)(SCIF_BASE + 0x20) |
08c5fabe | 75 | # define SCLSR (vu_short *)(SCIF_BASE + 0x24) |
3ecff1d7 NI |
76 | # define LSR_ORER 1 |
77 | # define FIFOLEVEL_MASK 0x1F | |
b55523ef | 78 | #elif defined(CONFIG_CPU_SH7720) |
08c5fabe | 79 | # define SCLSR (vu_short *)(SCIF_BASE + 0x24) |
3ecff1d7 NI |
80 | # define LSR_ORER 0x0200 |
81 | # define FIFOLEVEL_MASK 0x1F | |
08c5fabe | 82 | #elif defined(CONFIG_CPU_SH7710) || \ |
b55523ef | 83 | defined(CONFIG_CPU_SH7712) |
08c5fabe | 84 | # define SCLSR SCFSR /* SCSSR */ |
3ecff1d7 NI |
85 | # define LSR_ORER 1 |
86 | # define FIFOLEVEL_MASK 0x1F | |
76e49aa7 | 87 | #endif |
ac331da0 | 88 | |
b55523ef | 89 | /* SCBRR register value setting */ |
ac331da0 | 90 | #if defined(CONFIG_CPU_SH7720) |
3ecff1d7 | 91 | # define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) |
08c5fabe | 92 | #else /* Generic SuperH */ |
3ecff1d7 | 93 | # define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1) |
0b135cfc NI |
94 | #endif |
95 | ||
08c5fabe NI |
96 | #define SCR_RE (1 << 4) |
97 | #define SCR_TE (1 << 5) | |
98 | #define FCR_RFRST (1 << 1) /* RFCL */ | |
99 | #define FCR_TFRST (1 << 2) /* TFCL */ | |
100 | #define FSR_DR (1 << 0) | |
101 | #define FSR_RDF (1 << 1) | |
102 | #define FSR_FER (1 << 3) | |
103 | #define FSR_BRK (1 << 4) | |
104 | #define FSR_FER (1 << 3) | |
105 | #define FSR_TEND (1 << 6) | |
106 | #define FSR_ER (1 << 7) | |
0b135cfc NI |
107 | |
108 | /*----------------------------------------------------------------------*/ | |
109 | ||
08c5fabe | 110 | void serial_setbrg(void) |
0b135cfc NI |
111 | { |
112 | DECLARE_GLOBAL_DATA_PTR; | |
08c5fabe | 113 | *SCBRR = SCBRR_VALUE(gd->baudrate, CONFIG_SYS_CLK_FREQ); |
0b135cfc NI |
114 | } |
115 | ||
08c5fabe | 116 | int serial_init(void) |
0b135cfc NI |
117 | { |
118 | *SCSCR = (SCR_RE | SCR_TE); | |
08c5fabe | 119 | *SCSMR = 0; |
0b135cfc NI |
120 | *SCSMR = 0; |
121 | *SCFCR = (FCR_RFRST | FCR_TFRST); | |
122 | *SCFCR; | |
123 | *SCFCR = 0; | |
124 | ||
125 | serial_setbrg(); | |
126 | return 0; | |
127 | } | |
128 | ||
08c5fabe | 129 | static int serial_rx_fifo_level(void) |
0b135cfc | 130 | { |
08c5fabe | 131 | #if defined(SCRFDR) |
3ecff1d7 NI |
132 | return (*SCRFDR >> 0) & FIFOLEVEL_MASK; |
133 | #else | |
134 | return (*SCFDR >> 0) & FIFOLEVEL_MASK; | |
135 | #endif | |
0b135cfc NI |
136 | } |
137 | ||
08c5fabe | 138 | void serial_raw_putc(const char c) |
0b135cfc NI |
139 | { |
140 | unsigned int fsr_bits_to_clear; | |
141 | ||
142 | while (1) { | |
08c5fabe | 143 | if (*SCFSR & FSR_TEND) { /* Tx fifo is empty */ |
0b135cfc NI |
144 | fsr_bits_to_clear = FSR_TEND; |
145 | break; | |
146 | } | |
147 | } | |
148 | ||
149 | *SCFTDR = c; | |
150 | if (fsr_bits_to_clear != 0) | |
151 | *SCFSR &= ~fsr_bits_to_clear; | |
152 | } | |
153 | ||
08c5fabe | 154 | void serial_putc(const char c) |
0b135cfc NI |
155 | { |
156 | if (c == '\n') | |
08c5fabe NI |
157 | serial_raw_putc('\r'); |
158 | serial_raw_putc(c); | |
0b135cfc NI |
159 | } |
160 | ||
08c5fabe | 161 | void serial_puts(const char *s) |
0b135cfc NI |
162 | { |
163 | char c; | |
164 | while ((c = *s++) != 0) | |
08c5fabe | 165 | serial_putc(c); |
0b135cfc NI |
166 | } |
167 | ||
08c5fabe | 168 | int serial_tstc(void) |
0b135cfc | 169 | { |
08c5fabe | 170 | return serial_rx_fifo_level()? 1 : 0; |
0b135cfc NI |
171 | } |
172 | ||
08c5fabe NI |
173 | #define FSR_ERR_CLEAR 0x0063 |
174 | #define RDRF_CLEAR 0x00fc | |
175 | void handle_error(void) | |
176 | { | |
0b135cfc | 177 | |
08c5fabe NI |
178 | (void)*SCFSR; |
179 | *SCFSR = FSR_ERR_CLEAR; | |
180 | (void)*SCLSR; | |
181 | *SCLSR = 0x00; | |
0b135cfc NI |
182 | } |
183 | ||
08c5fabe NI |
184 | int serial_getc_check(void) |
185 | { | |
0b135cfc NI |
186 | unsigned short status; |
187 | ||
08c5fabe | 188 | status = *SCFSR; |
0b135cfc | 189 | |
08c5fabe | 190 | if (status & (FSR_FER | FSR_ER | FSR_BRK)) |
0b135cfc | 191 | handle_error(); |
08c5fabe | 192 | if (*SCLSR & LSR_ORER) |
0b135cfc | 193 | handle_error(); |
08c5fabe | 194 | return (status & (FSR_DR | FSR_RDF)); |
0b135cfc NI |
195 | } |
196 | ||
08c5fabe | 197 | int serial_getc(void) |
0b135cfc | 198 | { |
08c5fabe | 199 | unsigned short status; |
0b135cfc | 200 | char ch; |
08c5fabe | 201 | while (!serial_getc_check()) ; |
0b135cfc NI |
202 | |
203 | ch = *SCFRDR; | |
08c5fabe | 204 | status = *SCFSR; |
0b135cfc | 205 | |
08c5fabe | 206 | *SCFSR = RDRF_CLEAR; |
0b135cfc NI |
207 | |
208 | if (status & (FSR_FER | FSR_FER | FSR_ER | FSR_BRK)) | |
209 | handle_error(); | |
210 | ||
08c5fabe | 211 | if (*SCLSR & LSR_ORER) |
0b135cfc NI |
212 | handle_error(); |
213 | ||
08c5fabe | 214 | return ch; |
0b135cfc | 215 | } |