pati.c 17 KB

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