xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/ssv6xxx/smac/efuse.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3  * Copyright (c) 2015 iComm Corporation
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <linux/etherdevice.h>
18 #include <ssv6200.h>
19 #include "efuse.h"
20 mm_segment_t oldfs;
openFile(char * path,int flag,int mode)21 struct file *openFile(char *path,int flag,int mode)
22 {
23     struct file *fp=NULL;
24     fp=filp_open(path, flag, 0);
25     if(IS_ERR(fp))
26         return NULL;
27     else
28         return fp;
29 }
readFile(struct file * fp,char * buf,int readlen)30 int readFile(struct file *fp,char *buf,int readlen)
31 {
32     if (fp->f_op && fp->f_op->read)
33         return fp->f_op->read(fp,buf,readlen, &fp->f_pos);
34     else
35     return -1;
36 }
closeFile(struct file * fp)37 int closeFile(struct file *fp)
38 {
39     filp_close(fp,NULL);
40     return 0;
41 }
initKernelEnv(void)42 void initKernelEnv(void)
43 {
44     oldfs = get_fs();
45     set_fs(KERNEL_DS);
46 }
parseMac(char * mac,u_int8_t addr[])47 void parseMac(char* mac, u_int8_t addr[])
48 {
49     long b;
50     int i;
51     for (i = 0; i < 6; i++)
52     {
53         b = simple_strtol(mac+(3*i), (char **) NULL, 16);
54         addr[i] = (char)b;
55     }
56 }
readfile_mac(u8 * path,u8 * mac_addr)57 static int readfile_mac(u8 *path,u8 *mac_addr)
58 {
59     char buf[128];
60     struct file *fp=NULL;
61     int ret=0;
62     fp=openFile(path,O_RDONLY,0);
63     if (fp!=NULL)
64     {
65         initKernelEnv();
66         memset(buf,0,128);
67         if ((ret=readFile(fp,buf,128))>0)
68         {
69             parseMac(buf,(uint8_t *)mac_addr);
70         }
71         else
72             printk("read file error %d=[%s]\n",ret,path);
73         set_fs(oldfs);
74         closeFile(fp);
75     }
76     else
77         printk("Read open File fail[%s]!!!! \n",path);
78     return ret;
79 }
write_mac_to_file(u8 * mac_path,u8 * mac_addr)80 static int write_mac_to_file(u8 *mac_path,u8 *mac_addr)
81 {
82     char buf[128];
83     struct file *fp=NULL;
84     int ret=0,len;
85     mm_segment_t old_fs;
86     fp=openFile(mac_path,O_WRONLY|O_CREAT,0640);
87     if (fp!=NULL)
88     {
89         initKernelEnv();
90         memset(buf,0,128);
91         sprintf(buf,"%x:%x:%x:%x:%x:%x",mac_addr[0],mac_addr[1],mac_addr[2],mac_addr[3],mac_addr[4],mac_addr[5]);
92         len = strlen(buf)+1;
93         old_fs = get_fs();
94         set_fs(KERNEL_DS);
95         fp->f_op->write(fp, (char *)buf, len, &fp->f_pos);
96         set_fs(old_fs);
97         closeFile(fp);
98     }
99     else
100         printk("Write open File fail!!!![%s] \n",mac_path);
101     return ret;
102 }
103 static struct efuse_map SSV_EFUSE_ITEM_TABLE[] = {
104     {4, 0, 0},
105     {4, 8, 0},
106     {4, 8, 0},
107     {4, 48, 0},
108     {4, 8, 0},
109     {4, 8, 0},
110     {4, 8, 0},
111 };
read_efuse(struct ssv_hw * sh,u8 * pbuf)112 static u8 read_efuse(struct ssv_hw *sh, u8 *pbuf)
113 {
114     extern struct ssv6xxx_cfg ssv_cfg;
115     u32 val, i;
116     u32 *temp = (u32 *)pbuf;
117     SMAC_REG_WRITE(sh,0xC0000328,0x11);
118     SMAC_REG_WRITE(sh, SSV_EFUSE_ID_READ_SWITCH, 0x1);
119     SMAC_REG_READ(sh, SSV_EFUSE_ID_RAW_DATA_BASE, &val);
120     ssv_cfg.chip_identity = val;
121  SMAC_REG_WRITE(sh, SSV_EFUSE_READ_SWITCH, 0x1);
122     SMAC_REG_READ(sh, SSV_EFUSE_RAW_DATA_BASE, &val);
123     if (val == 0x00) {
124     return 0;
125     }
126     for (i = 0; i < (EFUSE_MAX_SECTION_MAP); i++)
127     {
128         SMAC_REG_WRITE(sh, SSV_EFUSE_READ_SWITCH+i*4, 0x1);
129         SMAC_REG_READ(sh, SSV_EFUSE_RAW_DATA_BASE+i*4, &val);
130         *temp++ = val;
131     }
132     SMAC_REG_WRITE(sh,0xC0000328,0x1800000a);
133     return 1;
134 }
parser_efuse(u8 * pbuf,u8 * mac_addr)135 static u16 parser_efuse(u8 *pbuf, u8 *mac_addr)
136 {
137     u8 *rtemp8,idx=0;
138  u16 shift=0,i;
139     u16 efuse_real_content_len = 0;
140  rtemp8 = pbuf;
141     if (*rtemp8 == 0x00) {
142   return efuse_real_content_len;
143     }
144  do
145  {
146   idx = (*(rtemp8) >> shift)&0xf;
147   switch(idx)
148   {
149    case EFUSE_R_CALIBRATION_RESULT:
150    case EFUSE_CRYSTAL_FREQUENCY_OFFSET:
151    case EFUSE_TX_POWER_INDEX_1:
152    case EFUSE_TX_POWER_INDEX_2:
153    case EFUSE_SAR_RESULT:
154     if(shift)
155     {
156      rtemp8 ++;
157      SSV_EFUSE_ITEM_TABLE[idx].value = (u16)((u8)(*((u16*)rtemp8)) & ((1<< SSV_EFUSE_ITEM_TABLE[idx].byte_cnts) - 1));
158     }
159     else
160     {
161      SSV_EFUSE_ITEM_TABLE[idx].value = (u16)((u8)(*((u16*)rtemp8) >> 4) & ((1<< SSV_EFUSE_ITEM_TABLE[idx].byte_cnts) - 1));
162     }
163     efuse_real_content_len += (SSV_EFUSE_ITEM_TABLE[idx].offset + SSV_EFUSE_ITEM_TABLE[idx].byte_cnts);
164     break;
165    case EFUSE_MAC:
166                 if(shift)
167     {
168      rtemp8 ++;
169      memcpy(mac_addr,rtemp8,6);
170     }
171     else
172     {
173      for(i=0;i<6;i++)
174      {
175       mac_addr[i] = (u16)(*((u16*)rtemp8) >> 4) & 0xff;
176       rtemp8++;
177      }
178     }
179     efuse_real_content_len += (SSV_EFUSE_ITEM_TABLE[idx].offset + SSV_EFUSE_ITEM_TABLE[idx].byte_cnts);
180     break;
181 #if 0
182    case EFUSE_IQ_CALIBRAION_RESULT:
183     if(shift)
184     {
185      rtemp8 ++;
186      SSV_EFUSE_ITEM_TABLE[idx].value = (u16)(*((u16*)rtemp8)) & ((1<< SSV_EFUSE_ITEM_TABLE[idx].byte_cnts) - 1);
187     }
188     else
189     {
190      SSV_EFUSE_ITEM_TABLE[idx].value = (u16)(*((u16*)rtemp8) >> 4) & ((1<< SSV_EFUSE_ITEM_TABLE[idx].byte_cnts) - 1);
191     }
192     efuse_real_content_len += (SSV_EFUSE_ITEM_TABLE[idx].offset + SSV_EFUSE_ITEM_TABLE[idx].byte_cnts);
193     break;
194 #endif
195    default:
196                 idx = 0;
197     break;
198   }
199   shift = efuse_real_content_len % 8;
200   rtemp8 = &pbuf[efuse_real_content_len / 8];
201  }while(idx != 0);
202     return efuse_real_content_len;
203 }
addr_increase_copy(u8 * dst,u8 * src)204 void addr_increase_copy(u8 *dst, u8 *src)
205 {
206 #if 0
207  u16 *a = (u16 *)dst;
208  const u16 *b = (const u16 *)src;
209  a[0] = b[0];
210  a[1] = b[1];
211  if (b[2] == 0xffff)
212   a[2] = b[2] - 1;
213  else
214   a[2] = b[2] + 1;
215 #endif
216     u8 *a = (u8 *)dst;
217     const u8 *b = (const u8 *)src;
218     a[0] = b[0];
219     a[1] = b[1];
220     a[2] = b[2];
221     a[3] = b[3];
222     a[4] = b[4];
223     if (b[5]&0x1)
224         a[5] = b[5] - 1;
225     else
226         a[5] = b[5] + 1;
227 }
key_char2num(u8 ch)228 static u8 key_char2num(u8 ch)
229 {
230     if((ch>='0')&&(ch<='9'))
231         return ch - '0';
232     else if ((ch>='a')&&(ch<='f'))
233         return ch - 'a' + 10;
234     else if ((ch>='A')&&(ch<='F'))
235         return ch - 'A' + 10;
236     else
237         return 0xff;
238 }
key_2char2num(u8 hch,u8 lch)239 u8 key_2char2num(u8 hch, u8 lch)
240 {
241     return ((key_char2num(hch) << 4) | key_char2num(lch));
242 }
243 extern struct ssv6xxx_cfg ssv_cfg;
244 extern char* ssv_initmac;
245 #ifdef ROCKCHIP_3126_SUPPORT
246 extern int rockchip_wifi_mac_addr(unsigned char *buf);
247 #endif
248 #ifdef AML_WIFI_MAC
249 extern u8 *wifi_get_mac(void);
250 #endif
efuse_read_all_map(struct ssv_hw * sh)251 void efuse_read_all_map(struct ssv_hw *sh)
252 {
253     u8 mac[ETH_ALEN] = {0};
254     int jj,kk;
255     u8 efuse_mapping_table[EFUSE_HWSET_MAX_SIZE/8];
256 #ifndef CONFIG_SSV_RANDOM_MAC
257     u8 pseudo_mac0[ETH_ALEN] = { 0x00, 0x33, 0x33, 0x33, 0x33, 0x33 };
258 #endif
259     u8 rom_mac0[ETH_ALEN];
260 #ifdef EFUSE_DEBUG
261     int i;
262 #endif
263     memset(rom_mac0,0x00,ETH_ALEN);
264  memset(efuse_mapping_table,0x00,EFUSE_HWSET_MAX_SIZE/8);
265     read_efuse(sh, efuse_mapping_table);
266 #ifdef EFUSE_DEBUG
267     for(i=0;i<(EFUSE_HWSET_MAX_SIZE/8);i++)
268     {
269         if(i%4 == 0)
270             printk("\n");
271         printk("%02x-",efuse_mapping_table[i]);
272     }
273     printk("\n");
274 #endif
275     parser_efuse(efuse_mapping_table,rom_mac0);
276     ssv_cfg.r_calbration_result = (u8)SSV_EFUSE_ITEM_TABLE[EFUSE_R_CALIBRATION_RESULT].value;
277     ssv_cfg.sar_result = (u8)SSV_EFUSE_ITEM_TABLE[EFUSE_SAR_RESULT].value;
278     ssv_cfg.crystal_frequency_offset = (u8)SSV_EFUSE_ITEM_TABLE[EFUSE_CRYSTAL_FREQUENCY_OFFSET].value;
279     ssv_cfg.tx_power_index_1 = (u8)SSV_EFUSE_ITEM_TABLE[EFUSE_TX_POWER_INDEX_1].value;
280     ssv_cfg.tx_power_index_2 = (u8)SSV_EFUSE_ITEM_TABLE[EFUSE_TX_POWER_INDEX_2].value;
281     if (!is_valid_ether_addr(&sh->cfg.maddr[0][0]))
282     {
283 #ifdef AML_WIFI_MAC
284         memcpy(mac, wifi_get_mac(),ETH_ALEN);
285         if (is_valid_ether_addr(mac)) {
286             printk("Aml  get mac address from key " \
287                     "[%02x:%02x:%02x:%02x:%02x:%02x]\n", \
288                      mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
289              memcpy(&sh->cfg.maddr[0][0], mac, ETH_ALEN);
290              addr_increase_copy(&sh->cfg.maddr[1][0], mac);
291             goto Done;
292         }
293         else {
294             printk(">=========Aml invalid_wifi_addr=========< \n");
295         }
296 #endif
297 #ifdef ROCKCHIP_3126_SUPPORT
298         if (!rockchip_wifi_mac_addr(mac)) {
299             printk("=========> get mac address from flash [%02x:%02x:%02x:%02x:%02x:%02x]\n", mac[0], mac[1],
300                     mac[2], mac[3], mac[4], mac[5]);
301             if(is_valid_ether_addr(mac)) {
302                 memcpy(&sh->cfg.maddr[0][0],mac,ETH_ALEN);
303                 addr_increase_copy(&sh->cfg.maddr[1][0],mac);
304                 goto Done;
305             }
306         }
307 #endif
308         if(!sh->cfg.ignore_efuse_mac)
309         {
310             if (is_valid_ether_addr(rom_mac0)) {
311                 printk("MAC address from e-fuse\n");
312                 memcpy(&sh->cfg.maddr[0][0], rom_mac0, ETH_ALEN);
313                 addr_increase_copy(&sh->cfg.maddr[1][0], rom_mac0);
314                 goto Done;
315             }
316         }
317         if (ssv_initmac != NULL)
318         {
319             for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3 ) {
320                 mac[jj] = key_2char2num(ssv_initmac[kk], ssv_initmac[kk+ 1]);
321             }
322             if(is_valid_ether_addr(mac)) {
323                 printk("MAC address from insert module\n");
324                 memcpy(&sh->cfg.maddr[0][0],mac,ETH_ALEN);
325                 addr_increase_copy(&sh->cfg.maddr[1][0],mac);
326                 goto Done;
327             }
328         }
329         if (sh->cfg.mac_address_path[0] != 0x00)
330         {
331             if((readfile_mac(sh->cfg.mac_address_path,&sh->cfg.maddr[0][0])) && (is_valid_ether_addr(&sh->cfg.maddr[0][0])))
332             {
333                 printk("MAC address from sh->cfg.mac_address_path[wifi.cfg]\n");
334                 addr_increase_copy(&sh->cfg.maddr[1][0], &sh->cfg.maddr[0][0]);
335                 goto Done;
336             }
337         }
338         switch (sh->cfg.mac_address_mode) {
339         case 1:
340             get_random_bytes(&sh->cfg.maddr[0][0],ETH_ALEN);
341             sh->cfg.maddr[0][0] = sh->cfg.maddr[0][0] & 0xF0;
342             addr_increase_copy(&sh->cfg.maddr[1][0], &sh->cfg.maddr[0][0]);
343             break;
344         case 2:
345             if((readfile_mac(sh->cfg.mac_output_path,&sh->cfg.maddr[0][0])) && (is_valid_ether_addr(&sh->cfg.maddr[0][0])))
346             {
347                 addr_increase_copy(&sh->cfg.maddr[1][0], &sh->cfg.maddr[0][0]);
348             }
349             else
350             {
351                 {
352                     get_random_bytes(&sh->cfg.maddr[0][0],ETH_ALEN);
353                     sh->cfg.maddr[0][0] = sh->cfg.maddr[0][0] & 0xF0;
354                     addr_increase_copy(&sh->cfg.maddr[1][0], &sh->cfg.maddr[0][0]);
355                     if (sh->cfg.mac_output_path[0] != 0x00)
356                         write_mac_to_file(sh->cfg.mac_output_path,&sh->cfg.maddr[0][0]);
357                 }
358             }
359             break;
360         default:
361             memcpy(&sh->cfg.maddr[0][0], pseudo_mac0, ETH_ALEN);
362             addr_increase_copy(&sh->cfg.maddr[1][0], pseudo_mac0);
363             break;
364         }
365         printk("MAC address from Software MAC mode[%d]\n",sh->cfg.mac_address_mode);
366     }
367 Done:
368     printk("EFUSE configuration\n");
369     printk("Read efuse chip identity[%08x]\n",ssv_cfg.chip_identity);
370     printk("r_calbration_result- %x\n",ssv_cfg.r_calbration_result);
371     printk("sar_result- %x\n",ssv_cfg.sar_result);
372     printk("crystal_frequency_offset- %x\n",ssv_cfg.crystal_frequency_offset);
373     printk("tx_power_index_1- %x\n",ssv_cfg.tx_power_index_1);
374     printk("tx_power_index_2- %x\n",ssv_cfg.tx_power_index_2);
375  printk("MAC address - %pM\n", rom_mac0);
376     sh->cfg.crystal_frequency_offset = ssv_cfg.crystal_frequency_offset;
377     sh->cfg.tx_power_index_1 = ssv_cfg.tx_power_index_1;
378     sh->cfg.tx_power_index_2 = ssv_cfg.tx_power_index_2;
379     sh->cfg.chip_identity = ssv_cfg.chip_identity;
380 }
381