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