aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/Kconfig6
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/eeprom_93cx6.c229
-rw-r--r--include/linux/eeprom_93cx6.h72
4 files changed, 307 insertions, 1 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 616eee9c04f1..bd601efa7bd1 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -34,6 +34,11 @@ config PHANTOM
34 If you choose to build module, its name will be phantom. If unsure, 34 If you choose to build module, its name will be phantom. If unsure,
35 say N here. 35 say N here.
36 36
37config EEPROM_93CX6
38 tristate "EEPROM 93CX6 support"
39 ---help---
40 This is a driver for the EEPROM chipsets 93c46 and 93c66.
41 The driver supports both read as well as write commands.
37 42
38 If unsure, say N. 43 If unsure, say N.
39 44
@@ -187,5 +192,4 @@ config THINKPAD_ACPI_BAY
187 192
188 If you are not sure, say Y here. 193 If you are not sure, say Y here.
189 194
190
191endmenu 195endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 8abbf2f07a65..b5ce0e3dba86 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_PHANTOM) += phantom.o
14obj-$(CONFIG_SGI_IOC4) += ioc4.o 14obj-$(CONFIG_SGI_IOC4) += ioc4.o
15obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o 15obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o
16obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o 16obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o
17obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 000000000000..bfcb43424dcd
--- /dev/null
+++ b/drivers/misc/eeprom_93cx6.c
@@ -0,0 +1,229 @@
1/*
2 Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
3 <http://rt2x00.serialmonkey.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*
22 Module: eeprom_93cx6
23 Abstract: EEPROM reader routines for 93cx6 chipsets.
24 Supported chipsets: 93c46 & 93c66.
25 */
26
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/version.h>
30#include <linux/delay.h>
31#include <linux/eeprom_93cx6.h>
32
33MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
34MODULE_VERSION("1.0");
35MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
36MODULE_LICENSE("GPL");
37
38static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
39{
40 eeprom->reg_data_clock = 1;
41 eeprom->register_write(eeprom);
42 udelay(1);
43}
44
45static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
46{
47 eeprom->reg_data_clock = 0;
48 eeprom->register_write(eeprom);
49 udelay(1);
50}
51
52static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
53{
54 /*
55 * Clear all flags, and enable chip select.
56 */
57 eeprom->register_read(eeprom);
58 eeprom->reg_data_in = 0;
59 eeprom->reg_data_out = 0;
60 eeprom->reg_data_clock = 0;
61 eeprom->reg_chip_select = 1;
62 eeprom->register_write(eeprom);
63
64 /*
65 * kick a pulse.
66 */
67 eeprom_93cx6_pulse_high(eeprom);
68 eeprom_93cx6_pulse_low(eeprom);
69}
70
71static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
72{
73 /*
74 * Clear chip_select and data_in flags.
75 */
76 eeprom->register_read(eeprom);
77 eeprom->reg_data_in = 0;
78 eeprom->reg_chip_select = 0;
79 eeprom->register_write(eeprom);
80
81 /*
82 * kick a pulse.
83 */
84 eeprom_93cx6_pulse_high(eeprom);
85 eeprom_93cx6_pulse_low(eeprom);
86}
87
88static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
89 const u16 data, const u16 count)
90{
91 unsigned int i;
92
93 eeprom->register_read(eeprom);
94
95 /*
96 * Clear data flags.
97 */
98 eeprom->reg_data_in = 0;
99 eeprom->reg_data_out = 0;
100
101 /*
102 * Start writing all bits.
103 */
104 for (i = count; i > 0; i--) {
105 /*
106 * Check if this bit needs to be set.
107 */
108 eeprom->reg_data_in = !!(data & (1 << (i - 1)));
109
110 /*
111 * Write the bit to the eeprom register.
112 */
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 eeprom->reg_data_in = 0;
123 eeprom->register_write(eeprom);
124}
125
126static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
127 u16 *data, const u16 count)
128{
129 unsigned int i;
130 u16 buf = 0;
131
132 eeprom->register_read(eeprom);
133
134 /*
135 * Clear data flags.
136 */
137 eeprom->reg_data_in = 0;
138 eeprom->reg_data_out = 0;
139
140 /*
141 * Start reading all bits.
142 */
143 for (i = count; i > 0; i--) {
144 eeprom_93cx6_pulse_high(eeprom);
145
146 eeprom->register_read(eeprom);
147
148 /*
149 * Clear data_in flag.
150 */
151 eeprom->reg_data_in = 0;
152
153 /*
154 * Read if the bit has been set.
155 */
156 if (eeprom->reg_data_out)
157 buf |= (1 << (i - 1));
158
159 eeprom_93cx6_pulse_low(eeprom);
160 }
161
162 *data = buf;
163}
164
165/**
166 * eeprom_93cx6_read - Read multiple words from eeprom
167 * @eeprom: Pointer to eeprom structure
168 * @word: Word index from where we should start reading
169 * @data: target pointer where the information will have to be stored
170 *
171 * This function will read the eeprom data as host-endian word
172 * into the given data pointer.
173 */
174void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
175 u16 *data)
176{
177 u16 command;
178
179 /*
180 * Initialize the eeprom register
181 */
182 eeprom_93cx6_startup(eeprom);
183
184 /*
185 * Select the read opcode and the word to be read.
186 */
187 command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
188 eeprom_93cx6_write_bits(eeprom, command,
189 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
190
191 /*
192 * Read the requested 16 bits.
193 */
194 eeprom_93cx6_read_bits(eeprom, data, 16);
195
196 /*
197 * Cleanup eeprom register.
198 */
199 eeprom_93cx6_cleanup(eeprom);
200}
201EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
202
203/**
204 * eeprom_93cx6_multiread - Read multiple words from eeprom
205 * @eeprom: Pointer to eeprom structure
206 * @word: Word index from where we should start reading
207 * @data: target pointer where the information will have to be stored
208 * @words: Number of words that should be read.
209 *
210 * This function will read all requested words from the eeprom,
211 * this is done by calling eeprom_93cx6_read() multiple times.
212 * But with the additional change that while the eeprom_93cx6_read
213 * will return host ordered bytes, this method will return little
214 * endian words.
215 */
216void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
217 __le16 *data, const u16 words)
218{
219 unsigned int i;
220 u16 tmp;
221
222 for (i = 0; i < words; i++) {
223 tmp = 0;
224 eeprom_93cx6_read(eeprom, word + i, &tmp);
225 data[i] = cpu_to_le16(tmp);
226 }
227}
228EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
229
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
new file mode 100644
index 000000000000..d774b7778c91
--- /dev/null
+++ b/include/linux/eeprom_93cx6.h
@@ -0,0 +1,72 @@
1/*
2 Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
3 <http://rt2x00.serialmonkey.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the
17 Free Software Foundation, Inc.,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21/*
22 Module: eeprom_93cx6
23 Abstract: EEPROM reader datastructures for 93cx6 chipsets.
24 Supported chipsets: 93c46 & 93c66.
25 */
26
27/*
28 * EEPROM operation defines.
29 */
30#define PCI_EEPROM_WIDTH_93C46 6
31#define PCI_EEPROM_WIDTH_93C66 8
32#define PCI_EEPROM_WIDTH_OPCODE 3
33#define PCI_EEPROM_WRITE_OPCODE 0x05
34#define PCI_EEPROM_READ_OPCODE 0x06
35#define PCI_EEPROM_EWDS_OPCODE 0x10
36#define PCI_EEPROM_EWEN_OPCODE 0x13
37
38/**
39 * struct eeprom_93cx6 - control structure for setting the commands
40 * for reading the eeprom data.
41 * @data: private pointer for the driver.
42 * @register_read(struct eeprom_93cx6 *eeprom): handler to
43 * read the eeprom register, this function should set all reg_* fields.
44 * @register_write(struct eeprom_93cx6 *eeprom): handler to
45 * write to the eeprom register by using all reg_* fields.
46 * @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
47 * @reg_data_in: register field to indicate data input
48 * @reg_data_out: register field to indicate data output
49 * @reg_data_clock: register field to set the data clock
50 * @reg_chip_select: register field to set the chip select
51 *
52 * This structure is used for the communication between the driver
53 * and the eeprom_93cx6 handlers for reading the eeprom.
54 */
55struct eeprom_93cx6 {
56 void *data;
57
58 void (*register_read)(struct eeprom_93cx6 *eeprom);
59 void (*register_write)(struct eeprom_93cx6 *eeprom);
60
61 int width;
62
63 char reg_data_in;
64 char reg_data_out;
65 char reg_data_clock;
66 char reg_chip_select;
67};
68
69extern void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom,
70 const u8 word, u16 *data);
71extern void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom,
72 const u8 word, __le16 *data, const u16 words);