]>
Commit | Line | Data |
---|---|---|
3a473b2a WD |
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 DB64360 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 "../include/memory.h" | |
44 | ||
d87080b7 WD |
45 | DECLARE_GLOBAL_DATA_PTR; |
46 | ||
3a473b2a WD |
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* */ | |
d87080b7 | 119 | temp = GTREGREAD (GALMPSC_CHANNELREG_4 + (CHANNEL * GALMPSC_REG_GAP)); |
3a473b2a WD |
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 | { | |
3a473b2a WD |
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 Bank0 */ | |
376 | if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_0_BIT, | |
377 | MV64360_SDMA_DRAM_CS_0_TARGET, | |
378 | 0, | |
379 | memoryGetBankBaseAddress | |
380 | (CS_0_LOW_DECODE_ADDRESS), | |
381 | memoryGetBankSize (BANK0)) != true) | |
382 | printf ("%s: SDMA_Window0 memory setup failed !!! \n", | |
383 | __FUNCTION__); | |
384 | ||
385 | ||
386 | /* Disable MPSC-Window1 */ | |
387 | if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_1_BIT, | |
388 | MV64360_SDMA_DRAM_CS_0_TARGET, | |
389 | 0, | |
390 | memoryGetBankBaseAddress | |
391 | (CS_1_LOW_DECODE_ADDRESS), | |
392 | memoryGetBankSize (BANK3)) != true) | |
393 | printf ("%s: SDMA_Window1 memory setup failed !!! \n", | |
394 | __FUNCTION__); | |
395 | ||
396 | ||
397 | /* Disable MPSC-Window2 */ | |
398 | if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_2_BIT, | |
399 | MV64360_SDMA_DRAM_CS_0_TARGET, | |
400 | 0, | |
401 | memoryGetBankBaseAddress | |
402 | (CS_2_LOW_DECODE_ADDRESS), | |
403 | memoryGetBankSize (BANK3)) != true) | |
404 | printf ("%s: SDMA_Window2 memory setup failed !!! \n", | |
405 | __FUNCTION__); | |
406 | ||
407 | ||
408 | /* Disable MPSC-Window3 */ | |
409 | if (galsdma_set_mem_space (MV64360_CUNIT_BASE_ADDR_WIN_3_BIT, | |
410 | MV64360_SDMA_DRAM_CS_0_TARGET, | |
411 | 0, | |
412 | memoryGetBankBaseAddress | |
413 | (CS_3_LOW_DECODE_ADDRESS), | |
414 | memoryGetBankSize (BANK3)) != true) | |
415 | printf ("%s: SDMA_Window3 memory setup failed !!! \n", | |
416 | __FUNCTION__); | |
417 | ||
418 | /* Setup MPSC0 access mode Window0 full access */ | |
419 | GT_SET_REG_BITS (MPSC0_ACCESS_PROTECTION_REG, | |
420 | (MV64360_SDMA_WIN_ACCESS_FULL << | |
421 | (MV64360_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); | |
422 | ||
423 | /* Setup MPSC1 access mode Window1 full access */ | |
424 | GT_SET_REG_BITS (MPSC1_ACCESS_PROTECTION_REG, | |
425 | (MV64360_SDMA_WIN_ACCESS_FULL << | |
426 | (MV64360_CUNIT_BASE_ADDR_WIN_0_BIT * 2))); | |
427 | ||
53677ef1 | 428 | /* Setup MPSC internal address space base address */ |
6d0f6bcf | 429 | GT_REG_WRITE (CUNIT_INTERNAL_SPACE_BASE_ADDR_REG, CONFIG_SYS_GT_REGS); |
3a473b2a WD |
430 | |
431 | /* no high address remap*/ | |
432 | GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG0, 0x00); | |
433 | GT_REG_WRITE (CUNIT_HIGH_ADDR_REMAP_REG1, 0x00); | |
434 | ||
435 | /* clear interrupt cause register for MPSC (fault register)*/ | |
436 | GT_REG_WRITE (CUNIT_INTERRUPT_CAUSE_REG, 0x00); | |
437 | } | |
438 | ||
439 | ||
440 | void mpsc_init2 (void) | |
441 | { | |
442 | int i; | |
443 | ||
444 | #ifndef CONFIG_MPSC_DEBUG_PORT | |
445 | mpsc_putchar = mpsc_putchar_sdma; | |
446 | mpsc_getchar = mpsc_getchar_sdma; | |
447 | mpsc_test_char = mpsc_test_char_sdma; | |
448 | #endif | |
449 | /* RX descriptors */ | |
450 | rx_desc_base = (unsigned int *) malloc (((RX_DESC + 1) * 8) * | |
451 | sizeof (unsigned int)); | |
452 | ||
453 | /* align descriptors */ | |
454 | rx_desc_base = (unsigned int *) | |
455 | (((unsigned int) rx_desc_base + 32) & 0xFFFFFFF0); | |
456 | ||
457 | rx_desc_index = 0; | |
458 | ||
459 | memset ((void *) rx_desc_base, 0, | |
460 | (RX_DESC * 8) * sizeof (unsigned int)); | |
461 | ||
462 | for (i = 0; i < RX_DESC; i++) { | |
463 | rx_desc_base[i * 8 + 3] = (unsigned int) &rx_desc_base[i * 8 + 4]; /* Buffer */ | |
464 | rx_desc_base[i * 8 + 2] = (unsigned int) &rx_desc_base[(i + 1) * 8]; /* Next descriptor */ | |
465 | rx_desc_base[i * 8 + 1] = DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; /* Command & control */ | |
466 | rx_desc_base[i * 8] = 0x00100000; | |
467 | } | |
468 | rx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &rx_desc_base[0]; | |
469 | ||
470 | FLUSH_DCACHE (&rx_desc_base[0], &rx_desc_base[RX_DESC * 8]); | |
471 | GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR + (CHANNEL * GALSDMA_REG_DIFF), | |
472 | (unsigned int) &rx_desc_base[0]); | |
473 | ||
474 | /* TX descriptors */ | |
475 | tx_desc_base = (unsigned int *) malloc (((TX_DESC + 1) * 8) * | |
476 | sizeof (unsigned int)); | |
477 | ||
478 | /* align descriptors */ | |
479 | tx_desc_base = (unsigned int *) | |
480 | (((unsigned int) tx_desc_base + 32) & 0xFFFFFFF0); | |
481 | ||
482 | tx_desc_index = -1; | |
483 | ||
484 | memset ((void *) tx_desc_base, 0, | |
485 | (TX_DESC * 8) * sizeof (unsigned int)); | |
486 | ||
487 | for (i = 0; i < TX_DESC; i++) { | |
488 | tx_desc_base[i * 8 + 5] = (unsigned int) 0x23232323; | |
489 | tx_desc_base[i * 8 + 4] = (unsigned int) 0x23232323; | |
490 | tx_desc_base[i * 8 + 3] = | |
491 | (unsigned int) &tx_desc_base[i * 8 + 4]; | |
492 | tx_desc_base[i * 8 + 2] = | |
493 | (unsigned int) &tx_desc_base[(i + 1) * 8]; | |
494 | tx_desc_base[i * 8 + 1] = | |
495 | DESC_OWNER_BIT | DESC_FIRST | DESC_LAST; | |
496 | ||
497 | /* set sbytecnt and shadow byte cnt to 1 */ | |
498 | tx_desc_base[i * 8] = 0x00010001; | |
499 | } | |
500 | tx_desc_base[(i - 1) * 8 + 2] = (unsigned int) &tx_desc_base[0]; | |
501 | ||
502 | FLUSH_DCACHE (&tx_desc_base[0], &tx_desc_base[TX_DESC * 8]); | |
503 | ||
504 | udelay (100); | |
505 | ||
506 | galsdma_enable_rx (); | |
507 | ||
508 | return; | |
509 | } | |
510 | ||
511 | int galbrg_set_baudrate (int channel, int rate) | |
512 | { | |
3a473b2a WD |
513 | int clock; |
514 | ||
515 | galbrg_disable (channel); /*ok */ | |
516 | ||
517 | #ifdef ZUMA_NTL | |
518 | /* from tclk */ | |
6d0f6bcf | 519 | clock = (CONFIG_SYS_TCLK / (16 * rate)) - 1; |
3a473b2a | 520 | #else |
6d0f6bcf | 521 | clock = (CONFIG_SYS_TCLK / (16 * rate)) - 1; |
3a473b2a WD |
522 | #endif |
523 | ||
524 | galbrg_set_CDV (channel, clock); /* set timer Reg. for BRG */ | |
525 | ||
526 | galbrg_enable (channel); | |
527 | ||
528 | gd->baudrate = rate; | |
529 | ||
530 | return 0; | |
531 | } | |
532 | ||
533 | /* ------------------------------------------------------------------ */ | |
534 | ||
535 | /* Below are all the private functions that no one else needs */ | |
536 | ||
537 | static int galbrg_set_CDV (int channel, int value) | |
538 | { | |
539 | unsigned int temp; | |
540 | ||
541 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
542 | temp &= 0xFFFF0000; | |
543 | temp |= (value & 0x0000FFFF); | |
544 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
545 | ||
546 | return 0; | |
547 | } | |
548 | ||
549 | static int galbrg_enable (int channel) | |
550 | { | |
551 | unsigned int temp; | |
552 | ||
553 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
554 | temp |= 0x00010000; | |
555 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
556 | ||
557 | return 0; | |
558 | } | |
559 | ||
560 | static int galbrg_disable (int channel) | |
561 | { | |
562 | unsigned int temp; | |
563 | ||
564 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
565 | temp &= 0xFFFEFFFF; | |
566 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
567 | ||
568 | return 0; | |
569 | } | |
570 | ||
571 | static int galbrg_set_clksrc (int channel, int value) | |
572 | { | |
573 | unsigned int temp; | |
574 | ||
575 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
576 | temp &= 0xFFC3FFFF; /* Bit 18 - 21 (MV 64260 18-22) */ | |
577 | temp |= (value << 18); | |
578 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
579 | return 0; | |
580 | } | |
581 | ||
582 | static int galbrg_set_CUV (int channel, int value) | |
583 | { | |
584 | /* set CountUpValue */ | |
585 | GT_REG_WRITE (GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value); | |
586 | ||
587 | return 0; | |
588 | } | |
589 | ||
590 | #if 0 | |
591 | static int galbrg_reset (int channel) | |
592 | { | |
593 | unsigned int temp; | |
594 | ||
595 | temp = GTREGREAD (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); | |
596 | temp |= 0x20000; | |
597 | GT_REG_WRITE (GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); | |
598 | ||
599 | return 0; | |
600 | } | |
601 | #endif | |
602 | ||
603 | static int galsdma_set_RFT (int channel) | |
604 | { | |
605 | unsigned int temp; | |
606 | ||
607 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
608 | temp |= 0x00000001; | |
609 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
610 | temp); | |
611 | ||
612 | return 0; | |
613 | } | |
614 | ||
615 | static int galsdma_set_SFM (int channel) | |
616 | { | |
617 | unsigned int temp; | |
618 | ||
619 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
620 | temp |= 0x00000002; | |
621 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
622 | temp); | |
623 | ||
624 | return 0; | |
625 | } | |
626 | ||
627 | static int galsdma_set_rxle (int channel) | |
628 | { | |
629 | unsigned int temp; | |
630 | ||
631 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
632 | temp |= 0x00000040; | |
633 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
634 | temp); | |
635 | ||
636 | return 0; | |
637 | } | |
638 | ||
639 | static int galsdma_set_txle (int channel) | |
640 | { | |
641 | unsigned int temp; | |
642 | ||
643 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
644 | temp |= 0x00000080; | |
645 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
646 | temp); | |
647 | ||
648 | return 0; | |
649 | } | |
650 | ||
651 | static int galsdma_set_RC (int channel, unsigned int value) | |
652 | { | |
653 | unsigned int temp; | |
654 | ||
655 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
656 | temp &= ~0x0000003c; | |
657 | temp |= (value << 2); | |
658 | GT_REG_WRITE (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF), | |
659 | temp); | |
660 | ||
661 | return 0; | |
662 | } | |
663 | ||
664 | static int galsdma_set_burstsize (int channel, unsigned int value) | |
665 | { | |
666 | unsigned int temp; | |
667 | ||
668 | temp = GTREGREAD (GALSDMA_0_CONF_REG + (channel * GALSDMA_REG_DIFF)); | |
669 | temp &= 0xFFFFCFFF; | |
670 | switch (value) { | |
671 | case 8: | |
672 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
673 | (channel * GALSDMA_REG_DIFF), | |
674 | (temp | (0x3 << 12))); | |
675 | break; | |
676 | ||
677 | case 4: | |
678 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
679 | (channel * GALSDMA_REG_DIFF), | |
680 | (temp | (0x2 << 12))); | |
681 | break; | |
682 | ||
683 | case 2: | |
684 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
685 | (channel * GALSDMA_REG_DIFF), | |
686 | (temp | (0x1 << 12))); | |
687 | break; | |
688 | ||
689 | case 1: | |
690 | GT_REG_WRITE (GALSDMA_0_CONF_REG + | |
691 | (channel * GALSDMA_REG_DIFF), | |
692 | (temp | (0x0 << 12))); | |
693 | break; | |
694 | ||
695 | default: | |
696 | return -1; | |
697 | break; | |
698 | } | |
699 | ||
700 | return 0; | |
701 | } | |
702 | ||
703 | static int galmpsc_connect (int channel, int connect) | |
704 | { | |
705 | unsigned int temp; | |
706 | ||
707 | temp = GTREGREAD (GALMPSC_ROUTING_REGISTER); | |
708 | ||
709 | if ((channel == 0) && connect) | |
710 | temp &= ~0x00000007; | |
711 | else if ((channel == 1) && connect) | |
712 | temp &= ~(0x00000007 << 6); | |
713 | else if ((channel == 0) && !connect) | |
714 | temp |= 0x00000007; | |
715 | else | |
716 | temp |= (0x00000007 << 6); | |
717 | ||
718 | /* Just in case... */ | |
719 | temp &= 0x3fffffff; | |
720 | ||
721 | GT_REG_WRITE (GALMPSC_ROUTING_REGISTER, temp); | |
722 | ||
723 | return 0; | |
724 | } | |
725 | ||
726 | static int galmpsc_route_rx_clock (int channel, int brg) | |
727 | { | |
728 | unsigned int temp; | |
729 | ||
730 | temp = GTREGREAD (GALMPSC_RxC_ROUTE); | |
731 | ||
732 | if (channel == 0) { | |
733 | temp &= ~0x0000000F; | |
734 | temp |= brg; | |
735 | } else { | |
736 | temp &= ~0x00000F00; | |
737 | temp |= (brg << 8); | |
738 | } | |
739 | ||
740 | GT_REG_WRITE (GALMPSC_RxC_ROUTE, temp); | |
741 | ||
742 | return 0; | |
743 | } | |
744 | ||
745 | static int galmpsc_route_tx_clock (int channel, int brg) | |
746 | { | |
747 | unsigned int temp; | |
748 | ||
749 | temp = GTREGREAD (GALMPSC_TxC_ROUTE); | |
750 | ||
751 | if (channel == 0) { | |
752 | temp &= ~0x0000000F; | |
753 | temp |= brg; | |
754 | } else { | |
755 | temp &= ~0x00000F00; | |
756 | temp |= (brg << 8); | |
757 | } | |
758 | ||
759 | GT_REG_WRITE (GALMPSC_TxC_ROUTE, temp); | |
760 | ||
761 | return 0; | |
762 | } | |
763 | ||
764 | static int galmpsc_write_config_regs (int mpsc, int mode) | |
765 | { | |
766 | if (mode == GALMPSC_UART) { | |
767 | /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */ | |
768 | GT_REG_WRITE (GALMPSC_MCONF_LOW + (mpsc * GALMPSC_REG_GAP), | |
769 | 0x000004c4); | |
770 | ||
771 | /* Main config reg High (32x Rx/Tx clock mode, width=8bits */ | |
772 | GT_REG_WRITE (GALMPSC_MCONF_HIGH + (mpsc * GALMPSC_REG_GAP), | |
773 | 0x024003f8); | |
774 | /* 22 2222 1111 */ | |
775 | /* 54 3210 9876 */ | |
776 | /* 0000 0010 0000 0000 */ | |
777 | /* 1 */ | |
778 | /* 098 7654 3210 */ | |
779 | /* 0000 0011 1111 1000 */ | |
780 | } else | |
781 | return -1; | |
782 | ||
783 | return 0; | |
784 | } | |
785 | ||
786 | static int galmpsc_config_channel_regs (int mpsc) | |
787 | { | |
788 | GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), 0); | |
789 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), 0); | |
790 | GT_REG_WRITE (GALMPSC_CHANNELREG_3 + (mpsc * GALMPSC_REG_GAP), 1); | |
791 | GT_REG_WRITE (GALMPSC_CHANNELREG_4 + (mpsc * GALMPSC_REG_GAP), 0); | |
792 | GT_REG_WRITE (GALMPSC_CHANNELREG_5 + (mpsc * GALMPSC_REG_GAP), 0); | |
793 | GT_REG_WRITE (GALMPSC_CHANNELREG_6 + (mpsc * GALMPSC_REG_GAP), 0); | |
794 | GT_REG_WRITE (GALMPSC_CHANNELREG_7 + (mpsc * GALMPSC_REG_GAP), 0); | |
795 | GT_REG_WRITE (GALMPSC_CHANNELREG_8 + (mpsc * GALMPSC_REG_GAP), 0); | |
796 | GT_REG_WRITE (GALMPSC_CHANNELREG_9 + (mpsc * GALMPSC_REG_GAP), 0); | |
797 | GT_REG_WRITE (GALMPSC_CHANNELREG_10 + (mpsc * GALMPSC_REG_GAP), 0); | |
798 | ||
799 | galmpsc_set_brkcnt (mpsc, 0x3); | |
800 | galmpsc_set_tcschar (mpsc, 0xab); | |
801 | ||
802 | return 0; | |
803 | } | |
804 | ||
805 | static int galmpsc_set_brkcnt (int mpsc, int value) | |
806 | { | |
807 | unsigned int temp; | |
808 | ||
809 | temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); | |
810 | temp &= 0x0000FFFF; | |
811 | temp |= (value << 16); | |
812 | GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); | |
813 | ||
814 | return 0; | |
815 | } | |
816 | ||
817 | static int galmpsc_set_tcschar (int mpsc, int value) | |
818 | { | |
819 | unsigned int temp; | |
820 | ||
821 | temp = GTREGREAD (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP)); | |
822 | temp &= 0xFFFF0000; | |
823 | temp |= value; | |
824 | GT_REG_WRITE (GALMPSC_CHANNELREG_1 + (mpsc * GALMPSC_REG_GAP), temp); | |
825 | ||
826 | return 0; | |
827 | } | |
828 | ||
829 | static int galmpsc_set_char_length (int mpsc, int value) | |
830 | { | |
831 | unsigned int temp; | |
832 | ||
833 | temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); | |
834 | temp &= 0xFFFFCFFF; | |
835 | temp |= (value << 12); | |
836 | GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); | |
837 | ||
838 | return 0; | |
839 | } | |
840 | ||
841 | static int galmpsc_set_stop_bit_length (int mpsc, int value) | |
842 | { | |
843 | unsigned int temp; | |
844 | ||
845 | temp = GTREGREAD (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP)); | |
846 | temp &= 0xFFFFBFFF; | |
847 | temp |= (value << 14); | |
848 | GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), temp); | |
849 | ||
850 | return 0; | |
851 | } | |
852 | ||
853 | static int galmpsc_set_parity (int mpsc, int value) | |
854 | { | |
855 | unsigned int temp; | |
856 | ||
857 | temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); | |
858 | if (value != -1) { | |
859 | temp &= 0xFFF3FFF3; | |
860 | temp |= ((value << 18) | (value << 2)); | |
861 | temp |= ((value << 17) | (value << 1)); | |
862 | } else { | |
863 | temp &= 0xFFF1FFF1; | |
864 | } | |
865 | ||
866 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); | |
867 | ||
868 | return 0; | |
869 | } | |
870 | ||
871 | static int galmpsc_enter_hunt (int mpsc) | |
872 | { | |
873 | int temp; | |
874 | ||
875 | temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); | |
876 | temp |= 0x80000000; | |
877 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); | |
878 | ||
879 | while (GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)) & | |
880 | MPSC_ENTER_HUNT) { | |
881 | udelay (1); | |
882 | } | |
883 | return 0; | |
884 | } | |
885 | ||
886 | ||
887 | static int galmpsc_shutdown (int mpsc) | |
888 | { | |
889 | unsigned int temp; | |
890 | ||
891 | /* cause RX abort (clears RX) */ | |
892 | temp = GTREGREAD (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP)); | |
893 | temp |= MPSC_RX_ABORT | MPSC_TX_ABORT; | |
894 | temp &= ~MPSC_ENTER_HUNT; | |
895 | GT_REG_WRITE (GALMPSC_CHANNELREG_2 + (mpsc * GALMPSC_REG_GAP), temp); | |
896 | ||
897 | GT_REG_WRITE (GALSDMA_0_COM_REG, 0); | |
898 | GT_REG_WRITE (GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT); | |
899 | ||
900 | /* shut down the MPSC */ | |
901 | GT_REG_WRITE (GALMPSC_MCONF_LOW, 0); | |
902 | GT_REG_WRITE (GALMPSC_MCONF_HIGH, 0); | |
903 | GT_REG_WRITE (GALMPSC_PROTOCONF_REG + (mpsc * GALMPSC_REG_GAP), 0); | |
904 | ||
905 | udelay (100); | |
906 | ||
907 | /* shut down the sdma engines. */ | |
908 | /* reset config to default */ | |
909 | GT_REG_WRITE (GALSDMA_0_CONF_REG, 0x000000fc); | |
910 | ||
911 | udelay (100); | |
912 | ||
913 | /* clear the SDMA current and first TX and RX pointers */ | |
914 | GT_REG_WRITE (GALSDMA_0_CUR_RX_PTR, 0); | |
915 | GT_REG_WRITE (GALSDMA_0_CUR_TX_PTR, 0); | |
916 | GT_REG_WRITE (GALSDMA_0_FIR_TX_PTR, 0); | |
917 | ||
918 | udelay (100); | |
919 | ||
920 | return 0; | |
921 | } | |
922 | ||
923 | static void galsdma_enable_rx (void) | |
924 | { | |
925 | int temp; | |
926 | ||
927 | /* Enable RX processing */ | |
928 | temp = GTREGREAD (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF)); | |
929 | temp |= RX_ENABLE; | |
930 | GT_REG_WRITE (GALSDMA_0_COM_REG + (CHANNEL * GALSDMA_REG_DIFF), temp); | |
931 | ||
932 | galmpsc_enter_hunt (CHANNEL); | |
933 | } | |
934 | ||
935 | static int galmpsc_set_snoop (int mpsc, int value) | |
936 | { | |
937 | int reg = | |
938 | mpsc ? MPSC_1_ADDRESS_CONTROL_LOW : | |
939 | MPSC_0_ADDRESS_CONTROL_LOW; | |
940 | int temp = GTREGREAD (reg); | |
941 | ||
942 | if (value) | |
943 | temp |= (1 << 6) | (1 << 14) | (1 << 22) | (1 << 30); | |
944 | else | |
945 | temp &= ~((1 << 6) | (1 << 14) | (1 << 22) | (1 << 30)); | |
946 | GT_REG_WRITE (reg, temp); | |
947 | return 0; | |
948 | } | |
949 | ||
950 | /******************************************************************************* | |
951 | * galsdma_set_mem_space - Set MV64360 IDMA memory decoding map. | |
952 | * | |
953 | * DESCRIPTION: | |
954 | * the MV64360 SDMA has its own address decoding map that is de-coupled | |
955 | * from the CPU interface address decoding windows. The SDMA channels | |
956 | * share four address windows. Each region can be individually configured | |
957 | * by this function by associating it to a target interface and setting | |
958 | * base and size values. | |
959 | * | |
960 | * NOTE!!! | |
961 | * The size must be in 64Kbyte granularity. | |
962 | * The base address must be aligned to the size. | |
963 | * The size must be a series of 1s followed by a series of zeros | |
964 | * | |
965 | * OUTPUT: | |
966 | * None. | |
967 | * | |
968 | * RETURN: | |
969 | * True for success, false otherwise. | |
970 | * | |
971 | *******************************************************************************/ | |
972 | ||
973 | static int galsdma_set_mem_space (unsigned int memSpace, | |
974 | unsigned int memSpaceTarget, | |
975 | unsigned int memSpaceAttr, | |
976 | unsigned int baseAddress, unsigned int size) | |
977 | { | |
978 | unsigned int temp; | |
979 | ||
980 | if (size == 0) { | |
981 | GT_RESET_REG_BITS (MV64360_CUNIT_BASE_ADDR_ENABLE_REG, | |
982 | 1 << memSpace); | |
983 | return true; | |
984 | } | |
985 | ||
986 | /* The base address must be aligned to the size. */ | |
987 | if (baseAddress % size != 0) { | |
988 | return false; | |
989 | } | |
990 | if (size < 0x10000) { | |
991 | return false; | |
992 | } | |
993 | ||
994 | /* Align size and base to 64K */ | |
995 | baseAddress &= 0xffff0000; | |
996 | size &= 0xffff0000; | |
997 | temp = size >> 16; | |
998 | ||
999 | /* Checking that the size is a sequence of '1' followed by a | |
1000 | sequence of '0' starting from LSB to MSB. */ | |
1001 | while ((temp > 0) && (temp & 0x1)) { | |
1002 | temp = temp >> 1; | |
1003 | } | |
1004 | ||
1005 | if (temp != 0) { | |
1006 | GT_REG_WRITE (MV64360_CUNIT_BASE_ADDR_REG0 + memSpace * 8, | |
1007 | (baseAddress | memSpaceTarget | memSpaceAttr)); | |
1008 | GT_REG_WRITE ((MV64360_CUNIT_SIZE0 + memSpace * 8), | |
1009 | (size - 1) & 0xffff0000); | |
1010 | GT_RESET_REG_BITS (MV64360_CUNIT_BASE_ADDR_ENABLE_REG, | |
1011 | 1 << memSpace); | |
1012 | } else { | |
1013 | /* An invalid size was specified */ | |
1014 | return false; | |
1015 | } | |
1016 | return true; | |
1017 | } |