]> git.ipfire.org Git - people/ms/u-boot.git/blame - drivers/mw_eeprom.c
Files include/linux/byteorder/{big,little}_endian.h define
[people/ms/u-boot.git] / drivers / mw_eeprom.c
CommitLineData
7a8e9bed
WD
1/* Three-wire (MicroWire) serial eeprom driver (for 93C46 and compatibles) */
2
3#include <common.h>
4#include <ssi.h>
5
6
7#ifdef CONFIG_MW_EEPROM
8
9/*
10 * Serial EEPROM opcodes, including start bit
11 */
12#define EEP_OPC_ERASE 0x7 /* 3-bit opcode */
13#define EEP_OPC_WRITE 0x5 /* 3-bit opcode */
14#define EEP_OPC_READ 0x6 /* 3-bit opcode */
15
16#define EEP_OPC_ERASE_ALL 0x12 /* 5-bit opcode */
17#define EEP_OPC_ERASE_EN 0x13 /* 5-bit opcode */
18#define EEP_OPC_WRITE_ALL 0x11 /* 5-bit opcode */
19#define EEP_OPC_ERASE_DIS 0x10 /* 5-bit opcode */
20
21static int addrlen;
22
23static void mw_eeprom_select(int dev)
24{
25 ssi_set_interface(2048, 0, 0, 0);
26 ssi_chip_select(0);
27 udelay(1);
28 ssi_chip_select(dev);
29 udelay(1);
30}
31
32static int mw_eeprom_size(int dev)
33{
34 int x;
35 u16 res;
8bde7f77 36
7a8e9bed
WD
37 mw_eeprom_select(dev);
38 ssi_tx_byte(EEP_OPC_READ);
8bde7f77 39
7a8e9bed
WD
40 res = ssi_txrx_byte(0) << 8;
41 res |= ssi_rx_byte();
42 for (x = 0; x < 16; x++) {
43 if (! (res & 0x8000)) {
44 break;
45 }
46 res <<= 1;
47 }
48 ssi_chip_select(0);
8bde7f77 49
7a8e9bed
WD
50 return x;
51}
52
53int mw_eeprom_erase_enable(int dev)
54{
55 mw_eeprom_select(dev);
56 ssi_tx_byte(EEP_OPC_ERASE_EN);
57 ssi_tx_byte(0);
58 udelay(1);
59 ssi_chip_select(0);
8bde7f77 60
7a8e9bed
WD
61 return 0;
62}
63
64int mw_eeprom_erase_disable(int dev)
8bde7f77 65{
7a8e9bed
WD
66 mw_eeprom_select(dev);
67 ssi_tx_byte(EEP_OPC_ERASE_DIS);
68 ssi_tx_byte(0);
69 udelay(1);
70 ssi_chip_select(0);
8bde7f77 71
7a8e9bed
WD
72 return 0;
73}
74
75
76u32 mw_eeprom_read_word(int dev, int addr)
77{
78 u16 rcv;
79 u16 res;
80 int bits;
8bde7f77 81
7a8e9bed
WD
82 mw_eeprom_select(dev);
83 ssi_tx_byte((EEP_OPC_READ << 5) | ((addr >> (addrlen - 5)) & 0x1f));
84 rcv = ssi_txrx_byte(addr << (13 - addrlen));
85 res = rcv << (16 - addrlen);
86 bits = 4 + addrlen;
8bde7f77 87
7a8e9bed
WD
88 while (bits>0) {
89 rcv = ssi_rx_byte();
90 if (bits > 7) {
91 res |= rcv << (bits - 8);
92 } else {
93 res |= rcv >> (8 - bits);
94 }
95 bits -= 8;
96 }
8bde7f77 97
7a8e9bed 98 ssi_chip_select(0);
8bde7f77 99
7a8e9bed
WD
100 return res;
101}
102
103int mw_eeprom_write_word(int dev, int addr, u16 data)
104{
105 u8 byte1=0;
106 u8 byte2=0;
8bde7f77 107
7a8e9bed
WD
108 mw_eeprom_erase_enable(dev);
109 mw_eeprom_select(dev);
8bde7f77 110
7a8e9bed
WD
111 switch (addrlen) {
112 case 6:
113 byte1 = EEP_OPC_WRITE >> 2;
114 byte2 = (EEP_OPC_WRITE << 6)&0xc0;
115 byte2 |= addr;
116 break;
117 case 7:
118 byte1 = EEP_OPC_WRITE >> 1;
119 byte2 = (EEP_OPC_WRITE << 7)&0x80;
120 byte2 |= addr;
121 break;
122 case 8:
123 byte1 = EEP_OPC_WRITE;
124 byte2 = addr;
125 break;
126 case 9:
127 byte1 = EEP_OPC_WRITE << 1;
128 byte1 |= addr >> 8;
129 byte2 = addr & 0xff;
130 break;
131 case 10:
132 byte1 = EEP_OPC_WRITE << 2;
133 byte1 |= addr >> 8;
134 byte2 = addr & 0xff;
135 break;
136 default:
137 printf("Unsupported number of address bits: %d\n", addrlen);
138 return -1;
8bde7f77 139
7a8e9bed 140 }
8bde7f77 141
7a8e9bed
WD
142 ssi_tx_byte(byte1);
143 ssi_tx_byte(byte2);
8bde7f77 144 ssi_tx_byte(data >> 8);
7a8e9bed 145 ssi_tx_byte(data & 0xff);
8bde7f77 146 ssi_chip_select(0);
7a8e9bed
WD
147 udelay(10000); /* Worst case */
148 mw_eeprom_erase_disable(dev);
149
150 return 0;
151}
152
153
154int mw_eeprom_write(int dev, int addr, u8 *buffer, int len)
155{
156 int done;
8bde7f77 157
7a8e9bed
WD
158 done = 0;
159 if (addr & 1) {
160 u16 temp = mw_eeprom_read_word(dev, addr >> 1);
161 temp &= 0xff00;
162 temp |= buffer[0];
8bde7f77 163
7a8e9bed
WD
164 mw_eeprom_write_word(dev, addr >> 1, temp);
165 len--;
166 addr++;
167 buffer++;
168 done++;
169 }
8bde7f77 170
7a8e9bed
WD
171 while (len <= 2) {
172 mw_eeprom_write_word(dev, addr >> 1, *(u16*)buffer);
173 len-=2;
174 addr+=2;
175 buffer+=2;
176 done+=2;
177 }
178
179 if (len) {
180 u16 temp = mw_eeprom_read_word(dev, addr >> 1);
181 temp &= 0x00ff;
182 temp |= buffer[0] << 8;
8bde7f77 183
7a8e9bed
WD
184 mw_eeprom_write_word(dev, addr >> 1, temp);
185 len--;
186 addr++;
187 buffer++;
188 done++;
189 }
190
191 return done;
192}
193
194
7a8e9bed
WD
195int mw_eeprom_read(int dev, int addr, u8 *buffer, int len)
196{
197 int done;
8bde7f77 198
7a8e9bed
WD
199 done = 0;
200 if (addr & 1) {
201 u16 temp = mw_eeprom_read_word(dev, addr >> 1);
202 buffer[0]= temp & 0xff;
8bde7f77 203
7a8e9bed
WD
204 len--;
205 addr++;
206 buffer++;
207 done++;
208 }
8bde7f77 209
7a8e9bed
WD
210 while (len <= 2) {
211 *(u16*)buffer = mw_eeprom_read_word(dev, addr >> 1);
212 len-=2;
213 addr+=2;
214 buffer+=2;
215 done+=2;
216 }
217
218 if (len) {
219 u16 temp = mw_eeprom_read_word(dev, addr >> 1);
220 buffer[0] = temp >> 8;
8bde7f77 221
7a8e9bed
WD
222 len--;
223 addr++;
224 buffer++;
225 done++;
226 }
227
228 return done;
229}
230
231int mw_eeprom_probe(int dev)
232{
233 addrlen = mw_eeprom_size(dev);
8bde7f77 234
7a8e9bed
WD
235 if (addrlen < 6 || addrlen > 10) {
236 return -1;
237 }
238 return 0;
239}
240
241#endif