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

📄 skgespi.c

📁 这是Marvell Technology Group Ltd. 4355 (rev 12)网卡在linux下的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************** * * Name:	skspi.c * Project:	Flash Programmer, Manufacturing and Diagnostic Tools * Version:	$Revision: 1.1.2.7 $ * Date:	$Date: 2007/11/20 10:22:20 $ * Purpose:	Contains SPI-Flash EEPROM specific functions * ******************************************************************************//****************************************************************************** * *	(C)Copyright 1998-2002 SysKonnect GmbH. *	(C)Copyright 2002-2007 Marvell. * *	Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet  *      Server Adapters. * *	Address all question to: gr-msgg-linux@marvell.com * *      LICENSE: *      (C)Copyright Marvell. *       *      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. *       *      The information in this file is provided "AS IS" without warranty. *      /LICENSE * *****************************************************************************/static const char SysKonnectFileId[] =	"@(#) $Id: skgespi.c,v 1.1.2.7 2007/11/20 10:22:20 mlindner Exp $ (C) Marvell.";/*#include <stdio.h>#include <malloc.h>#include <assert.h>*/#include "h/skdrv1st.h"#include "h/skdrv2nd.h"#include "h/skgespi.h"#ifdef Core	#include "h/skdrv1st.h"	#include "h/skdrv2nd.h"	#define fl_print pAC->Gui.WPrint#else	extern void fl_print(char *msg, ...);	#endif /* Core */extern int fl_type;extern long max_pages;extern long max_faddr;/* low level SPI programming external interface */extern void spi_in8(unsigned short, unsigned char *);extern void spi_in16(unsigned short, unsigned short *);extern void spi_in32(unsigned short, unsigned long *);extern void spi_out8(unsigned short, unsigned char);extern void spi_out16(unsigned short, unsigned short);extern void spi_out32(unsigned short, unsigned long);extern int  spi_timer(unsigned int);extern void *spi_malloc(unsigned long);extern void spi_free(void *);/* global variables */unsigned char chip_id;/* local variables */static int spi_yuk2_dev = -1;/* * Yukon 2/EC SPI flash device structure/table */static struct {	char			*man_name;	unsigned char	man_id;	char			*dev_name;	unsigned char	dev_id;	unsigned long	sector_size;	unsigned long	sector_num;	char			set_protocol;	struct {		unsigned char	op_read;		unsigned char	op_write;		unsigned char	op_write_enable;		unsigned char	op_write_disable;		unsigned char	op_read_status;		unsigned char	op_read_id;		unsigned char	op_sector_erase;		unsigned char	op_chip_erase;	} opcodes;} spi_yuk2_dev_table[] = {	{ "Atmel",	SPI_MAN_ID_ATMEL,		"AT25F2048",	0x63,	0x10000,	4,		0,	{0x03,0x02,0x06,0x04,0x05,0x15,0x52,0x62}	} ,	{ "Atmel",	SPI_MAN_ID_ATMEL,		"AT25F1024",	0x60,	0x8000,		4,		0,	{0x03,0x02,0x06,0x04,0x05,0x15,0x52,0x62}	} ,	{ "Intel",		SPI_MAN_ID_INTEL,	"QB25F016S33B8",		0x89,	0x10000,		32,		0,	{0x03,0x02,0x06,0x04,0x05,0x9f,0xd8,0xc7}	}, 	{ "SST",	SPI_MAN_ID_SST,			"SST25VF512",	0x48,	0x1000,		16,		1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,	{ "SST",	SPI_MAN_ID_SST,			"SST25VF010",	0x49,	0x1000,		32,		1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,	{ "SST",	SPI_MAN_ID_SST,			"SST25VF020",	0x43,	0x1000,		64,		1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,	{ "SST",	SPI_MAN_ID_SST,			"SST25VF040",	0x44,	0x1000,		128,	1,	{0x03,0x02,0x06,0x04,0x05,0x90,0x20,0x60}	} ,	{ "ST",		SPI_MAN_ID_ST_M25P20,	"M25P20",		0x11,	0x10000,	4,		1,	{0x03,0x02,0x06,0x04,0x05,0xab,0xd8,0xc7}	} ,	{ "ST",		SPI_MAN_ID_ST_M25P10,	"M25P10",		0x10,	0x8000,		4,		1,	{0x03,0x02,0x06,0x04,0x05,0xab,0xd8,0xc7}	}};/* * BEGIN_MANUAL_ENTRY() * *	int     spi_yuk_flash_erase(unsigned long off,unsigned long len) * *	Send chip erase command to SPI Eprom * * 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 nessesory sectors will be erased) * * return: *	0	Success *	1	Timeout * * END_MANUAL_ENTRY() */static int spi_yuk_flash_erase(unsigned long off,unsigned long len){	char cr;	unsigned long creg, i;	/* Save SPI control register */	spi_in32(SPI_CTRL_REG, &creg);	if ((off+len-1) > 0x1ffffL) {		return(1);	/* more than 4 segments for erase */	}#ifdef XXX    /* there is some problem with chip erase. dr */    /* use faster chip erase command if all sectors should be erased */	if(len > SPI_SECT_SIZE*3L) {		spi_out32(SPI_CTRL_REG, SPI_CHIP_ERASE);				spi_timer(SPI_TIMER_SET);		do {			/* Read device status */							spi_in8(SPI_CTRL_REG, &cr);						if (spi_timer(SPI_TIMEOUT)) {				fl_print("\nSPI chip erase timeout: %d sec\n", SPI_TIMER_SET);				return(1);			}		}		while (cr & 1);          /* is chip busy ? */		/* Restore SPI control register */		spi_out32(SPI_CTRL_REG, creg);			return(0);	}#endif	for (i = (off >> 15); i <= ((off + len - 1) >> 15); i++) {		/* Clear chip command */		spi_out32(SPI_CTRL_REG, (i << 22) | SPI_SECT_ERASE);				spi_timer(SPI_TIMER_SET);		do {			/* Read device status */							spi_in8(SPI_CTRL_REG, &cr);						if (spi_timer(SPI_TIMEOUT)) {				fl_print("\nSPI chip erase timeout: %d sec\n", SPI_TIMER_SET);				return(1);			}		}		while (cr & 1);          /* is chip busy ? */	}	/* Restore SPI control register */	spi_out32(SPI_CTRL_REG, creg);		return(0);}/* * BEGIN_MANUAL_ENTRY() * *	int     spi_yuk_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() */static unsigned short rol2(unsigned short adr){	unsigned short	adr2;		/* YUKON-Lite Rev. A1 */	if (chip_id == CHIP_ID_YUKON_LITE || chip_id == CHIP_ID_YUKON_LP) {				/* switch address bits [1:0] with [14:13] */		adr2 = adr & 0x6000;		adr2 = adr2 >> 13;		adr2 = adr2 & 0x0003;		adr  = adr << 2;		adr  = adr & 0x7ffc;		adr  = adr | adr2;	}		return(adr);}static int spi_yuk_flash_manage(unsigned char  *data,unsigned long off,unsigned long len,int flag){	unsigned long a1, a2, cr, i;	unsigned short adr, as, ret=0;	unsigned char ch, tr;	unsigned long progress;	unsigned long last_progress;	/* Save VPD lower address */	spi_in32(SPI_ADR_REG1, &a1);	/* Save VPD higher address */	spi_in32(SPI_ADR_REG2, &a2);	/* Set VPD lower address to 0 (15 higher bit)*/	spi_out32(SPI_ADR_REG1, SPI_VPD_MIN);	/* Set VPD higher address to 0x7fff (15 higher bit)*/	spi_out32(SPI_ADR_REG2, SPI_VPD_MAX);	/* Save SPI control register */	spi_in32(SPI_CTRL_REG, &cr);	/* Enable VPD to SPI mapping (set bit 19) */	spi_out32(SPI_CTRL_REG, SPI_VPD_MAP);	/* Save Test Control Register 1 */	spi_in8(B2_TST_REG1, &tr);	/* Enable write to mapped PCI config register file */	spi_out8(B2_TST_REG1, 2);	progress = last_progress = 0;	for (i = off, adr = (unsigned short)(off >> 2); i < off + len; i++) {				progress = (i * 100) / len;		if((progress - last_progress) >= 10) {			fl_print(".");			last_progress += 10;		}		/* Set new address to VPD Address reg, initiate reading */		if ((i % 4) == 0) {					spi_out16(VPD_ADR_REG, rol2(adr++));						/* Wait for termination */			spi_timer(SPI_TIMER_SET);			do {				/* Read VPD_ADDR reg for flag check */					spi_in16(VPD_ADR_REG, &as);								if (spi_timer(SPI_TIMEOUT)) {					fl_print("\nSPI read timeout: %d sec. Offset:0x%05lx\n",						SPI_TIMER_SET, i);					ret = 1;					break;				}			}			while (!(as & VPD_FLAG_MASK)); /* check  flag */						if (ret) {				break;			}		}				switch (flag) {		case SPI_READ:			/* Read byte from VPD port */			spi_in8((unsigned short)(VPD_DATA_PORT +				(unsigned short)(i % 4)), &ch);			*(data++) = ch;			break;		case SPI_VERIFY:			/* Read and verify byte from VPD port */			spi_in8((unsigned short)(VPD_DATA_PORT +				(unsigned short)(i % 4)), &ch);			if (ch != *(data++)) {				fl_print("\n*** SPI data verify error at address 0x%05lx, ",					"is %x, should %x\n",					i, ch, *(data - 1));				ret = 1;			}			break;		case SPI_WRITE:			/* Write byte to VPD port */			spi_out8((unsigned short)(VPD_DATA_PORT +				(unsigned short)(i % 4)), *(data++));				if ((i % 4) == 3) {				/* Set old Address to VPD_ADDR reg, initiate writing */				spi_out16((unsigned short)VPD_ADR_REG,					(unsigned short)(rol2((unsigned short)(adr - 1)) | VPD_FLAG_MASK));						/* Wait for termination */				spi_timer(SPI_TIMER_SET);				do {					/* Read VPD_ADDR reg for flag check*/						spi_in16(VPD_ADR_REG, &as);										if (spi_timer(SPI_TIMEOUT)) {						fl_print("\nSPI write timeout: %d sec. Offset:0x%05lx\n",							SPI_TIMER_SET, i);						ret = 1;						break;					}				}				while (as & VPD_FLAG_MASK); /* check  flag */			}			break;		}		if (ret) {			break;			}	}	/* Restore Test Control Register 1 */	spi_out8(B2_TST_REG1, tr);	/* Restore VPD lower address*/	spi_out32(SPI_ADR_REG1, a1);	/* Restore VPD higher address*/	spi_out32(SPI_ADR_REG2, a2);	/* Restore SPI control register */	spi_out32(SPI_CTRL_REG, cr);	fl_print(".");	return(ret);	}/* * BEGIN_MANUAL_ENTRY() * *	int     spi_yuk_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() */static int spi_yuk_update_config(unsigned char  *data,unsigned long off,unsigned long len){	unsigned char *spibuf;	unsigned long i;	spibuf = spi_malloc((unsigned long)SPI_SECT_SIZE);	if(spibuf == NULL) {		return(51);	}		if (spi_flash_manage(spibuf, SPI_LSECT_OFF, SPI_SECT_SIZE, SPI_READ)) {			spi_free(spibuf);		return(1);	}		for (i = 0; i < len; i++) {		spibuf[off + i - SPI_LSECT_OFF] = data[i];	}		if (spi_flash_erase(SPI_LSECT_OFF, SPI_SECT_SIZE)) {		spi_free(spibuf);		return(7);	}		if (spi_flash_manage(spibuf, SPI_LSECT_OFF, SPI_SECT_SIZE, SPI_WRITE)) {			spi_free(spibuf);		return(8);	}	spi_free(spibuf);		return(0);}	/* * BEGIN_MANUAL_ENTRY() * *	void spi_yuk2_write_enable() * *	This function will set the Write enable setting of the SPI EPROM * * Uses: * * IN: * * return: *	nothing * * END_MANUAL_ENTRY() */void spi_yuk2_write_enable(){	unsigned long spi_ctrl_reg;		/* execute write 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 command */	SPI_Y2_WAIT_SE_FINISH_WR();}/* * BEGIN_MANUAL_ENTRY() * *	static unsigned long spi_yuk2_read_dword( *  unsigned long	address) * *	The function reads a dword from the specified address in the SPI EPROM. * * Uses: * * IN: * * return: *	dword read from given address * * END_MANUAL_ENTRY() */static unsigned long spi_yuk2_read_dword(unsigned long	address)		/* addres in the SPI EPROM to read from */{	unsigned long reg_val = 0;	unsigned long spi_ctrl_reg;	/* write spi address */	spi_out32(SPI_Y2_ADDRESS_REG, address);	/* execute spi read 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();   	/* read the returned data */	spi_in32(SPI_Y2_DATA_REG, &reg_val);	return reg_val;}/* * BEGIN_MANUAL_ENTRY() * *	static int spi_yuk2_write_dword( *	unsigned long	address, *	unsigned long	value) * *	This function writes the specified dword in the specified SPI EPROM location. *  The SPI EPROM should have been put previously in write enable mode and *  the target sector erased for the access to succeed. * * Uses: * * IN: * * return: *	0 - if successful *	1 - if fails * * END_MANUAL_ENTRY() */static int spi_yuk2_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;	spi_yuk2_write_enable();		/* write spi address */	spi_out32(SPI_Y2_ADDRESS_REG, address);   	/* write the new value */	spi_out32(SPI_Y2_DATA_REG, value);	/* 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 == value ) {		return 0;	} 	else {		fl_print("\n*** SPI data write error at address 0x%08x, ","is 0x%08x, should 0x%08x\n", address, 																	verify_value, value);		return 1;	}}/* * BEGIN_MANUAL_ENTRY() * *	static int spi_yuk2_sst_write_dword( *	unsigned long	address, *	unsigned long	value) * *	This function writes the specified dword in the specified SPI EPROM location. *  The SPI EPROM should have been put previously in write enable mode and *  the target sector erased for the access to succeed. * * Uses: * * IN: *

⌨️ 快捷键说明

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