pati.c
来自「适合KS8695X」· C语言 代码 · 共 619 行 · 第 1/2 页
C
619 行
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 *) CFG_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)
{
mem_test_reloc();
init_ios();
return 0;
}
/****************************************************************
* Check the board
****************************************************************/
#define BOARD_NAME "PATI"
int checkboard (void)
{
unsigned char s[50];
unsigned long 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 CFG_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;
device_t 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;
device_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 CFG_PCI_CON_DEVICE */
/*
* Absolute environment address for linker file.
*/
GEN_ABS(env_start, CFG_ENV_OFFSET + CFG_FLASH_BASE);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?