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