]> Git Repo - J-linux.git/blob - drivers/misc/eeprom/eeprom_93cx6.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / misc / eeprom / eeprom_93cx6.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2004 - 2006 rt2x00 SourceForge Project
4  * <http://rt2x00.serialmonkey.com>
5  *
6  * Module: eeprom_93cx6
7  * Abstract: EEPROM reader routines for 93cx6 chipsets.
8  * Supported chipsets: 93c46 & 93c66.
9  */
10
11 #include <linux/bits.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/delay.h>
15 #include <linux/eeprom_93cx6.h>
16
17 MODULE_AUTHOR("http://rt2x00.serialmonkey.com");
18 MODULE_VERSION("1.0");
19 MODULE_DESCRIPTION("EEPROM 93cx6 chip driver");
20 MODULE_LICENSE("GPL");
21
22 static inline void eeprom_93cx6_pulse_high(struct eeprom_93cx6 *eeprom)
23 {
24         eeprom->reg_data_clock = 1;
25         eeprom->register_write(eeprom);
26
27         /*
28          * Add a short delay for the pulse to work.
29          * According to the specifications the "maximum minimum"
30          * time should be 450ns.
31          */
32         ndelay(450);
33 }
34
35 static inline void eeprom_93cx6_pulse_low(struct eeprom_93cx6 *eeprom)
36 {
37         eeprom->reg_data_clock = 0;
38         eeprom->register_write(eeprom);
39
40         /*
41          * Add a short delay for the pulse to work.
42          * According to the specifications the "maximum minimum"
43          * time should be 450ns.
44          */
45         ndelay(450);
46 }
47
48 static void eeprom_93cx6_startup(struct eeprom_93cx6 *eeprom)
49 {
50         /*
51          * Clear all flags, and enable chip select.
52          */
53         eeprom->register_read(eeprom);
54         eeprom->reg_data_in = 0;
55         eeprom->reg_data_out = 0;
56         eeprom->reg_data_clock = 0;
57         eeprom->reg_chip_select = 1;
58         eeprom->drive_data = 1;
59         eeprom->register_write(eeprom);
60
61         /*
62          * kick a pulse.
63          */
64         eeprom_93cx6_pulse_high(eeprom);
65         eeprom_93cx6_pulse_low(eeprom);
66 }
67
68 static void eeprom_93cx6_cleanup(struct eeprom_93cx6 *eeprom)
69 {
70         /*
71          * Clear chip_select and data_in flags.
72          */
73         eeprom->register_read(eeprom);
74         eeprom->reg_data_in = 0;
75         eeprom->reg_chip_select = 0;
76         eeprom->register_write(eeprom);
77
78         /*
79          * kick a pulse.
80          */
81         eeprom_93cx6_pulse_high(eeprom);
82         eeprom_93cx6_pulse_low(eeprom);
83 }
84
85 static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
86         const u16 data, const u16 count)
87 {
88         unsigned int i;
89
90         eeprom->register_read(eeprom);
91
92         /*
93          * Clear data flags.
94          */
95         eeprom->reg_data_in = 0;
96         eeprom->reg_data_out = 0;
97         eeprom->drive_data = 1;
98
99         /*
100          * Start writing all bits.
101          */
102         for (i = count; i > 0; i--) {
103                 /*
104                  * Check if this bit needs to be set.
105                  */
106                 eeprom->reg_data_in = !!(data & BIT(i - 1));
107
108                 /*
109                  * Write the bit to the eeprom register.
110                  */
111                 eeprom->register_write(eeprom);
112
113                 /*
114                  * Kick a pulse.
115                  */
116                 eeprom_93cx6_pulse_high(eeprom);
117                 eeprom_93cx6_pulse_low(eeprom);
118         }
119
120         eeprom->reg_data_in = 0;
121         eeprom->register_write(eeprom);
122 }
123
124 static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
125         u16 *data, const u16 count)
126 {
127         unsigned int i;
128         u16 buf = 0;
129
130         eeprom->register_read(eeprom);
131
132         /*
133          * Clear data flags.
134          */
135         eeprom->reg_data_in = 0;
136         eeprom->reg_data_out = 0;
137         eeprom->drive_data = 0;
138
139         /*
140          * Start reading all bits.
141          */
142         for (i = count; i > 0; i--) {
143                 eeprom_93cx6_pulse_high(eeprom);
144
145                 eeprom->register_read(eeprom);
146
147                 /*
148                  * Clear data_in flag.
149                  */
150                 eeprom->reg_data_in = 0;
151
152                 /*
153                  * Read if the bit has been set.
154                  */
155                 if (eeprom->reg_data_out)
156                         buf |= BIT(i - 1);
157
158                 eeprom_93cx6_pulse_low(eeprom);
159         }
160
161         *data = buf;
162 }
163
164 /**
165  * eeprom_93cx6_read - Read a word from eeprom
166  * @eeprom: Pointer to eeprom structure
167  * @word: Word index from where we should start reading
168  * @data: target pointer where the information will have to be stored
169  *
170  * This function will read the eeprom data as host-endian word
171  * into the given data pointer.
172  */
173 void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
174         u16 *data)
175 {
176         u16 command;
177
178         /*
179          * Initialize the eeprom register
180          */
181         eeprom_93cx6_startup(eeprom);
182
183         /*
184          * Select the read opcode and the word to be read.
185          */
186         command = (PCI_EEPROM_READ_OPCODE << eeprom->width) | word;
187         eeprom_93cx6_write_bits(eeprom, command,
188                 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
189
190         if (has_quirk_extra_read_cycle(eeprom)) {
191                 eeprom_93cx6_pulse_high(eeprom);
192                 eeprom_93cx6_pulse_low(eeprom);
193         }
194
195         /*
196          * Read the requested 16 bits.
197          */
198         eeprom_93cx6_read_bits(eeprom, data, 16);
199
200         /*
201          * Cleanup eeprom register.
202          */
203         eeprom_93cx6_cleanup(eeprom);
204 }
205 EXPORT_SYMBOL_GPL(eeprom_93cx6_read);
206
207 /**
208  * eeprom_93cx6_multiread - Read multiple words from eeprom
209  * @eeprom: Pointer to eeprom structure
210  * @word: Word index from where we should start reading
211  * @data: target pointer where the information will have to be stored
212  * @words: Number of words that should be read.
213  *
214  * This function will read all requested words from the eeprom,
215  * this is done by calling eeprom_93cx6_read() multiple times.
216  * But with the additional change that while the eeprom_93cx6_read
217  * will return host ordered bytes, this method will return little
218  * endian words.
219  */
220 void eeprom_93cx6_multiread(struct eeprom_93cx6 *eeprom, const u8 word,
221         __le16 *data, const u16 words)
222 {
223         unsigned int i;
224         u16 tmp;
225
226         for (i = 0; i < words; i++) {
227                 tmp = 0;
228                 eeprom_93cx6_read(eeprom, word + i, &tmp);
229                 data[i] = cpu_to_le16(tmp);
230         }
231 }
232 EXPORT_SYMBOL_GPL(eeprom_93cx6_multiread);
233
234 /**
235  * eeprom_93cx6_readb - Read a byte from eeprom
236  * @eeprom: Pointer to eeprom structure
237  * @byte: Byte index from where we should start reading
238  * @data: target pointer where the information will have to be stored
239  *
240  * This function will read a byte of the eeprom data
241  * into the given data pointer.
242  */
243 void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
244         u8 *data)
245 {
246         u16 command;
247         u16 tmp;
248
249         /*
250          * Initialize the eeprom register
251          */
252         eeprom_93cx6_startup(eeprom);
253
254         /*
255          * Select the read opcode and the byte to be read.
256          */
257         command = (PCI_EEPROM_READ_OPCODE << (eeprom->width + 1)) | byte;
258         eeprom_93cx6_write_bits(eeprom, command,
259                 PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
260
261         if (has_quirk_extra_read_cycle(eeprom)) {
262                 eeprom_93cx6_pulse_high(eeprom);
263                 eeprom_93cx6_pulse_low(eeprom);
264         }
265
266         /*
267          * Read the requested 8 bits.
268          */
269         eeprom_93cx6_read_bits(eeprom, &tmp, 8);
270         *data = tmp & 0xff;
271
272         /*
273          * Cleanup eeprom register.
274          */
275         eeprom_93cx6_cleanup(eeprom);
276 }
277 EXPORT_SYMBOL_GPL(eeprom_93cx6_readb);
278
279 /**
280  * eeprom_93cx6_multireadb - Read multiple bytes from eeprom
281  * @eeprom: Pointer to eeprom structure
282  * @byte: Index from where we should start reading
283  * @data: target pointer where the information will have to be stored
284  * @bytes: Number of bytes that should be read.
285  *
286  * This function will read all requested bytes from the eeprom,
287  * this is done by calling eeprom_93cx6_readb() multiple times.
288  */
289 void eeprom_93cx6_multireadb(struct eeprom_93cx6 *eeprom, const u8 byte,
290         u8 *data, const u16 bytes)
291 {
292         unsigned int i;
293
294         for (i = 0; i < bytes; i++)
295                 eeprom_93cx6_readb(eeprom, byte + i, &data[i]);
296 }
297 EXPORT_SYMBOL_GPL(eeprom_93cx6_multireadb);
298
299 /**
300  * eeprom_93cx6_wren - set the write enable state
301  * @eeprom: Pointer to eeprom structure
302  * @enable: true to enable writes, otherwise disable writes
303  *
304  * Set the EEPROM write enable state to either allow or deny
305  * writes depending on the @enable value.
306  */
307 void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable)
308 {
309         u16 command;
310
311         /* start the command */
312         eeprom_93cx6_startup(eeprom);
313
314         /* create command to enable/disable */
315
316         command = enable ? PCI_EEPROM_EWEN_OPCODE : PCI_EEPROM_EWDS_OPCODE;
317         command <<= (eeprom->width - 2);
318
319         eeprom_93cx6_write_bits(eeprom, command,
320                                 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
321
322         eeprom_93cx6_cleanup(eeprom);
323 }
324 EXPORT_SYMBOL_GPL(eeprom_93cx6_wren);
325
326 /**
327  * eeprom_93cx6_write - write data to the EEPROM
328  * @eeprom: Pointer to eeprom structure
329  * @addr: Address to write data to.
330  * @data: The data to write to address @addr.
331  *
332  * Write the @data to the specified @addr in the EEPROM and
333  * waiting for the device to finish writing.
334  *
335  * Note, since we do not expect large number of write operations
336  * we delay in between parts of the operation to avoid using excessive
337  * amounts of CPU time busy waiting.
338  */
339 void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom, u8 addr, u16 data)
340 {
341         int timeout = 100;
342         u16 command;
343
344         /* start the command */
345         eeprom_93cx6_startup(eeprom);
346
347         command = PCI_EEPROM_WRITE_OPCODE << eeprom->width;
348         command |= addr;
349
350         /* send write command */
351         eeprom_93cx6_write_bits(eeprom, command,
352                                 PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
353
354         /* send data */
355         eeprom_93cx6_write_bits(eeprom, data, 16);
356
357         /* get ready to check for busy */
358         eeprom->drive_data = 0;
359         eeprom->reg_chip_select = 1;
360         eeprom->register_write(eeprom);
361
362         /* wait at-least 250ns to get DO to be the busy signal */
363         usleep_range(1000, 2000);
364
365         /* wait for DO to go high to signify finish */
366
367         while (true) {
368                 eeprom->register_read(eeprom);
369
370                 if (eeprom->reg_data_out)
371                         break;
372
373                 usleep_range(1000, 2000);
374
375                 if (--timeout <= 0) {
376                         printk(KERN_ERR "%s: timeout\n", __func__);
377                         break;
378                 }
379         }
380
381         eeprom_93cx6_cleanup(eeprom);
382 }
383 EXPORT_SYMBOL_GPL(eeprom_93cx6_write);
This page took 0.04598 seconds and 4 git commands to generate.