diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/cris/arch-v10/drivers/eeprom.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/cris/arch-v10/drivers/eeprom.c')
-rw-r--r-- | arch/cris/arch-v10/drivers/eeprom.c | 945 |
1 files changed, 945 insertions, 0 deletions
diff --git a/arch/cris/arch-v10/drivers/eeprom.c b/arch/cris/arch-v10/drivers/eeprom.c new file mode 100644 index 000000000000..316ca15d6802 --- /dev/null +++ b/arch/cris/arch-v10/drivers/eeprom.c | |||
@@ -0,0 +1,945 @@ | |||
1 | /*!***************************************************************************** | ||
2 | *! | ||
3 | *! Implements an interface for i2c compatible eeproms to run under linux. | ||
4 | *! Supports 2k, 8k(?) and 16k. Uses adaptive timing adjustents by | ||
5 | *! Johan.Adolfsson@axis.com | ||
6 | *! | ||
7 | *! Probing results: | ||
8 | *! 8k or not is detected (the assumes 2k or 16k) | ||
9 | *! 2k or 16k detected using test reads and writes. | ||
10 | *! | ||
11 | *!------------------------------------------------------------------------ | ||
12 | *! HISTORY | ||
13 | *! | ||
14 | *! DATE NAME CHANGES | ||
15 | *! ---- ---- ------- | ||
16 | *! Aug 28 1999 Edgar Iglesias Initial Version | ||
17 | *! Aug 31 1999 Edgar Iglesias Allow simultaneous users. | ||
18 | *! Sep 03 1999 Edgar Iglesias Updated probe. | ||
19 | *! Sep 03 1999 Edgar Iglesias Added bail-out stuff if we get interrupted | ||
20 | *! in the spin-lock. | ||
21 | *! | ||
22 | *! $Log: eeprom.c,v $ | ||
23 | *! Revision 1.10 2003/09/11 07:29:48 starvik | ||
24 | *! Merge of Linux 2.6.0-test5 | ||
25 | *! | ||
26 | *! Revision 1.9 2003/07/04 08:27:37 starvik | ||
27 | *! Merge of Linux 2.5.74 | ||
28 | *! | ||
29 | *! Revision 1.8 2003/04/09 05:20:47 starvik | ||
30 | *! Merge of Linux 2.5.67 | ||
31 | *! | ||
32 | *! Revision 1.6 2003/02/10 07:19:28 starvik | ||
33 | *! Removed misplaced ; | ||
34 | *! | ||
35 | *! Revision 1.5 2002/12/11 13:13:57 starvik | ||
36 | *! Added arch/ to v10 specific includes | ||
37 | *! Added fix from Linux 2.4 in serial.c (flush_to_flip_buffer) | ||
38 | *! | ||
39 | *! Revision 1.4 2002/11/20 11:56:10 starvik | ||
40 | *! Merge of Linux 2.5.48 | ||
41 | *! | ||
42 | *! Revision 1.3 2002/11/18 13:16:06 starvik | ||
43 | *! Linux 2.5 port of latest 2.4 drivers | ||
44 | *! | ||
45 | *! Revision 1.8 2001/06/15 13:24:29 jonashg | ||
46 | *! * Added verification of pointers from userspace in read and write. | ||
47 | *! * Made busy counter volatile. | ||
48 | *! * Added define for inital write delay. | ||
49 | *! * Removed warnings by using loff_t instead of unsigned long. | ||
50 | *! | ||
51 | *! Revision 1.7 2001/06/14 15:26:54 jonashg | ||
52 | *! Removed test because condition is always true. | ||
53 | *! | ||
54 | *! Revision 1.6 2001/06/14 15:18:20 jonashg | ||
55 | *! Kb -> kB (makes quite a difference if you don't know if you have 2k or 16k). | ||
56 | *! | ||
57 | *! Revision 1.5 2001/06/14 14:39:51 jonashg | ||
58 | *! Forgot to use name when registering the driver. | ||
59 | *! | ||
60 | *! Revision 1.4 2001/06/14 14:35:47 jonashg | ||
61 | *! * Gave driver a name and used it in printk's. | ||
62 | *! * Cleanup. | ||
63 | *! | ||
64 | *! Revision 1.3 2001/03/19 16:04:46 markusl | ||
65 | *! Fixed init of fops struct | ||
66 | *! | ||
67 | *! Revision 1.2 2001/03/19 10:35:07 markusl | ||
68 | *! 2.4 port of eeprom driver | ||
69 | *! | ||
70 | *! Revision 1.8 2000/05/18 10:42:25 edgar | ||
71 | *! Make sure to end write cycle on _every_ write | ||
72 | *! | ||
73 | *! Revision 1.7 2000/01/17 17:41:01 johana | ||
74 | *! Adjusted probing and return -ENOSPC when writing outside EEPROM | ||
75 | *! | ||
76 | *! Revision 1.6 2000/01/17 15:50:36 johana | ||
77 | *! Added adaptive timing adjustments and fixed autoprobing for 2k and 16k(?) | ||
78 | *! EEPROMs | ||
79 | *! | ||
80 | *! Revision 1.5 1999/09/03 15:07:37 edgar | ||
81 | *! Added bail-out check to the spinlock | ||
82 | *! | ||
83 | *! Revision 1.4 1999/09/03 12:11:17 bjornw | ||
84 | *! Proper atomicity (need to use spinlocks, not if's). users -> busy. | ||
85 | *! | ||
86 | *! | ||
87 | *! (c) 1999 Axis Communications AB, Lund, Sweden | ||
88 | *!*****************************************************************************/ | ||
89 | |||
90 | #include <linux/config.h> | ||
91 | #include <linux/kernel.h> | ||
92 | #include <linux/sched.h> | ||
93 | #include <linux/fs.h> | ||
94 | #include <linux/init.h> | ||
95 | #include <linux/delay.h> | ||
96 | #include <linux/interrupt.h> | ||
97 | #include <asm/uaccess.h> | ||
98 | #include "i2c.h" | ||
99 | |||
100 | #define D(x) | ||
101 | |||
102 | /* If we should use adaptive timing or not: */ | ||
103 | //#define EEPROM_ADAPTIVE_TIMING | ||
104 | |||
105 | #define EEPROM_MAJOR_NR 122 /* use a LOCAL/EXPERIMENTAL major for now */ | ||
106 | #define EEPROM_MINOR_NR 0 | ||
107 | |||
108 | /* Empirical sane initial value of the delay, the value will be adapted to | ||
109 | * what the chip needs when using EEPROM_ADAPTIVE_TIMING. | ||
110 | */ | ||
111 | #define INITIAL_WRITEDELAY_US 4000 | ||
112 | #define MAX_WRITEDELAY_US 10000 /* 10 ms according to spec for 2KB EEPROM */ | ||
113 | |||
114 | /* This one defines how many times to try when eeprom fails. */ | ||
115 | #define EEPROM_RETRIES 10 | ||
116 | |||
117 | #define EEPROM_2KB (2 * 1024) | ||
118 | /*#define EEPROM_4KB (4 * 1024)*/ /* Exists but not used in Axis products */ | ||
119 | #define EEPROM_8KB (8 * 1024 - 1 ) /* Last byte has write protection bit */ | ||
120 | #define EEPROM_16KB (16 * 1024) | ||
121 | |||
122 | #define i2c_delay(x) udelay(x) | ||
123 | |||
124 | /* | ||
125 | * This structure describes the attached eeprom chip. | ||
126 | * The values are probed for. | ||
127 | */ | ||
128 | |||
129 | struct eeprom_type | ||
130 | { | ||
131 | unsigned long size; | ||
132 | unsigned long sequential_write_pagesize; | ||
133 | unsigned char select_cmd; | ||
134 | unsigned long usec_delay_writecycles; /* Min time between write cycles | ||
135 | (up to 10ms for some models) */ | ||
136 | unsigned long usec_delay_step; /* For adaptive algorithm */ | ||
137 | int adapt_state; /* 1 = To high , 0 = Even, -1 = To low */ | ||
138 | |||
139 | /* this one is to keep the read/write operations atomic */ | ||
140 | wait_queue_head_t wait_q; | ||
141 | volatile int busy; | ||
142 | int retry_cnt_addr; /* Used to keep track of number of retries for | ||
143 | adaptive timing adjustments */ | ||
144 | int retry_cnt_read; | ||
145 | }; | ||
146 | |||
147 | static int eeprom_open(struct inode * inode, struct file * file); | ||
148 | static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig); | ||
149 | static ssize_t eeprom_read(struct file * file, char * buf, size_t count, | ||
150 | loff_t *off); | ||
151 | static ssize_t eeprom_write(struct file * file, const char * buf, size_t count, | ||
152 | loff_t *off); | ||
153 | static int eeprom_close(struct inode * inode, struct file * file); | ||
154 | |||
155 | static int eeprom_address(unsigned long addr); | ||
156 | static int read_from_eeprom(char * buf, int count); | ||
157 | static int eeprom_write_buf(loff_t addr, const char * buf, int count); | ||
158 | static int eeprom_read_buf(loff_t addr, char * buf, int count); | ||
159 | |||
160 | static void eeprom_disable_write_protect(void); | ||
161 | |||
162 | |||
163 | static const char eeprom_name[] = "eeprom"; | ||
164 | |||
165 | /* chip description */ | ||
166 | static struct eeprom_type eeprom; | ||
167 | |||
168 | /* This is the exported file-operations structure for this device. */ | ||
169 | struct file_operations eeprom_fops = | ||
170 | { | ||
171 | .llseek = eeprom_lseek, | ||
172 | .read = eeprom_read, | ||
173 | .write = eeprom_write, | ||
174 | .open = eeprom_open, | ||
175 | .release = eeprom_close | ||
176 | }; | ||
177 | |||
178 | /* eeprom init call. Probes for different eeprom models. */ | ||
179 | |||
180 | int __init eeprom_init(void) | ||
181 | { | ||
182 | init_waitqueue_head(&eeprom.wait_q); | ||
183 | eeprom.busy = 0; | ||
184 | |||
185 | #ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE | ||
186 | #define EETEXT "Found" | ||
187 | #else | ||
188 | #define EETEXT "Assuming" | ||
189 | #endif | ||
190 | if (register_chrdev(EEPROM_MAJOR_NR, eeprom_name, &eeprom_fops)) | ||
191 | { | ||
192 | printk(KERN_INFO "%s: unable to get major %d for eeprom device\n", | ||
193 | eeprom_name, EEPROM_MAJOR_NR); | ||
194 | return -1; | ||
195 | } | ||
196 | |||
197 | printk("EEPROM char device v0.3, (c) 2000 Axis Communications AB\n"); | ||
198 | |||
199 | /* | ||
200 | * Note: Most of this probing method was taken from the printserver (5470e) | ||
201 | * codebase. It did not contain a way of finding the 16kB chips | ||
202 | * (M24128 or variants). The method used here might not work | ||
203 | * for all models. If you encounter problems the easiest way | ||
204 | * is probably to define your model within #ifdef's, and hard- | ||
205 | * code it. | ||
206 | */ | ||
207 | |||
208 | eeprom.size = 0; | ||
209 | eeprom.usec_delay_writecycles = INITIAL_WRITEDELAY_US; | ||
210 | eeprom.usec_delay_step = 128; | ||
211 | eeprom.adapt_state = 0; | ||
212 | |||
213 | #ifdef CONFIG_ETRAX_I2C_EEPROM_PROBE | ||
214 | i2c_start(); | ||
215 | i2c_outbyte(0x80); | ||
216 | if(!i2c_getack()) | ||
217 | { | ||
218 | /* It's not 8k.. */ | ||
219 | int success = 0; | ||
220 | unsigned char buf_2k_start[16]; | ||
221 | |||
222 | /* Im not sure this will work... :) */ | ||
223 | /* assume 2kB, if failure go for 16kB */ | ||
224 | /* Test with 16kB settings.. */ | ||
225 | /* If it's a 2kB EEPROM and we address it outside it's range | ||
226 | * it will mirror the address space: | ||
227 | * 1. We read two locations (that are mirrored), | ||
228 | * if the content differs * it's a 16kB EEPROM. | ||
229 | * 2. if it doesn't differ - write different value to one of the locations, | ||
230 | * check the other - if content still is the same it's a 2k EEPROM, | ||
231 | * restore original data. | ||
232 | */ | ||
233 | #define LOC1 8 | ||
234 | #define LOC2 (0x1fb) /*1fb, 3ed, 5df, 7d1 */ | ||
235 | |||
236 | /* 2k settings */ | ||
237 | i2c_stop(); | ||
238 | eeprom.size = EEPROM_2KB; | ||
239 | eeprom.select_cmd = 0xA0; | ||
240 | eeprom.sequential_write_pagesize = 16; | ||
241 | if( eeprom_read_buf( 0, buf_2k_start, 16 ) == 16 ) | ||
242 | { | ||
243 | D(printk("2k start: '%16.16s'\n", buf_2k_start)); | ||
244 | } | ||
245 | else | ||
246 | { | ||
247 | printk(KERN_INFO "%s: Failed to read in 2k mode!\n", eeprom_name); | ||
248 | } | ||
249 | |||
250 | /* 16k settings */ | ||
251 | eeprom.size = EEPROM_16KB; | ||
252 | eeprom.select_cmd = 0xA0; | ||
253 | eeprom.sequential_write_pagesize = 64; | ||
254 | |||
255 | { | ||
256 | unsigned char loc1[4], loc2[4], tmp[4]; | ||
257 | if( eeprom_read_buf(LOC2, loc2, 4) == 4) | ||
258 | { | ||
259 | if( eeprom_read_buf(LOC1, loc1, 4) == 4) | ||
260 | { | ||
261 | D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", | ||
262 | LOC1, loc1, LOC2, loc2)); | ||
263 | #if 0 | ||
264 | if (memcmp(loc1, loc2, 4) != 0 ) | ||
265 | { | ||
266 | /* It's 16k */ | ||
267 | printk(KERN_INFO "%s: 16k detected in step 1\n", eeprom_name); | ||
268 | eeprom.size = EEPROM_16KB; | ||
269 | success = 1; | ||
270 | } | ||
271 | else | ||
272 | #endif | ||
273 | { | ||
274 | /* Do step 2 check */ | ||
275 | /* Invert value */ | ||
276 | loc1[0] = ~loc1[0]; | ||
277 | if (eeprom_write_buf(LOC1, loc1, 1) == 1) | ||
278 | { | ||
279 | /* If 2k EEPROM this write will actually write 10 bytes | ||
280 | * from pos 0 | ||
281 | */ | ||
282 | D(printk("1 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", | ||
283 | LOC1, loc1, LOC2, loc2)); | ||
284 | if( eeprom_read_buf(LOC1, tmp, 4) == 4) | ||
285 | { | ||
286 | D(printk("2 loc1: (%i) '%4.4s' tmp '%4.4s'\n", | ||
287 | LOC1, loc1, tmp)); | ||
288 | if (memcmp(loc1, tmp, 4) != 0 ) | ||
289 | { | ||
290 | printk(KERN_INFO "%s: read and write differs! Not 16kB\n", | ||
291 | eeprom_name); | ||
292 | loc1[0] = ~loc1[0]; | ||
293 | |||
294 | if (eeprom_write_buf(LOC1, loc1, 1) == 1) | ||
295 | { | ||
296 | success = 1; | ||
297 | } | ||
298 | else | ||
299 | { | ||
300 | printk(KERN_INFO "%s: Restore 2k failed during probe," | ||
301 | " EEPROM might be corrupt!\n", eeprom_name); | ||
302 | |||
303 | } | ||
304 | i2c_stop(); | ||
305 | /* Go to 2k mode and write original data */ | ||
306 | eeprom.size = EEPROM_2KB; | ||
307 | eeprom.select_cmd = 0xA0; | ||
308 | eeprom.sequential_write_pagesize = 16; | ||
309 | if( eeprom_write_buf(0, buf_2k_start, 16) == 16) | ||
310 | { | ||
311 | } | ||
312 | else | ||
313 | { | ||
314 | printk(KERN_INFO "%s: Failed to write back 2k start!\n", | ||
315 | eeprom_name); | ||
316 | } | ||
317 | |||
318 | eeprom.size = EEPROM_2KB; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | if(!success) | ||
323 | { | ||
324 | if( eeprom_read_buf(LOC2, loc2, 1) == 1) | ||
325 | { | ||
326 | D(printk("0 loc1: (%i) '%4.4s' loc2 (%i) '%4.4s'\n", | ||
327 | LOC1, loc1, LOC2, loc2)); | ||
328 | if (memcmp(loc1, loc2, 4) == 0 ) | ||
329 | { | ||
330 | /* Data the same, must be mirrored -> 2k */ | ||
331 | /* Restore data */ | ||
332 | printk(KERN_INFO "%s: 2k detected in step 2\n", eeprom_name); | ||
333 | loc1[0] = ~loc1[0]; | ||
334 | if (eeprom_write_buf(LOC1, loc1, 1) == 1) | ||
335 | { | ||
336 | success = 1; | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | printk(KERN_INFO "%s: Restore 2k failed during probe," | ||
341 | " EEPROM might be corrupt!\n", eeprom_name); | ||
342 | |||
343 | } | ||
344 | |||
345 | eeprom.size = EEPROM_2KB; | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | printk(KERN_INFO "%s: 16k detected in step 2\n", | ||
350 | eeprom_name); | ||
351 | loc1[0] = ~loc1[0]; | ||
352 | /* Data differs, assume 16k */ | ||
353 | /* Restore data */ | ||
354 | if (eeprom_write_buf(LOC1, loc1, 1) == 1) | ||
355 | { | ||
356 | success = 1; | ||
357 | } | ||
358 | else | ||
359 | { | ||
360 | printk(KERN_INFO "%s: Restore 16k failed during probe," | ||
361 | " EEPROM might be corrupt!\n", eeprom_name); | ||
362 | } | ||
363 | |||
364 | eeprom.size = EEPROM_16KB; | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | } | ||
369 | } /* read LOC1 */ | ||
370 | } /* address LOC1 */ | ||
371 | if (!success) | ||
372 | { | ||
373 | printk(KERN_INFO "%s: Probing failed!, using 2KB!\n", eeprom_name); | ||
374 | eeprom.size = EEPROM_2KB; | ||
375 | } | ||
376 | } /* read */ | ||
377 | } | ||
378 | } | ||
379 | else | ||
380 | { | ||
381 | i2c_outbyte(0x00); | ||
382 | if(!i2c_getack()) | ||
383 | { | ||
384 | /* No 8k */ | ||
385 | eeprom.size = EEPROM_2KB; | ||
386 | } | ||
387 | else | ||
388 | { | ||
389 | i2c_start(); | ||
390 | i2c_outbyte(0x81); | ||
391 | if (!i2c_getack()) | ||
392 | { | ||
393 | eeprom.size = EEPROM_2KB; | ||
394 | } | ||
395 | else | ||
396 | { | ||
397 | /* It's a 8kB */ | ||
398 | i2c_inbyte(); | ||
399 | eeprom.size = EEPROM_8KB; | ||
400 | } | ||
401 | } | ||
402 | } | ||
403 | i2c_stop(); | ||
404 | #elif defined(CONFIG_ETRAX_I2C_EEPROM_16KB) | ||
405 | eeprom.size = EEPROM_16KB; | ||
406 | #elif defined(CONFIG_ETRAX_I2C_EEPROM_8KB) | ||
407 | eeprom.size = EEPROM_8KB; | ||
408 | #elif defined(CONFIG_ETRAX_I2C_EEPROM_2KB) | ||
409 | eeprom.size = EEPROM_2KB; | ||
410 | #endif | ||
411 | |||
412 | switch(eeprom.size) | ||
413 | { | ||
414 | case (EEPROM_2KB): | ||
415 | printk("%s: " EETEXT " i2c compatible 2kB eeprom.\n", eeprom_name); | ||
416 | eeprom.sequential_write_pagesize = 16; | ||
417 | eeprom.select_cmd = 0xA0; | ||
418 | break; | ||
419 | case (EEPROM_8KB): | ||
420 | printk("%s: " EETEXT " i2c compatible 8kB eeprom.\n", eeprom_name); | ||
421 | eeprom.sequential_write_pagesize = 16; | ||
422 | eeprom.select_cmd = 0x80; | ||
423 | break; | ||
424 | case (EEPROM_16KB): | ||
425 | printk("%s: " EETEXT " i2c compatible 16kB eeprom.\n", eeprom_name); | ||
426 | eeprom.sequential_write_pagesize = 64; | ||
427 | eeprom.select_cmd = 0xA0; | ||
428 | break; | ||
429 | default: | ||
430 | eeprom.size = 0; | ||
431 | printk("%s: Did not find a supported eeprom\n", eeprom_name); | ||
432 | break; | ||
433 | } | ||
434 | |||
435 | |||
436 | |||
437 | eeprom_disable_write_protect(); | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | /* Opens the device. */ | ||
443 | |||
444 | static int eeprom_open(struct inode * inode, struct file * file) | ||
445 | { | ||
446 | |||
447 | if(MINOR(inode->i_rdev) != EEPROM_MINOR_NR) | ||
448 | return -ENXIO; | ||
449 | if(MAJOR(inode->i_rdev) != EEPROM_MAJOR_NR) | ||
450 | return -ENXIO; | ||
451 | |||
452 | if( eeprom.size > 0 ) | ||
453 | { | ||
454 | /* OK */ | ||
455 | return 0; | ||
456 | } | ||
457 | |||
458 | /* No EEprom found */ | ||
459 | return -EFAULT; | ||
460 | } | ||
461 | |||
462 | /* Changes the current file position. */ | ||
463 | |||
464 | static loff_t eeprom_lseek(struct file * file, loff_t offset, int orig) | ||
465 | { | ||
466 | /* | ||
467 | * orig 0: position from begning of eeprom | ||
468 | * orig 1: relative from current position | ||
469 | * orig 2: position from last eeprom address | ||
470 | */ | ||
471 | |||
472 | switch (orig) | ||
473 | { | ||
474 | case 0: | ||
475 | file->f_pos = offset; | ||
476 | break; | ||
477 | case 1: | ||
478 | file->f_pos += offset; | ||
479 | break; | ||
480 | case 2: | ||
481 | file->f_pos = eeprom.size - offset; | ||
482 | break; | ||
483 | default: | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | /* truncate position */ | ||
488 | if (file->f_pos < 0) | ||
489 | { | ||
490 | file->f_pos = 0; | ||
491 | return(-EOVERFLOW); | ||
492 | } | ||
493 | |||
494 | if (file->f_pos >= eeprom.size) | ||
495 | { | ||
496 | file->f_pos = eeprom.size - 1; | ||
497 | return(-EOVERFLOW); | ||
498 | } | ||
499 | |||
500 | return ( file->f_pos ); | ||
501 | } | ||
502 | |||
503 | /* Reads data from eeprom. */ | ||
504 | |||
505 | static int eeprom_read_buf(loff_t addr, char * buf, int count) | ||
506 | { | ||
507 | struct file f; | ||
508 | |||
509 | f.f_pos = addr; | ||
510 | return eeprom_read(&f, buf, count, &addr); | ||
511 | } | ||
512 | |||
513 | |||
514 | |||
515 | /* Reads data from eeprom. */ | ||
516 | |||
517 | static ssize_t eeprom_read(struct file * file, char * buf, size_t count, loff_t *off) | ||
518 | { | ||
519 | int read=0; | ||
520 | unsigned long p = file->f_pos; | ||
521 | |||
522 | unsigned char page; | ||
523 | |||
524 | if(p >= eeprom.size) /* Address i 0 - (size-1) */ | ||
525 | { | ||
526 | return -EFAULT; | ||
527 | } | ||
528 | |||
529 | while(eeprom.busy) | ||
530 | { | ||
531 | interruptible_sleep_on(&eeprom.wait_q); | ||
532 | |||
533 | /* bail out if we get interrupted */ | ||
534 | if (signal_pending(current)) | ||
535 | return -EINTR; | ||
536 | |||
537 | } | ||
538 | eeprom.busy++; | ||
539 | |||
540 | page = (unsigned char) (p >> 8); | ||
541 | |||
542 | if(!eeprom_address(p)) | ||
543 | { | ||
544 | printk(KERN_INFO "%s: Read failed to address the eeprom: " | ||
545 | "0x%08X (%i) page: %i\n", eeprom_name, (int)p, (int)p, page); | ||
546 | i2c_stop(); | ||
547 | |||
548 | /* don't forget to wake them up */ | ||
549 | eeprom.busy--; | ||
550 | wake_up_interruptible(&eeprom.wait_q); | ||
551 | return -EFAULT; | ||
552 | } | ||
553 | |||
554 | if( (p + count) > eeprom.size) | ||
555 | { | ||
556 | /* truncate count */ | ||
557 | count = eeprom.size - p; | ||
558 | } | ||
559 | |||
560 | /* stop dummy write op and initiate the read op */ | ||
561 | i2c_start(); | ||
562 | |||
563 | /* special case for small eeproms */ | ||
564 | if(eeprom.size < EEPROM_16KB) | ||
565 | { | ||
566 | i2c_outbyte( eeprom.select_cmd | 1 | (page << 1) ); | ||
567 | } | ||
568 | |||
569 | /* go on with the actual read */ | ||
570 | read = read_from_eeprom( buf, count); | ||
571 | |||
572 | if(read > 0) | ||
573 | { | ||
574 | file->f_pos += read; | ||
575 | } | ||
576 | |||
577 | eeprom.busy--; | ||
578 | wake_up_interruptible(&eeprom.wait_q); | ||
579 | return read; | ||
580 | } | ||
581 | |||
582 | /* Writes data to eeprom. */ | ||
583 | |||
584 | static int eeprom_write_buf(loff_t addr, const char * buf, int count) | ||
585 | { | ||
586 | struct file f; | ||
587 | |||
588 | f.f_pos = addr; | ||
589 | |||
590 | return eeprom_write(&f, buf, count, &addr); | ||
591 | } | ||
592 | |||
593 | |||
594 | /* Writes data to eeprom. */ | ||
595 | |||
596 | static ssize_t eeprom_write(struct file * file, const char * buf, size_t count, | ||
597 | loff_t *off) | ||
598 | { | ||
599 | int i, written, restart=1; | ||
600 | unsigned long p; | ||
601 | |||
602 | if (!access_ok(VERIFY_READ, buf, count)) | ||
603 | { | ||
604 | return -EFAULT; | ||
605 | } | ||
606 | |||
607 | while(eeprom.busy) | ||
608 | { | ||
609 | interruptible_sleep_on(&eeprom.wait_q); | ||
610 | /* bail out if we get interrupted */ | ||
611 | if (signal_pending(current)) | ||
612 | return -EINTR; | ||
613 | } | ||
614 | eeprom.busy++; | ||
615 | for(i = 0; (i < EEPROM_RETRIES) && (restart > 0); i++) | ||
616 | { | ||
617 | restart = 0; | ||
618 | written = 0; | ||
619 | p = file->f_pos; | ||
620 | |||
621 | |||
622 | while( (written < count) && (p < eeprom.size)) | ||
623 | { | ||
624 | /* address the eeprom */ | ||
625 | if(!eeprom_address(p)) | ||
626 | { | ||
627 | printk(KERN_INFO "%s: Write failed to address the eeprom: " | ||
628 | "0x%08X (%i) \n", eeprom_name, (int)p, (int)p); | ||
629 | i2c_stop(); | ||
630 | |||
631 | /* don't forget to wake them up */ | ||
632 | eeprom.busy--; | ||
633 | wake_up_interruptible(&eeprom.wait_q); | ||
634 | return -EFAULT; | ||
635 | } | ||
636 | #ifdef EEPROM_ADAPTIVE_TIMING | ||
637 | /* Adaptive algorithm to adjust timing */ | ||
638 | if (eeprom.retry_cnt_addr > 0) | ||
639 | { | ||
640 | /* To Low now */ | ||
641 | D(printk(">D=%i d=%i\n", | ||
642 | eeprom.usec_delay_writecycles, eeprom.usec_delay_step)); | ||
643 | |||
644 | if (eeprom.usec_delay_step < 4) | ||
645 | { | ||
646 | eeprom.usec_delay_step++; | ||
647 | eeprom.usec_delay_writecycles += eeprom.usec_delay_step; | ||
648 | } | ||
649 | else | ||
650 | { | ||
651 | |||
652 | if (eeprom.adapt_state > 0) | ||
653 | { | ||
654 | /* To Low before */ | ||
655 | eeprom.usec_delay_step *= 2; | ||
656 | if (eeprom.usec_delay_step > 2) | ||
657 | { | ||
658 | eeprom.usec_delay_step--; | ||
659 | } | ||
660 | eeprom.usec_delay_writecycles += eeprom.usec_delay_step; | ||
661 | } | ||
662 | else if (eeprom.adapt_state < 0) | ||
663 | { | ||
664 | /* To High before (toggle dir) */ | ||
665 | eeprom.usec_delay_writecycles += eeprom.usec_delay_step; | ||
666 | if (eeprom.usec_delay_step > 1) | ||
667 | { | ||
668 | eeprom.usec_delay_step /= 2; | ||
669 | eeprom.usec_delay_step--; | ||
670 | } | ||
671 | } | ||
672 | } | ||
673 | |||
674 | eeprom.adapt_state = 1; | ||
675 | } | ||
676 | else | ||
677 | { | ||
678 | /* To High (or good) now */ | ||
679 | D(printk("<D=%i d=%i\n", | ||
680 | eeprom.usec_delay_writecycles, eeprom.usec_delay_step)); | ||
681 | |||
682 | if (eeprom.adapt_state < 0) | ||
683 | { | ||
684 | /* To High before */ | ||
685 | if (eeprom.usec_delay_step > 1) | ||
686 | { | ||
687 | eeprom.usec_delay_step *= 2; | ||
688 | eeprom.usec_delay_step--; | ||
689 | |||
690 | if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step) | ||
691 | { | ||
692 | eeprom.usec_delay_writecycles -= eeprom.usec_delay_step; | ||
693 | } | ||
694 | } | ||
695 | } | ||
696 | else if (eeprom.adapt_state > 0) | ||
697 | { | ||
698 | /* To Low before (toggle dir) */ | ||
699 | if (eeprom.usec_delay_writecycles > eeprom.usec_delay_step) | ||
700 | { | ||
701 | eeprom.usec_delay_writecycles -= eeprom.usec_delay_step; | ||
702 | } | ||
703 | if (eeprom.usec_delay_step > 1) | ||
704 | { | ||
705 | eeprom.usec_delay_step /= 2; | ||
706 | eeprom.usec_delay_step--; | ||
707 | } | ||
708 | |||
709 | eeprom.adapt_state = -1; | ||
710 | } | ||
711 | |||
712 | if (eeprom.adapt_state > -100) | ||
713 | { | ||
714 | eeprom.adapt_state--; | ||
715 | } | ||
716 | else | ||
717 | { | ||
718 | /* Restart adaption */ | ||
719 | D(printk("#Restart\n")); | ||
720 | eeprom.usec_delay_step++; | ||
721 | } | ||
722 | } | ||
723 | #endif /* EEPROM_ADAPTIVE_TIMING */ | ||
724 | /* write until we hit a page boundary or count */ | ||
725 | do | ||
726 | { | ||
727 | i2c_outbyte(buf[written]); | ||
728 | if(!i2c_getack()) | ||
729 | { | ||
730 | restart=1; | ||
731 | printk(KERN_INFO "%s: write error, retrying. %d\n", eeprom_name, i); | ||
732 | i2c_stop(); | ||
733 | break; | ||
734 | } | ||
735 | written++; | ||
736 | p++; | ||
737 | } while( written < count && ( p % eeprom.sequential_write_pagesize )); | ||
738 | |||
739 | /* end write cycle */ | ||
740 | i2c_stop(); | ||
741 | i2c_delay(eeprom.usec_delay_writecycles); | ||
742 | } /* while */ | ||
743 | } /* for */ | ||
744 | |||
745 | eeprom.busy--; | ||
746 | wake_up_interruptible(&eeprom.wait_q); | ||
747 | if (written == 0 && file->f_pos >= eeprom.size){ | ||
748 | return -ENOSPC; | ||
749 | } | ||
750 | file->f_pos += written; | ||
751 | return written; | ||
752 | } | ||
753 | |||
754 | /* Closes the device. */ | ||
755 | |||
756 | static int eeprom_close(struct inode * inode, struct file * file) | ||
757 | { | ||
758 | /* do nothing for now */ | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | /* Sets the current address of the eeprom. */ | ||
763 | |||
764 | static int eeprom_address(unsigned long addr) | ||
765 | { | ||
766 | int i; | ||
767 | unsigned char page, offset; | ||
768 | |||
769 | page = (unsigned char) (addr >> 8); | ||
770 | offset = (unsigned char) addr; | ||
771 | |||
772 | for(i = 0; i < EEPROM_RETRIES; i++) | ||
773 | { | ||
774 | /* start a dummy write for addressing */ | ||
775 | i2c_start(); | ||
776 | |||
777 | if(eeprom.size == EEPROM_16KB) | ||
778 | { | ||
779 | i2c_outbyte( eeprom.select_cmd ); | ||
780 | i2c_getack(); | ||
781 | i2c_outbyte(page); | ||
782 | } | ||
783 | else | ||
784 | { | ||
785 | i2c_outbyte( eeprom.select_cmd | (page << 1) ); | ||
786 | } | ||
787 | if(!i2c_getack()) | ||
788 | { | ||
789 | /* retry */ | ||
790 | i2c_stop(); | ||
791 | /* Must have a delay here.. 500 works, >50, 100->works 5th time*/ | ||
792 | i2c_delay(MAX_WRITEDELAY_US / EEPROM_RETRIES * i); | ||
793 | /* The chip needs up to 10 ms from write stop to next start */ | ||
794 | |||
795 | } | ||
796 | else | ||
797 | { | ||
798 | i2c_outbyte(offset); | ||
799 | |||
800 | if(!i2c_getack()) | ||
801 | { | ||
802 | /* retry */ | ||
803 | i2c_stop(); | ||
804 | } | ||
805 | else | ||
806 | break; | ||
807 | } | ||
808 | } | ||
809 | |||
810 | |||
811 | eeprom.retry_cnt_addr = i; | ||
812 | D(printk("%i\n", eeprom.retry_cnt_addr)); | ||
813 | if(eeprom.retry_cnt_addr == EEPROM_RETRIES) | ||
814 | { | ||
815 | /* failed */ | ||
816 | return 0; | ||
817 | } | ||
818 | return 1; | ||
819 | } | ||
820 | |||
821 | /* Reads from current address. */ | ||
822 | |||
823 | static int read_from_eeprom(char * buf, int count) | ||
824 | { | ||
825 | int i, read=0; | ||
826 | |||
827 | for(i = 0; i < EEPROM_RETRIES; i++) | ||
828 | { | ||
829 | if(eeprom.size == EEPROM_16KB) | ||
830 | { | ||
831 | i2c_outbyte( eeprom.select_cmd | 1 ); | ||
832 | } | ||
833 | |||
834 | if(i2c_getack()) | ||
835 | { | ||
836 | break; | ||
837 | } | ||
838 | } | ||
839 | |||
840 | if(i == EEPROM_RETRIES) | ||
841 | { | ||
842 | printk(KERN_INFO "%s: failed to read from eeprom\n", eeprom_name); | ||
843 | i2c_stop(); | ||
844 | |||
845 | return -EFAULT; | ||
846 | } | ||
847 | |||
848 | while( (read < count)) | ||
849 | { | ||
850 | if (put_user(i2c_inbyte(), &buf[read++])) | ||
851 | { | ||
852 | i2c_stop(); | ||
853 | |||
854 | return -EFAULT; | ||
855 | } | ||
856 | |||
857 | /* | ||
858 | * make sure we don't ack last byte or you will get very strange | ||
859 | * results! | ||
860 | */ | ||
861 | if(read < count) | ||
862 | { | ||
863 | i2c_sendack(); | ||
864 | } | ||
865 | } | ||
866 | |||
867 | /* stop the operation */ | ||
868 | i2c_stop(); | ||
869 | |||
870 | return read; | ||
871 | } | ||
872 | |||
873 | /* Disables write protection if applicable. */ | ||
874 | |||
875 | #define DBP_SAVE(x) | ||
876 | #define ax_printf printk | ||
877 | static void eeprom_disable_write_protect(void) | ||
878 | { | ||
879 | /* Disable write protect */ | ||
880 | if (eeprom.size == EEPROM_8KB) | ||
881 | { | ||
882 | /* Step 1 Set WEL = 1 (write 00000010 to address 1FFFh */ | ||
883 | i2c_start(); | ||
884 | i2c_outbyte(0xbe); | ||
885 | if(!i2c_getack()) | ||
886 | { | ||
887 | DBP_SAVE(ax_printf("Get ack returns false\n")); | ||
888 | } | ||
889 | i2c_outbyte(0xFF); | ||
890 | if(!i2c_getack()) | ||
891 | { | ||
892 | DBP_SAVE(ax_printf("Get ack returns false 2\n")); | ||
893 | } | ||
894 | i2c_outbyte(0x02); | ||
895 | if(!i2c_getack()) | ||
896 | { | ||
897 | DBP_SAVE(ax_printf("Get ack returns false 3\n")); | ||
898 | } | ||
899 | i2c_stop(); | ||
900 | |||
901 | i2c_delay(1000); | ||
902 | |||
903 | /* Step 2 Set RWEL = 1 (write 00000110 to address 1FFFh */ | ||
904 | i2c_start(); | ||
905 | i2c_outbyte(0xbe); | ||
906 | if(!i2c_getack()) | ||
907 | { | ||
908 | DBP_SAVE(ax_printf("Get ack returns false 55\n")); | ||
909 | } | ||
910 | i2c_outbyte(0xFF); | ||
911 | if(!i2c_getack()) | ||
912 | { | ||
913 | DBP_SAVE(ax_printf("Get ack returns false 52\n")); | ||
914 | } | ||
915 | i2c_outbyte(0x06); | ||
916 | if(!i2c_getack()) | ||
917 | { | ||
918 | DBP_SAVE(ax_printf("Get ack returns false 53\n")); | ||
919 | } | ||
920 | i2c_stop(); | ||
921 | |||
922 | /* Step 3 Set BP1, BP0, and/or WPEN bits (write 00000110 to address 1FFFh */ | ||
923 | i2c_start(); | ||
924 | i2c_outbyte(0xbe); | ||
925 | if(!i2c_getack()) | ||
926 | { | ||
927 | DBP_SAVE(ax_printf("Get ack returns false 56\n")); | ||
928 | } | ||
929 | i2c_outbyte(0xFF); | ||
930 | if(!i2c_getack()) | ||
931 | { | ||
932 | DBP_SAVE(ax_printf("Get ack returns false 57\n")); | ||
933 | } | ||
934 | i2c_outbyte(0x06); | ||
935 | if(!i2c_getack()) | ||
936 | { | ||
937 | DBP_SAVE(ax_printf("Get ack returns false 58\n")); | ||
938 | } | ||
939 | i2c_stop(); | ||
940 | |||
941 | /* Write protect disabled */ | ||
942 | } | ||
943 | } | ||
944 | |||
945 | module_init(eeprom_init); | ||