summaryrefslogtreecommitdiff
path: root/drivers/mw_eeprom.c
diff options
context:
space:
mode:
authorwdenk <wdenk>2003-05-31 18:35:21 +0000
committerwdenk <wdenk>2003-05-31 18:35:21 +0000
commit7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed (patch)
tree5c273df9c5efa7b1b6a4ca88904e48039ef591e8 /drivers/mw_eeprom.c
parent3b57fe0a70b903f4db66c558bb9828bc58acf06b (diff)
downloadu-boot-imx-7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed.zip
u-boot-imx-7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed.tar.gz
u-boot-imx-7a8e9bed17d7924a9c5c4699b1f6a3a0359524ed.tar.bz2
* Patch by Marc Singer, 29 May 2003:
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.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/drivers/mw_eeprom.c b/drivers/mw_eeprom.c
new file mode 100644
index 0000000..30a51fa
--- /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