]>
Commit | Line | Data |
---|---|---|
b6e4c403 WD |
1 | /* |
2 | * (C) Copyright 2003 | |
3 | * Martin Winistoerfer, [email protected]. | |
4 | * Atapted for PATI | |
5 | * Denis Peter, [email protected] | |
6 | * See file CREDITS for list of people who contributed to this | |
7 | * project. | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License as | |
11 | * published by the Free Software Foundation; either version 2 of | |
12 | * the License, or (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
22 | * MA 02111-1307 USA | |
23 | */ | |
24 | ||
25 | /*********************************************************************************** | |
26 | * Bits for the SDRAM controller | |
27 | * ----------------------------- | |
28 | * | |
29 | * CAL: CAS Latency. If cleared to 0 (default) the SDRAM controller asserts TA# on | |
30 | * the 2nd Clock after ACTIVE command (CAS Latency = 2). If set to 1 the SDRAM | |
31 | * controller asserts TA# on the 3rd Clock after ACTIVE command (CAS Latency = 3). | |
32 | * RCD: RCD ACTIVE to READ or WRITE Delay (Ras to Cas Delay). If cleared 0 (default) | |
33 | * tRCD of the SDRAM must equal or less 25ns. If set to 1 tRCD must be equal or less 50ns. | |
34 | * WREC:Write Recovery. If cleared 0 (default) tWR of the SDRAM must equal or less 25ns. | |
35 | * If set to 1 tWR must be equal or less 50ns. | |
36 | * RP: Precharge Command Time. If cleared 0 (default) tRP of the SDRAM must equal or less | |
37 | * 25ns. If set to 1 tRP must be equal or less 50ns. | |
38 | * RC: Auto Refresh to Active Time. If cleared 0 (default) tRC of the SDRAM must equal | |
39 | * or less 75ns. If set to 1 tRC must be equal or less 100ns. | |
40 | * LMR: Bit to set the Mode Register of the SDRAM. If set, the next access to the SDRAM | |
41 | * is the Load Mode Register Command. | |
42 | * IIP: Init in progress. Set to 1 for starting the init sequence | |
43 | * (Precharge All). As long this bit is set, the Precharge All is still in progress. | |
44 | * After command has completed, wait at least for 8 refresh (200usec) before proceed. | |
45 | **********************************************************************************/ | |
46 | ||
47 | #include <common.h> | |
48 | #include <mpc5xx.h> | |
49 | #include <devices.h> | |
50 | #include <pci_ids.h> | |
51 | #define PLX9056_LOC | |
52 | #include "plx9056.h" | |
53 | #include "pati.h" | |
54 | ||
55 | #if defined(__APPLE__) | |
56 | /* Leading underscore on symbols */ | |
57 | # define SYM_CHAR "_" | |
58 | #else /* No leading character on symbols */ | |
59 | # define SYM_CHAR | |
60 | #endif | |
61 | ||
62 | #undef SDRAM_DEBUG | |
63 | /* | |
64 | * Macros to generate global absolutes. | |
65 | */ | |
66 | #define GEN_SYMNAME(str) SYM_CHAR #str | |
67 | #define GEN_VALUE(str) #str | |
68 | #define GEN_ABS(name, value) \ | |
69 | asm (".globl " GEN_SYMNAME(name)); \ | |
70 | asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) | |
71 | ||
72 | ||
73 | /************************************************************************ | |
74 | * Early debug routines | |
75 | */ | |
76 | void write_hex (unsigned char i) | |
77 | { | |
78 | char cc; | |
79 | ||
80 | cc = i >> 4; | |
81 | cc &= 0xf; | |
82 | if (cc > 9) | |
83 | serial_putc (cc + 55); | |
84 | else | |
85 | serial_putc (cc + 48); | |
86 | cc = i & 0xf; | |
87 | if (cc > 9) | |
88 | serial_putc (cc + 55); | |
89 | else | |
90 | serial_putc (cc + 48); | |
91 | } | |
92 | ||
93 | #if defined(SDRAM_DEBUG) | |
94 | ||
95 | void write_4hex (unsigned long val) | |
96 | { | |
97 | write_hex ((unsigned char) (val >> 24)); | |
98 | write_hex ((unsigned char) (val >> 16)); | |
99 | write_hex ((unsigned char) (val >> 8)); | |
100 | write_hex ((unsigned char) val); | |
101 | } | |
102 | ||
103 | #endif | |
104 | ||
105 | unsigned long in32(unsigned long addr) | |
106 | { | |
107 | unsigned long *p=(unsigned long *)addr; | |
108 | return *p; | |
109 | } | |
110 | ||
111 | void out32(unsigned long addr,unsigned long data) | |
112 | { | |
113 | unsigned long *p=(unsigned long *)addr; | |
114 | *p=data; | |
115 | } | |
116 | ||
117 | typedef struct { | |
118 | unsigned short boardtype; /* Board revision and Population Options */ | |
119 | unsigned char cal; /* cas Latency 0:CAL=2 1:CAL=3 */ | |
120 | unsigned char rcd; /* ras to cas delay 0:<25ns 1:<50ns*/ | |
121 | unsigned char wrec; /* write recovery 0:<25ns 1:<50ns */ | |
122 | unsigned char pr; /* Precharge Command Time 0:<25ns 1:<50ns */ | |
123 | unsigned char rc; /* Auto Refresh to Active Time 0:<75ns 1:<100ns */ | |
124 | unsigned char sz; /* log binary => Size = (4MByte<<sz) 5 = 128, 4 = 64, 3 = 32, 2 = 16, 1=8 */ | |
125 | } sdram_t; | |
126 | ||
127 | const sdram_t sdram_table[] = { | |
128 | { 0x0000, /* PATI Rev A, 16MByte -1 Board */ | |
129 | 1, /* Case Latenty = 3 */ | |
130 | 0, /* ras to cas delay 0 (20ns) */ | |
131 | 0, /* write recovery 0:<25ns 1:<50ns*/ | |
132 | 0, /* Precharge Command Time 0 (20ns) */ | |
133 | 0, /* Auto Refresh to Active Time 0 (68) */ | |
134 | 2 /* log binary => Size 2 = 16MByte, 1=8 */ | |
135 | }, | |
136 | { 0xffff, /* terminator */ | |
137 | 0xff, | |
138 | 0xff, | |
139 | 0xff, | |
140 | 0xff, | |
141 | 0xff, | |
142 | 0xff } | |
143 | }; | |
144 | ||
145 | ||
146 | extern int mem_test (unsigned long start, unsigned long ramsize, int quiet); | |
147 | extern void mem_test_reloc(void); | |
148 | ||
149 | /* | |
150 | * Get RAM size. | |
151 | */ | |
152 | long int initdram(int board_type) | |
153 | { | |
154 | unsigned char board_rev; | |
155 | unsigned long reg; | |
156 | unsigned long lmr; | |
157 | int i,timeout; | |
158 | ||
159 | #if defined(SDRAM_DEBUG) | |
160 | reg=in32(PLD_CONFIG_BASE+PLD_PART_ID); | |
161 | puts("\n\nSYSTEM part 0x"); write_4hex(SYSCNTR_PART(reg)); | |
162 | puts(" Vers 0x"); write_4hex(SYSCNTR_ID(reg)); | |
163 | puts("\nSDRAM part 0x"); write_4hex(SDRAM_PART(reg)); | |
164 | puts(" Vers 0x"); write_4hex(SDRAM_ID(reg)); | |
165 | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | |
166 | puts("\nBoard rev. 0x"); write_4hex(SYSCNTR_BREV(reg)); | |
167 | putc('\n'); | |
168 | #endif | |
169 | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | |
170 | board_rev=(unsigned char)(SYSCNTR_BREV(reg)); | |
171 | i=0; | |
172 | while(1) { | |
173 | if(sdram_table[i].boardtype==0xffff) { | |
174 | puts("ERROR, found no table for Board 0x"); | |
175 | write_hex(board_rev); | |
176 | while(1); | |
177 | } | |
178 | if(sdram_table[i].boardtype==(unsigned char)board_rev) | |
179 | break; | |
180 | i++; | |
181 | } | |
182 | /* Set CAL, RCD, WREQ, PR and RC Bits */ | |
183 | #if defined(SDRAM_DEBUG) | |
184 | puts("Set CAL, RCD, WREQ, PR and RC Bits\n"); | |
185 | #endif | |
186 | /* mask bits */ | |
187 | reg &= ~(SET_REG_BIT(1,SDRAM_CAL) | SET_REG_BIT(1,SDRAM_RCD) | SET_REG_BIT(1,SDRAM_WREQ) | | |
188 | SET_REG_BIT(1,SDRAM_PR) | SET_REG_BIT(1,SDRAM_RC) | SET_REG_BIT(1,SDRAM_LMR) | | |
189 | SET_REG_BIT(1,SDRAM_IIP) | SET_REG_BIT(1,SDRAM_RES0)); | |
190 | /* set bits */ | |
191 | reg |= (SET_REG_BIT(sdram_table[i].cal,SDRAM_CAL) | | |
192 | SET_REG_BIT(sdram_table[i].rcd,SDRAM_RCD) | | |
193 | SET_REG_BIT(sdram_table[i].wrec,SDRAM_WREQ) | | |
194 | SET_REG_BIT(sdram_table[i].pr,SDRAM_PR) | | |
195 | SET_REG_BIT(sdram_table[i].rc,SDRAM_RC)); | |
196 | ||
197 | out32(PLD_CONFIG_BASE+PLD_BOARD_TIMING,reg); | |
198 | /* step 2 set IIP */ | |
199 | #if defined(SDRAM_DEBUG) | |
200 | puts("step 2 set IIP\n"); | |
201 | #endif | |
202 | /* step 2 set IIP */ | |
203 | reg |= SET_REG_BIT(1,SDRAM_IIP); | |
204 | timeout=0; | |
205 | while (timeout!=0xffff) { | |
206 | __asm__ volatile("eieio"); | |
207 | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | |
208 | if((reg & SET_REG_BIT(1,SDRAM_IIP))==0) | |
209 | break; | |
210 | timeout++; | |
211 | udelay(1); | |
212 | } | |
213 | /* wait for at least 8 refresh */ | |
214 | udelay(1000); | |
215 | /* set LMR */ | |
216 | reg |= SET_REG_BIT(1,SDRAM_LMR); | |
217 | out32(PLD_CONFIG_BASE+PLD_BOARD_TIMING,reg); | |
218 | __asm__ volatile("eieio"); | |
219 | lmr=0x00000002; /* sequential burst 4 data */ | |
220 | if(sdram_table[i].cal==1) | |
221 | lmr|=0x00000030; /* cal = 3 */ | |
222 | else | |
223 | lmr|=0000000020; /* cal = 2 */ | |
224 | /* rest standard operation programmed write burst length */ | |
225 | /* we have a x32 bit bus to the SDRAM, so shift the addr with 2 */ | |
226 | lmr<<=2; | |
227 | in32(CFG_SDRAM_BASE + lmr); | |
228 | /* ok, we're done, return SDRAM size */ | |
229 | return ((0x400000 << sdram_table[i].sz)); /* log2 value of 4MByte */ | |
230 | } | |
231 | ||
232 | ||
233 | void set_flash_vpp(int ext_vpp, int ext_wp, int int_vpp) | |
234 | { | |
235 | unsigned long reg; | |
236 | reg=in32(PLD_CONF_REG2+PLD_CONFIG_BASE); | |
237 | reg &= ~(SET_REG_BIT(1,SYSCNTR_CPU_VPP) | | |
238 | SET_REG_BIT(1,SYSCNTR_FL_VPP) | | |
239 | SET_REG_BIT(1,SYSCNTR_FL_WP)); | |
240 | ||
241 | reg |= (SET_REG_BIT(int_vpp,SYSCNTR_CPU_VPP) | | |
242 | SET_REG_BIT(ext_vpp,SYSCNTR_FL_VPP) | | |
243 | SET_REG_BIT(ext_wp,SYSCNTR_FL_WP)); | |
244 | out32(PLD_CONF_REG2+PLD_CONFIG_BASE,reg); | |
245 | udelay(100); | |
246 | } | |
247 | ||
248 | ||
249 | void show_pld_regs(void) | |
250 | { | |
251 | unsigned long reg,reg1; | |
252 | reg=in32(PLD_CONFIG_BASE+PLD_PART_ID); | |
253 | printf("\nSYSTEM part %ld, Vers %ld\n",SYSCNTR_PART(reg),SYSCNTR_ID(reg)); | |
254 | printf("SDRAM part %ld, Vers %ld\n",SDRAM_PART(reg),SDRAM_ID(reg)); | |
255 | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | |
256 | printf("Board rev. %c\n",(char) (SYSCNTR_BREV(reg)+'A')); | |
257 | printf("Waitstates %ld\n",GET_SYSCNTR_FLWAIT(reg)); | |
258 | printf("SDRAM: CAL=%ld RCD=%ld WREQ=%ld PR=%ld\n RC=%ld LMR=%ld IIP=%ld\n", | |
259 | GET_REG_BIT(reg,SDRAM_CAL),GET_REG_BIT(reg,SDRAM_RCD), | |
260 | GET_REG_BIT(reg,SDRAM_WREQ),GET_REG_BIT(reg,SDRAM_PR), | |
261 | GET_REG_BIT(reg,SDRAM_RC),GET_REG_BIT(reg,SDRAM_LMR), | |
262 | GET_REG_BIT(reg,SDRAM_IIP)); | |
263 | reg=in32(PLD_CONFIG_BASE+PLD_CONF_REG1); | |
264 | reg1=in32(PLD_CONFIG_BASE+PLD_CONF_REG2); | |
265 | printf("HW Config: FLAG=%ld IP=%ld index=%ld PRPM=%ld\n ICW=%ld ISB=%ld BDIS=%ld PCIM=%ld\n", | |
266 | GET_REG_BIT(reg,SYSCNTR_FLAG),GET_REG_BIT(reg,SYSCNTR_IP), | |
267 | GET_SYSCNTR_BOOTIND(reg),GET_REG_BIT(reg,SYSCNTR_PRM), | |
268 | GET_REG_BIT(reg,SYSCNTR_ICW),GET_SYSCNTR_ISB(reg), | |
269 | GET_REG_BIT(reg1,SYSCNTR_BDIS),GET_REG_BIT(reg1,SYSCNTR_PCIM)); | |
270 | printf("Switches: MUX=%ld PCI_DIS=%ld Boot_EN=%ld Config=%ld\n",GET_SDRAM_MUX(reg), | |
271 | GET_REG_BIT(reg,SDRAM_PDIS),GET_REG_BIT(reg1,SYSCNTR_BOOTEN), | |
272 | GET_SYSCNTR_CFG(reg1)); | |
273 | printf("Misc: RIP=%ld CPU_VPP=%ld FLSH_VPP=%ld FLSH_WP=%ld\n\n", | |
274 | GET_REG_BIT(reg,SDRAM_RIP),GET_REG_BIT(reg1,SYSCNTR_CPU_VPP), | |
275 | GET_REG_BIT(reg1,SYSCNTR_FL_VPP),GET_REG_BIT(reg1,SYSCNTR_FL_WP)); | |
276 | } | |
277 | ||
278 | ||
279 | /**************************************************************** | |
280 | * Setting IOs | |
281 | * ----------- | |
282 | * GPIO6 is User LED1 | |
283 | * GPIO7 is Interrupt PLX (Output) | |
284 | * GPIO5 is User LED0 | |
285 | * GPIO2 is PLX USERi (Output) | |
286 | * GPIO1 is PLX Interrupt (Input) | |
287 | ****************************************************************/ | |
288 | void init_ios(void) | |
289 | { | |
290 | volatile immap_t * immr = (immap_t *) CFG_IMMR; | |
291 | volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; | |
292 | unsigned long reg; | |
293 | reg=sysconf->sc_sgpiocr; /* Data direction register */ | |
294 | reg &= ~0x67000000; | |
295 | reg |= 0x27000000; /* set outpupts */ | |
296 | sysconf->sc_sgpiocr=reg; /* Data direction register */ | |
297 | reg=sysconf->sc_sgpiodt2; /* Data register */ | |
298 | /* set output to 0 */ | |
299 | reg &= ~0x27000000; | |
300 | /* set IRQ and USERi to 1 */ | |
301 | reg |= 0x28000000; | |
302 | sysconf->sc_sgpiodt2=reg; /* Data register */ | |
303 | } | |
304 | ||
305 | void user_led0(int led_on) | |
306 | { | |
307 | volatile immap_t * immr = (immap_t *) CFG_IMMR; | |
308 | volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; | |
309 | unsigned long reg; | |
310 | reg=sysconf->sc_sgpiodt2; /* Data register */ | |
311 | if(led_on) /* set output to 1 */ | |
312 | reg |= 0x04000000; | |
313 | else | |
314 | reg &= ~0x04000000; | |
315 | sysconf->sc_sgpiodt2=reg; /* Data register */ | |
316 | } | |
317 | ||
318 | void user_led1(int led_on) | |
319 | { | |
320 | volatile immap_t * immr = (immap_t *) CFG_IMMR; | |
321 | volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; | |
322 | unsigned long reg; | |
323 | reg=sysconf->sc_sgpiodt2; /* Data register */ | |
324 | if(led_on) /* set output to 1 */ | |
325 | reg |= 0x02000000; | |
326 | else | |
327 | reg &= ~0x02000000; | |
328 | sysconf->sc_sgpiodt2=reg; /* Data register */ | |
329 | } | |
330 | ||
331 | ||
332 | /**************************************************************** | |
333 | * Last Stage Init | |
334 | ****************************************************************/ | |
335 | int last_stage_init (void) | |
336 | { | |
337 | mem_test_reloc(); | |
338 | init_ios(); | |
339 | return 0; | |
340 | } | |
341 | ||
342 | /**************************************************************** | |
343 | * Check the board | |
344 | ****************************************************************/ | |
345 | ||
346 | #define BOARD_NAME "PATI" | |
347 | ||
348 | int checkboard (void) | |
349 | { | |
350 | unsigned char s[50]; | |
351 | unsigned long reg; | |
352 | char rev; | |
353 | int i; | |
354 | ||
355 | puts ("\nBoard: "); | |
356 | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | |
357 | rev=(char)(SYSCNTR_BREV(reg)+'A'); | |
358 | i = getenv_r ("serial#", s, 32); | |
359 | if ((i == -1)) { | |
360 | puts ("### No HW ID - assuming " BOARD_NAME); | |
361 | printf(" Rev. %c\n",rev); | |
362 | } | |
363 | else { | |
364 | s[sizeof(BOARD_NAME)-1] = 0; | |
365 | printf ("%s-1 Rev %c SN: %s\n", s,rev, | |
366 | &s[sizeof(BOARD_NAME)]); | |
367 | } | |
368 | set_flash_vpp(1,0,0); /* set Flash VPP */ | |
369 | return 0; | |
370 | } | |
371 | ||
372 | ||
373 | #ifdef CFG_PCI_CON_DEVICE | |
374 | /************************************************************************ | |
375 | * PCI Communication | |
376 | * | |
377 | * Alive (Pinging): | |
378 | * ---------------- | |
379 | * PCI Host sends message ALIVE, Local acknowledges with ALIVE | |
380 | * | |
381 | * PCI_CON console over PCI: | |
382 | * ------------------------- | |
383 | * Local side: | |
384 | * - uses PCI9056_LOC_TO_PCI_DBELL register to signal that | |
385 | * data is avaible (PCIMSG_CONN) | |
386 | * - uses PCI9056_MAILBOX1 to send data | |
387 | * - uses PCI9056_MAILBOX0 to receive data | |
388 | * PCI side: | |
389 | * - uses PCI9056_PCI_TO_LOC_DBELL register to signal that | |
390 | * data is avaible (PCIMSG_CONN) | |
391 | * - uses PCI9056_MAILBOX0 to send data | |
392 | * - uses PCI9056_MAILBOX1 to receive data | |
393 | * | |
394 | * How it works: | |
395 | * Send: | |
396 | * - check if PCICON_TRANSMIT_REG is empty | |
397 | * - write data or'ed with 0x80000000 into the PCICON_TRANSMIT_REG | |
398 | * - write PCIMSG_CONN into the PCICON_DBELL_REG to signal a data | |
399 | * is waiting | |
400 | * Receive: | |
401 | * - get an interrupt via the PCICON_ACK_REG register message | |
402 | * PCIMSG_CONN | |
403 | * - write the data from the PCICON_RECEIVE_REG into the receive | |
404 | * buffer and if the receive buffer is not full, clear the | |
405 | * PCICON_RECEIVE_REG (this allows the counterpart to write more data) | |
406 | * - Clear the interrupt by writing 0xFFFFFFFF to the PCICON_ACK_REG | |
407 | * | |
408 | * The PCICON_RECEIVE_REG must be cleared by the routine which reads | |
409 | * the receive buffer if the buffer is not full any more | |
410 | * | |
411 | */ | |
412 | ||
413 | #undef PCI_CON_DEBUG | |
414 | ||
415 | #ifdef PCI_CON_DEBUG | |
416 | #define PCI_CON_PRINTF(fmt,args...) serial_printf (fmt ,##args) | |
417 | #else | |
418 | #define PCI_CON_PRINTF(fmt,args...) | |
419 | #endif | |
420 | ||
421 | ||
422 | /********************************************************* | |
423 | * we work only with a receive buffer on eiter side. | |
424 | * Transmit buffer is free, if mailbox is cleared. | |
425 | * Transmit character is or'ed with 0x80000000 | |
426 | * PATI receive register MAILBOX0 | |
427 | * PATI transmit register MAILBOX1 | |
428 | *********************************************************/ | |
429 | #define PCICON_RECEIVE_REG PCI9056_MAILBOX0 | |
430 | #define PCICON_TRANSMIT_REG PCI9056_MAILBOX1 | |
431 | #define PCICON_DBELL_REG PCI9056_LOC_TO_PCI_DBELL | |
432 | #define PCICON_ACK_REG PCI9056_PCI_TO_LOC_DBELL | |
433 | ||
434 | ||
435 | #define PCIMSG_ALIVE 0x1 | |
436 | #define PCIMSG_CONN 0x2 | |
437 | #define PCIMSG_DISC 0x3 | |
438 | #define PCIMSG_CON_DATA 0x5 | |
439 | ||
440 | ||
441 | #define PCICON_GET_REG(x) (in32(x + PCI_CONFIG_BASE)) | |
442 | #define PCICON_SET_REG(x,y) (out32(x + PCI_CONFIG_BASE,y)) | |
443 | #define PCICON_TX_FLAG 0x80000000 | |
444 | ||
445 | ||
446 | #define REC_BUFFER_SIZE 0x100 | |
447 | int recbuf[REC_BUFFER_SIZE]; | |
448 | static int r_ptr = 0; | |
449 | int w_ptr; | |
450 | device_t pci_con_dev; | |
451 | int conn=0; | |
452 | int buff_full=0; | |
453 | ||
454 | void pci_con_put_it(const char c) | |
455 | { | |
456 | /* Test for completition */ | |
457 | unsigned long reg; | |
458 | do { | |
459 | reg=PCICON_GET_REG(PCICON_TRANSMIT_REG); | |
460 | }while(reg); | |
461 | reg=PCICON_TX_FLAG + c; | |
462 | PCICON_SET_REG(PCICON_TRANSMIT_REG,reg); | |
463 | PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_CON_DATA); | |
464 | } | |
465 | ||
466 | void pci_con_putc(const char c) | |
467 | { | |
468 | pci_con_put_it(c); | |
469 | if(c == '\n') | |
470 | pci_con_put_it('\r'); | |
471 | } | |
472 | ||
473 | ||
474 | int pci_con_getc(void) | |
475 | { | |
476 | int res; | |
477 | int diff; | |
478 | while(r_ptr==(volatile int)w_ptr); | |
479 | res=recbuf[r_ptr++]; | |
480 | if(r_ptr==REC_BUFFER_SIZE) | |
481 | r_ptr=0; | |
482 | if(w_ptr<r_ptr) | |
483 | diff=r_ptr+REC_BUFFER_SIZE-w_ptr; | |
484 | else | |
485 | diff=r_ptr-w_ptr; | |
486 | if((diff<(REC_BUFFER_SIZE-4)) && buff_full) { | |
53677ef1 | 487 | /* clear Mail box */ |
b6e4c403 WD |
488 | buff_full=0; |
489 | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | |
490 | } | |
491 | return res; | |
492 | } | |
493 | ||
494 | int pci_con_tstc(void) | |
495 | { | |
496 | if(r_ptr==(volatile int)w_ptr) | |
497 | return 0; | |
498 | return 1; | |
499 | } | |
500 | ||
501 | void pci_con_puts (const char *s) | |
502 | { | |
503 | while (*s) { | |
504 | pci_con_putc(*s); | |
505 | ++s; | |
506 | } | |
507 | } | |
508 | ||
509 | void pci_con_init (void) | |
510 | { | |
511 | w_ptr = 0; | |
512 | r_ptr = 0; | |
513 | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | |
514 | conn=1; | |
515 | } | |
516 | ||
517 | /******************************************* | |
518 | * IRQ routine | |
519 | ******************************************/ | |
520 | int pci_dorbell_irq(void) | |
521 | { | |
522 | unsigned long reg,data; | |
523 | int diff; | |
524 | reg=PCICON_GET_REG(PCI9056_INT_CTRL_STAT); | |
525 | PCI_CON_PRINTF(" PCI9056_INT_CTRL_STAT = %08lX\n",reg); | |
526 | if(reg & (1<<20) ) { | |
527 | /* read doorbell */ | |
528 | reg=PCICON_GET_REG(PCICON_ACK_REG); | |
529 | switch(reg) { | |
530 | case PCIMSG_ALIVE: | |
531 | PCI_CON_PRINTF(" Alive\n"); | |
532 | PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_ALIVE); | |
533 | break; | |
534 | case PCIMSG_CONN: | |
535 | PCI_CON_PRINTF(" Conn %d",conn); | |
536 | w_ptr = 0; | |
537 | r_ptr = 0; | |
538 | buff_full=0; | |
539 | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | |
540 | conn=1; | |
541 | PCI_CON_PRINTF(" ... %d\n",conn); | |
542 | break; | |
543 | case PCIMSG_CON_DATA: | |
544 | data=PCICON_GET_REG(PCICON_RECEIVE_REG); | |
545 | recbuf[w_ptr++]=(int)(data&0xff); | |
546 | PCI_CON_PRINTF(" Data Console %lX, %X %d %d %X\n",data,((int)(data&0xFF)), | |
547 | r_ptr,w_ptr,recbuf[w_ptr-1]); | |
548 | if(w_ptr==REC_BUFFER_SIZE) | |
549 | w_ptr=0; | |
550 | if(w_ptr<r_ptr) | |
551 | diff=r_ptr+REC_BUFFER_SIZE-w_ptr; | |
552 | else | |
553 | diff=r_ptr-w_ptr; | |
554 | if(diff>(REC_BUFFER_SIZE-4)) | |
555 | buff_full=1; | |
556 | else | |
557 | /* clear Mail box */ | |
558 | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | |
559 | break; | |
560 | default: | |
561 | serial_printf(" PCI9056_PCI_TO_LOC_DBELL = %08lX\n",reg); | |
562 | } | |
563 | /* clear IRQ */ | |
564 | PCICON_SET_REG(PCICON_ACK_REG,~0L); | |
565 | } | |
566 | return 0; | |
567 | } | |
568 | ||
569 | void pci_con_connect(void) | |
570 | { | |
571 | unsigned long reg; | |
572 | conn=0; | |
573 | reg=PCICON_GET_REG(PCI9056_INT_CTRL_STAT); | |
574 | /* default 0x0f010180 */ | |
575 | reg &= 0xff000000; | |
576 | reg |= 0x00030000; /* enable local dorbell */ | |
577 | reg |= 0x00000300; /* enable PCI dorbell */ | |
578 | PCICON_SET_REG(PCI9056_INT_CTRL_STAT , reg); | |
579 | irq_install_handler (0x2, (interrupt_handler_t *) pci_dorbell_irq,NULL); | |
580 | memset (&pci_con_dev, 0, sizeof (pci_con_dev)); | |
581 | strcpy (pci_con_dev.name, "pci_con"); | |
582 | pci_con_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; | |
583 | pci_con_dev.putc = pci_con_putc; | |
584 | pci_con_dev.puts = pci_con_puts; | |
585 | pci_con_dev.getc = pci_con_getc; | |
586 | pci_con_dev.tstc = pci_con_tstc; | |
587 | device_register (&pci_con_dev); | |
588 | printf("PATI ready for PCI connection, type ctrl-c for exit\n"); | |
589 | do { | |
590 | udelay(10); | |
591 | if((volatile int)conn) | |
592 | break; | |
593 | if(ctrlc()) { | |
594 | irq_free_handler(0x2); | |
595 | return; | |
596 | } | |
597 | }while(1); | |
598 | console_assign(stdin,"pci_con"); | |
599 | console_assign(stderr,"pci_con"); | |
600 | console_assign(stdout,"pci_con"); | |
601 | } | |
602 | ||
603 | void pci_con_disc(void) | |
604 | { | |
605 | console_assign(stdin,"serial"); | |
606 | console_assign(stderr,"serial"); | |
607 | console_assign(stdout,"serial"); | |
608 | PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_DISC); | |
609 | /* reconnection */ | |
610 | irq_free_handler(0x02); | |
611 | pci_con_connect(); | |
612 | } | |
613 | #endif /* #ifdef CFG_PCI_CON_DEVICE */ | |
614 | ||
615 | /* | |
616 | * Absolute environment address for linker file. | |
617 | */ | |
618 | GEN_ABS(env_start, CFG_ENV_OFFSET + CFG_FLASH_BASE); |