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