xref: /linux/drivers/misc/eeprom/eeprom_93cx6.c (revision 7f71507851fc7764b36a3221839607d3a45c2025)
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);
384