]>
Commit | Line | Data |
---|---|---|
3a473b2a WD |
1 | /* |
2 | * (C) Copyright 2001 | |
3 | * John Clemens <clemens@mclx.com>, Mission Critical Linux, Inc. | |
4 | * | |
1a459660 | 5 | * SPDX-License-Identifier: GPL-2.0+ |
3a473b2a WD |
6 | */ |
7 | ||
8 | /************************************************************************* | |
9 | * changes for Marvell DB64460 eval board 2003 by Ingo Assmus <ingo.assmus@keymile.com> | |
10 | * | |
11 | ************************************************************************/ | |
12 | ||
13 | /* | |
14 | * mpsc.c - driver for console over the MPSC. | |
15 | */ | |
16 | ||
17 | ||
18 | #include <common.h> | |
19 | #include <config.h> | |
20 | #include <asm/cache.h> | |
21 | ||
22 | #include <malloc.h> | |
23 | #include "mpsc.h" | |
24 | ||
25 | #include "mv_regs.h" | |
26 | ||
27 | #include "../include/memory.h" | |
28 | ||
d87080b7 WD |
29 | DECLARE_GLOBAL_DATA_PTR; |
30 | ||
3a473b2a WD |
31 | /* Define this if you wish to use the MPSC as a register based UART. |
32 | * This will force the serial port to not use the SDMA engine at all. | |
33 | */ | |
34 | #undef CONFIG_MPSC_DEBUG_PORT | |
35 | ||
36 | ||
37 | int (*mpsc_putchar) (char ch) = mpsc_putchar_early; | |
38 | char (*mpsc_getchar) (void) = mpsc_getchar_debug; | |
39 | int (*mpsc_test_char) (void) = mpsc_test_char_debug; | |
40 | ||
41 | ||
42 | static volatile unsigned int *rx_desc_base = NULL; | |
43 | static unsigned int rx_desc_index = 0; | |
44 | static volatile unsigned int *tx_desc_base = NULL; | |
45 | static unsigned int tx_desc_index = 0; | |
46 | ||
47 | /* local function declarations */ | |
48 | static int galmpsc_connect (int channel, int connect); | |
49 | static int galmpsc_route_rx_clock (int channel, int brg); | |
50 | static int galmpsc_route_tx_clock (int channel, int brg); | |
51 | static int galmpsc_write_config_regs (int mpsc, int mode); | |
52 | static int galmpsc_config_channel_regs (int mpsc); | |
53 | static int galmpsc_set_char_length (int mpsc, int value); | |
54 | static int galmpsc_set_stop_bit_length (int mpsc, int value); | |
55 | static int galmpsc_set_parity (int mpsc, int value); | |
56 | static int galmpsc_enter_hunt (int mpsc); | |
57 | static int galmpsc_set_brkcnt (int mpsc, int value); | |
58 | static int galmpsc_set_tcschar (int mpsc, int value); | |
59 | static int galmpsc_set_snoop (int mpsc, int value); | |
60 | static int galmpsc_shutdown (int mpsc); | |
61 | ||
62 | static int galsdma_set_RFT (int channel); | |
63 | static int galsdma_set_SFM (int channel); | |
64 | static int galsdma_set_rxle (int channel); | |
65 | static int galsdma_set_txle (int channel); | |
66 | static int galsdma_set_burstsize (int channel, unsigned int value); | |
67 | static int galsdma_set_RC (int channel, unsigned int value); | |
68 | ||
69 | static int galbrg_set_CDV (int channel, int value); | |
70 | static int galbrg_enable (int channel); | |
71 | static int galbrg_disable (int channel); | |
72 | static int galbrg_set_clksrc (int channel, int value); | |
73 | static int galbrg_set_CUV (int channel, int value); | |
74 | ||
75 | static void galsdma_enable_rx (void); | |
76 | static int galsdma_set_mem_space (unsigned int memSpace, | |
77 | unsigned int memSpaceTarget, | |
78 | unsigned int memSpaceAttr, | |
79 | unsigned int baseAddress, | |
80 | unsigned int size); | |
81 | ||
82 | ||
83 | #define SOFTWARE_CACHE_MANAGEMENT | |
84 | ||
85 | #ifdef SOFTWARE_CACHE_MANAGEMENT | |
86 | #define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));} | |
87 | #define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));} | |
88 | #define INVALIDATE_DCACHE(a,b) if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));} | |
89 | #else | |
90 | #define FLUSH_DCACHE(a,b) | |
91 | #define FLUSH_AND_INVALIDATE_DCACHE(a,b) | |
92 | #define INVALIDATE_DCACHE(a,b) | |
93 | #endif | |
94 | ||
95 | #ifdef CONFIG_MPSC_DEBUG_PORT | |
96 | static void mpsc_debug_init (void) | |
97 | { | |
98 | ||
99 | volatile unsigned int temp; | |
100 | ||
101 | /* Clear the CFR (CHR4) */ | |
102 | /* Write random 'Z' bit (bit 29) of CHR4 to enable debug uart *UNDOCUMENTED FEATURE* */ | |
d87080b7 | 103 | temp = GTREGREAD (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP)); |
3a473b2a WD |
104 | temp &= 0xffffff00; |
105 | temp |= BIT29; | |
106 | GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP), | |
107 | temp); | |
108 | ||
109 | /* Set the Valid bit 'V' (bit 12) and int generation bit 'INT' (bit 15) */ | |
110 | temp = GTREGREAD (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP)); | |
111 | temp |= (BIT12 | BIT15); | |
112 | GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (CHANNEL * GALMPSC_REG_GAP), | |
113 | temp); | |
114 | ||
115 | /* Set int mask */ | |
116 | temp = GTREGREAD (GALMPSC_0_INT_MASK); | |
117 | temp |= BIT6; | |
118 | GT_REG_WRITE (GALMPSC_0_INT_MASK, temp); | |
119 | } | |
120 | #endif | |
121 | ||
122 | char mpsc_getchar_debug (void) | |
123 | { | |
124 | volatile int temp; | |
125 | volatile unsigned int cause; | |
126 | ||
127 | cause = GTREGREAD (GALMPSC_0_INT_CAUSE); | |
128 | while ((cause & BIT6) == 0) { | |
129 | cause = GTREGREAD (GALMPSC_0_INT_CAUSE); | |
130 | } | |
131 | ||
132 | temp = GTREGREAD (GALMPSC_CHANNELREG_10 + | |
133 | (CHANNEL * GALMPSC_REG_GAP)); | |
134 | /* By writing 1's to the set bits, the register is cleared */ | |
135 | GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (CHANNEL * GALMPSC_REG_GAP), | |
136 | temp); | |
137 | GT_REG_WRITE (GALMPSC_0_INT_CAUSE, cause & ~BIT6); | |
138 | return (temp >> 16) & 0xff; | |
139 | } | |
140 | ||
141 | /* special function for running out of flash. doesn't modify any | |
142 | * global variables [josh] */ | |
143 | int mpsc_putchar_early (char ch) | |
144 | { | |
3a473b2a WD |
145 | int mpsc = CHANNEL; |
146 | int temp = | |
147 | GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); | |
148 | galmpsc_set_tcschar (mpsc, ch); | |
149 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), | |
150 | temp | 0x200); | |
151 | ||
152 | #define MAGIC_FACTOR (10*1000000) | |
153 | ||
154 | udelay (MAGIC_FACTOR / gd->baudrate); | |
155 | return 0; | |
156 | } | |
157 | ||
158 | /* This is used after relocation, see serial.c and mpsc_init2 */ | |
159 | static int mpsc_putchar_sdma (char ch) | |
160 | { | |
161 | volatile unsigned int *p; | |
162 | unsigned int temp; | |
163 | ||
164 | ||
165 | /* align the descriptor */ | |
166 | p = tx_desc_base; | |
167 | memset ((void *) p, 0, 8 * sizeof (unsigned int)); | |
168 | ||
169 | /* fill one 64 bit buffer */ | |
170 | /* word swap, pad with 0 */ | |
171 | p[4] = 0; /* x */ | |
172 | p[5] = (unsigned int) ch; /* x */ | |
173 | ||
174 | /* CHANGED completely according to GT64260A dox - NTL */ | |
175 | p[0] = 0x00010001; /* 0 */ | |
176 | p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; /* 4 */ | |
177 | p[2] = 0; /* 8 */ | |
178 | p[3] = (unsigned int) &p[4]; /* c */ | |
179 | ||
180 | #if 0 | |
181 | p[9] = DESC_FIRST | DESC_LAST; | |
182 | p[10] = (unsigned int) &p[0]; | |
183 | p[11] = (unsigned int) &p[12]; | |
184 | #endif | |
185 | ||
186 | FLUSH_DCACHE (&p[0], &p[8]); | |
187 | ||
188 | GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF), | |
189 | (unsigned int) &p[0]); | |
190 | GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR + (CHANNEL * GALSDMA_REG_DIFF), | |
191 | (unsigned int) &p[0]); | |
192 | ||
193 | temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF)); | |
194 | temp |= (TX_DEMAND | TX_STOP); | |
195 | GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp); | |
196 | ||
197 | INVALIDATE_DCACHE (&p[1], &p[2]); | |
198 | ||
199 | while (p[1] & DESC_OWNER_BIT) { | |
200 | udelay (100); | |
201 | INVALIDATE_DCACHE (&p[1], &p[2]); | |
202 | } | |
203 | return 0; | |
204 | } | |
205 | ||
206 | char mpsc_getchar_sdma (void) | |
207 | { | |
208 | static unsigned int done = 0; | |
209 | volatile char ch; | |
210 | unsigned int len = 0, idx = 0, temp; | |
211 | ||
212 | volatile unsigned int *p; | |
213 | ||
214 | ||
215 | do { | |
216 | p = &rx_desc_base[rx_desc_index * 8]; | |
217 | ||
218 | INVALIDATE_DCACHE (&p[0], &p[1]); | |
219 | /* Wait for character */ | |
220 | while (p[1] & DESC_OWNER_BIT) { | |
221 | udelay (100); | |
222 | INVALIDATE_DCACHE (&p[0], &p[1]); | |
223 | } | |
224 | ||
225 | /* Handle error case */ | |
226 | if (p[1] & (1 << 15)) { | |
227 | printf ("oops, error: %08x\n", p[1]); | |
228 | ||
229 | temp = GTREGREAD (GALMPSC_CHANNELREG_2 + | |
230 | (CHANNEL * GALMPSC_REG_GAP)); | |
231 | temp |= (1 << 23); | |
232 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + | |
233 | (CHANNEL * GALMPSC_REG_GAP), temp); | |
234 | ||
235 | /* Can't poll on abort bit, so we just wait. */ | |
236 | udelay (100); | |
237 | ||
238 | galsdma_enable_rx (); | |
239 | } | |
240 | ||
241 | /* Number of bytes left in this descriptor */ | |
242 | len = p[0] & 0xffff; | |
243 | ||
244 | if (len) { | |
245 | /* Where to look */ | |
246 | idx = 5; | |
247 | if (done > 3) | |
248 | idx = 4; | |
249 | if (done > 7) | |
250 | idx = 7; | |
251 | if (done > 11) | |
252 | idx = 6; | |
253 | ||
254 | INVALIDATE_DCACHE (&p[idx], &p[idx + 1]); | |
255 | ch = p[idx] & 0xff; | |
256 | done++; | |
257 | } | |
258 | ||
259 | if (done < len) { | |
260 | /* this descriptor has more bytes still | |
261 | * shift down the char we just read, and leave the | |
262 | * buffer in place for the next time around | |
263 | */ | |
264 | p[idx] = p[idx] >> 8; | |
265 | FLUSH_DCACHE (&p[idx], &p[idx + 1]); | |
266 | } | |
267 | ||
268 | if (done == len) { | |
269 | /* nothing left in this descriptor. | |
270 | * go to next one | |
271 | */ | |
272 | p[1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; | |
273 | p[0] = 0x00100000; | |
274 | FLUSH_DCACHE (&p[0], &p[1]); | |
275 | /* Next descriptor */ | |
276 | rx_desc_index = (rx_desc_index + 1) % RX_DESC; | |
277 | done = 0; | |
278 | } | |
279 | } while (len == 0); /* galileo bug.. len might be zero */ | |
280 | ||
281 | return ch; | |
282 | } | |
283 | ||
284 | ||
285 | int mpsc_test_char_debug (void) | |
286 | { | |
287 | if ((GTREGREAD (GALMPSC_0_INT_CAUSE) & BIT6) == 0) | |
288 | return 0; | |
289 | else { | |
290 | return 1; | |
291 | } | |
292 | } | |
293 | ||
294 | ||
295 | int mpsc_test_char_sdma (void) | |
296 | { | |
297 | volatile unsigned int *p = &rx_desc_base[rx_desc_index * 8]; | |
298 | ||
299 | INVALIDATE_DCACHE (&p[1], &p[2]); | |
300 | ||
301 | if (p[1] & DESC_OWNER_BIT) | |
302 | return 0; | |
303 | else | |
304 | return 1; | |
305 | } | |
306 | ||
307 | int mpsc_init (int baud) | |
308 | { | |
309 | /* BRG CONFIG */ | |
310 | galbrg_set_baudrate (CHANNEL, baud); | |
311 | galbrg_set_clksrc (CHANNEL, 8); /* set source=Tclk */ | |
312 | galbrg_set_CUV (CHANNEL, 0); /* set up CountUpValue */ | |
313 | galbrg_enable (CHANNEL); /* Enable BRG */ | |
314 | ||
315 | /* Set up clock routing */ | |
316 | galmpsc_connect (CHANNEL, GALMPSC_CONNECT); /* connect it */ | |
317 | ||
318 | galmpsc_route_rx_clock (CHANNEL, CHANNEL); /* chosse BRG0 for Rx */ | |
319 | galmpsc_route_tx_clock (CHANNEL, CHANNEL); /* chose BRG0 for Tx */ | |
320 | ||
321 | /* reset MPSC state */ | |
322 | galmpsc_shutdown (CHANNEL); | |
323 | ||
324 | /* SDMA CONFIG */ | |
325 | galsdma_set_burstsize (CHANNEL, L1_CACHE_BYTES / 8); /* in 64 bit words (8 bytes) */ | |
326 | galsdma_set_txle (CHANNEL); | |
327 | galsdma_set_rxle (CHANNEL); | |
328 | galsdma_set_RC (CHANNEL, 0xf); | |
329 | galsdma_set_SFM (CHANNEL); | |
330 | galsdma_set_RFT (CHANNEL); | |
331 | ||
332 | /* MPSC CONFIG */ | |
333 | galmpsc_write_config_regs (CHANNEL, GALMPSC_UART); | |
334 | galmpsc_config_channel_regs (CHANNEL); | |
335 | galmpsc_set_char_length (CHANNEL, GALMPSC_CHAR_LENGTH_8); /* 8 */ | |
336 | galmpsc_set_parity (CHANNEL, GALMPSC_PARITY_NONE); /* N */ | |
337 | galmpsc_set_stop_bit_length (CHANNEL, GALMPSC_STOP_BITS_1); /* 1 */ | |
338 | ||
339 | #ifdef CONFIG_MPSC_DEBUG_PORT | |
340 | mpsc_debug_init (); | |
341 | #endif | |
342 | ||
343 | /* COMM_MPSC CONFIG */ | |
344 | #ifdef SOFTWARE_CACHE_MANAGEMENT | |
345 | galmpsc_set_snoop (CHANNEL, 0); /* disable snoop */ | |
346 | #else | |
347 | galmpsc_set_snoop (CHANNEL, 1); /* enable snoop */ | |
348 | #endif | |
349 | ||
350 | return 0; | |
351 | } | |
352 | ||
353 | ||
354 | void mpsc_sdma_init (void) | |
355 | { | |
356 | /* Setup SDMA channel0 SDMA_CONFIG_REG*/ | |
357 | GT_REG_WRITE (SDMA_CONFIG_REG (0), 0x000020ff); | |
358 | ||
359 | /* Enable MPSC-Window0 for DRAM Bank0 */ | |
360 | if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT, | |
361 | MV64460_SDMA_DRAM_CS_0_TARGET, | |
362 | 0, | |
363 | memoryGetBankBaseAddress | |
364 | (CS_0_LOW_DECODE_ADDRESS), | |
365 | memoryGetBankSize (BANK0)) != true) | |
366 | printf ("%s: SDMA_Window0 memory setup failed !!! \n", | |
367 | __FUNCTION__); | |
368 | ||
369 | ||
370 | /* Disable MPSC-Window1 */ | |
371 | if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_1_BIT, | |
372 | MV64460_SDMA_DRAM_CS_0_TARGET, | |
373 | 0, | |
374 | memoryGetBankBaseAddress | |
375 | (CS_1_LOW_DECODE_ADDRESS), | |
376 | memoryGetBankSize (BANK3)) != true) | |
377 | printf ("%s: SDMA_Window1 memory setup failed !!! \n", | |
378 | __FUNCTION__); | |
379 | ||
380 | ||
381 | /* Disable MPSC-Window2 */ | |
382 | if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_2_BIT, | |
383 | MV64460_SDMA_DRAM_CS_0_TARGET, | |
384 | 0, | |
385 | memoryGetBankBaseAddress | |
386 | (CS_2_LOW_DECODE_ADDRESS), | |
387 | memoryGetBankSize (BANK3)) != true) | |
388 | printf ("%s: SDMA_Window2 memory setup failed !!! \n", | |
389 | __FUNCTION__); | |
390 | ||
391 | ||
392 | /* Disable MPSC-Window3 */ | |
393 | if (galsdma_set_mem_space (MV64460_CUNIT_BASE_ADDR_WIN_3_BIT, | |
394 | MV64460_SDMA_DRAM_CS_0_TARGET, | |
395 | 0, | |
396 | memoryGetBankBaseAddress | |
397 | (CS_3_LOW_DECODE_ADDRESS), | |
398 | memoryGetBankSize (BANK3)) != true) | |
399 | printf ("%s: SDMA_Window3 memory setup failed !!! \n", | |
400 | __FUNCTION__); | |
401 | ||
402 | /* Setup MPSC0 access mode Window0 full access */ | |
403 | GT_SET_REG_BITS (MPSC0_ACCESS_PROTECTION_REG, | |
404 | (MV64460_SDMA_WIN_ACCESS_FULL << | |
405 | (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); | |
406 | ||
407 | /* Setup MPSC1 access mode Window1 full access */ | |
408 | GT_SET_REG_BITS (MPSC1_ACCESS_PROTECTION_REG, | |
409 | (MV64460_SDMA_WIN_ACCESS_FULL << | |
410 | (MV64460_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); | |
411 | ||
53677ef1 | 412 | /* Setup MPSC internal address space base address */ |
6d0f6bcf | 413 | GT_REG_WRITE (CUNIT_INTERNAL_SPACE_BASE_ADDR_REG, CONFIG_SYS_GT_REGS); |
3a473b2a WD |
414 | |
415 | /* no high address remap*/ | |
416 | GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG0, 0x00); | |
417 | GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG1, 0x00); | |
418 | ||
419 | /* clear interrupt cause register for MPSC (fault register)*/ | |
420 | GT_REG_WRITE (CUNIT_INTERRUPT_CAUSE_REG, 0x00); | |
421 | } | |
422 | ||
423 | ||
424 | void mpsc_init2 (void) | |
425 | { | |
426 | int i; | |
427 | ||
428 | #ifndef CONFIG_MPSC_DEBUG_PORT | |
429 | mpsc_putchar = mpsc_putchar_sdma; | |
430 | mpsc_getchar = mpsc_getchar_sdma; | |
431 | mpsc_test_char = mpsc_test_char_sdma; | |
432 | #endif | |
433 | /* RX descriptors */ | |
434 | rx_desc_base = (unsigned int *) malloc (((RX_DESC + 1) * 8) * | |
435 | sizeof (unsigned int)); | |
436 | ||
437 | /* align descriptors */ | |
438 | rx_desc_base = (unsigned int *) | |
439 | (((unsigned int) rx_desc_base + 32) & 0xFFFFFFF0); | |
440 | ||
441 | rx_desc_index = 0; | |
442 | ||
443 | memset ((void *) rx_desc_base, 0, | |
444 | (RX_DESC * 8) * sizeof (unsigned int)); | |
445 | ||
446 | for (i = 0; i < RX_DESC; i++) { | |
447 | rx_desc_base[i * 8 + 3] = (unsigned int) &rx_desc_base[i * 8 + 4]; /* Buffer */ | |
448 | rx_desc_base[i * 8 + 2] = (unsigned int) &rx_desc_base[(i + 1) * 8]; /* Next descriptor */ | |
449 | rx_desc_base[i * 8 + 1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; /* Command & control */ | |
450 | rx_desc_base[i * 8] = 0x00100000; | |
451 | } | |
452 | rx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &rx_desc_base[0]; | |
453 | ||
454 | FLUSH_DCACHE (&rx_desc_base[0], &rx_desc_base[RX_DESC * 8]); | |
455 | GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR + (CHANNEL * GALSDMA_REG_DIFF), | |
456 | (unsigned int) &rx_desc_base[0]); | |
457 | ||
458 | /* TX descriptors */ | |
459 | tx_desc_base = (unsigned int *) malloc (((TX_DESC + 1) * 8) * | |
460 | sizeof (unsigned int)); | |
461 | ||
462 | /* align descriptors */ | |
463 | tx_desc_base = (unsigned int *) | |
464 | (((unsigned int) tx_desc_base + 32) & 0xFFFFFFF0); | |
465 | ||
466 | tx_desc_index = -1; | |
467 | ||
468 | memset ((void *) tx_desc_base, 0, | |
469 | (TX_DESC * 8) * sizeof (unsigned int)); | |
470 | ||
471 | for (i = 0; i < TX_DESC; i++) { | |
472 | tx_desc_base[i * 8 + 5] = (unsigned int) 0x23232323; | |
473 | tx_desc_base[i * 8 + 4] = (unsigned int) 0x23232323; | |
474 | tx_desc_base[i * 8 + 3] = | |
475 | (unsigned int) &tx_desc_base[i * 8 + 4]; | |
476 | tx_desc_base[i * 8 + 2] = | |
477 | (unsigned int) &tx_desc_base[(i + 1) * 8]; | |
478 | tx_desc_base[i * 8 + 1] = | |
479 | DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; | |
480 | ||
481 | /* set sbytecnt and shadow byte cnt to 1 */ | |
482 | tx_desc_base[i * 8] = 0x00010001; | |
483 | } | |
484 | tx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &tx_desc_base[0]; | |
485 | ||
486 | FLUSH_DCACHE (&tx_desc_base[0], &tx_desc_base[TX_DESC * 8]); | |
487 | ||
488 | udelay (100); | |
489 | ||
490 | galsdma_enable_rx (); | |
491 | ||
492 | return; | |
493 | } | |
494 | ||
495 | int galbrg_set_baudrate (int channel, int rate) | |
496 | { | |
3a473b2a WD |
497 | int clock; |
498 | ||
499 | galbrg_disable (channel); /*ok */ | |
500 | ||
501 | #ifdef ZUMA_NTL | |
502 | /* from tclk */ | |
6d0f6bcf | 503 | clock = (CONFIG_SYS_TCLK / (16 * rate)) - 1; |
3a473b2a | 504 | #else |
6d0f6bcf | 505 | clock = (CONFIG_SYS_TCLK / (16 * rate)) - 1; |
3a473b2a WD |
506 | #endif |
507 | ||
508 | galbrg_set_CDV (channel, clock); /* set timer Reg. for BRG */ | |
509 | ||
510 | galbrg_enable (channel); | |
511 | ||
512 | gd->baudrate = rate; | |
513 | ||
514 | return 0; | |
515 | } | |
516 | ||
517 | /* ------------------------------------------------------------------ */ | |
518 | ||
519 | /* Below are all the private functions that no one else needs */ | |
520 | ||
521 | static int galbrg_set_CDV (int channel, int value) | |
522 | { | |
523 | unsigned int temp; | |
524 | ||
525 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
526 | temp &= 0xFFFF0000; | |
527 | temp |= (value & 0x0000FFFF); | |
528 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
529 | ||
530 | return 0; | |
531 | } | |
532 | ||
533 | static int galbrg_enable (int channel) | |
534 | { | |
535 | unsigned int temp; | |
536 | ||
537 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
538 | temp |= 0x00010000; | |
539 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
540 | ||
541 | return 0; | |
542 | } | |
543 | ||
544 | static int galbrg_disable (int channel) | |
545 | { | |
546 | unsigned int temp; | |
547 | ||
548 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
549 | temp &= 0xFFFEFFFF; | |
550 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
551 | ||
552 | return 0; | |
553 | } | |
554 | ||
555 | static int galbrg_set_clksrc (int channel, int value) | |
556 | { | |
557 | unsigned int temp; | |
558 | ||
559 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
560 | temp &= 0xFFC3FFFF; /* Bit 18 - 21 (MV 64260 18-22) */ | |
561 | temp |= (value << 18); | |
562 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
563 | return 0; | |
564 | } | |
565 | ||
566 | static int galbrg_set_CUV (int channel, int value) | |
567 | { | |
568 | /* set CountUpValue */ | |
569 | GT_REG_WRITE (GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value); | |
570 | ||
571 | return 0; | |
572 | } | |
573 | ||
574 | #if 0 | |
575 | static int galbrg_reset (int channel) | |
576 | { | |
577 | unsigned int temp; | |
578 | ||
579 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
580 | temp |= 0x20000; | |
581 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
582 | ||
583 | return 0; | |
584 | } | |
585 | #endif | |
586 | ||
587 | static int galsdma_set_RFT (int channel) | |
588 | { | |
589 | unsigned int temp; | |
590 | ||
591 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
592 | temp |= 0x00000001; | |
593 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
594 | temp); | |
595 | ||
596 | return 0; | |
597 | } | |
598 | ||
599 | static int galsdma_set_SFM (int channel) | |
600 | { | |
601 | unsigned int temp; | |
602 | ||
603 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
604 | temp |= 0x00000002; | |
605 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
606 | temp); | |
607 | ||
608 | return 0; | |
609 | } | |
610 | ||
611 | static int galsdma_set_rxle (int channel) | |
612 | { | |
613 | unsigned int temp; | |
614 | ||
615 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
616 | temp |= 0x00000040; | |
617 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
618 | temp); | |
619 | ||
620 | return 0; | |
621 | } | |
622 | ||
623 | static int galsdma_set_txle (int channel) | |
624 | { | |
625 | unsigned int temp; | |
626 | ||
627 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
628 | temp |= 0x00000080; | |
629 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
630 | temp); | |
631 | ||
632 | return 0; | |
633 | } | |
634 | ||
635 | static int galsdma_set_RC (int channel, unsigned int value) | |
636 | { | |
637 | unsigned int temp; | |
638 | ||
639 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
640 | temp &= ~0x0000003c; | |
641 | temp |= (value << 2); | |
642 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
643 | temp); | |
644 | ||
645 | return 0; | |
646 | } | |
647 | ||
648 | static int galsdma_set_burstsize (int channel, unsigned int value) | |
649 | { | |
650 | unsigned int temp; | |
651 | ||
652 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
653 | temp &= 0xFFFFCFFF; | |
654 | switch (value) { | |
655 | case 8: | |
656 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
657 | (channel * GALSDMA_REG_DIFF), | |
658 | (temp | (0x3 << 12))); | |
659 | break; | |
660 | ||
661 | case 4: | |
662 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
663 | (channel * GALSDMA_REG_DIFF), | |
664 | (temp | (0x2 << 12))); | |
665 | break; | |
666 | ||
667 | case 2: | |
668 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
669 | (channel * GALSDMA_REG_DIFF), | |
670 | (temp | (0x1 << 12))); | |
671 | break; | |
672 | ||
673 | case 1: | |
674 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
675 | (channel * GALSDMA_REG_DIFF), | |
676 | (temp | (0x0 << 12))); | |
677 | break; | |
678 | ||
679 | default: | |
680 | return -1; | |
681 | break; | |
682 | } | |
683 | ||
684 | return 0; | |
685 | } | |
686 | ||
687 | static int galmpsc_connect (int channel, int connect) | |
688 | { | |
689 | unsigned int temp; | |
690 | ||
691 | temp = GTREGREAD (GALMPSC_ROUTING_REGISTER); | |
692 | ||
693 | if ((channel == 0) && connect) | |
694 | temp &= ~0x00000007; | |
695 | else if ((channel == 1) && connect) | |
696 | temp &= ~(0x00000007 << 6); | |
697 | else if ((channel == 0) && !connect) | |
698 | temp |= 0x00000007; | |
699 | else | |
700 | temp |= (0x00000007 << 6); | |
701 | ||
702 | /* Just in case... */ | |
703 | temp &= 0x3fffffff; | |
704 | ||
705 | GT_REG_WRITE (GALMPSC_ROUTING_REGISTER, temp); | |
706 | ||
707 | return 0; | |
708 | } | |
709 | ||
710 | static int galmpsc_route_rx_clock (int channel, int brg) | |
711 | { | |
712 | unsigned int temp; | |
713 | ||
714 | temp = GTREGREAD (GALMPSC_RxC_ROUTE); | |
715 | ||
716 | if (channel == 0) { | |
717 | temp &= ~0x0000000F; | |
718 | temp |= brg; | |
719 | } else { | |
720 | temp &= ~0x00000F00; | |
721 | temp |= (brg << 8); | |
722 | } | |
723 | ||
724 | GT_REG_WRITE (GALMPSC_RxC_ROUTE, temp); | |
725 | ||
726 | return 0; | |
727 | } | |
728 | ||
729 | static int galmpsc_route_tx_clock (int channel, int brg) | |
730 | { | |
731 | unsigned int temp; | |
732 | ||
733 | temp = GTREGREAD (GALMPSC_TxC_ROUTE); | |
734 | ||
735 | if (channel == 0) { | |
736 | temp &= ~0x0000000F; | |
737 | temp |= brg; | |
738 | } else { | |
739 | temp &= ~0x00000F00; | |
740 | temp |= (brg << 8); | |
741 | } | |
742 | ||
743 | GT_REG_WRITE (GALMPSC_TxC_ROUTE, temp); | |
744 | ||
745 | return 0; | |
746 | } | |
747 | ||
748 | static int galmpsc_write_config_regs (int mpsc, int mode) | |
749 | { | |
750 | if (mode == GALMPSC_UART) { | |
751 | /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */ | |
752 | GT_REG_WRITE (GALMPSC_MCONF_LOW + (mpsc * GALMPSC_REG_GAP), | |
753 | 0x000004c4); | |
754 | ||
755 | /* Main config reg High (32x Rx/Tx clock mode, width=8bits */ | |
756 | GT_REG_WRITE (GALMPSC_MCONF_HIGH + (mpsc * GALMPSC_REG_GAP), | |
757 | 0x024003f8); | |
758 | /* 22 2222 1111 */ | |
759 | /* 54 3210 9876 */ | |
760 | /* 0000 0010 0000 0000 */ | |
761 | /* 1 */ | |
762 | /* 098 7654 3210 */ | |
763 | /* 0000 0011 1111 1000 */ | |
764 | } else | |
765 | return -1; | |
766 | ||
767 | return 0; | |
768 | } | |
769 | ||
770 | static int galmpsc_config_channel_regs (int mpsc) | |
771 | { | |
772 | GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), 0); | |
773 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), 0); | |
774 | GT_REG_WRITE (GALMPSC_CHANNELREG_3 + (mpsc * GALMPSC_REG_GAP), 1); | |
775 | GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (mpsc * GALMPSC_REG_GAP), 0); | |
776 | GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (mpsc * GALMPSC_REG_GAP), 0); | |
777 | GT_REG_WRITE (GALMPSC_CHANNELREG_6 + (mpsc * GALMPSC_REG_GAP), 0); | |
778 | GT_REG_WRITE (GALMPSC_CHANNELREG_7 + (mpsc * GALMPSC_REG_GAP), 0); | |
779 | GT_REG_WRITE (GALMPSC_CHANNELREG_8 + (mpsc * GALMPSC_REG_GAP), 0); | |
780 | GT_REG_WRITE (GALMPSC_CHANNELREG_9 + (mpsc * GALMPSC_REG_GAP), 0); | |
781 | GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (mpsc * GALMPSC_REG_GAP), 0); | |
782 | ||
783 | galmpsc_set_brkcnt (mpsc, 0x3); | |
784 | galmpsc_set_tcschar (mpsc, 0xab); | |
785 | ||
786 | return 0; | |
787 | } | |
788 | ||
789 | static int galmpsc_set_brkcnt (int mpsc, int value) | |
790 | { | |
791 | unsigned int temp; | |
792 | ||
793 | temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); | |
794 | temp &= 0x0000FFFF; | |
795 | temp |= (value << 16); | |
796 | GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); | |
797 | ||
798 | return 0; | |
799 | } | |
800 | ||
801 | static int galmpsc_set_tcschar (int mpsc, int value) | |
802 | { | |
803 | unsigned int temp; | |
804 | ||
805 | temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); | |
806 | temp &= 0xFFFF0000; | |
807 | temp |= value; | |
808 | GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); | |
809 | ||
810 | return 0; | |
811 | } | |
812 | ||
813 | static int galmpsc_set_char_length (int mpsc, int value) | |
814 | { | |
815 | unsigned int temp; | |
816 | ||
817 | temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); | |
818 | temp &= 0xFFFFCFFF; | |
819 | temp |= (value << 12); | |
820 | GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); | |
821 | ||
822 | return 0; | |
823 | } | |
824 | ||
825 | static int galmpsc_set_stop_bit_length (int mpsc, int value) | |
826 | { | |
827 | unsigned int temp; | |
828 | ||
829 | temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); | |
830 | temp &= 0xFFFFBFFF; | |
831 | temp |= (value << 14); | |
832 | GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); | |
833 | ||
834 | return 0; | |
835 | } | |
836 | ||
837 | static int galmpsc_set_parity (int mpsc, int value) | |
838 | { | |
839 | unsigned int temp; | |
840 | ||
841 | temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); | |
842 | if (value != -1) { | |
843 | temp &= 0xFFF3FFF3; | |
844 | temp |= ((value << 18) | (value << 2)); | |
845 | temp |= ((value << 17) | (value << 1)); | |
846 | } else { | |
847 | temp &= 0xFFF1FFF1; | |
848 | } | |
849 | ||
850 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); | |
851 | ||
852 | return 0; | |
853 | } | |
854 | ||
855 | static int galmpsc_enter_hunt (int mpsc) | |
856 | { | |
857 | int temp; | |
858 | ||
859 | temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); | |
860 | temp |= 0x80000000; | |
861 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); | |
862 | ||
863 | while (GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)) & | |
864 | MPSC_ENTER_HUNT) { | |
865 | udelay (1); | |
866 | } | |
867 | return 0; | |
868 | } | |
869 | ||
870 | ||
871 | static int galmpsc_shutdown (int mpsc) | |
872 | { | |
873 | unsigned int temp; | |
874 | ||
875 | /* cause RX abort (clears RX) */ | |
876 | temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); | |
877 | temp |= MPSC_RX_ABORT | MPSC_TX_ABORT; | |
878 | temp &= ~MPSC_ENTER_HUNT; | |
879 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); | |
880 | ||
881 | GT_REG_WRITE (GALSDMA_0_COM_REG, 0); | |
882 | GT_REG_WRITE (GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT); | |
883 | ||
884 | /* shut down the MPSC */ | |
885 | GT_REG_WRITE (GALMPSC_MCONF_LOW, 0); | |
886 | GT_REG_WRITE (GALMPSC_MCONF_HIGH, 0); | |
887 | GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), 0); | |
888 | ||
889 | udelay (100); | |
890 | ||
891 | /* shut down the sdma engines. */ | |
892 | /* reset config to default */ | |
893 | GT_REG_WRITE (GALSDMA_0_CONF_REG, 0x000000fc); | |
894 | ||
895 | udelay (100); | |
896 | ||
897 | /* clear the SDMA current and first TX and RX pointers */ | |
898 | GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR, 0); | |
899 | GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR, 0); | |
900 | GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR, 0); | |
901 | ||
902 | udelay (100); | |
903 | ||
904 | return 0; | |
905 | } | |
906 | ||
907 | static void galsdma_enable_rx (void) | |
908 | { | |
909 | int temp; | |
910 | ||
911 | /* Enable RX processing */ | |
912 | temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF)); | |
913 | temp |= RX_ENABLE; | |
914 | GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp); | |
915 | ||
916 | galmpsc_enter_hunt (CHANNEL); | |
917 | } | |
918 | ||
919 | static int galmpsc_set_snoop (int mpsc, int value) | |
920 | { | |
921 | int reg = | |
922 | mpsc ? MPSC_1_ADDRESS_CONTROL_LOW : | |
923 | MPSC_0_ADDRESS_CONTROL_LOW; | |
924 | int temp = GTREGREAD (reg); | |
925 | ||
926 | if (value) | |
927 | temp |= (1 << 6) | (1 << 14) | (1 << 22) | (1 << 30); | |
928 | else | |
929 | temp &= ~((1 << 6) | (1 << 14) | (1 << 22) | (1 << 30)); | |
930 | GT_REG_WRITE (reg, temp); | |
931 | return 0; | |
932 | } | |
933 | ||
934 | /******************************************************************************* | |
935 | * galsdma_set_mem_space - Set MV64460 IDMA memory decoding map. | |
936 | * | |
937 | * DESCRIPTION: | |
938 | * the MV64460 SDMA has its own address decoding map that is de-coupled | |
939 | * from the CPU interface address decoding windows. The SDMA channels | |
940 | * share four address windows. Each region can be individually configured | |
941 | * by this function by associating it to a target interface and setting | |
942 | * base and size values. | |
943 | * | |
944 | * NOTE!!! | |
945 | * The size must be in 64Kbyte granularity. | |
946 | * The base address must be aligned to the size. | |
947 | * The size must be a series of 1s followed by a series of zeros | |
948 | * | |
949 | * OUTPUT: | |
950 | * None. | |
951 | * | |
952 | * RETURN: | |
472d5460 | 953 | * true for success, false otherwise. |
3a473b2a WD |
954 | * |
955 | *******************************************************************************/ | |
956 | ||
957 | static int galsdma_set_mem_space (unsigned int memSpace, | |
958 | unsigned int memSpaceTarget, | |
959 | unsigned int memSpaceAttr, | |
960 | unsigned int baseAddress, unsigned int size) | |
961 | { | |
962 | unsigned int temp; | |
963 | ||
964 | if (size == 0) { | |
965 | GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG, | |
966 | 1 << memSpace); | |
967 | return true; | |
968 | } | |
969 | ||
970 | /* The base address must be aligned to the size. */ | |
971 | if (baseAddress % size != 0) { | |
972 | return false; | |
973 | } | |
974 | if (size < 0x10000) { | |
975 | return false; | |
976 | } | |
977 | ||
978 | /* Align size and base to 64K */ | |
979 | baseAddress &= 0xffff0000; | |
980 | size &= 0xffff0000; | |
981 | temp = size >> 16; | |
982 | ||
983 | /* Checking that the size is a sequence of '1' followed by a | |
984 | sequence of '0' starting from LSB to MSB. */ | |
985 | while ((temp > 0) && (temp & 0x1)) { | |
986 | temp = temp >> 1; | |
987 | } | |
988 | ||
989 | if (temp != 0) { | |
990 | GT_REG_WRITE (MV64460_CUNIT_BASE_ADDR_REG0 + memSpace * 8, | |
991 | (baseAddress | memSpaceTarget | memSpaceAttr)); | |
992 | GT_REG_WRITE ((MV64460_CUNIT_SIZE0 + memSpace * 8), | |
993 | (size - 1) & 0xffff0000); | |
994 | GT_RESET_REG_BITS (MV64460_CUNIT_BASE_ADDR_ENABLE_REG, | |
995 | 1 << memSpace); | |
996 | } else { | |
997 | /* An invalid size was specified */ | |
998 | return false; | |
999 | } | |
1000 | return true; | |
1001 | } |