|  | /* | 
|  | * (C) Copyright 2003 | 
|  | * Martin Winistoerfer, martinwinistoerfer@gmx.ch. | 
|  | * Atapted for PATI | 
|  | * Denis Peter, d.peter@mpl.ch | 
|  | * See file CREDITS for list of people who contributed to this | 
|  | * project. | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License as | 
|  | * published by the Free Software Foundation; either version 2 of | 
|  | * the License, or (at your option) any later version. | 
|  | * | 
|  | * This program is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | * GNU General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU General Public License | 
|  | * along with this program; if not, write to the Free Software | 
|  | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | 
|  | * MA 02111-1307 USA | 
|  | */ | 
|  |  | 
|  | /*********************************************************************************** | 
|  | * Bits for the SDRAM controller | 
|  | * ----------------------------- | 
|  | * | 
|  | * CAL:	CAS Latency. If cleared to 0 (default) the SDRAM controller asserts TA# on | 
|  | *	the 2nd Clock after ACTIVE command (CAS Latency = 2). If set to 1 the SDRAM | 
|  | *	controller asserts TA# on the 3rd Clock after ACTIVE command (CAS Latency = 3). | 
|  | * RCD:	RCD ACTIVE to READ or WRITE Delay (Ras to Cas Delay). If cleared 0 (default) | 
|  | *	tRCD of the SDRAM must equal or less 25ns. If set to 1 tRCD must be equal or less 50ns. | 
|  | * WREC:Write Recovery. If cleared 0 (default) tWR of the SDRAM must equal or less 25ns. | 
|  | *	If set to 1 tWR must be equal or less 50ns. | 
|  | * RP:	Precharge Command Time. If cleared 0 (default) tRP of the SDRAM must equal or less | 
|  | *	25ns. If set to 1 tRP must be equal or less 50ns. | 
|  | * RC:	Auto Refresh to Active Time. If cleared 0 (default) tRC of the SDRAM must equal | 
|  | *	or less 75ns. If set to 1 tRC must be equal or less 100ns. | 
|  | * LMR:	Bit to set the Mode Register of the SDRAM. If set, the next access to the SDRAM | 
|  | *	is the Load Mode Register Command. | 
|  | * IIP:	Init in progress. Set to 1 for starting the init sequence | 
|  | *	(Precharge All). As long this bit is set, the Precharge All is still in progress. | 
|  | *	After command has completed, wait at least for 8 refresh (200usec) before proceed. | 
|  | **********************************************************************************/ | 
|  |  | 
|  | #include <common.h> | 
|  | #include <mpc5xx.h> | 
|  | #include <stdio_dev.h> | 
|  | #include <pci_ids.h> | 
|  | #define PLX9056_LOC | 
|  | #include "plx9056.h" | 
|  | #include "pati.h" | 
|  |  | 
|  | #if defined(__APPLE__) | 
|  | /* Leading underscore on symbols */ | 
|  | #  define SYM_CHAR "_" | 
|  | #else /* No leading character on symbols */ | 
|  | #  define SYM_CHAR | 
|  | #endif | 
|  |  | 
|  | #undef SDRAM_DEBUG | 
|  | /* | 
|  | * Macros to generate global absolutes. | 
|  | */ | 
|  | #define GEN_SYMNAME(str) SYM_CHAR #str | 
|  | #define GEN_VALUE(str) #str | 
|  | #define GEN_ABS(name, value) \ | 
|  | asm (".globl " GEN_SYMNAME(name)); \ | 
|  | asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) | 
|  |  | 
|  |  | 
|  | /************************************************************************ | 
|  | * Early debug routines | 
|  | */ | 
|  | void write_hex (unsigned char i) | 
|  | { | 
|  | char cc; | 
|  |  | 
|  | cc = i >> 4; | 
|  | cc &= 0xf; | 
|  | if (cc > 9) | 
|  | serial_putc (cc + 55); | 
|  | else | 
|  | serial_putc (cc + 48); | 
|  | cc = i & 0xf; | 
|  | if (cc > 9) | 
|  | serial_putc (cc + 55); | 
|  | else | 
|  | serial_putc (cc + 48); | 
|  | } | 
|  |  | 
|  | #if defined(SDRAM_DEBUG) | 
|  |  | 
|  | void write_4hex (unsigned long val) | 
|  | { | 
|  | write_hex ((unsigned char) (val >> 24)); | 
|  | write_hex ((unsigned char) (val >> 16)); | 
|  | write_hex ((unsigned char) (val >> 8)); | 
|  | write_hex ((unsigned char) val); | 
|  | } | 
|  |  | 
|  | #endif | 
|  |  | 
|  | unsigned long in32(unsigned long addr) | 
|  | { | 
|  | unsigned long *p=(unsigned long *)addr; | 
|  | return *p; | 
|  | } | 
|  |  | 
|  | void out32(unsigned long addr,unsigned long data) | 
|  | { | 
|  | unsigned long *p=(unsigned long *)addr; | 
|  | *p=data; | 
|  | } | 
|  |  | 
|  | typedef struct { | 
|  | unsigned short boardtype; /* Board revision and Population Options */ | 
|  | unsigned char cal;		/* cas Latency  0:CAL=2 1:CAL=3 */ | 
|  | unsigned char rcd;		/* ras to cas delay  0:<25ns 1:<50ns*/ | 
|  | unsigned char wrec;		/* write recovery 0:<25ns 1:<50ns */ | 
|  | unsigned char pr;		/* Precharge Command Time 0:<25ns 1:<50ns */ | 
|  | unsigned char rc;		/* Auto Refresh to Active Time 0:<75ns 1:<100ns */ | 
|  | unsigned char sz;		/* log binary => Size = (4MByte<<sz) 5 = 128, 4 = 64, 3 = 32, 2 = 16, 1=8 */ | 
|  | } sdram_t; | 
|  |  | 
|  | const sdram_t sdram_table[] = { | 
|  | { 0x0000,	/* PATI Rev A, 16MByte -1 Board */ | 
|  | 1,	/* Case Latenty = 3 */ | 
|  | 0,	/* ras to cas delay  0 (20ns) */ | 
|  | 0,	/* write recovery 0:<25ns 1:<50ns*/ | 
|  | 0,	/* Precharge Command Time 0 (20ns) */ | 
|  | 0,	/* Auto Refresh to Active Time 0 (68) */ | 
|  | 2	/* log binary => Size 2 = 16MByte, 1=8 */ | 
|  | }, | 
|  | { 0xffff, /* terminator */ | 
|  | 0xff, | 
|  | 0xff, | 
|  | 0xff, | 
|  | 0xff, | 
|  | 0xff, | 
|  | 0xff } | 
|  | }; | 
|  |  | 
|  |  | 
|  | extern int mem_test (unsigned long start, unsigned long ramsize, int quiet); | 
|  |  | 
|  | /* | 
|  | * Get RAM size. | 
|  | */ | 
|  | phys_size_t initdram(int board_type) | 
|  | { | 
|  | unsigned char board_rev; | 
|  | unsigned long reg; | 
|  | unsigned long lmr; | 
|  | int i,timeout; | 
|  |  | 
|  | #if defined(SDRAM_DEBUG) | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_PART_ID); | 
|  | puts("\n\nSYSTEM part 0x"); write_4hex(SYSCNTR_PART(reg)); | 
|  | puts(" Vers 0x"); write_4hex(SYSCNTR_ID(reg)); | 
|  | puts("\nSDRAM  part  0x"); write_4hex(SDRAM_PART(reg)); | 
|  | puts(" Vers 0x"); write_4hex(SDRAM_ID(reg)); | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | 
|  | puts("\nBoard rev.   0x"); write_4hex(SYSCNTR_BREV(reg)); | 
|  | putc('\n'); | 
|  | #endif | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | 
|  | board_rev=(unsigned char)(SYSCNTR_BREV(reg)); | 
|  | i=0; | 
|  | while(1) { | 
|  | if(sdram_table[i].boardtype==0xffff) { | 
|  | puts("ERROR, found no table for Board 0x"); | 
|  | write_hex(board_rev); | 
|  | while(1); | 
|  | } | 
|  | if(sdram_table[i].boardtype==(unsigned char)board_rev) | 
|  | break; | 
|  | i++; | 
|  | } | 
|  | /* Set CAL, RCD, WREQ, PR and RC Bits */ | 
|  | #if defined(SDRAM_DEBUG) | 
|  | puts("Set CAL, RCD, WREQ, PR and RC Bits\n"); | 
|  | #endif | 
|  | /* mask bits */ | 
|  | reg &= ~(SET_REG_BIT(1,SDRAM_CAL) | SET_REG_BIT(1,SDRAM_RCD) | SET_REG_BIT(1,SDRAM_WREQ) | | 
|  | SET_REG_BIT(1,SDRAM_PR)  |  SET_REG_BIT(1,SDRAM_RC) | SET_REG_BIT(1,SDRAM_LMR)  | | 
|  | SET_REG_BIT(1,SDRAM_IIP) | SET_REG_BIT(1,SDRAM_RES0)); | 
|  | /* set bits */ | 
|  | reg |= (SET_REG_BIT(sdram_table[i].cal,SDRAM_CAL) | | 
|  | SET_REG_BIT(sdram_table[i].rcd,SDRAM_RCD) | | 
|  | SET_REG_BIT(sdram_table[i].wrec,SDRAM_WREQ) | | 
|  | SET_REG_BIT(sdram_table[i].pr,SDRAM_PR) | | 
|  | SET_REG_BIT(sdram_table[i].rc,SDRAM_RC)); | 
|  |  | 
|  | out32(PLD_CONFIG_BASE+PLD_BOARD_TIMING,reg); | 
|  | /* step 2 set IIP */ | 
|  | #if defined(SDRAM_DEBUG) | 
|  | puts("step 2 set IIP\n"); | 
|  | #endif | 
|  | /* step 2 set IIP */ | 
|  | reg |= SET_REG_BIT(1,SDRAM_IIP); | 
|  | timeout=0; | 
|  | while (timeout!=0xffff) { | 
|  | __asm__ volatile("eieio"); | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | 
|  | if((reg & SET_REG_BIT(1,SDRAM_IIP))==0) | 
|  | break; | 
|  | timeout++; | 
|  | udelay(1); | 
|  | } | 
|  | /* wait for at least 8 refresh */ | 
|  | udelay(1000); | 
|  | /* set LMR */ | 
|  | reg |= SET_REG_BIT(1,SDRAM_LMR); | 
|  | out32(PLD_CONFIG_BASE+PLD_BOARD_TIMING,reg); | 
|  | __asm__ volatile("eieio"); | 
|  | lmr=0x00000002; /* sequential burst 4 data */ | 
|  | if(sdram_table[i].cal==1) | 
|  | lmr|=0x00000030; /* cal = 3 */ | 
|  | else | 
|  | lmr|=0000000020; /* cal = 2 */ | 
|  | /* rest standard operation programmed write burst length */ | 
|  | /* we have a x32 bit bus to the SDRAM, so shift the addr with 2 */ | 
|  | lmr<<=2; | 
|  | in32(CONFIG_SYS_SDRAM_BASE + lmr); | 
|  | /* ok, we're done, return SDRAM size */ | 
|  | return ((0x400000 << sdram_table[i].sz));		/* log2 value of 4MByte  */ | 
|  | } | 
|  |  | 
|  |  | 
|  | void set_flash_vpp(int ext_vpp, int ext_wp, int int_vpp) | 
|  | { | 
|  | unsigned long reg; | 
|  | reg=in32(PLD_CONF_REG2+PLD_CONFIG_BASE); | 
|  | reg &= ~(SET_REG_BIT(1,SYSCNTR_CPU_VPP) | | 
|  | SET_REG_BIT(1,SYSCNTR_FL_VPP) | | 
|  | SET_REG_BIT(1,SYSCNTR_FL_WP)); | 
|  |  | 
|  | reg |= (SET_REG_BIT(int_vpp,SYSCNTR_CPU_VPP) | | 
|  | SET_REG_BIT(ext_vpp,SYSCNTR_FL_VPP) | | 
|  | SET_REG_BIT(ext_wp,SYSCNTR_FL_WP)); | 
|  | out32(PLD_CONF_REG2+PLD_CONFIG_BASE,reg); | 
|  | udelay(100); | 
|  | } | 
|  |  | 
|  |  | 
|  | void show_pld_regs(void) | 
|  | { | 
|  | unsigned long reg,reg1; | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_PART_ID); | 
|  | printf("\nSYSTEM part %ld, Vers %ld\n",SYSCNTR_PART(reg),SYSCNTR_ID(reg)); | 
|  | printf("SDRAM  part %ld, Vers %ld\n",SDRAM_PART(reg),SDRAM_ID(reg)); | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | 
|  | printf("Board rev.  %c\n",(char) (SYSCNTR_BREV(reg)+'A')); | 
|  | printf("Waitstates  %ld\n",GET_SYSCNTR_FLWAIT(reg)); | 
|  | printf("SDRAM:      CAL=%ld RCD=%ld WREQ=%ld PR=%ld\n            RC=%ld  LMR=%ld IIP=%ld\n", | 
|  | GET_REG_BIT(reg,SDRAM_CAL),GET_REG_BIT(reg,SDRAM_RCD), | 
|  | GET_REG_BIT(reg,SDRAM_WREQ),GET_REG_BIT(reg,SDRAM_PR), | 
|  | GET_REG_BIT(reg,SDRAM_RC),GET_REG_BIT(reg,SDRAM_LMR), | 
|  | GET_REG_BIT(reg,SDRAM_IIP)); | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_CONF_REG1); | 
|  | reg1=in32(PLD_CONFIG_BASE+PLD_CONF_REG2); | 
|  | printf("HW Config:  FLAG=%ld IP=%ld  index=%ld PRPM=%ld\n            ICW=%ld  ISB=%ld BDIS=%ld  PCIM=%ld\n", | 
|  | GET_REG_BIT(reg,SYSCNTR_FLAG),GET_REG_BIT(reg,SYSCNTR_IP), | 
|  | GET_SYSCNTR_BOOTIND(reg),GET_REG_BIT(reg,SYSCNTR_PRM), | 
|  | GET_REG_BIT(reg,SYSCNTR_ICW),GET_SYSCNTR_ISB(reg), | 
|  | GET_REG_BIT(reg1,SYSCNTR_BDIS),GET_REG_BIT(reg1,SYSCNTR_PCIM)); | 
|  | printf("Switches:   MUX=%ld PCI_DIS=%ld Boot_EN=%ld  Config=%ld\n",GET_SDRAM_MUX(reg), | 
|  | GET_REG_BIT(reg,SDRAM_PDIS),GET_REG_BIT(reg1,SYSCNTR_BOOTEN), | 
|  | GET_SYSCNTR_CFG(reg1)); | 
|  | printf("Misc:       RIP=%ld CPU_VPP=%ld FLSH_VPP=%ld FLSH_WP=%ld\n\n", | 
|  | GET_REG_BIT(reg,SDRAM_RIP),GET_REG_BIT(reg1,SYSCNTR_CPU_VPP), | 
|  | GET_REG_BIT(reg1,SYSCNTR_FL_VPP),GET_REG_BIT(reg1,SYSCNTR_FL_WP)); | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************** | 
|  | * Setting IOs | 
|  | * ----------- | 
|  | * GPIO6 is User LED1 | 
|  | * GPIO7 is Interrupt PLX (Output) | 
|  | * GPIO5 is User LED0 | 
|  | * GPIO2 is PLX USERi (Output) | 
|  | * GPIO1 is PLX Interrupt (Input) | 
|  | ****************************************************************/ | 
|  | void init_ios(void) | 
|  | { | 
|  | volatile immap_t * immr = (immap_t *) CONFIG_SYS_IMMR; | 
|  | volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; | 
|  | unsigned long reg; | 
|  | reg=sysconf->sc_sgpiocr; /* Data direction register */ | 
|  | reg &= ~0x67000000; | 
|  | reg |= 0x27000000; /* set outpupts */ | 
|  | sysconf->sc_sgpiocr=reg; /* Data direction register */ | 
|  | reg=sysconf->sc_sgpiodt2; /* Data register */ | 
|  | /* set output to 0 */ | 
|  | reg &= ~0x27000000; | 
|  | /* set IRQ and USERi to 1 */ | 
|  | reg |= 0x28000000; | 
|  | sysconf->sc_sgpiodt2=reg; /* Data register */ | 
|  | } | 
|  |  | 
|  | void user_led0(int led_on) | 
|  | { | 
|  | volatile immap_t * immr = (immap_t *) CONFIG_SYS_IMMR; | 
|  | volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; | 
|  | unsigned long reg; | 
|  | reg=sysconf->sc_sgpiodt2; /* Data register */ | 
|  | if(led_on)	/* set output to 1 */ | 
|  | reg |= 0x04000000; | 
|  | else | 
|  | reg &= ~0x04000000; | 
|  | sysconf->sc_sgpiodt2=reg; /* Data register */ | 
|  | } | 
|  |  | 
|  | void user_led1(int led_on) | 
|  | { | 
|  | volatile immap_t * immr = (immap_t *) CONFIG_SYS_IMMR; | 
|  | volatile sysconf5xx_t *sysconf = &immr->im_siu_conf; | 
|  | unsigned long reg; | 
|  | reg=sysconf->sc_sgpiodt2; /* Data register */ | 
|  | if(led_on)	/* set output to 1 */ | 
|  | reg |= 0x02000000; | 
|  | else | 
|  | reg &= ~0x02000000; | 
|  | sysconf->sc_sgpiodt2=reg; /* Data register */ | 
|  | } | 
|  |  | 
|  |  | 
|  | /**************************************************************** | 
|  | * Last Stage Init | 
|  | ****************************************************************/ | 
|  | int last_stage_init (void) | 
|  | { | 
|  | init_ios(); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /**************************************************************** | 
|  | * Check the board | 
|  | ****************************************************************/ | 
|  |  | 
|  | #define BOARD_NAME	"PATI" | 
|  |  | 
|  | int checkboard (void) | 
|  | { | 
|  | char s[50]; | 
|  | ulong reg; | 
|  | char rev; | 
|  | int i; | 
|  |  | 
|  | puts ("\nBoard: "); | 
|  | reg=in32(PLD_CONFIG_BASE+PLD_BOARD_TIMING); | 
|  | rev=(char)(SYSCNTR_BREV(reg)+'A'); | 
|  | i = getenv_r ("serial#", s, 32); | 
|  | if ((i == -1)) { | 
|  | puts ("### No HW ID - assuming " BOARD_NAME); | 
|  | printf(" Rev. %c\n",rev); | 
|  | } | 
|  | else { | 
|  | s[sizeof(BOARD_NAME)-1] = 0; | 
|  | printf ("%s-1 Rev %c SN: %s\n", s,rev, | 
|  | &s[sizeof(BOARD_NAME)]); | 
|  | } | 
|  | set_flash_vpp(1,0,0); /* set Flash VPP */ | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | #ifdef CONFIG_SYS_PCI_CON_DEVICE | 
|  | /************************************************************************ | 
|  | * PCI Communication | 
|  | * | 
|  | * Alive (Pinging): | 
|  | * ---------------- | 
|  | * PCI Host sends message ALIVE, Local acknowledges with ALIVE | 
|  | * | 
|  | * PCI_CON console over PCI: | 
|  | * ------------------------- | 
|  | * Local side: | 
|  | *     - uses PCI9056_LOC_TO_PCI_DBELL register to signal that | 
|  | *       data is avaible (PCIMSG_CONN) | 
|  | *     - uses PCI9056_MAILBOX1 to send data | 
|  | *     - uses PCI9056_MAILBOX0 to receive data | 
|  | * PCI side: | 
|  | *     - uses PCI9056_PCI_TO_LOC_DBELL register to signal that | 
|  | *       data is avaible (PCIMSG_CONN) | 
|  | *     - uses PCI9056_MAILBOX0 to send data | 
|  | *     - uses PCI9056_MAILBOX1 to receive data | 
|  | * | 
|  | * How it works: | 
|  | *     Send: | 
|  | *     - check if PCICON_TRANSMIT_REG is empty | 
|  | *     - write data or'ed with 0x80000000 into the PCICON_TRANSMIT_REG | 
|  | *     - write PCIMSG_CONN into the PCICON_DBELL_REG to signal a data | 
|  | *       is waiting | 
|  | *     Receive: | 
|  | *     - get an interrupt via the PCICON_ACK_REG register message | 
|  | *       PCIMSG_CONN | 
|  | *     - write the data from the PCICON_RECEIVE_REG into the receive | 
|  | *       buffer and if the receive buffer is not full, clear the | 
|  | *       PCICON_RECEIVE_REG (this allows the counterpart to write more data) | 
|  | *     - Clear the interrupt by writing 0xFFFFFFFF to the PCICON_ACK_REG | 
|  | * | 
|  | *     The PCICON_RECEIVE_REG must be cleared by the routine which reads | 
|  | *     the receive buffer if the buffer is not full any more | 
|  | * | 
|  | */ | 
|  |  | 
|  | #undef PCI_CON_DEBUG | 
|  |  | 
|  | #ifdef	PCI_CON_DEBUG | 
|  | #define	PCI_CON_PRINTF(fmt,args...)	serial_printf (fmt ,##args) | 
|  | #else | 
|  | #define PCI_CON_PRINTF(fmt,args...) | 
|  | #endif | 
|  |  | 
|  |  | 
|  | /********************************************************* | 
|  | * we work only with a receive buffer on eiter side. | 
|  | * Transmit buffer is free, if mailbox is cleared. | 
|  | * Transmit character is or'ed with 0x80000000 | 
|  | * PATI receive register MAILBOX0 | 
|  | * PATI transmit register MAILBOX1 | 
|  | *********************************************************/ | 
|  | #define PCICON_RECEIVE_REG	PCI9056_MAILBOX0 | 
|  | #define PCICON_TRANSMIT_REG	PCI9056_MAILBOX1 | 
|  | #define PCICON_DBELL_REG	PCI9056_LOC_TO_PCI_DBELL | 
|  | #define PCICON_ACK_REG		PCI9056_PCI_TO_LOC_DBELL | 
|  |  | 
|  |  | 
|  | #define PCIMSG_ALIVE		0x1 | 
|  | #define PCIMSG_CONN		0x2 | 
|  | #define PCIMSG_DISC		0x3 | 
|  | #define PCIMSG_CON_DATA	0x5 | 
|  |  | 
|  |  | 
|  | #define PCICON_GET_REG(x)	(in32(x + PCI_CONFIG_BASE)) | 
|  | #define PCICON_SET_REG(x,y)	(out32(x + PCI_CONFIG_BASE,y)) | 
|  | #define PCICON_TX_FLAG		0x80000000 | 
|  |  | 
|  |  | 
|  | #define REC_BUFFER_SIZE	0x100 | 
|  | int recbuf[REC_BUFFER_SIZE]; | 
|  | static int r_ptr = 0; | 
|  | int w_ptr; | 
|  | struct stdio_dev pci_con_dev; | 
|  | int conn=0; | 
|  | int buff_full=0; | 
|  |  | 
|  | void pci_con_put_it(const char c) | 
|  | { | 
|  | /* Test for completition */ | 
|  | unsigned long reg; | 
|  | do { | 
|  | reg=PCICON_GET_REG(PCICON_TRANSMIT_REG); | 
|  | }while(reg); | 
|  | reg=PCICON_TX_FLAG + c; | 
|  | PCICON_SET_REG(PCICON_TRANSMIT_REG,reg); | 
|  | PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_CON_DATA); | 
|  | } | 
|  |  | 
|  | void pci_con_putc(const char c) | 
|  | { | 
|  | pci_con_put_it(c); | 
|  | if(c == '\n') | 
|  | pci_con_put_it('\r'); | 
|  | } | 
|  |  | 
|  |  | 
|  | int pci_con_getc(void) | 
|  | { | 
|  | int res; | 
|  | int diff; | 
|  | while(r_ptr==(volatile int)w_ptr); | 
|  | res=recbuf[r_ptr++]; | 
|  | if(r_ptr==REC_BUFFER_SIZE) | 
|  | r_ptr=0; | 
|  | if(w_ptr<r_ptr) | 
|  | diff=r_ptr+REC_BUFFER_SIZE-w_ptr; | 
|  | else | 
|  | diff=r_ptr-w_ptr; | 
|  | if((diff<(REC_BUFFER_SIZE-4)) && buff_full) { | 
|  | /* clear Mail box */ | 
|  | buff_full=0; | 
|  | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | 
|  | } | 
|  | return res; | 
|  | } | 
|  |  | 
|  | int pci_con_tstc(void) | 
|  | { | 
|  | if(r_ptr==(volatile int)w_ptr) | 
|  | return 0; | 
|  | return 1; | 
|  | } | 
|  |  | 
|  | void pci_con_puts (const char *s) | 
|  | { | 
|  | while (*s) { | 
|  | pci_con_putc(*s); | 
|  | ++s; | 
|  | } | 
|  | } | 
|  |  | 
|  | void pci_con_init (void) | 
|  | { | 
|  | w_ptr = 0; | 
|  | r_ptr = 0; | 
|  | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | 
|  | conn=1; | 
|  | } | 
|  |  | 
|  | /******************************************* | 
|  | * IRQ routine | 
|  | ******************************************/ | 
|  | int pci_dorbell_irq(void) | 
|  | { | 
|  | unsigned long reg,data; | 
|  | int diff; | 
|  | reg=PCICON_GET_REG(PCI9056_INT_CTRL_STAT); | 
|  | PCI_CON_PRINTF(" PCI9056_INT_CTRL_STAT = %08lX\n",reg); | 
|  | if(reg & (1<<20) ) { | 
|  | /* read doorbell */ | 
|  | reg=PCICON_GET_REG(PCICON_ACK_REG); | 
|  | switch(reg) { | 
|  | case PCIMSG_ALIVE: | 
|  | PCI_CON_PRINTF(" Alive\n"); | 
|  | PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_ALIVE); | 
|  | break; | 
|  | case PCIMSG_CONN: | 
|  | PCI_CON_PRINTF(" Conn %d",conn); | 
|  | w_ptr = 0; | 
|  | r_ptr = 0; | 
|  | buff_full=0; | 
|  | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | 
|  | conn=1; | 
|  | PCI_CON_PRINTF(" ... %d\n",conn); | 
|  | break; | 
|  | case PCIMSG_CON_DATA: | 
|  | data=PCICON_GET_REG(PCICON_RECEIVE_REG); | 
|  | recbuf[w_ptr++]=(int)(data&0xff); | 
|  | PCI_CON_PRINTF(" Data Console %lX, %X %d %d %X\n",data,((int)(data&0xFF)), | 
|  | r_ptr,w_ptr,recbuf[w_ptr-1]); | 
|  | if(w_ptr==REC_BUFFER_SIZE) | 
|  | w_ptr=0; | 
|  | if(w_ptr<r_ptr) | 
|  | diff=r_ptr+REC_BUFFER_SIZE-w_ptr; | 
|  | else | 
|  | diff=r_ptr-w_ptr; | 
|  | if(diff>(REC_BUFFER_SIZE-4)) | 
|  | buff_full=1; | 
|  | else | 
|  | /* clear Mail box */ | 
|  | PCICON_SET_REG(PCICON_RECEIVE_REG,0L); | 
|  | break; | 
|  | default: | 
|  | serial_printf(" PCI9056_PCI_TO_LOC_DBELL = %08lX\n",reg); | 
|  | } | 
|  | /* clear IRQ */ | 
|  | PCICON_SET_REG(PCICON_ACK_REG,~0L); | 
|  | } | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | void pci_con_connect(void) | 
|  | { | 
|  | unsigned long reg; | 
|  | conn=0; | 
|  | reg=PCICON_GET_REG(PCI9056_INT_CTRL_STAT); | 
|  | /* default 0x0f010180 */ | 
|  | reg &= 0xff000000; | 
|  | reg |= 0x00030000; /* enable local dorbell */ | 
|  | reg |= 0x00000300; /* enable PCI dorbell */ | 
|  | PCICON_SET_REG(PCI9056_INT_CTRL_STAT , reg); | 
|  | irq_install_handler (0x2, (interrupt_handler_t *) pci_dorbell_irq,NULL); | 
|  | memset (&pci_con_dev, 0, sizeof (pci_con_dev)); | 
|  | strcpy (pci_con_dev.name, "pci_con"); | 
|  | pci_con_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; | 
|  | pci_con_dev.putc = pci_con_putc; | 
|  | pci_con_dev.puts = pci_con_puts; | 
|  | pci_con_dev.getc = pci_con_getc; | 
|  | pci_con_dev.tstc = pci_con_tstc; | 
|  | stdio_register (&pci_con_dev); | 
|  | printf("PATI ready for PCI connection, type ctrl-c for exit\n"); | 
|  | do { | 
|  | udelay(10); | 
|  | if((volatile int)conn) | 
|  | break; | 
|  | if(ctrlc()) { | 
|  | irq_free_handler(0x2); | 
|  | return; | 
|  | } | 
|  | }while(1); | 
|  | console_assign(stdin,"pci_con"); | 
|  | console_assign(stderr,"pci_con"); | 
|  | console_assign(stdout,"pci_con"); | 
|  | } | 
|  |  | 
|  | void pci_con_disc(void) | 
|  | { | 
|  | console_assign(stdin,"serial"); | 
|  | console_assign(stderr,"serial"); | 
|  | console_assign(stdout,"serial"); | 
|  | PCICON_SET_REG(PCICON_DBELL_REG,PCIMSG_DISC); | 
|  | /* reconnection */ | 
|  | irq_free_handler(0x02); | 
|  | pci_con_connect(); | 
|  | } | 
|  | #endif /* #ifdef CONFIG_SYS_PCI_CON_DEVICE */ | 
|  |  | 
|  | /* | 
|  | * Absolute environment address for linker file. | 
|  | */ | 
|  | GEN_ABS(env_start, CONFIG_ENV_OFFSET + CONFIG_SYS_FLASH_BASE); |