Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
[pandora-kernel.git] / drivers / staging / ath6kl / os / linux / eeprom.c
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2004-2010 Atheros Communications Inc.
3 // All rights reserved.
4 //
5 // 
6 //
7 // Permission to use, copy, modify, and/or distribute this software for any
8 // purpose with or without fee is hereby granted, provided that the above
9 // copyright notice and this permission notice appear in all copies.
10 //
11 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 //
19 //
20 //
21 // Author(s): ="Atheros"
22 //------------------------------------------------------------------------------
23
24
25 #include "ar6000_drv.h"
26 #include "htc.h"
27 #include <linux/fs.h>
28
29 #include "AR6002/hw2.0/hw/gpio_reg.h"
30 #include "AR6002/hw2.0/hw/si_reg.h"
31
32 //
33 // defines
34 //
35
36 #define MAX_FILENAME 1023
37 #define EEPROM_WAIT_LIMIT 16 
38
39 #define HOST_INTEREST_ITEM_ADDRESS(item)          \
40         (AR6002_HOST_INTEREST_ITEM_ADDRESS(item))
41
42 #define EEPROM_SZ 768
43
44 /* soft mac */
45 #define ATH_MAC_LEN                         6
46 #define ATH_SOFT_MAC_TMP_BUF_LEN            64
47 unsigned char mac_addr[ATH_MAC_LEN];
48 unsigned char soft_mac_tmp_buf[ATH_SOFT_MAC_TMP_BUF_LEN];
49 char *p_mac = NULL;
50 /* soft mac */
51
52 //
53 // static variables
54 //
55
56 static A_UCHAR eeprom_data[EEPROM_SZ];
57 static A_UINT32 sys_sleep_reg;
58 static HIF_DEVICE *p_bmi_device;
59
60 //
61 // Functions
62 //
63
64 /* soft mac */
65 static int
66 wmic_ether_aton(const char *orig, A_UINT8 *eth)
67 {
68   const char *bufp;
69   int i;
70
71   i = 0;
72   for(bufp = orig; *bufp != '\0'; ++bufp) {
73     unsigned int val;
74         int h, l;
75
76         h = hex_to_bin(*bufp++);
77
78         if (h < 0) {
79                 printk("%s: MAC value is invalid\n", __FUNCTION__);
80                 break;
81         }
82
83         l = hex_to_bin(*bufp++);
84         if (l < 0) {
85                 printk("%s: MAC value is invalid\n", __FUNCTION__);
86                 break;
87         }
88
89         val = (h << 4) | l;
90
91     eth[i] = (unsigned char) (val & 0377);
92     if(++i == ATH_MAC_LEN) {
93             /* That's it.  Any trailing junk? */
94             if (*bufp != '\0') {
95                     return 0;
96             }
97             return 1;
98     }
99     if (*bufp != ':')
100             break;
101   }
102   return 0;
103 }
104
105 static void
106 update_mac(unsigned char* eeprom, int size, unsigned char* macaddr)
107 {
108         int i;
109         A_UINT16* ptr = (A_UINT16*)(eeprom+4);
110         A_UINT16  checksum = 0;
111
112         memcpy(eeprom+10,macaddr,6);
113
114         *ptr = 0;
115         ptr = (A_UINT16*)eeprom;
116
117         for (i=0; i<size; i+=2) {
118                 checksum ^= *ptr++;
119         }
120         checksum = ~checksum;
121
122         ptr = (A_UINT16*)(eeprom+4);
123         *ptr = checksum;
124         return;
125 }
126 /* soft mac */
127
128 /* Read a Target register and return its value. */
129 inline void
130 BMI_read_reg(A_UINT32 address, A_UINT32 *pvalue)
131 {
132     BMIReadSOCRegister(p_bmi_device, address, pvalue);
133 }
134
135 /* Write a value to a Target register. */
136 inline void
137 BMI_write_reg(A_UINT32 address, A_UINT32 value)
138 {
139     BMIWriteSOCRegister(p_bmi_device, address, value);
140 }
141
142 /* Read Target memory word and return its value. */
143 inline void
144 BMI_read_mem(A_UINT32 address, A_UINT32 *pvalue)
145 {
146     BMIReadMemory(p_bmi_device, address, (A_UCHAR*)(pvalue), 4);
147 }
148
149 /* Write a word to a Target memory. */
150 inline void
151 BMI_write_mem(A_UINT32 address, A_UINT8 *p_data, A_UINT32 sz)
152 {
153     BMIWriteMemory(p_bmi_device, address, (A_UCHAR*)(p_data), sz); 
154 }
155
156 /*
157  * Enable and configure the Target's Serial Interface
158  * so we can access the EEPROM.
159  */
160 static void
161 enable_SI(HIF_DEVICE *p_device)
162 {
163     A_UINT32 regval;
164
165     printk("%s\n", __FUNCTION__);
166
167     p_bmi_device = p_device;
168
169     BMI_read_reg(RTC_BASE_ADDRESS+SYSTEM_SLEEP_OFFSET, &sys_sleep_reg);
170     BMI_write_reg(RTC_BASE_ADDRESS+SYSTEM_SLEEP_OFFSET, SYSTEM_SLEEP_DISABLE_SET(1)); //disable system sleep temporarily
171
172     BMI_read_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, &regval);
173     regval &= ~CLOCK_CONTROL_SI0_CLK_MASK;
174     BMI_write_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, regval);
175
176     BMI_read_reg(RTC_BASE_ADDRESS+RESET_CONTROL_OFFSET, &regval);
177     regval &= ~RESET_CONTROL_SI0_RST_MASK;
178     BMI_write_reg(RTC_BASE_ADDRESS+RESET_CONTROL_OFFSET, regval);
179
180
181     BMI_read_reg(GPIO_BASE_ADDRESS+GPIO_PIN0_OFFSET, &regval);
182     regval &= ~GPIO_PIN0_CONFIG_MASK;
183     BMI_write_reg(GPIO_BASE_ADDRESS+GPIO_PIN0_OFFSET, regval);
184
185     BMI_read_reg(GPIO_BASE_ADDRESS+GPIO_PIN1_OFFSET, &regval);
186     regval &= ~GPIO_PIN1_CONFIG_MASK;
187     BMI_write_reg(GPIO_BASE_ADDRESS+GPIO_PIN1_OFFSET, regval);
188
189     /* SI_CONFIG = 0x500a6; */
190     regval =    SI_CONFIG_BIDIR_OD_DATA_SET(1)  |
191                 SI_CONFIG_I2C_SET(1)            |
192                 SI_CONFIG_POS_SAMPLE_SET(1)     |
193                 SI_CONFIG_INACTIVE_CLK_SET(1)   |
194                 SI_CONFIG_INACTIVE_DATA_SET(1)   |
195                 SI_CONFIG_DIVIDER_SET(6);
196     BMI_write_reg(SI_BASE_ADDRESS+SI_CONFIG_OFFSET, regval);
197     
198 }
199
200 static void
201 disable_SI(void)
202 {
203     A_UINT32 regval;
204     
205     printk("%s\n", __FUNCTION__);
206
207     BMI_write_reg(RTC_BASE_ADDRESS+RESET_CONTROL_OFFSET, RESET_CONTROL_SI0_RST_MASK);
208     BMI_read_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, &regval);
209     regval |= CLOCK_CONTROL_SI0_CLK_MASK;
210     BMI_write_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, regval);//Gate SI0 clock
211     BMI_write_reg(RTC_BASE_ADDRESS+SYSTEM_SLEEP_OFFSET, sys_sleep_reg); //restore system sleep setting
212 }
213
214 /*
215  * Tell the Target to start an 8-byte read from EEPROM,
216  * putting the results in Target RX_DATA registers.
217  */
218 static void
219 request_8byte_read(int offset)
220 {
221     A_UINT32 regval;
222
223 //    printk("%s: request_8byte_read from offset 0x%x\n", __FUNCTION__, offset);
224
225     
226     /* SI_TX_DATA0 = read from offset */
227         regval =(0xa1<<16)|
228                 ((offset & 0xff)<<8)    |
229                 (0xa0 | ((offset & 0xff00)>>7));
230     
231         BMI_write_reg(SI_BASE_ADDRESS+SI_TX_DATA0_OFFSET, regval);
232
233         regval = SI_CS_START_SET(1)      |
234                 SI_CS_RX_CNT_SET(8)     |
235                 SI_CS_TX_CNT_SET(3);
236         BMI_write_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, regval);
237 }
238
239 /*
240  * Tell the Target to start a 4-byte write to EEPROM,
241  * writing values from Target TX_DATA registers.
242  */
243 static void
244 request_4byte_write(int offset, A_UINT32 data)
245 {
246     A_UINT32 regval;
247
248     printk("%s: request_4byte_write (0x%x) to offset 0x%x\n", __FUNCTION__, data, offset);
249
250         /* SI_TX_DATA0 = write data to offset */
251         regval =    ((data & 0xffff) <<16)    |
252                 ((offset & 0xff)<<8)    |
253                 (0xa0 | ((offset & 0xff00)>>7));
254         BMI_write_reg(SI_BASE_ADDRESS+SI_TX_DATA0_OFFSET, regval);
255
256         regval =    data >> 16;
257         BMI_write_reg(SI_BASE_ADDRESS+SI_TX_DATA1_OFFSET, regval);
258
259         regval =    SI_CS_START_SET(1)      |
260                 SI_CS_RX_CNT_SET(0)     |
261                 SI_CS_TX_CNT_SET(6);
262         BMI_write_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, regval);
263 }
264
265 /*
266  * Check whether or not an EEPROM request that was started
267  * earlier has completed yet.
268  */
269 static A_BOOL
270 request_in_progress(void)
271 {
272     A_UINT32 regval;
273
274     /* Wait for DONE_INT in SI_CS */
275     BMI_read_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, &regval);
276
277 //    printk("%s: request in progress SI_CS=0x%x\n", __FUNCTION__, regval);
278     if (regval & SI_CS_DONE_ERR_MASK) {
279         printk("%s: EEPROM signaled ERROR (0x%x)\n", __FUNCTION__, regval);
280     }
281
282     return (!(regval & SI_CS_DONE_INT_MASK));
283 }
284
285 /*
286  * try to detect the type of EEPROM,16bit address or 8bit address
287  */
288
289 static void eeprom_type_detect(void)
290 {
291     A_UINT32 regval;
292     A_UINT8 i = 0;
293
294     request_8byte_read(0x100);
295    /* Wait for DONE_INT in SI_CS */
296     do{
297         BMI_read_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, &regval);
298         if (regval & SI_CS_DONE_ERR_MASK) {
299             printk("%s: ERROR : address type was wrongly set\n", __FUNCTION__);     
300             break;
301         }
302         if (i++ == EEPROM_WAIT_LIMIT) {
303             printk("%s: EEPROM not responding\n", __FUNCTION__);
304         }
305     } while(!(regval & SI_CS_DONE_INT_MASK));
306 }
307
308 /*
309  * Extract the results of a completed EEPROM Read request
310  * and return them to the caller.
311  */
312 inline void
313 read_8byte_results(A_UINT32 *data)
314 {
315     /* Read SI_RX_DATA0 and SI_RX_DATA1 */
316     BMI_read_reg(SI_BASE_ADDRESS+SI_RX_DATA0_OFFSET, &data[0]);
317     BMI_read_reg(SI_BASE_ADDRESS+SI_RX_DATA1_OFFSET, &data[1]);
318 }
319
320
321 /*
322  * Wait for a previously started command to complete.
323  * Timeout if the command is takes "too long".
324  */
325 static void
326 wait_for_eeprom_completion(void)
327 {
328     int i=0;
329
330     while (request_in_progress()) {
331         if (i++ == EEPROM_WAIT_LIMIT) {
332             printk("%s: EEPROM not responding\n", __FUNCTION__);
333         }
334     }
335 }
336
337 /*
338  * High-level function which starts an 8-byte read,
339  * waits for it to complete, and returns the result.
340  */
341 static void
342 fetch_8bytes(int offset, A_UINT32 *data)
343 {
344     request_8byte_read(offset);
345     wait_for_eeprom_completion();
346     read_8byte_results(data);
347
348     /* Clear any pending intr */
349     BMI_write_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, SI_CS_DONE_INT_MASK);
350 }
351
352 /*
353  * High-level function which starts a 4-byte write,
354  * and waits for it to complete.
355  */
356 inline void
357 commit_4bytes(int offset, A_UINT32 data)
358 {
359     request_4byte_write(offset, data);
360     wait_for_eeprom_completion();
361 }
362 /* ATHENV */
363 #ifdef ANDROID_ENV
364 void eeprom_ar6000_transfer(HIF_DEVICE *device, char *fake_file, char *p_mac)
365 {
366     A_UINT32 first_word;
367     A_UINT32 board_data_addr;
368     int i;
369
370     printk("%s: Enter\n", __FUNCTION__);
371
372     enable_SI(device);
373     eeprom_type_detect();
374
375     if (fake_file) {
376         /*
377          * Transfer from file to Target RAM.
378          * Fetch source data from file.
379          */
380         mm_segment_t            oldfs;
381         struct file             *filp;
382         struct inode            *inode = NULL;
383         int                     length;
384
385         /* open file */
386         oldfs = get_fs();
387         set_fs(KERNEL_DS);
388         filp = filp_open(fake_file, O_RDONLY, S_IRUSR);
389
390         if (IS_ERR(filp)) {
391             printk("%s: file %s filp_open error\n", __FUNCTION__, fake_file);
392             set_fs(oldfs);
393             return;
394         }
395
396         if (!filp->f_op) {
397             printk("%s: File Operation Method Error\n", __FUNCTION__);
398             filp_close(filp, NULL);
399             set_fs(oldfs);
400             return;
401         }
402
403         inode = GET_INODE_FROM_FILEP(filep);
404         if (!inode) {
405             printk("%s: Get inode from filp failed\n", __FUNCTION__);
406             filp_close(filp, NULL);
407             set_fs(oldfs);
408             return;
409         }
410
411         printk("%s file offset opsition: %xh\n", __FUNCTION__, (unsigned)filp->f_pos);
412
413         /* file's size */
414         length = i_size_read(inode->i_mapping->host);
415         printk("%s: length=%d\n", __FUNCTION__, length);
416         if (length != EEPROM_SZ) {
417             printk("%s: The file's size is not as expected\n", __FUNCTION__);
418             filp_close(filp, NULL);
419             set_fs(oldfs);
420             return;
421         }
422
423         /* read data */
424         if (filp->f_op->read(filp, eeprom_data, length, &filp->f_pos) != length) {
425             printk("%s: file read error\n", __FUNCTION__);
426             filp_close(filp, NULL);
427             set_fs(oldfs);
428             return;
429         }
430
431         /* read data out successfully */
432         filp_close(filp, NULL);
433         set_fs(oldfs);
434     } else {
435         /*
436          * Read from EEPROM to file OR transfer from EEPROM to Target RAM.
437          * Fetch EEPROM_SZ Bytes of Board Data, 8 bytes at a time.
438          */
439
440         fetch_8bytes(0, (A_UINT32 *)(&eeprom_data[0]));
441
442         /* Check the first word of EEPROM for validity */
443         first_word = *((A_UINT32 *)eeprom_data);
444
445         if ((first_word == 0) || (first_word == 0xffffffff)) {
446             printk("Did not find EEPROM with valid Board Data.\n");
447         }
448
449         for (i=8; i<EEPROM_SZ; i+=8) {
450             fetch_8bytes(i, (A_UINT32 *)(&eeprom_data[i]));
451         }
452     }
453
454     /* soft mac */
455     if (p_mac) {
456
457         mm_segment_t            oldfs;
458         struct file             *filp;
459         struct inode            *inode = NULL;
460         int                     length;
461         
462         /* open file */
463         oldfs = get_fs();
464         set_fs(KERNEL_DS);
465         filp = filp_open(p_mac, O_RDONLY, S_IRUSR);
466         
467         printk("%s try to open file %s\n", __FUNCTION__, p_mac);
468
469         if (IS_ERR(filp)) {
470             printk("%s: file %s filp_open error\n", __FUNCTION__, p_mac);
471             set_fs(oldfs);
472             return;
473         }
474         
475         if (!filp->f_op) {
476             printk("%s: File Operation Method Error\n", __FUNCTION__);
477             filp_close(filp, NULL);
478             set_fs(oldfs);
479             return;
480         }
481         
482         inode = GET_INODE_FROM_FILEP(filep);
483         if (!inode) {
484             printk("%s: Get inode from filp failed\n", __FUNCTION__);
485             filp_close(filp, NULL);
486             set_fs(oldfs);
487             return;
488         }
489         
490         printk("%s file offset opsition: %xh\n", __FUNCTION__, (unsigned)filp->f_pos);
491         
492         /* file's size */
493         length = i_size_read(inode->i_mapping->host);
494         printk("%s: length=%d\n", __FUNCTION__, length);
495         if (length > ATH_SOFT_MAC_TMP_BUF_LEN) {
496             printk("%s: MAC file's size is not as expected\n", __FUNCTION__);
497             filp_close(filp, NULL);
498             set_fs(oldfs);
499             return;
500         }
501         
502         /* read data */
503         if (filp->f_op->read(filp, soft_mac_tmp_buf, length, &filp->f_pos) != length) {
504             printk("%s: file read error\n", __FUNCTION__);
505             filp_close(filp, NULL);
506             set_fs(oldfs);
507             return;
508         }
509
510 #if 0
511         /* the data we just read */
512         printk("%s: mac address from the file:\n", __FUNCTION__);
513         for (i = 0; i < length; i++)
514             printk("[%c(0x%x)],", soft_mac_tmp_buf[i], soft_mac_tmp_buf[i]);
515         printk("\n");
516 #endif
517
518         /* read data out successfully */
519         filp_close(filp, NULL);
520         set_fs(oldfs);
521
522         /* convert mac address */
523         if (!wmic_ether_aton(soft_mac_tmp_buf, mac_addr)) {
524             printk("%s: convert mac value fail\n", __FUNCTION__);
525             return;
526         }
527
528 #if 0
529         /* the converted mac address */
530         printk("%s: the converted mac value\n", __FUNCTION__);
531         for (i = 0; i < ATH_MAC_LEN; i++)
532             printk("[0x%x],", mac_addr[i]);
533         printk("\n");
534 #endif
535     }
536     /* soft mac */
537
538     /* Determine where in Target RAM to write Board Data */
539     BMI_read_mem( HOST_INTEREST_ITEM_ADDRESS(hi_board_data), &board_data_addr);
540     if (board_data_addr == 0) {
541         printk("hi_board_data is zero\n");
542     }
543
544     /* soft mac */
545 #if 1
546     /* Update MAC address in RAM */
547     if (p_mac) {
548             update_mac(eeprom_data, EEPROM_SZ, mac_addr);
549     }
550 #endif
551 #if 0
552     /* mac address in eeprom array */
553     printk("%s: mac values in eeprom array\n", __FUNCTION__);
554     for (i = 10; i < 10 + 6; i++)
555         printk("[0x%x],", eeprom_data[i]);
556     printk("\n");
557 #endif
558     /* soft mac */
559
560     /* Write EEPROM data to Target RAM */
561     BMI_write_mem(board_data_addr, ((A_UINT8 *)eeprom_data), EEPROM_SZ);
562
563     /* Record the fact that Board Data IS initialized */
564     {
565        A_UINT32 one = 1;
566        BMI_write_mem(HOST_INTEREST_ITEM_ADDRESS(hi_board_data_initialized),
567                      (A_UINT8 *)&one, sizeof(A_UINT32));
568     }
569
570     disable_SI();
571 }
572 #endif
573 /* ATHENV */
574