1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/delay.h>
23#include <linux/eeprom_93cx6.h>
24
25MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
26MODULE_VERSION("1.0");
27MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
28MODULE_LICENSE("GPL");
29
30static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
31{
32 eeprom->reg_data_clock = 1;
33 eeprom->register_write(eeprom);
34
35
36
37
38
39
40 ndelay(450);
41}
42
43static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
44{
45 eeprom->reg_data_clock = 0;
46 eeprom->register_write(eeprom);
47
48
49
50
51
52
53 ndelay(450);
54}
55
56static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
57{
58
59
60
61 eeprom->register_read(eeprom);
62 eeprom->reg_data_in = 0;
63 eeprom->reg_data_out = 0;
64 eeprom->reg_data_clock = 0;
65 eeprom->reg_chip_select = 1;
66 eeprom->drive_data = 1;
67 eeprom->register_write(eeprom);
68
69
70
71
72 eeprom_93cx6_pulse_high(eeprom);
73 eeprom_93cx6_pulse_low(eeprom);
74}
75
76static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
77{
78
79
80
81 eeprom->register_read(eeprom);
82 eeprom->reg_data_in = 0;
83 eeprom->reg_chip_select = 0;
84 eeprom->register_write(eeprom);
85
86
87
88
89 eeprom_93cx6_pulse_high(eeprom);
90 eeprom_93cx6_pulse_low(eeprom);
91}
92
93static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
94 const u16 data, const u16 count)
95{
96 unsigned int i;
97
98 eeprom->register_read(eeprom);
99
100
101
102
103 eeprom->reg_data_in = 0;
104 eeprom->reg_data_out = 0;
105 eeprom->drive_data = 1;
106
107
108
109
110 for (i = count; i > 0; i--) {
111
112
113
114 eeprom->reg_data_in = !!(data & (1 << (i - 1)));
115
116
117
118
119 eeprom->register_write(eeprom);
120
121
122
123
124 eeprom_93cx6_pulse_high(eeprom);
125 eeprom_93cx6_pulse_low(eeprom);
126 }
127
128 eeprom->reg_data_in = 0;
129 eeprom->register_write(eeprom);
130}
131
132static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
133 u16 *data, const u16 count)
134{
135 unsigned int i;
136 u16 buf = 0;
137
138 eeprom->register_read(eeprom);
139
140
141
142
143 eeprom->reg_data_in = 0;
144 eeprom->reg_data_out = 0;
145 eeprom->drive_data = 0;
146
147
148
149
150 for (i = count; i > 0; i--) {
151 eeprom_93cx6_pulse_high(eeprom);
152
153 eeprom->register_read(eeprom);
154
155
156
157
158 eeprom->reg_data_in = 0;
159
160
161
162
163 if (eeprom->reg_data_out)
164 buf |= (1 << (i - 1));
165
166 eeprom_93cx6_pulse_low(eeprom);
167 }
168
169 *data = buf;
170}
171
172
173
174
175
176
177
178
179
180
181void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
182 u16 *data)
183{
184 u16 command;
185
186
187
188
189 eeprom_93cx6_startup(eeprom);
190
191
192
193
194 command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
195 eeprom_93cx6_write_bits(eeprom, command,
196 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
197
198
199
200
201 eeprom_93cx6_read_bits(eeprom, data, 16);
202
203
204
205
206 eeprom_93cx6_cleanup(eeprom);
207}
208EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
224 __le16 *data, const u16 words)
225{
226 unsigned int i;
227 u16 tmp;
228
229 for (i = 0; i < words; i++) {
230 tmp = 0;
231 eeprom_93cx6_read(eeprom, word + i, &tmp);
232 data[i] = cpu_to_le16(tmp);
233 }
234}
235EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
236
237
238
239
240
241
242
243
244
245
246void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
247 u8 *data)
248{
249 u16 command;
250 u16 tmp;
251
252
253
254
255 eeprom_93cx6_startup(eeprom);
256
257
258
259
260 command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte;
261 eeprom_93cx6_write_bits(eeprom, command,
262 PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
263
264
265
266
267 eeprom_93cx6_read_bits(eeprom, &tmp, 8);
268 *data = tmp & 0xff;
269
270
271
272
273 eeprom_93cx6_cleanup(eeprom);
274}
275EXPORT_SYMBOL_GPL(eeprom_93cx6_readb);
276
277
278
279
280
281
282
283
284
285
286
287void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte,
288 u8 *data, const u16 bytes)
289{
290 unsigned int i;
291
292 for (i = 0; i < bytes; i++)
293 eeprom_93cx6_readb(eeprom, byte + i, &data[i]);
294}
295EXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb);
296
297
298
299
300
301
302
303
304
305void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable)
306{
307 u16 command;
308
309
310 eeprom_93cx6_startup(eeprom);
311
312
313
314 command = enable ? PCI_EEPROM_EWEN_OPCODE : PCI_EEPROM_EWDS_OPCODE;
315 command <<= (eeprom->width - 2);
316
317 eeprom_93cx6_write_bits(eeprom, command,
318 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
319
320 eeprom_93cx6_cleanup(eeprom);
321}
322EXPORT_SYMBOL_GPL(eeprom_93cx6_wren);
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, u8 addr, u16 data)
338{
339 int timeout = 100;
340 u16 command;
341
342
343 eeprom_93cx6_startup(eeprom);
344
345 command = PCI_EEPROM_WRITE_OPCODE << eeprom->width;
346 command |= addr;
347
348
349 eeprom_93cx6_write_bits(eeprom, command,
350 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
351
352
353 eeprom_93cx6_write_bits(eeprom, data, 16);
354
355
356 eeprom->drive_data = 0;
357 eeprom->reg_chip_select = 1;
358 eeprom->register_write(eeprom);
359
360
361 usleep_range(1000, 2000);
362
363
364
365 while (true) {
366 eeprom->register_read(eeprom);
367
368 if (eeprom->reg_data_out)
369 break;
370
371 usleep_range(1000, 2000);
372
373 if (--timeout <= 0) {
374 printk(KERN_ERR "%s: timeout\n", __func__);
375 break;
376 }
377 }
378
379 eeprom_93cx6_cleanup(eeprom);
380}
381EXPORT_SYMBOL_GPL(eeprom_93cx6_write);
382