1
2
3
4
5#include <config.h>
6#include <common.h>
7#include <asm/inca-ip.h>
8#include <serial.h>
9#include <linux/compiler.h>
10#include "asc_serial.h"
11
12
13#define SET_BIT(reg, mask) reg |= (mask)
14#define CLEAR_BIT(reg, mask) reg &= (~mask)
15#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
16#define SET_BITS(reg, mask) SET_BIT(reg, mask)
17#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
18
19extern uint incaip_get_fpiclk(void);
20
21static int serial_setopt (void);
22
23
24static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
25
26
27
28
29
30
31
32
33
34
35
36
37static int asc_serial_init(void)
38{
39
40 INCAASC_PMU_ENABLE(13);
41
42
43 CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
44 SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
45
46
47 pAsc->asc_con = ASCCON_M_8ASYNC;
48
49
50 pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
51
52
53 SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
54 ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
55
56 SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
57
58
59 SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
60 ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
61
62 SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
63
64
65 SET_BIT(pAsc->asc_con, ASCCON_FEN);
66 SET_BIT(pAsc->asc_con, ASCCON_OEN);
67
68
69 ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
70
71
72 ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
73
74
75 SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
76 SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
77
78
79 serial_setbrg();
80
81
82 serial_setopt();
83
84 return 0;
85}
86
87static void asc_serial_setbrg(void)
88{
89 ulong uiReloadValue, fdv;
90 ulong f_ASC;
91
92 f_ASC = incaip_get_fpiclk();
93
94#ifndef INCAASC_USE_FDV
95 fdv = 2;
96 uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
97#else
98 fdv = INCAASC_FDV_HIGH_BAUDRATE;
99 uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
100#endif
101
102 if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
103 {
104#ifndef INCAASC_USE_FDV
105 fdv = 3;
106 uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
107#else
108 fdv = INCAASC_FDV_LOW_BAUDRATE;
109 uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
110#endif
111
112 if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
113 {
114 return;
115 }
116 }
117
118
119 CLEAR_BIT(pAsc->asc_con, ASCCON_R);
120
121#ifndef INCAASC_USE_FDV
122
123
124
125
126
127 CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
128
129 if ( fdv == 2 )
130 CLEAR_BIT(pAsc->asc_con, ASCCON_BRS);
131 else
132 SET_BIT(pAsc->asc_con, ASCCON_BRS);
133
134#else
135
136
137 SET_BIT(pAsc->asc_con, ASCCON_FDE);
138
139
140 pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
141
142#endif
143
144
145 pAsc->asc_bg = uiReloadValue;
146
147
148 SET_BIT(pAsc->asc_con, ASCCON_R);
149}
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165static int serial_setopt (void)
166{
167 ulong con;
168
169 switch ( ASC_OPTIONS & ASCOPT_CSIZE )
170 {
171
172 case ASCOPT_CS7:
173 con = ASCCON_M_7ASYNCPAR;
174 break;
175
176
177 case ASCOPT_CS8:
178 if ( ASC_OPTIONS & ASCOPT_PARENB )
179 con = ASCCON_M_8ASYNCPAR;
180 else
181 con = ASCCON_M_8ASYNC;
182 break;
183
184
185
186
187
188 default:
189 return -1;
190 }
191
192 if ( ASC_OPTIONS & ASCOPT_STOPB )
193 SET_BIT(con, ASCCON_STP);
194 else
195 CLEAR_BIT(con, ASCCON_STP);
196
197 if ( ASC_OPTIONS & ASCOPT_PARENB )
198 SET_BIT(con, ASCCON_PEN);
199 else
200 CLEAR_BIT(con, ASCCON_PEN);
201
202 if ( ASC_OPTIONS & ASCOPT_PARODD )
203 SET_BIT(con, ASCCON_ODD);
204 else
205 CLEAR_BIT(con, ASCCON_ODD);
206
207 if ( ASC_OPTIONS & ASCOPT_CREAD )
208 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN);
209
210 pAsc->asc_con |= con;
211
212 return 0;
213}
214
215static void asc_serial_putc(const char c)
216{
217 uint txFl = 0;
218
219 if (c == '\n') serial_putc ('\r');
220
221
222
223 do
224 {
225 txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
226 }
227 while ( txFl == INCAASC_TXFIFO_FULL );
228
229 pAsc->asc_tbuf = c;
230
231
232 if ( pAsc->asc_con & ASCCON_OE )
233 {
234 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
235 return;
236 }
237}
238
239static int asc_serial_getc(void)
240{
241 ulong symbol_mask;
242 char c;
243
244 while (!serial_tstc());
245
246 symbol_mask =
247 ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
248
249 c = (char)(pAsc->asc_rbuf & symbol_mask);
250
251 return c;
252}
253
254static int asc_serial_tstc(void)
255{
256 int res = 1;
257
258 if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
259 {
260 res = 0;
261 }
262 else if ( pAsc->asc_con & ASCCON_FE )
263 {
264 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
265 res = 0;
266 }
267 else if ( pAsc->asc_con & ASCCON_PE )
268 {
269 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
270 res = 0;
271 }
272 else if ( pAsc->asc_con & ASCCON_OE )
273 {
274 SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
275 res = 0;
276 }
277
278 return res;
279}
280
281static struct serial_device asc_serial_drv = {
282 .name = "asc_serial",
283 .start = asc_serial_init,
284 .stop = NULL,
285 .setbrg = asc_serial_setbrg,
286 .putc = asc_serial_putc,
287 .puts = default_serial_puts,
288 .getc = asc_serial_getc,
289 .tstc = asc_serial_tstc,
290};
291
292void asc_serial_initialize(void)
293{
294 serial_register(&asc_serial_drv);
295}
296
297__weak struct serial_device *default_serial_console(void)
298{
299 return &asc_serial_drv;
300}
301