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 + -
显示快捷键?