aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/eeprom_93cx6.c
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2007-05-11 15:59:40 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-08 22:16:36 -0400
commit9467d64b0e88763914c01f71ddf591b166c4f526 (patch)
tree594dca21215cff58b17189ed50071faa154b2f64 /drivers/misc/eeprom_93cx6.c
parent7dcca30a32aadb0520417521b0c44f42d09fe05c (diff)
[PATCH] Add 93cx6 eeprom library
This patch adds a library for reading from 93cx6 eeproms. Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/misc/eeprom_93cx6.c')
-rw-r--r--drivers/misc/eeprom_93cx6.c229
1 files changed, 229 insertions, 0 deletions
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c
new file mode 100644
index 00000000000..bfcb43424dc
--- /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