e8bcd5acee64c314e3927f3fff30f369985be590
[openwrt.git] / target / linux / generic-2.6 / patches-2.6.22 / 600-eeprom_93cx6.patch
1 From: Ivo van Doorn <ivdoorn@gmail.com>
2 Date: Fri, 11 May 2007 19:59:40 +0000 (-0400)
3 Subject: [PATCH] Add 93cx6 eeprom library
4 X-Git-Tag: v2.6.23-rc1~1201^2~74
5 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9467d64b0e88763914c01f71ddf591b166c4f526
6
7 [PATCH] Add 93cx6 eeprom library
8
9 This patch adds a library for reading from 93cx6 eeproms.
10
11 Signed-off-by: Michael Wu <flamingice@sourmilk.net>
12 Signed-off-by: John W. Linville <linville@tuxdriver.com>
13 ---
14
15 diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
16 index 616eee9..bd601ef 100644
17 --- a/drivers/misc/Kconfig
18 +++ b/drivers/misc/Kconfig
19 @@ -34,6 +34,11 @@ config PHANTOM
20 If you choose to build module, its name will be phantom. If unsure,
21 say N here.
22
23 +config EEPROM_93CX6
24 + tristate "EEPROM 93CX6 support"
25 + ---help---
26 + This is a driver for the EEPROM chipsets 93c46 and 93c66.
27 + The driver supports both read as well as write commands.
28
29 If unsure, say N.
30
31 @@ -187,5 +192,4 @@ config THINKPAD_ACPI_BAY
32
33 If you are not sure, say Y here.
34
35 -
36 endmenu
37 diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
38 index 8abbf2f..b5ce0e3 100644
39 --- a/drivers/misc/Makefile
40 +++ b/drivers/misc/Makefile
41 @@ -14,3 +14,4 @@ obj-$(CONFIG_PHANTOM) += phantom.o
42 obj-$(CONFIG_SGI_IOC4) += ioc4.o
43 obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
44 obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
45 +obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
46 diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
47 new file mode 100644
48 index 0000000..bfcb434
49 --- /dev/null
50 +++ b/drivers/misc/eeprom_93cx6.c
51 @@ -0,0 +1,229 @@
52 +/*
53 + Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
54 + <http://rt2x00.serialmonkey.com>
55 +
56 + This program is free software; you can redistribute it and/or modify
57 + it under the terms of the GNU General Public License as published by
58 + the Free Software Foundation; either version 2 of the License, or
59 + (at your option) any later version.
60 +
61 + This program is distributed in the hope that it will be useful,
62 + but WITHOUT ANY WARRANTY; without even the implied warranty of
63 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
64 + GNU General Public License for more details.
65 +
66 + You should have received a copy of the GNU General Public License
67 + along with this program; if not, write to the
68 + Free Software Foundation, Inc.,
69 + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
70 + */
71 +
72 +/*
73 + Module: eeprom_93cx6
74 + Abstract: EEPROM reader routines for 93cx6 chipsets.
75 + Supported chipsets: 93c46 & 93c66.
76 + */
77 +
78 +#include <linux/kernel.h>
79 +#include <linux/module.h>
80 +#include <linux/version.h>
81 +#include <linux/delay.h>
82 +#include <linux/eeprom_93cx6.h>
83 +
84 +MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
85 +MODULE_VERSION("1.0");
86 +MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
87 +MODULE_LICENSE("GPL");
88 +
89 +static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
90 +{
91 + eeprom->reg_data_clock = 1;
92 + eeprom->register_write(eeprom);
93 + udelay(1);
94 +}
95 +
96 +static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
97 +{
98 + eeprom->reg_data_clock = 0;
99 + eeprom->register_write(eeprom);
100 + udelay(1);
101 +}
102 +
103 +static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
104 +{
105 + /*
106 + * Clear all flags, and enable chip select.
107 + */
108 + eeprom->register_read(eeprom);
109 + eeprom->reg_data_in = 0;
110 + eeprom->reg_data_out = 0;
111 + eeprom->reg_data_clock = 0;
112 + eeprom->reg_chip_select = 1;
113 + eeprom->register_write(eeprom);
114 +
115 + /*
116 + * kick a pulse.
117 + */
118 + eeprom_93cx6_pulse_high(eeprom);
119 + eeprom_93cx6_pulse_low(eeprom);
120 +}
121 +
122 +static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
123 +{
124 + /*
125 + * Clear chip_select and data_in flags.
126 + */
127 + eeprom->register_read(eeprom);
128 + eeprom->reg_data_in = 0;
129 + eeprom->reg_chip_select = 0;
130 + eeprom->register_write(eeprom);
131 +
132 + /*
133 + * kick a pulse.
134 + */
135 + eeprom_93cx6_pulse_high(eeprom);
136 + eeprom_93cx6_pulse_low(eeprom);
137 +}
138 +
139 +static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
140 + const u16 data, const u16 count)
141 +{
142 + unsigned int i;
143 +
144 + eeprom->register_read(eeprom);
145 +
146 + /*
147 + * Clear data flags.
148 + */
149 + eeprom->reg_data_in = 0;
150 + eeprom->reg_data_out = 0;
151 +
152 + /*
153 + * Start writing all bits.
154 + */
155 + for (i = count; i > 0; i--) {
156 + /*
157 + * Check if this bit needs to be set.
158 + */
159 + eeprom->reg_data_in = !!(data & (1 << (i - 1)));
160 +
161 + /*
162 + * Write the bit to the eeprom register.
163 + */
164 + eeprom->register_write(eeprom);
165 +
166 + /*
167 + * Kick a pulse.
168 + */
169 + eeprom_93cx6_pulse_high(eeprom);
170 + eeprom_93cx6_pulse_low(eeprom);
171 + }
172 +
173 + eeprom->reg_data_in = 0;
174 + eeprom->register_write(eeprom);
175 +}
176 +
177 +static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
178 + u16 *data, const u16 count)
179 +{
180 + unsigned int i;
181 + u16 buf = 0;
182 +
183 + eeprom->register_read(eeprom);
184 +
185 + /*
186 + * Clear data flags.
187 + */
188 + eeprom->reg_data_in = 0;
189 + eeprom->reg_data_out = 0;
190 +
191 + /*
192 + * Start reading all bits.
193 + */
194 + for (i = count; i > 0; i--) {
195 + eeprom_93cx6_pulse_high(eeprom);
196 +
197 + eeprom->register_read(eeprom);
198 +
199 + /*
200 + * Clear data_in flag.
201 + */
202 + eeprom->reg_data_in = 0;
203 +
204 + /*
205 + * Read if the bit has been set.
206 + */
207 + if (eeprom->reg_data_out)
208 + buf |= (1 << (i - 1));
209 +
210 + eeprom_93cx6_pulse_low(eeprom);
211 + }
212 +
213 + *data = buf;
214 +}
215 +
216 +/**
217 + * eeprom_93cx6_read - Read multiple words from eeprom
218 + * @eeprom: Pointer to eeprom structure
219 + * @word: Word index from where we should start reading
220 + * @data: target pointer where the information will have to be stored
221 + *
222 + * This function will read the eeprom data as host-endian word
223 + * into the given data pointer.
224 + */
225 +void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
226 + u16 *data)
227 +{
228 + u16 command;
229 +
230 + /*
231 + * Initialize the eeprom register
232 + */
233 + eeprom_93cx6_startup(eeprom);
234 +
235 + /*
236 + * Select the read opcode and the word to be read.
237 + */
238 + command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
239 + eeprom_93cx6_write_bits(eeprom, command,
240 + PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
241 +
242 + /*
243 + * Read the requested 16 bits.
244 + */
245 + eeprom_93cx6_read_bits(eeprom, data, 16);
246 +
247 + /*
248 + * Cleanup eeprom register.
249 + */
250 + eeprom_93cx6_cleanup(eeprom);
251 +}
252 +EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
253 +
254 +/**
255 + * eeprom_93cx6_multiread - Read multiple words from eeprom
256 + * @eeprom: Pointer to eeprom structure
257 + * @word: Word index from where we should start reading
258 + * @data: target pointer where the information will have to be stored
259 + * @words: Number of words that should be read.
260 + *
261 + * This function will read all requested words from the eeprom,
262 + * this is done by calling eeprom_93cx6_read() multiple times.
263 + * But with the additional change that while the eeprom_93cx6_read
264 + * will return host ordered bytes, this method will return little
265 + * endian words.
266 + */
267 +void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
268 + __le16 *data, const u16 words)
269 +{
270 + unsigned int i;
271 + u16 tmp;
272 +
273 + for (i = 0; i < words; i++) {
274 + tmp = 0;
275 + eeprom_93cx6_read(eeprom, word + i, &tmp);
276 + data[i] = cpu_to_le16(tmp);
277 + }
278 +}
279 +EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
280 +
281 diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
282 new file mode 100644
283 index 0000000..d774b77
284 --- /dev/null
285 +++ b/include/linux/eeprom_93cx6.h
286 @@ -0,0 +1,72 @@
287 +/*
288 + Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
289 + <http://rt2x00.serialmonkey.com>
290 +
291 + This program is free software; you can redistribute it and/or modify
292 + it under the terms of the GNU General Public License as published by
293 + the Free Software Foundation; either version 2 of the License, or
294 + (at your option) any later version.
295 +
296 + This program is distributed in the hope that it will be useful,
297 + but WITHOUT ANY WARRANTY; without even the implied warranty of
298 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
299 + GNU General Public License for more details.
300 +
301 + You should have received a copy of the GNU General Public License
302 + along with this program; if not, write to the
303 + Free Software Foundation, Inc.,
304 + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
305 + */
306 +
307 +/*
308 + Module: eeprom_93cx6
309 + Abstract: EEPROM reader datastructures for 93cx6 chipsets.
310 + Supported chipsets: 93c46 & 93c66.
311 + */
312 +
313 +/*
314 + * EEPROM operation defines.
315 + */
316 +#define PCI_EEPROM_WIDTH_93C46 6
317 +#define PCI_EEPROM_WIDTH_93C66 8
318 +#define PCI_EEPROM_WIDTH_OPCODE 3
319 +#define PCI_EEPROM_WRITE_OPCODE 0x05
320 +#define PCI_EEPROM_READ_OPCODE 0x06
321 +#define PCI_EEPROM_EWDS_OPCODE 0x10
322 +#define PCI_EEPROM_EWEN_OPCODE 0x13
323 +
324 +/**
325 + * struct eeprom_93cx6 - control structure for setting the commands
326 + * for reading the eeprom data.
327 + * @data: private pointer for the driver.
328 + * @register_read(struct eeprom_93cx6 *eeprom): handler to
329 + * read the eeprom register, this function should set all reg_* fields.
330 + * @register_write(struct eeprom_93cx6 *eeprom): handler to
331 + * write to the eeprom register by using all reg_* fields.
332 + * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
333 + * @reg_data_in: register field to indicate data input
334 + * @reg_data_out: register field to indicate data output
335 + * @reg_data_clock: register field to set the data clock
336 + * @reg_chip_select: register field to set the chip select
337 + *
338 + * This structure is used for the communication between the driver
339 + * and the eeprom_93cx6 handlers for reading the eeprom.
340 + */
341 +struct eeprom_93cx6 {
342 + void *data;
343 +
344 + void (*register_read)(struct eeprom_93cx6 *eeprom);
345 + void (*register_write)(struct eeprom_93cx6 *eeprom);
346 +
347 + int width;
348 +
349 + char reg_data_in;
350 + char reg_data_out;
351 + char reg_data_clock;
352 + char reg_chip_select;
353 +};
354 +
355 +extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
356 + const u8 word, u16 *data);
357 +extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
358 + const u8 word, __le16 *data, const u16 words);
359 From: Ivo van Doorn <ivdoorn@gmail.com>
360 Date: Mon, 14 May 2007 21:06:01 +0000 (+0200)
361 Subject: [PATCH] eeprom_93cx6: Add comment for 1us delay after pulse
362 X-Git-Tag: v2.6.23-rc1~1201^2~73
363 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=4b914dc0493edff19ff698a18198a173a14ba9d2
364
365 [PATCH] eeprom_93cx6: Add comment for 1us delay after pulse
366
367 This will add a comment for the 1us delay which is taken
368 after the pulse has been switched. The 1us delay is based
369 on the specifications so that should be made clear.
370
371 Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
372 Signed-off-by: John W. Linville <linville@tuxdriver.com>
373 ---
374
375 diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
376 index bfcb434..0d6d742 100644
377 --- a/drivers/misc/eeprom_93cx6.c
378 +++ b/drivers/misc/eeprom_93cx6.c
379 @@ -39,6 +39,12 @@ static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
380 {
381 eeprom->reg_data_clock = 1;
382 eeprom->register_write(eeprom);
383 +
384 + /*
385 + * Add a short delay for the pulse to work.
386 + * According to the specifications the minimal time
387 + * should be 450ns so a 1us delay is sufficient.
388 + */
389 udelay(1);
390 }
391
392 @@ -46,6 +52,12 @@ static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
393 {
394 eeprom->reg_data_clock = 0;
395 eeprom->register_write(eeprom);
396 +
397 + /*
398 + * Add a short delay for the pulse to work.
399 + * According to the specifications the minimal time
400 + * should be 450ns so a 1us delay is sufficient.
401 + */
402 udelay(1);
403 }
404
405 From: John W. Linville <linville@tuxdriver.com>
406 Date: Tue, 12 Jun 2007 01:37:46 +0000 (-0400)
407 Subject: [PATCH] eeprom_93cx6: shorten pulse timing to match spec
408 X-Git-Tag: v2.6.23-rc1~1201^2~71
409 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=7e9400f178d291b2208c4ed9aac0f425c1364000
410
411 [PATCH] eeprom_93cx6: shorten pulse timing to match spec
412
413 93cx6 datasheet available here:
414
415 http://ww1.microchip.com/downloads/en/DeviceDoc/21749F.pdf
416
417 Figure 1-1 and Table 1-2 on pages 4-5 indicate that both Clock High
418 Time and Clock Low Time have largest minimum times of 450ns.
419
420 Signed-off-by: John W. Linville <linville@tuxdriver.com>
421 ---
422
423 diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
424 index 0d6d742..ac515b0 100644
425 --- a/drivers/misc/eeprom_93cx6.c
426 +++ b/drivers/misc/eeprom_93cx6.c
427 @@ -42,10 +42,10 @@ static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
428
429 /*
430 * Add a short delay for the pulse to work.
431 - * According to the specifications the minimal time
432 - * should be 450ns so a 1us delay is sufficient.
433 + * According to the specifications the "maximum minimum"
434 + * time should be 450ns.
435 */
436 - udelay(1);
437 + ndelay(450);
438 }
439
440 static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
441 From: Francois Romieu <romieu@fr.zoreil.com>
442 Date: Tue, 3 Jul 2007 22:31:44 +0000 (+0200)
443 Subject: eeprom_93cx6: shorten pulse timing to match spec (bis)
444 X-Git-Tag: v2.6.23-rc1~1151^2~11
445 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=8abd531e3f77188de2fc41e677d075cc66e61631
446
447 eeprom_93cx6: shorten pulse timing to match spec (bis)
448
449 Based on an original idea by John W. Linville.
450
451 It is the missing part of 42d45ccd60636c28e35c2016f091783bc14ad99c
452
453 Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
454 Signed-off-by: Jeff Garzik <jeff@garzik.org>
455 ---
456
457 diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
458 index ac515b0..ea55654 100644
459 --- a/drivers/misc/eeprom_93cx6.c
460 +++ b/drivers/misc/eeprom_93cx6.c
461 @@ -55,10 +55,10 @@ static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
462
463 /*
464 * Add a short delay for the pulse to work.
465 - * According to the specifications the minimal time
466 - * should be 450ns so a 1us delay is sufficient.
467 + * According to the specifications the "maximum minimum"
468 + * time should be 450ns.
469 */
470 - udelay(1);
471 + ndelay(450);
472 }
473
474 static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
This page took 0.064839 seconds and 3 git commands to generate.