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