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