1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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
43
44
45
46
47
48 ndelay(450);
49}
50
51static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
52{
53 eeprom->reg_data_clock = 0;
54 eeprom->register_write(eeprom);
55
56
57
58
59
60
61 ndelay(450);
62}
63
64static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
65{
66
67
68
69 eeprom->register_read(eeprom);
70 eeprom->reg_data_in = 0;
71 eeprom->reg_data_out = 0;
72 eeprom->reg_data_clock = 0;
73 eeprom->reg_chip_select = 1;
74 eeprom->register_write(eeprom);
75
76
77
78
79 eeprom_93cx6_pulse_high(eeprom);
80 eeprom_93cx6_pulse_low(eeprom);
81}
82
83static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
84{
85
86
87
88 eeprom->register_read(eeprom);
89 eeprom->reg_data_in = 0;
90 eeprom->reg_chip_select = 0;
91 eeprom->register_write(eeprom);
92
93
94
95
96 eeprom_93cx6_pulse_high(eeprom);
97 eeprom_93cx6_pulse_low(eeprom);
98}
99
100static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
101 const u16 data, const u16 count)
102{
103 unsigned int i;
104
105 eeprom->register_read(eeprom);
106
107
108
109
110 eeprom->reg_data_in = 0;
111 eeprom->reg_data_out = 0;
112
113
114
115
116 for (i = count; i > 0; i--) {
117
118
119
120 eeprom->reg_data_in = !!(data & (1 << (i - 1)));
121
122
123
124
125 eeprom->register_write(eeprom);
126
127
128
129
130 eeprom_93cx6_pulse_high(eeprom);
131 eeprom_93cx6_pulse_low(eeprom);
132 }
133
134 eeprom->reg_data_in = 0;
135 eeprom->register_write(eeprom);
136}
137
138static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
139 u16 *data, const u16 count)
140{
141 unsigned int i;
142 u16 buf = 0;
143
144 eeprom->register_read(eeprom);
145
146
147
148
149 eeprom->reg_data_in = 0;
150 eeprom->reg_data_out = 0;
151
152
153
154
155 for (i = count; i > 0; i--) {
156 eeprom_93cx6_pulse_high(eeprom);
157
158 eeprom->register_read(eeprom);
159
160
161
162
163 eeprom->reg_data_in = 0;
164
165
166
167
168 if (eeprom->reg_data_out)
169 buf |= (1 << (i - 1));
170
171 eeprom_93cx6_pulse_low(eeprom);
172 }
173
174 *data = buf;
175}
176
177
178
179
180
181
182
183
184
185
186void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
187 u16 *data)
188{
189 u16 command;
190
191
192
193
194 eeprom_93cx6_startup(eeprom);
195
196
197
198
199 command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
200 eeprom_93cx6_write_bits(eeprom, command,
201 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
202
203
204
205
206 eeprom_93cx6_read_bits(eeprom, data, 16);
207
208
209
210
211 eeprom_93cx6_cleanup(eeprom);
212}
213EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
229 __le16 *data, const u16 words)
230{
231 unsigned int i;
232 u16 tmp;
233
234 for (i = 0; i < words; i++) {
235 tmp = 0;
236 eeprom_93cx6_read(eeprom, word + i, &tmp);
237 data[i] = cpu_to_le16(tmp);
238 }
239}
240EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
241
242