diff options
| author | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2007-11-24 21:26:56 +0100 | 
|---|---|---|
| committer | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2007-11-25 23:28:52 +0100 | 
| commit | 59829cc189378c142c13d2aa8d9a897d8bef3961 (patch) | |
| tree | 9db7b0647e82c7d3edbd33caa89a71eb4e123d0c /drivers/mtd/mw_eeprom.c | |
| parent | 318c0b90431f2648552e5ade78833f42652ce859 (diff) | |
| download | olio-uboot-2014.01-59829cc189378c142c13d2aa8d9a897d8bef3961.tar.xz olio-uboot-2014.01-59829cc189378c142c13d2aa8d9a897d8bef3961.zip | |
drivers/mtd : move mtd drivers to drivers/mtd
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Diffstat (limited to 'drivers/mtd/mw_eeprom.c')
| -rw-r--r-- | drivers/mtd/mw_eeprom.c | 241 | 
1 files changed, 241 insertions, 0 deletions
| diff --git a/drivers/mtd/mw_eeprom.c b/drivers/mtd/mw_eeprom.c new file mode 100644 index 000000000..2b3348810 --- /dev/null +++ b/drivers/mtd/mw_eeprom.c @@ -0,0 +1,241 @@ +/* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */ + +#include <common.h> + +#ifdef CONFIG_MW_EEPROM + +#include <ssi.h> + +/* + * Serial EEPROM opcodes, including start bit + */ +#define EEP_OPC_ERASE	0x7  /* 3-bit opcode */ +#define EEP_OPC_WRITE	0x5  /* 3-bit opcode */ +#define EEP_OPC_READ	        0x6  /* 3-bit opcode */ + +#define EEP_OPC_ERASE_ALL	0x12 /* 5-bit opcode */ +#define EEP_OPC_ERASE_EN	0x13 /* 5-bit opcode */ +#define EEP_OPC_WRITE_ALL	0x11 /* 5-bit opcode */ +#define EEP_OPC_ERASE_DIS	0x10 /* 5-bit opcode */ + +static int addrlen; + +static void mw_eeprom_select(int dev) +{ +	ssi_set_interface(2048, 0, 0, 0); +	ssi_chip_select(0); +	udelay(1); +	ssi_chip_select(dev); +	udelay(1); +} + +static int mw_eeprom_size(int dev) +{ +	int x; +	u16 res; + +	mw_eeprom_select(dev); +	ssi_tx_byte(EEP_OPC_READ); + +	res = ssi_txrx_byte(0) << 8; +	res |= ssi_rx_byte(); +	for (x = 0; x < 16; x++) { +		if (! (res & 0x8000)) { +			break; +		} +		res <<= 1; +	} +	ssi_chip_select(0); + +	return x; +} + +int mw_eeprom_erase_enable(int dev) +{ +	mw_eeprom_select(dev); +	ssi_tx_byte(EEP_OPC_ERASE_EN); +	ssi_tx_byte(0); +	udelay(1); +	ssi_chip_select(0); + +	return 0; +} + +int mw_eeprom_erase_disable(int dev) +{ +	mw_eeprom_select(dev); +	ssi_tx_byte(EEP_OPC_ERASE_DIS); +	ssi_tx_byte(0); +	udelay(1); +	ssi_chip_select(0); + +	return 0; +} + + +u32 mw_eeprom_read_word(int dev, int addr) +{ +	u16 rcv; +	u16 res; +	int bits; + +	mw_eeprom_select(dev); +	ssi_tx_byte((EEP_OPC_READ << 5) | ((addr >> (addrlen - 5)) & 0x1f)); +	rcv = ssi_txrx_byte(addr << (13 - addrlen)); +	res = rcv << (16 - addrlen); +	bits = 4 + addrlen; + +	while (bits>0) { +		rcv = ssi_rx_byte(); +		if (bits > 7) { +			res |= rcv << (bits - 8); +		} else { +			res |= rcv >> (8 - bits); +		} +		bits -= 8; +	} + +	ssi_chip_select(0); + +	return res; +} + +int mw_eeprom_write_word(int dev, int addr, u16 data) +{ +	u8 byte1=0; +	u8 byte2=0; + +	mw_eeprom_erase_enable(dev); +	mw_eeprom_select(dev); + +	switch (addrlen) { +	 case 6: +		byte1 = EEP_OPC_WRITE >> 2; +		byte2 = (EEP_OPC_WRITE << 6)&0xc0; +		byte2 |= addr; +		break; +	 case 7: +		byte1 = EEP_OPC_WRITE >> 1; +		byte2 = (EEP_OPC_WRITE << 7)&0x80; +		byte2 |= addr; +		break; +	 case 8: +		byte1 = EEP_OPC_WRITE; +		byte2 = addr; +		break; +	 case 9: +		byte1 = EEP_OPC_WRITE << 1; +		byte1 |= addr >> 8; +		byte2 = addr & 0xff; +		break; +	 case 10: +		byte1 = EEP_OPC_WRITE << 2; +		byte1 |= addr >> 8; +		byte2 = addr & 0xff; +		break; +	 default: +		printf("Unsupported number of address bits: %d\n", addrlen); +		return -1; + +	} + +	ssi_tx_byte(byte1); +	ssi_tx_byte(byte2); +	ssi_tx_byte(data >> 8); +	ssi_tx_byte(data & 0xff); +	ssi_chip_select(0); +	udelay(10000); /* Worst case */ +	mw_eeprom_erase_disable(dev); + +	return 0; +} + + +int mw_eeprom_write(int dev, int addr, u8 *buffer, int len) +{ +	int done; + +	done = 0; +	if (addr & 1) { +		u16 temp = mw_eeprom_read_word(dev, addr >> 1); +		temp &= 0xff00; +		temp |= buffer[0]; + +		mw_eeprom_write_word(dev, addr >> 1, temp); +		len--; +		addr++; +		buffer++; +		done++; +	} + +	while (len <= 2) { +		mw_eeprom_write_word(dev, addr >> 1, *(u16*)buffer); +		len-=2; +		addr+=2; +		buffer+=2; +		done+=2; +	} + +	if (len) { +		u16 temp = mw_eeprom_read_word(dev, addr >> 1); +		temp &= 0x00ff; +		temp |= buffer[0] << 8; + +		mw_eeprom_write_word(dev, addr >> 1, temp); +		len--; +		addr++; +		buffer++; +		done++; +	} + +	return done; +} + + +int mw_eeprom_read(int dev, int addr, u8 *buffer, int len) +{ +	int done; + +	done = 0; +	if (addr & 1) { +		u16 temp = mw_eeprom_read_word(dev, addr >> 1); +		buffer[0]= temp & 0xff; + +		len--; +		addr++; +		buffer++; +		done++; +	} + +	while (len <= 2) { +		*(u16*)buffer = mw_eeprom_read_word(dev, addr >> 1); +		len-=2; +		addr+=2; +		buffer+=2; +		done+=2; +	} + +	if (len) { +		u16 temp = mw_eeprom_read_word(dev, addr >> 1); +		buffer[0] = temp >> 8; + +		len--; +		addr++; +		buffer++; +		done++; +	} + +	return done; +} + +int mw_eeprom_probe(int dev) +{ +	addrlen = mw_eeprom_size(dev); + +	if (addrlen < 6 || addrlen > 10) { +		return -1; +	} +	return 0; +} + +#endif |