diff options
| author | wdenk <wdenk> | 2003-05-31 18:35:21 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2003-05-31 18:35:21 +0000 | 
| commit | 7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed (patch) | |
| tree | 5c273df9c5efa7b1b6a4ca88904e48039ef591e8 /drivers/mw_eeprom.c | |
| parent | 3b57fe0a70b903f4db66c558bb9828bc58acf06b (diff) | |
| download | olio-uboot-2014.01-7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed.tar.xz olio-uboot-2014.01-7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed.zip | |
* Patch by Marc Singer, 29 May 2003:LABEL_2003_05_31_2115
  Fixed rarp boot method for IA32 and other little-endian CPUs.
* Patch by Marc Singer, 28 May 2003:
  Added port I/O commands.
* Patch by Matthew McClintock, 28 May 2003
  - cpu/mpc824x/start.S: fix relocation code when booting from RAM
  - minor patches for utx8245
* Patch by Daniel Engström, 28 May 2003:
  x86 update
* Patch by Dave Ellis, 9 May 2003 + 27 May 2003:
  add nand flash support to SXNI855T configuration
  fix/extend nand flash support:
  - fix 'nand erase' command so does not erase bad blocks
  - fix 'nand write' command so does not write to bad blocks
  - fix nand_probe() so handles no flash detected properly
  - add doc/README.nand
  - add .jffs2 and .oob options to nand read/write
  - add 'nand bad' command to list bad blocks
  - add 'clean' option to 'nand erase' to write JFFS2 clean markers
  - make NAND read/write faster
* Patch by Rune Torgersen, 23 May 2003:
  Update for MPC8266ADS board
Diffstat (limited to 'drivers/mw_eeprom.c')
| -rw-r--r-- | drivers/mw_eeprom.c | 242 | 
1 files changed, 242 insertions, 0 deletions
| diff --git a/drivers/mw_eeprom.c b/drivers/mw_eeprom.c new file mode 100644 index 000000000..30a51fa05 --- /dev/null +++ b/drivers/mw_eeprom.c @@ -0,0 +1,242 @@ +/* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */ + +#include <common.h> +#include <ssi.h> + + +#ifdef CONFIG_MW_EEPROM + +/* + * 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 |