⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.c

📁 某个ARM9板子的实际bootloader 对裁剪
💻 C
字号:
/*				NOTES *   The instruction set of the 93C66/56/46/26/06 chips are as follows: * *               Start  OP	    * *     Function   Bit  Code  Address**  Data     Description *     ------------------------------------------------------------------- *     READ        1    10   A7 - A0             Reads data stored in memory, *                                               starting at specified address *     EWEN        1    00   11XXXXXX            Write enable must precede *                                               all programming modes *     ERASE       1    11   A7 - A0             Erase register A7A6A5A4A3A2A1A0 *     WRITE       1    01   A7 - A0   D15 - D0  Writes register *     ERAL        1    00   10XXXXXX            Erase all registers *     WRAL        1    00   01XXXXXX  D15 - D0  Writes to all registers *     EWDS        1    00   00XXXXXX            Disables all programming *                                               instructions *    *Note: A value of X for address is a don't care condition. *    **Note: There are 8 address bits for the 93C56/66 chips unlike *	      the 93C46/26/06 chips which have 6 address bits. * *   The 93Cx6 has a four wire interface: clock, chip select, data in, and *   data out.While the ADM6996 uning three interface: clock, chip select,and data line. *   The input and output are the same pin. ADM6996 can only recognize the write cmd. *   In order to perform above functions, you need *   1. to enable the chip select . *   2. send one clock of dummy clock *   3. send start bit and opcode *   4. send 8 bits address and 16 bits data *   5. to disable the chip select. *							Jason Lee 2003/07/30 */#include <define.h>//#include <board_config.h>//#include <sl2312.h>#define GPIO_BASE_ADDR  0x4E000000/***************************************//* define GPIO module base address     *//***************************************/#define GPIO_EECS	     0x80000000		/*   EECS: GPIO[22]   */#define GPIO_MOSI	     0x20000000         /*   EEDO: GPIO[29]   send to 6996*/#define GPIO_MISO	     0x40000000         /*   EEDI: GPIO[30]   receive from 6996*/#define GPIO_EECK	     0x10000000         /*   EECK: GPIO[31]   */#define ADM_EECS		0x01#define ADM_EECK		0x02#define ADM_EDIO		0x04/************************************************************** SPI protocol for ADM6996 control**************************************************************/#define SPI_OP_LEN	     0x08		// the length of start bit and opcode#define SPI_OPWRITE	     0X05		// write#define SPI_OPREAD	     0X06		// read#define SPI_OPERASE	     0X07		// erase#define SPI_OPWTEN	     0X04		// write enable#define SPI_OPWTDIS	     0X04		// write disable#define SPI_OPERSALL	     0X04		// erase all#define SPI_OPWTALL	     0X04		// write all#define SPI_ADD_LEN	     8			// bits of Address#define SPI_DAT_LEN	     32			// bits of Data#define ADM6996_PORT_NO	     6			// the port number of ADM6996#define ADM6999_PORT_NO	     9			// the port number of ADM6999#ifdef CONFIG_ADM_6996	#define ADM699X_PORT_NO		ADM6996_PORT_NO#endif#ifdef CONFIG_ADM_6999	#define ADM699X_PORT_NO		ADM6999_PORT_NO#endif#define LPC_GPIO_SET		3#define LPC_BASE_ADDR			IO_ADDRESS(IT8712_IO_BASE)extern int it8712_exist;#define inb_gpio(x)			inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)#define outb_gpio(x, y)		outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)#define readl(addr)								REG32(addr)#define writel(value, addr)						REG32(addr) = valueenum GPIO_REG{    GPIO_DATA_OUT   = 0x00,    GPIO_DATA_IN    = 0x04,    GPIO_PIN_DIR    = 0x08,    GPIO_BY_PASS    = 0x0c,    GPIO_DATA_SET   = 0x10,    GPIO_DATA_CLEAR = 0x14,};/****************************************//*	Function Declare		*//****************************************/unsigned int SPI_read_bit(void);void SPI_write_bit(char bit_EEDO);unsigned int SPI_read_bit(void);void SPI_CS_enable(unsigned char enable);unsigned int SPI_read(unsigned char block,unsigned char subblock,unsigned char addr);/******************************************* SPI_write* addr -> Write Address* value -> value to be write***************************************** */void SPI_write(unsigned char block,unsigned char subblock,unsigned char addr,unsigned int value){	int     i;	char    bit;	int     ad1;	unsigned int data;	SPI_CS_enable(1);		data = (block<<5) | 0x10 | subblock;	//send write command 	for(i=SPI_OP_LEN-1;i>=0;i--)	{		bit = (data>>i)& 0x01;		SPI_write_bit(bit);	}		// send 8 bits address (MSB first, LSB last)	for(i=SPI_ADD_LEN-1;i>=0;i--)	{		bit = (addr>>i)& 0x01;		SPI_write_bit(bit);	}	// send 32 bits data (MSB first, LSB last)	for(i=SPI_DAT_LEN-1;i>=0;i--)	{		bit = (value>>i)& 0x01;		SPI_write_bit(bit);	}	SPI_CS_enable(0);	// CS low}void phy_write(unsigned char port_no,unsigned char reg,unsigned int val){	unsigned int cmd;		cmd = (port_no<<21)|(reg<<16)|val;	SPI_write(3,0,1,cmd);}unsigned int phy_read(unsigned char port_no,unsigned char reg){	unsigned int cmd,reg_val;		cmd = BIT(26)|(port_no<<21)|(reg<<16);	SPI_write(3,0,1,cmd);	hal_delay_us(5 * 1000);	reg_val = SPI_read(3,0,2);	return reg_val;}void phy_write_masked(unsigned char port_no,unsigned char reg,unsigned int val,unsigned int mask){	unsigned int cmd,reg_val;		cmd = BIT(26)|(port_no<<21)|(reg<<16);	// Read reg_val	SPI_write(3,0,1,cmd);	hal_delay_us(2 * 1000);	reg_val = SPI_read(3,0,2);	reg_val &= ~mask;			// Clear masked bit	reg_val |= (val&mask) ;			// set masked bit ,if true	cmd = (port_no<<21)|(reg<<16)|reg_val;	SPI_write(3,0,1,cmd);}void init_seq_7385(unsigned char port_no) {	 unsigned char rev;    phy_write(port_no, 31, 0x2a30);	phy_write_masked(port_no, 8, 0x0200, 0x0200);	phy_write(port_no, 31, 0x52b5);	phy_write(port_no, 16, 0xb68a);	phy_write_masked(port_no, 18, 0x0003, 0xff07);	phy_write_masked(port_no, 17, 0x00a2, 0x00ff);	phy_write(port_no, 16, 0x968a);	phy_write(port_no, 31, 0x2a30);	phy_write_masked(port_no, 8, 0x0000, 0x0200);	phy_write(port_no, 31, 0x0000); /* Read revision */ 	rev = phy_read(port_no, 3) & 0x000f;	//printf("Port %d PHY REV:%x\n",port_no,rev);	if (rev == 0)	{		phy_write(port_no, 31, 0x2a30);		phy_write_masked(port_no, 8, 0x0200, 0x0200);		phy_write(port_no, 31, 0x52b5);		phy_write(port_no, 18, 0x0000);		phy_write(port_no, 17, 0x0689);		phy_write(port_no, 16, 0x8f92);		phy_write(port_no, 31, 0x52B5);		phy_write(port_no, 18, 0x0000);		phy_write(port_no, 17, 0x0E35);		phy_write(port_no, 16, 0x9786);		phy_write(port_no, 31, 0x2a30);		phy_write_masked(port_no, 8, 0x0000, 0x0200);		phy_write(port_no, 23, 0xFF80);		phy_write(port_no, 23, 0x0000);	}	phy_write(port_no, 31, 0x0000);	phy_write(port_no, 18, 0x0048);	if (rev == 0)	{		phy_write(port_no, 31, 0x2a30);		phy_write(port_no, 20, 0x6600);		phy_write(port_no, 31, 0x0000);		phy_write(port_no, 24, 0xa24e);	}	else	{		phy_write(port_no, 31, 0x2a30);		phy_write_masked(port_no, 22, 0x0240, 0x0fc0);		phy_write_masked(port_no, 20, 0x4000, 0x6000);		phy_write(port_no, 31, 1);		phy_write_masked(port_no, 20, 0x6000, 0xe000);		phy_write(port_no, 31, 0x0000);	}}void phy_receiver_init (unsigned char port_no){    phy_write(port_no,31,0x2a30);    phy_write_masked(port_no, 12, 0x0200, 0x0300);    phy_write(port_no,31,0);}void phy_receiver_reconfig (unsigned char port_no){    unsigned char vga_state_a;    phy_write(port_no, 31, 0x52b5);    phy_write(port_no, 16, 0xaff0);    vga_state_a = (phy_read(port_no, 17) >> 4) & 0x01f;    if ((vga_state_a < 16) || (vga_state_a > 20)) {        phy_write(port_no, 31, 0x2a30);        phy_write_masked(port_no, 12, 0x0000, 0x0300);    }    phy_write(port_no, 31, 0);}/************************************* SPI_write_bit* bit_EEDO -> 1 or 0 to be written************************************/void SPI_write_bit(char bit_EEDO){	unsigned int addr;	unsigned int value;	addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);	value = readl(addr) |GPIO_EECK |GPIO_MOSI ;   /* set EECK/MISO Pin to output */	writel(value,addr);	if(bit_EEDO)	{		addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);		writel(GPIO_MOSI,addr); /* set MISO to 1 */			}	else	{		addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);		writel(GPIO_MOSI,addr); /* set MISO to 0 */	}	addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);	writel(GPIO_EECK,addr); /* set EECK to 1 */	addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);	writel(GPIO_EECK,addr); /* set EECK to 0 */	//return ;}/*********************************************************************** read a bit from ADM6996 register***********************************************************************/unsigned int SPI_read_bit(void) // read data from{	unsigned int addr;	unsigned int value;	addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);	value = readl(addr) & (~GPIO_MOSI);   // set EECK to output and MISO to input	writel(value,addr);	addr =(GPIO_BASE_ADDR + GPIO_DATA_SET);	writel(GPIO_EECK,addr); // set EECK to 1	addr = (GPIO_BASE_ADDR + GPIO_DATA_IN);	value = readl(addr) ;	addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);	writel(GPIO_EECK,addr); // set EECK to 0			value = value >> 30;	return value ;}/******************************************* SPI_default* EEPROM content default value*******************************************/void SPI_default(void){	int i;	unsigned reg_val,cmd;	unsigned char timeout;		hal_delay_us(30*1000);		for(i=0;i<15;i++){		if(i!=6 && i!=7)			SPI_write(3,2,0,0x1010400+i);		// Initial memory		hal_delay_us(1*1000);	}		hal_delay_us(30*1000);				SPI_write(2,0,0xB0,0x05);			// Clear MAC table	SPI_write(2,0,0xD0,0x03);			// Clear VLAN		//for(i=0;i<5;i++)	SPI_write(1,6,0x19,0x2C);			// Double Data rate		for(i=0;i<4;i++){		SPI_write(1,i,0x00,0x30050472);		// MAC configure		SPI_write(1,i,0x00,0x10050442);		// MAC configure		SPI_write(1,i,0x10,0x5F4);		// Max length		SPI_write(1,i,0x04,0x00030000);		// Flow control		SPI_write(1,i,0xDF,0x00000001);		// Flow control		SPI_write(1,i,0x08,0x000050c2);		// Flow control mac high		SPI_write(1,i,0x0C,0x002b00f1);		// Flow control mac low		SPI_write(1,i,0x6E,BIT(3));		// forward pause frame	}	SPI_write(1,i,0x00,0x20000030);			// set port 4 as reset		SPI_write(1,6,0x00,0x300701B1);			// MAC configure	SPI_write(1,6,0x00,0x10070181);			// MAC configure	SPI_write(1,6,0x10,0x5F4);			// Max length	SPI_write(1,6,0x04,0x00030000);		// Flow control	SPI_write(1,6,0xDF,0x00000002);		// Flow control	SPI_write(1,6,0x08,0x000050c2);		// Flow control mac high	SPI_write(1,6,0x0C,0x002b00f1);		// Flow control mac low	SPI_write(1,6,0x6E,BIT(3));		// forward pause frame		//SPI_write(7,0,0x05,0x31);			// MII delay for loader	//SPI_write(7,0,0x05,0x01);			// MII delay for kernel	SPI_write(7,0,0x05,0x33);			SPI_write(2,0,0x10,0x4F);			// Receive mask		hal_delay_us(50*1000);		SPI_write(7,0,0x14,0x02);			// Release Reset		hal_delay_us(3*1000);		for(i=0;i<4;i++){		init_seq_7385(i);		phy_receiver_init(i);		cmd = BIT(26)|(i<<21)|(0x1B<<16);	// Config LED		SPI_write(3,0,1,cmd);		hal_delay_us(10*1000);		reg_val = SPI_read(3,0,2);		reg_val &= 0xFF00;		reg_val |= 0x61;		cmd = (i<<21)|(0x1B<<16)|reg_val;		SPI_write(3,0,1,cmd);				cmd = BIT(26)|(i<<21)|(0x04<<16);	// Pause enable		SPI_write(3,0,1,cmd);		hal_delay_us(10*1000);		reg_val = SPI_read(3,0,2);		reg_val |= BIT(10)|BIT(11);		cmd = (i<<21)|(0x04<<16)|reg_val;		SPI_write(3,0,1,cmd);				cmd = BIT(26)|(i<<21)|(0x0<<16);	// collision test and re-negotiation		SPI_write(3,0,1,cmd);		hal_delay_us(10*1000);		reg_val = SPI_read(3,0,2);		reg_val |= BIT(7)|BIT(8)|BIT(9);		cmd = (i<<21)|(0x0<<16)|reg_val;		SPI_write(3,0,1,cmd);	}	init_seq_7385(i);	phy_receiver_init(i);	}/************************************************************ SPI_CS_enable* before access ,you have to enable Chip Select. (pull high)* When fisish, you should pull low !!*************************************************************/void SPI_CS_enable(unsigned char enable){	unsigned int addr,value;	addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);	value = readl(addr) |GPIO_EECS |GPIO_EECK;   /* set EECS/EECK Pin to output */	writel(value,addr);	if(enable)	{		addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);		writel(GPIO_EECK,addr); /* set EECK to 0 */	// pull low clk first		addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);		writel(GPIO_EECS,addr); /* set EECS to 0 */	}	else	{		addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);		writel(GPIO_EECK,addr); /* set EECK to 1 */	// pull high clk before disable		writel(GPIO_EECS,addr); /* set EECS to 1 */	}}/************************************************* SPI_read* table -> which table to be read: 1/count  0/EEPROM* addr  -> Address to be read* return : Value of the register*************************************************/unsigned int SPI_read(unsigned char block,unsigned char subblock,unsigned char addr){	int     i;	char    bit;	int     ad1;	unsigned int data,value=0;	SPI_CS_enable(1);		data = (block<<5) | subblock;	//send write command 	for(i=SPI_OP_LEN-1;i>=0;i--)	{		bit = (data>>i)& 0x01;		SPI_write_bit(bit);	}		// send 8 bits address (MSB first, LSB last)	for(i=SPI_ADD_LEN-1;i>=0;i--)	{		bit = (addr>>i)& 0x01;		SPI_write_bit(bit);	}		// dummy read for chip ready	for(i=0;i<8;i++)		SPI_read_bit();		// read 32 bits data (MSB first, LSB last)	for(i=SPI_DAT_LEN-1;i>=0;i--)	{		bit = SPI_read_bit();		value |= bit<<i;	}	SPI_CS_enable(0);	// CS low	return(value);}unsigned int SPI_get_identifier(void){	unsigned int flag=0;	SPI_write(7,0,0x01,0x01);	flag = SPI_read(7,0,0x18);		// chip id	//printf("Get VSC-switch ID 0x%08x\n",flag);	if(((flag&0x0ffff000)>>12) == 0x7385)	{		printf("Init VSC-switch ...\n");		return 1;	}	else		return 0;}void phy_optimize_receiver_init(unsigned char port_no)		// link down{	/* BZ 1776/1860/2095/2107, part 1/3 and 2/3 */	phy_write(port_no, 31, 0x2A30);	phy_write_masked(port_no, 12, 0x0200, 0x0300);	phy_write(port_no, 31, 0);    	phy_write(port_no, 31, 0x2A30);	phy_write_masked(port_no, 20, 0x1500, 0x1F00);	phy_write_masked(port_no, 20, 0x1500, 0x1F00);	phy_write(port_no, 31, 0);}void  phy_optimize_receiver_reconfig(unsigned char port_no)	// link up{	unsigned short vga_state_a;    	/* BZ 1776/1860/2095/2107 part 3/3 */	phy_write(port_no, 31, 0x52b5);	phy_write(port_no, 16, 0xaff0);	vga_state_a = phy_read(port_no, 17);	vga_state_a = ((vga_state_a >> 4) & 0x01f);	if ((vga_state_a < 16) || (vga_state_a > 20)) {	    phy_write(port_no, 31, 0x2a30);	    phy_write_masked(port_no, 12, 0x0000, 0x0300);	}	phy_write(port_no, 31, 0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -