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