mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	- remove trailing white space, trailing empty lines, C++ comments, etc.
  - split cmd_boot.c (separate cmd_bdinfo.c and cmd_load.c)
* Patches by Kenneth Johansson, 25 Jun 2003:
  - major rework of command structure
    (work done mostly by Michal Cendrowski and Joakim Kristiansen)
		
	
			
		
			
				
	
	
		
			242 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* 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
 |