Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: chromeos/drivers/ath6kl/os/linux/eeprom.c

Issue 646055: Atheros AR600x driver + build glue (Closed)
Patch Set: Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 *
3 * Copyright (c) 2004-2009 Atheros Communications Inc.
4 * All rights reserved.
5 *
6 *
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2 as
9 // published by the Free Software Foundation;
10 //
11 // Software distributed under the License is distributed on an "AS
12 // IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13 // implied. See the License for the specific language governing
14 // rights and limitations under the License.
15 //
16 //
17 *
18 */
19
20
21 #include "ar6000_drv.h"
22 #include "htc.h"
23 #include <linux/fs.h>
24
25 #include "AR6002/hw2.0/hw/apb_map.h"
26 #include "AR6002/hw2.0/hw/gpio_reg.h"
27 #ifndef ANDROID_ENV
28 #include "AR6002/hw2.0/hw/rtc_reg.h"
29 #endif
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 unsigned char c = *bufp++;
75 if (c >= '0' && c <= '9') val = c - '0';
76 else if (c >= 'a' && c <= 'f') val = c - 'a' + 10;
77 else if (c >= 'A' && c <= 'F') val = c - 'A' + 10;
78 else {
79 printk("%s: MAC value is invalid\n", __FUNCTION__);
80 break;
81 }
82
83 val <<= 4;
84 c = *bufp++;
85 if (c >= '0' && c <= '9') val |= c - '0';
86 else if (c >= 'a' && c <= 'f') val |= c - 'a' + 10;
87 else if (c >= 'A' && c <= 'F') val |= c - 'A' + 10;
88 else {
89 printk("%s: MAC value is invalid\n", __FUNCTION__);
90 break;
91 }
92
93 eth[i] = (unsigned char) (val & 0377);
94 if(++i == ATH_MAC_LEN) {
95 /* That's it. Any trailing junk? */
96 if (*bufp != '\0') {
97 return 0;
98 }
99 return 1;
100 }
101 if (*bufp != ':')
102 break;
103 }
104 return 0;
105 }
106
107 static void
108 update_mac(unsigned char* eeprom, int size, unsigned char* macaddr)
109 {
110 int i;
111 A_UINT16* ptr = (A_UINT16*)(eeprom+4);
112 A_UINT16 checksum = 0;
113
114 memcpy(eeprom+10,macaddr,6);
115
116 *ptr = 0;
117 ptr = (A_UINT16*)eeprom;
118
119 for (i=0; i<size; i+=2) {
120 checksum ^= *ptr++;
121 }
122 checksum = ~checksum;
123
124 ptr = (A_UINT16*)(eeprom+4);
125 *ptr = checksum;
126 return;
127 }
128 /* soft mac */
129
130 /* Read a Target register and return its value. */
131 inline void
132 BMI_read_reg(A_UINT32 address, A_UINT32 *pvalue)
133 {
134 BMIReadSOCRegister(p_bmi_device, address, pvalue);
135 }
136
137 /* Write a value to a Target register. */
138 inline void
139 BMI_write_reg(A_UINT32 address, A_UINT32 value)
140 {
141 BMIWriteSOCRegister(p_bmi_device, address, value);
142 }
143
144 /* Read Target memory word and return its value. */
145 inline void
146 BMI_read_mem(A_UINT32 address, A_UINT32 *pvalue)
147 {
148 BMIReadMemory(p_bmi_device, address, (A_UCHAR*)(pvalue), 4);
149 }
150
151 /* Write a word to a Target memory. */
152 inline void
153 BMI_write_mem(A_UINT32 address, A_UINT8 *p_data, A_UINT32 sz)
154 {
155 BMIWriteMemory(p_bmi_device, address, (A_UCHAR*)(p_data), sz);
156 }
157
158 /*
159 * Enable and configure the Target's Serial Interface
160 * so we can access the EEPROM.
161 */
162 static void
163 enable_SI(HIF_DEVICE *p_device)
164 {
165 A_UINT32 regval;
166
167 printk("%s\n", __FUNCTION__);
168
169 p_bmi_device = p_device;
170
171 BMI_read_reg(RTC_BASE_ADDRESS+SYSTEM_SLEEP_OFFSET, &sys_sleep_reg);
172 BMI_write_reg(RTC_BASE_ADDRESS+SYSTEM_SLEEP_OFFSET, SYSTEM_SLEEP_DISABLE_SET (1)); //disable system sleep temporarily
173
174 BMI_read_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, &regval);
175 regval &= ~CLOCK_CONTROL_SI0_CLK_MASK;
176 BMI_write_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, regval);
177
178 BMI_read_reg(RTC_BASE_ADDRESS+RESET_CONTROL_OFFSET, &regval);
179 regval &= ~RESET_CONTROL_SI0_RST_MASK;
180 BMI_write_reg(RTC_BASE_ADDRESS+RESET_CONTROL_OFFSET, regval);
181
182
183 BMI_read_reg(GPIO_BASE_ADDRESS+GPIO_PIN0_OFFSET, &regval);
184 regval &= ~GPIO_PIN0_CONFIG_MASK;
185 BMI_write_reg(GPIO_BASE_ADDRESS+GPIO_PIN0_OFFSET, regval);
186
187 BMI_read_reg(GPIO_BASE_ADDRESS+GPIO_PIN1_OFFSET, &regval);
188 regval &= ~GPIO_PIN1_CONFIG_MASK;
189 BMI_write_reg(GPIO_BASE_ADDRESS+GPIO_PIN1_OFFSET, regval);
190
191 /* SI_CONFIG = 0x500a6; */
192 regval = SI_CONFIG_BIDIR_OD_DATA_SET(1) |
193 SI_CONFIG_I2C_SET(1) |
194 SI_CONFIG_POS_SAMPLE_SET(1) |
195 SI_CONFIG_INACTIVE_CLK_SET(1) |
196 SI_CONFIG_INACTIVE_DATA_SET(1) |
197 SI_CONFIG_DIVIDER_SET(6);
198 BMI_write_reg(SI_BASE_ADDRESS+SI_CONFIG_OFFSET, regval);
199
200 }
201
202 static void
203 disable_SI(void)
204 {
205 A_UINT32 regval;
206
207 printk("%s\n", __FUNCTION__);
208
209 BMI_write_reg(RTC_BASE_ADDRESS+RESET_CONTROL_OFFSET, RESET_CONTROL_SI0_RST_M ASK);
210 BMI_read_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, &regval);
211 regval |= CLOCK_CONTROL_SI0_CLK_MASK;
212 BMI_write_reg(RTC_BASE_ADDRESS+CLOCK_CONTROL_OFFSET, regval);//Gate SI0 cloc k
213 BMI_write_reg(RTC_BASE_ADDRESS+SYSTEM_SLEEP_OFFSET, sys_sleep_reg); //restor e system sleep setting
214 }
215
216 /*
217 * Tell the Target to start an 8-byte read from EEPROM,
218 * putting the results in Target RX_DATA registers.
219 */
220 static void
221 request_8byte_read(int offset)
222 {
223 A_UINT32 regval;
224
225 // printk("%s: request_8byte_read from offset 0x%x\n", __FUNCTION__, offset);
226
227
228 /* SI_TX_DATA0 = read from offset */
229 regval =(0xa1<<16)|
230 ((offset & 0xff)<<8) |
231 (0xa0 | ((offset & 0xff00)>>7));
232
233 BMI_write_reg(SI_BASE_ADDRESS+SI_TX_DATA0_OFFSET, regval);
234
235 regval = SI_CS_START_SET(1) |
236 SI_CS_RX_CNT_SET(8) |
237 SI_CS_TX_CNT_SET(3);
238 BMI_write_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, regval);
239 }
240
241 /*
242 * Tell the Target to start a 4-byte write to EEPROM,
243 * writing values from Target TX_DATA registers.
244 */
245 static void
246 request_4byte_write(int offset, A_UINT32 data)
247 {
248 A_UINT32 regval;
249
250 printk("%s: request_4byte_write (0x%x) to offset 0x%x\n", __FUNCTION__, data , offset);
251
252 /* SI_TX_DATA0 = write data to offset */
253 regval = ((data & 0xffff) <<16) |
254 ((offset & 0xff)<<8) |
255 (0xa0 | ((offset & 0xff00)>>7));
256 BMI_write_reg(SI_BASE_ADDRESS+SI_TX_DATA0_OFFSET, regval);
257
258 regval = data >> 16;
259 BMI_write_reg(SI_BASE_ADDRESS+SI_TX_DATA1_OFFSET, regval);
260
261 regval = SI_CS_START_SET(1) |
262 SI_CS_RX_CNT_SET(0) |
263 SI_CS_TX_CNT_SET(6);
264 BMI_write_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, regval);
265 }
266
267 /*
268 * Check whether or not an EEPROM request that was started
269 * earlier has completed yet.
270 */
271 static A_BOOL
272 request_in_progress(void)
273 {
274 A_UINT32 regval;
275
276 /* Wait for DONE_INT in SI_CS */
277 BMI_read_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, &regval);
278
279 // printk("%s: request in progress SI_CS=0x%x\n", __FUNCTION__, regval);
280 if (regval & SI_CS_DONE_ERR_MASK) {
281 printk("%s: EEPROM signaled ERROR (0x%x)\n", __FUNCTION__, regval);
282 }
283
284 return (!(regval & SI_CS_DONE_INT_MASK));
285 }
286
287 /*
288 * try to detect the type of EEPROM,16bit address or 8bit address
289 */
290
291 static void eeprom_type_detect(void)
292 {
293 A_UINT32 regval;
294 A_UINT8 i = 0;
295
296 request_8byte_read(0x100);
297 /* Wait for DONE_INT in SI_CS */
298 do{
299 BMI_read_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, &regval);
300 if (regval & SI_CS_DONE_ERR_MASK) {
301 printk("%s: ERROR : address type was wrongly set\n", __FUNCTION__);
302 break;
303 }
304 if (i++ == EEPROM_WAIT_LIMIT) {
305 printk("%s: EEPROM not responding\n", __FUNCTION__);
306 }
307 } while(!(regval & SI_CS_DONE_INT_MASK));
308 }
309
310 /*
311 * Extract the results of a completed EEPROM Read request
312 * and return them to the caller.
313 */
314 inline void
315 read_8byte_results(A_UINT32 *data)
316 {
317 /* Read SI_RX_DATA0 and SI_RX_DATA1 */
318 BMI_read_reg(SI_BASE_ADDRESS+SI_RX_DATA0_OFFSET, &data[0]);
319 BMI_read_reg(SI_BASE_ADDRESS+SI_RX_DATA1_OFFSET, &data[1]);
320 }
321
322
323 /*
324 * Wait for a previously started command to complete.
325 * Timeout if the command is takes "too long".
326 */
327 static void
328 wait_for_eeprom_completion(void)
329 {
330 int i=0;
331
332 while (request_in_progress()) {
333 if (i++ == EEPROM_WAIT_LIMIT) {
334 printk("%s: EEPROM not responding\n", __FUNCTION__);
335 }
336 }
337 }
338
339 /*
340 * High-level function which starts an 8-byte read,
341 * waits for it to complete, and returns the result.
342 */
343 static void
344 fetch_8bytes(int offset, A_UINT32 *data)
345 {
346 request_8byte_read(offset);
347 wait_for_eeprom_completion();
348 read_8byte_results(data);
349
350 /* Clear any pending intr */
351 BMI_write_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, SI_CS_DONE_INT_MASK);
352 }
353
354 /*
355 * High-level function which starts a 4-byte write,
356 * and waits for it to complete.
357 */
358 inline void
359 commit_4bytes(int offset, A_UINT32 data)
360 {
361 request_4byte_write(offset, data);
362 wait_for_eeprom_completion();
363 }
364 /* ATHENV */
365 #ifdef ANDROID_ENV
366 void eeprom_ar6000_transfer(HIF_DEVICE *device, char *fake_file, char *p_mac)
367 {
368 A_UINT32 first_word;
369 A_UINT32 board_data_addr;
370 int i;
371
372 printk("%s: Enter\n", __FUNCTION__);
373
374 enable_SI(device);
375 eeprom_type_detect();
376
377 if (fake_file) {
378 /*
379 * Transfer from file to Target RAM.
380 * Fetch source data from file.
381 */
382 mm_segment_t oldfs;
383 struct file *filp;
384 struct inode *inode = NULL;
385 int length;
386
387 /* open file */
388 oldfs = get_fs();
389 set_fs(KERNEL_DS);
390 filp = filp_open(fake_file, O_RDONLY, S_IRUSR);
391
392 if (IS_ERR(filp)) {
393 printk("%s: file %s filp_open error\n", __FUNCTION__, fake_file);
394 set_fs(oldfs);
395 return;
396 }
397
398 if (!filp->f_op) {
399 printk("%s: File Operation Method Error\n", __FUNCTION__);
400 filp_close(filp, NULL);
401 set_fs(oldfs);
402 return;
403 }
404
405 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
406 inode = filp->f_path.dentry->d_inode;
407 #else
408 inode = filp->f_dentry->d_inode;
409 #endif
410
411 if (!inode) {
412 printk("%s: Get inode from filp failed\n", __FUNCTION__);
413 filp_close(filp, NULL);
414 set_fs(oldfs);
415 return;
416 }
417
418 printk("%s file offset opsition: %xh\n", __FUNCTION__, (unsigned)filp->f _pos);
419
420 /* file's size */
421 length = i_size_read(inode->i_mapping->host);
422 printk("%s: length=%d\n", __FUNCTION__, length);
423 if (length != EEPROM_SZ) {
424 printk("%s: The file's size is not as expected\n", __FUNCTION__);
425 filp_close(filp, NULL);
426 set_fs(oldfs);
427 return;
428 }
429
430 /* read data */
431 if (filp->f_op->read(filp, eeprom_data, length, &filp->f_pos) != length) {
432 printk("%s: file read error\n", __FUNCTION__);
433 filp_close(filp, NULL);
434 set_fs(oldfs);
435 return;
436 }
437
438 /* read data out successfully */
439 filp_close(filp, NULL);
440 set_fs(oldfs);
441 } else {
442 /*
443 * Read from EEPROM to file OR transfer from EEPROM to Target RAM.
444 * Fetch EEPROM_SZ Bytes of Board Data, 8 bytes at a time.
445 */
446
447 fetch_8bytes(0, (A_UINT32 *)(&eeprom_data[0]));
448
449 /* Check the first word of EEPROM for validity */
450 first_word = *((A_UINT32 *)eeprom_data);
451
452 if ((first_word == 0) || (first_word == 0xffffffff)) {
453 printk("Did not find EEPROM with valid Board Data.\n");
454 }
455
456 for (i=8; i<EEPROM_SZ; i+=8) {
457 fetch_8bytes(i, (A_UINT32 *)(&eeprom_data[i]));
458 }
459 }
460
461 /* soft mac */
462 if (p_mac) {
463
464 mm_segment_t oldfs;
465 struct file *filp;
466 struct inode *inode = NULL;
467 int length;
468
469 /* open file */
470 oldfs = get_fs();
471 set_fs(KERNEL_DS);
472 filp = filp_open(p_mac, O_RDONLY, S_IRUSR);
473
474 printk("%s try to open file %s\n", __FUNCTION__, p_mac);
475
476 if (IS_ERR(filp)) {
477 printk("%s: file %s filp_open error\n", __FUNCTION__, p_mac);
478 set_fs(oldfs);
479 return;
480 }
481
482 if (!filp->f_op) {
483 printk("%s: File Operation Method Error\n", __FUNCTION__);
484 filp_close(filp, NULL);
485 set_fs(oldfs);
486 return;
487 }
488
489 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
490 inode = filp->f_path.dentry->d_inode;
491 #else
492 inode = filp->f_dentry->d_inode;
493 #endif
494 if (!inode) {
495 printk("%s: Get inode from filp failed\n", __FUNCTION__);
496 filp_close(filp, NULL);
497 set_fs(oldfs);
498 return;
499 }
500
501 printk("%s file offset opsition: %xh\n", __FUNCTION__, (unsigned)filp->f _pos);
502
503 /* file's size */
504 length = i_size_read(inode->i_mapping->host);
505 printk("%s: length=%d\n", __FUNCTION__, length);
506 if (length > ATH_SOFT_MAC_TMP_BUF_LEN) {
507 printk("%s: MAC file's size is not as expected\n", __FUNCTION__);
508 filp_close(filp, NULL);
509 set_fs(oldfs);
510 return;
511 }
512
513 /* read data */
514 if (filp->f_op->read(filp, soft_mac_tmp_buf, length, &filp->f_pos) != le ngth) {
515 printk("%s: file read error\n", __FUNCTION__);
516 filp_close(filp, NULL);
517 set_fs(oldfs);
518 return;
519 }
520
521 #if 0
522 /* the data we just read */
523 printk("%s: mac address from the file:\n", __FUNCTION__);
524 for (i = 0; i < length; i++)
525 printk("[%c(0x%x)],", soft_mac_tmp_buf[i], soft_mac_tmp_buf[i]);
526 printk("\n");
527 #endif
528
529 /* read data out successfully */
530 filp_close(filp, NULL);
531 set_fs(oldfs);
532
533 /* convert mac address */
534 if (!wmic_ether_aton(soft_mac_tmp_buf, mac_addr)) {
535 printk("%s: convert mac value fail\n", __FUNCTION__);
536 return;
537 }
538
539 #if 0
540 /* the converted mac address */
541 printk("%s: the converted mac value\n", __FUNCTION__);
542 for (i = 0; i < ATH_MAC_LEN; i++)
543 printk("[0x%x],", mac_addr[i]);
544 printk("\n");
545 #endif
546 }
547 /* soft mac */
548
549 /* Determine where in Target RAM to write Board Data */
550 BMI_read_mem( HOST_INTEREST_ITEM_ADDRESS(hi_board_data), &board_data_addr);
551 if (board_data_addr == 0) {
552 printk("hi_board_data is zero\n");
553 }
554
555 /* soft mac */
556 #if 1
557 /* Update MAC address in RAM */
558 if (p_mac) {
559 update_mac(eeprom_data, EEPROM_SZ, mac_addr);
560 }
561 #endif
562 #if 0
563 /* mac address in eeprom array */
564 printk("%s: mac values in eeprom array\n", __FUNCTION__);
565 for (i = 10; i < 10 + 6; i++)
566 printk("[0x%x],", eeprom_data[i]);
567 printk("\n");
568 #endif
569 /* soft mac */
570
571 /* Write EEPROM data to Target RAM */
572 BMI_write_mem(board_data_addr, ((A_UINT8 *)eeprom_data), EEPROM_SZ);
573
574 /* Record the fact that Board Data IS initialized */
575 {
576 A_UINT32 one = 1;
577 BMI_write_mem(HOST_INTEREST_ITEM_ADDRESS(hi_board_data_initialized),
578 (A_UINT8 *)&one, sizeof(A_UINT32));
579 }
580
581 disable_SI();
582 }
583 #endif
584 /* ATHENV */
585
OLDNEW
« no previous file with comments | « chromeos/drivers/ath6kl/os/linux/cfg80211.c ('k') | chromeos/drivers/ath6kl/os/linux/export_hci_transport.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698