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

📄 skgespi.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * return: *	0 - if successful *	1 - if fails * * END_MANUAL_ENTRY() */static int spi_yuk2_sst_write_dword(unsigned long	address,			/* address to write to */unsigned long	value)				/* new value to be written */{	unsigned long spi_ctrl_reg;	unsigned long verify_value;	unsigned long i;	for (i = 0; i < 4; i++) {		spi_yuk2_write_enable();		/* write spi address */		spi_out32(SPI_Y2_ADDRESS_REG, address + i);   		/* write the new value */		spi_out32(SPI_Y2_DATA_REG, (value >> i*8) & 0x000000ff);		/* execute the spi write command */		spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);		spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;		spi_ctrl_reg |= SPI_Y2_WR;			spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);				/* wait for write to finish */		SPI_Y2_WAIT_SE_FINISH_WR();				verify_value = spi_yuk2_read_dword(address);		/* verify if write was successful*/		if ( ((verify_value >> i*8) & 0x000000ff) != ((value >> i*8) & 0x000000ff) ) {			fl_print("\n*** SPI data write error at address 0x%08x, ","is 0x%08x, should 0x%08x\n", address + i, 																		((verify_value >> i*8) & 0x000000ff), ((value >> i*8) & 0x000000ff));			return 1;		}	}	return 0;}/* * BEGIN_MANUAL_ENTRY() * *	int spi_yuk2_sst_clear_write_protection() * *	Clear the write protection bits for SST flash types because *	they are set by default. * * Uses: * * IN: * * return: *	nothing * * END_MANUAL_ENTRY() */void spi_yuk2_sst_clear_write_protection(){	unsigned long spi_ctrl_reg;	unsigned long op;	unsigned long addr;	unsigned char status;	spi_in32(SPI_Y2_OPCODE_REG1, &op);	op &= 0xffff00ff;	op |= 0x00000100;	spi_out32(SPI_Y2_OPCODE_REG1, op);	spi_in32(SPI_Y2_OPCODE_REG2, &op);	op &= 0xffffff00;	op |= 0x00000050;	spi_out32(SPI_Y2_OPCODE_REG2, op);	/* execute write status register enable command */	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;	spi_ctrl_reg |= SPI_Y2_WEN;		spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);		/* wait for the SPI to finish RD operation */	SPI_Y2_WAIT_SE_FINISH_CMD();	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);	status = (unsigned char)(spi_ctrl_reg & 0xfffffff3);	addr = ((unsigned long)status | (unsigned long)(status << 8) | (unsigned long)(status << 16) | (unsigned long)(status << 24));        	/* write spi address */	spi_out32(SPI_Y2_ADDRESS_REG, addr);   	/* write the new value */	spi_out32(SPI_Y2_DATA_REG, addr);	/* execute the write status register command */	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;	spi_ctrl_reg |= SPI_Y2_RD;	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);        /* wait for the SPI to finish RD operation */	SPI_Y2_WAIT_SE_FINISH_CMD();				spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);}/* * BEGIN_MANUAL_ENTRY() * *	static void spi_yuk2_erase_sector( *	unsigned long	sector_num) * *	This function will erase the sector specified allowing thus data to be written * * Uses: * * IN: * * return: *	nothing * * END_MANUAL_ENTRY() */static void spi_yuk2_erase_sector(unsigned long	sector_num)		/* sector to be erased */{	unsigned long spi_ctrl_reg;	spi_yuk2_write_enable();	/* write sector start address */	spi_out32(SPI_Y2_ADDRESS_REG, spi_yuk2_dev_table[spi_yuk2_dev].sector_size * sector_num);	/* execute erase sector command */	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;	spi_ctrl_reg |= SPI_Y2_SERS;			spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);	SPI_Y2_WAIT_SE_FINISH_WR();}/* * BEGIN_MANUAL_ENTRY() * *	void spi_yuk2_erase_chip() * *	This function will erase the complete SPI EPROM chip * * Uses: * * IN: * * return: *	nothing * * END_MANUAL_ENTRY() */void spi_yuk2_erase_chip(){	unsigned long spi_ctrl_reg;	spi_yuk2_write_enable();	/* execute erase chip command */	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);	spi_ctrl_reg &= ~SPI_Y2_CMD_MASK;	spi_ctrl_reg |= SPI_Y2_CERS;			spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);	SPI_Y2_WAIT_SE_FINISH_WR();}/* * BEGIN_MANUAL_ENTRY() * *	unsigned short spi_yuk2_read_chip_id() * *	Read SPI vendor and device id * * Uses: * * IN: * * return: *	The lower byte containes the device id and the upper the vendor id * * END_MANUAL_ENTRY() */unsigned short spi_yuk2_read_chip_id(){	unsigned short	chip_id_local;	unsigned long	spi_ctrl_reg = 0;	unsigned long	opcode_reg1;	/* for Yukon-Extreme SPI issue */	spi_out32(SPI_Y2_CONTROL_REG, 0x00);	/* 	 * set read id opcode for flash currently selected	 */	spi_in32(SPI_Y2_OPCODE_REG1, &opcode_reg1);	opcode_reg1 &= 0xff00ffffL;	opcode_reg1 |= (((unsigned long)spi_yuk2_dev_table[spi_yuk2_dev].opcodes.op_read_id) << 16);	spi_out32(SPI_Y2_OPCODE_REG1, opcode_reg1);	/*	 * read spi control register	 */	spi_in32(SPI_Y2_CONTROL_REG, &spi_ctrl_reg);	spi_ctrl_reg &= ~(SPI_Y2_CMD_MASK | SPI_Y2_RDID_PROT);	/* select protocol for chip id read out */	if( spi_yuk2_dev_table[spi_yuk2_dev].set_protocol ) {		spi_ctrl_reg |= SPI_Y2_RDID_PROT;	}		/* execute read chip id command */	spi_ctrl_reg |= SPI_Y2_RDID;	spi_out32(SPI_Y2_CONTROL_REG, spi_ctrl_reg);	SPI_Y2_WAIT_SE_FINISH_CMD();	spi_in16(SPI_Y2_VENDOR_DEVICE_ID_REG, &chip_id_local);	return (chip_id_local);}/* * BEGIN_MANUAL_ENTRY() * *	int spi_yuk2_get_dev_index(void) * *	Identify the SPI device and return its device *	table index * * Uses: * * IN: * * return: *	-1	unknown or no flash device *	>=0	flash device table index * * END_MANUAL_ENTRY() */#ifdef USE_ASF_DASH_FWint spi_yuk2_get_dev_index(){	unsigned short	spi_chip_id;	unsigned char	man_id;	unsigned char	dev_id;	unsigned int	i;	/* search for flash in device table */	for(i = 0; i < (sizeof(spi_yuk2_dev_table) / sizeof(spi_yuk2_dev_table[0])); i++) {		if (chip_id != CHIP_ID_YUKON_EC_U && chip_id != CHIP_ID_YUKON_EX &&			(i == 0 || i == 1)) {			continue;		}		spi_yuk2_dev = i;		spi_chip_id = spi_yuk2_read_chip_id();		man_id = (unsigned char)((spi_chip_id & SPI_Y2_MAN_ID_MASK) >> 8);		dev_id = (unsigned char)(spi_chip_id & SPI_Y2_DEV_ID_MASK);		if(spi_yuk2_dev_table[i].man_id == man_id &&		   spi_yuk2_dev_table[i].dev_id == dev_id) {			fl_print("\nFlash Device\t: %s ", spi_yuk2_dev_table[i].dev_name);			fl_print("(VID 0x%2.2x, ", man_id);			fl_print("DID 0x%2.2x)\n", dev_id);			return(i);		}	}	spi_yuk2_dev = -1;	return(-1);}#elseint spi_yuk2_get_dev_index(){	unsigned short	chip_id_local;	unsigned char	man_id;	unsigned char	dev_id;	int		i;	/* search for flash in device table */	for(i = 0; i < (sizeof(spi_yuk2_dev_table) / sizeof(spi_yuk2_dev_table[0])); i++) {      spi_yuk2_dev = i;		chip_id_local = spi_yuk2_read_chip_id();		man_id = (unsigned char)((chip_id_local & SPI_Y2_MAN_ID_MASK) >> 8);		dev_id = (unsigned char)(chip_id_local & SPI_Y2_DEV_ID_MASK);		if(spi_yuk2_dev_table[i].man_id == man_id &&		   spi_yuk2_dev_table[i].dev_id == dev_id) {			fl_print("\nFlash Device %s found\n", spi_yuk2_dev_table[i].dev_name);			fl_print("  - Vendor ID : 0x%2.2x \n", man_id);			fl_print("  - Device ID : 0x%2.2x \n", dev_id);			return(i);		}	}	spi_yuk2_dev = -1;	return(-1);}#endif/* * BEGIN_MANUAL_ENTRY() * *	static int spi_yuk2_flash_erase(unsigned long off,unsigned long len) * *	Erase all sectors of the flash prom affected by the address *	range denoted by parameters "off" (address offset) and "len" *	(length of address range). * * Uses:	spi_in32, spi_out32, spi_in8, spi_timer * * IN: *	off:	start offset in flash eprom for erase *  len:	length in flash eprom for erase *			(all necessary sectors will be erased) * * return: *	0	Success *	1	Timeout * * END_MANUAL_ENTRY() */static int spi_yuk2_flash_erase(unsigned long off,unsigned long len){	unsigned long	flash_size;	unsigned long	i;	unsigned long	start_sector;	unsigned long	end_sector;	if(len == 0) {		return(0);	}	flash_size = spi_yuk2_dev_table[spi_yuk2_dev].sector_size * 							spi_yuk2_dev_table[spi_yuk2_dev].sector_num;	/*	 * flash size is smaller than address range which	 * should be erased --> don't erase flash.	 */	if ((off+len-1) > flash_size) {		return(1);	}	/*	 * Erase complete flash if all sectors of flash are affected	 */	if(len > (spi_yuk2_dev_table[spi_yuk2_dev].sector_size * 		(spi_yuk2_dev_table[spi_yuk2_dev].sector_num - 1))) {				spi_yuk2_erase_chip();	}	/*	 * Erase all affected sectors	 */	else {		start_sector = off / spi_yuk2_dev_table[spi_yuk2_dev].sector_size;		end_sector   = (off + len - 1) / spi_yuk2_dev_table[spi_yuk2_dev].sector_size;				for (i = start_sector; i <= end_sector; i++) {			spi_yuk2_erase_sector(i);		}	}	return(0);}/* * BEGIN_MANUAL_ENTRY() * *	static int spi_yuk2_flash_manage( *	unsigned char  *data, *	unsigned long off, *	unsigned long len, *	int flag) * *	Read, Verify or Write SPI Eprom * * Uses:	spi_in32, spi_out32, spi_in8, spi_out8, spi_in16, spi_out16, spi_timer * * IN: *	data	data buffer *	off		start offset in flash eprom for operation *  len		length in flash eprom *	flag	SPI_READ *			SPI_VERIFY *			SPI_WRITE * * return: *	0	Success *	1	Timeout * * END_MANUAL_ENTRY() */#ifdef USE_ASF_DASH_FWstatic int spi_yuk2_flash_manage(unsigned char huge *data,unsigned long off,unsigned long len,int flag){	unsigned long		addr; 	unsigned long		spi_data;	unsigned long huge	*spi_data_ptr;	unsigned long		progress;	unsigned long		last_progress;	int					ret = 0;	unsigned char		ChipId,ChipRev,ByteVal;	// assert(!(off&3));	len = (len + 3) & ~3;	spi_in8(B2_CHIP_ID, &ChipId);	spi_in8(B2_MAC_CFG, &ChipRev);	ChipRev = (unsigned char)((ChipRev & CFG_CHIP_R_MSK) >> 4);		if ((ChipId == CHIP_ID_YUKON_EX) &&		(ChipRev != CHIP_REV_YU_EX_A0) &&		(spi_yuk2_dev_table[spi_yuk2_dev].sector_size *		spi_yuk2_dev_table[spi_yuk2_dev].sector_num >= 0x40000)) {		spi_in8(SPI_CFG, &ByteVal);		ByteVal |= SPI_CFG_A17_GATE;			spi_out8(SPI_CFG, ByteVal);	}	progress = last_progress = 0;	for (addr = off, spi_data_ptr = (unsigned long huge *)data;							addr < off + len; addr+=4, spi_data_ptr++) {		progress = ((addr - off) * 100) / len;		if((progress - last_progress) >= 10) {			fl_print(".");			last_progress += 10;		}		switch (flag) {			case SPI_READ:				/* Read a dword from SPI flash */				*(spi_data_ptr) = spi_yuk2_read_dword(addr);							break;			case SPI_VERIFY:				/* Read and verify dword from SPI flash */				spi_data = spi_yuk2_read_dword(addr);				if (spi_data != *(spi_data_ptr)) {					fl_print("\n*** SPI data verify error at address 0x%08lx, ",						"is %x, should %x\n", addr, spi_data, *(spi_data_ptr));					ret = 1;				}			break;			case SPI_WRITE:#if 0#ifndef SK_DIAG				/*				 * Flash-only adapters only support				 * Flash sector sizes of 4096 bytes				 */				if (max_faddr == 0x1000) {					if (ModifiedPages[addr >> 12] != (unsigned char)1) {#if 0						if ((addr % 4096) == 0) {							fl_print("not writing to sector %d\n",addr >> 12);						}#endif						continue;					}				}#endif	/* !SK_DIAG */#endif					/* Write a dword to SPI flash */				if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) {					ret = spi_yuk2_sst_write_dword(addr, *(spi_data_ptr));				}				else {					ret = spi_yuk2_write_dword(addr, *(spi_data_ptr));				}			break;		}		if (ret) {			break;			}	}	fl_print(".");	return(ret);}#elsestatic int spi_yuk2_flash_manage(unsigned char  *data,unsigned long off,unsigned long len,int flag){	unsigned long		addr; 	unsigned long		spi_data;	unsigned int		*spi_data_ptr;	int			ret = 0;	len = (len + 3) & ~3;	for (addr = off, spi_data_ptr = (unsigned int *)data; addr < off + len; addr+=4, spi_data_ptr++) {		switch (flag) {			case SPI_READ:				/* Read a dword from SPI flash */				*(spi_data_ptr) = spi_yuk2_read_dword(addr);			break;			case SPI_VERIFY:				/* Read and verify dword from SPI flash */				spi_data = spi_yuk2_read_dword(addr);			break;				if (spi_data != *(spi_data_ptr)) {					fl_print("\n*** SPI data verify error at address 0x%08lx, ","is %x, should %x\n", addr, 																				spi_data, *(spi_data_ptr));					ret = 1;				}			break;			case SPI_WRITE:				/* Write a dword to SPI flash */				if (spi_yuk2_dev_table[spi_yuk2_dev].man_id == SPI_MAN_ID_SST) {					ret = spi_yuk2_sst_write_dword(addr, *(spi_data_ptr));				}				else {					ret = spi_yuk2_write_dword(addr, *(spi_data_ptr));				}			break;		}		if (ret) {			break;			}	}	return(ret);}#endif/* * BEGIN_MANUAL_ENTRY() * *	static int spi_yuk2_update_config( *	unsigned char  *data, *	unsigned long off, *	unsigned long len) * *	Update part of config area * * Uses:	spi_flash_manage, spi_flash_erase * * IN: *	data	data buffer *	off	start offset in flash eprom (config area) for operation *      len	length of changing data * * return: *	0	Success *	1	Timeout * * END_MANUAL_ENTRY() */

⌨️ 快捷键说明

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