| /****************************************************************************** |
| * |
| * (c) Copyright 2008, RealTEK Technologies Inc. All Rights Reserved. |
| * |
| * Module: Efuse.c ( Source C File) |
| * |
| * Note: Copy from WMAC for the first version!!!! |
| * |
| * |
| * Function: |
| * |
| * Export: |
| * |
| * Abbrev: |
| * |
| * History: |
| * Data Who Remark |
| * |
| * 09/23/2008 MHC Porting Efuse R/W API from WMAC. |
| * 11/10/2008 MHC 1. Porting from 8712 EFUSE. |
| * 2. Add description and reorganize code arch. |
| * 11/16/2008 MHC 1. Reorganize code architecture. |
| * 2. Rename for some API and change extern or static type. |
| * |
| ******************************************************************************/ |
| #include "r8192U.h" |
| #include "r8192S_hw.h" |
| #include "r8192S_phy.h" |
| #include "r8192S_phyreg.h" |
| #include "r8192S_Efuse.h" |
| |
| #include <linux/types.h> |
| |
| //typedef int INT32; |
| // |
| // In the future, we will always support EFUSE!! |
| // |
| /*---------------------------Define Local Constant---------------------------*/ |
| #define _POWERON_DELAY_ |
| #define _PRE_EXECUTE_READ_CMD_ |
| |
| #define EFUSE_REPEAT_THRESHOLD_ 3 |
| #define EFUSE_ERROE_HANDLE 1 |
| |
| |
| // From 8712!!!!! |
| typedef struct _EFUSE_MAP_A{ |
| u8 offset; //0~15 |
| u8 word_start; //0~3 |
| u8 byte_start; //0 or 1 |
| u8 byte_cnts; |
| |
| }EFUSE_MAP, *PEFUSE_MAP; |
| |
| typedef struct PG_PKT_STRUCT_A{ |
| u8 offset; |
| u8 word_en; |
| u8 data[8]; |
| }PGPKT_STRUCT,*PPGPKT_STRUCT; |
| |
| typedef enum _EFUSE_DATA_ITEM{ |
| EFUSE_CHIP_ID=0, |
| EFUSE_LDO_SETTING, |
| EFUSE_CLK_SETTING, |
| EFUSE_SDIO_SETTING, |
| EFUSE_CCCR, |
| EFUSE_SDIO_MODE, |
| EFUSE_OCR, |
| EFUSE_F0CIS, |
| EFUSE_F1CIS, |
| EFUSE_MAC_ADDR, |
| EFUSE_EEPROM_VER, |
| EFUSE_CHAN_PLAN, |
| EFUSE_TXPW_TAB |
| } EFUSE_DATA_ITEM; |
| |
| struct efuse_priv |
| { |
| u8 id[2]; |
| u8 ldo_setting[2]; |
| u8 clk_setting[2]; |
| u8 cccr; |
| u8 sdio_mode; |
| u8 ocr[3]; |
| u8 cis0[17]; |
| u8 cis1[48]; |
| u8 mac_addr[6]; |
| u8 eeprom_verno; |
| u8 channel_plan; |
| u8 tx_power_b[14]; |
| u8 tx_power_g[14]; |
| }; |
| |
| /*---------------------------Define Local Constant---------------------------*/ |
| |
| |
| /*------------------------Define global variable-----------------------------*/ |
| const u8 MAX_PGPKT_SIZE = 9; //header+ 2* 4 words (BYTES) |
| const u8 PGPKT_DATA_SIZE = 8; //BYTES sizeof(u8)*8 |
| const u32 EFUSE_MAX_SIZE = 512; |
| |
| |
| const EFUSE_MAP RTL8712_SDIO_EFUSE_TABLE[]={ |
| //offset word_s byte_start byte_cnts |
| /*ID*/ {0 ,0 ,0 ,2 }, // 00~01h |
| /*LDO Setting*/ {0 ,1 ,0 ,2 }, // 02~03h |
| /*CLK Setting*/ {0 ,2 ,0 ,2 }, // 04~05h |
| /*SDIO Setting*/ {1 ,0 ,0 ,1 }, // 08h |
| /*CCCR*/ {1 ,0 ,1 ,1 }, // 09h |
| /*SDIO MODE*/ {1 ,1 ,0 ,1 }, // 0Ah |
| /*OCR*/ {1 ,1 ,1 ,3 }, // 0B~0Dh |
| /*CCIS*/ {1 ,3 ,0 ,17 }, // 0E~1Eh 2...1 |
| /*F1CIS*/ {3 ,3 ,1 ,48 }, // 1F~4Eh 6...0 |
| /*MAC Addr*/ {10 ,0 ,0 ,6 }, // 50~55h |
| /*EEPROM ver*/ {10 ,3 ,0 ,1 }, // 56h |
| /*Channel plan*/ {10 ,3 ,1 ,1 }, // 57h |
| /*TxPwIndex */ {11 ,0 ,0 ,28 } // 58~73h 3...4 |
| }; |
| |
| /*------------------------Define global variable-----------------------------*/ |
| |
| |
| /*------------------------Define local variable------------------------------*/ |
| |
| /*------------------------Define local variable------------------------------*/ |
| |
| |
| /*--------------------Define function prototype-----------------------*/ |
| // |
| // From WMAC Efuse one byte R/W |
| // |
| extern void |
| EFUSE_Initialize(struct net_device* dev); |
| extern u8 |
| EFUSE_Read1Byte(struct net_device* dev, u16 Address); |
| extern void |
| EFUSE_Write1Byte(struct net_device* dev, u16 Address,u8 Value); |
| |
| // |
| // Efuse Shadow Area operation |
| // |
| static void |
| efuse_ShadowRead1Byte(struct net_device* dev,u16 Offset,u8 *Value); |
| static void |
| efuse_ShadowRead2Byte(struct net_device* dev, u16 Offset,u16 *Value ); |
| static void |
| efuse_ShadowRead4Byte(struct net_device* dev, u16 Offset,u32 *Value ); |
| static void |
| efuse_ShadowWrite1Byte(struct net_device* dev, u16 Offset, u8 Value); |
| static void |
| efuse_ShadowWrite2Byte(struct net_device* dev, u16 Offset,u16 Value); |
| static void |
| efuse_ShadowWrite4Byte(struct net_device* dev, u16 Offset,u32 Value); |
| |
| // |
| // Real Efuse operation |
| // |
| static u8 |
| efuse_OneByteRead(struct net_device* dev,u16 addr,u8 *data); |
| static u8 |
| efuse_OneByteWrite(struct net_device* dev,u16 addr, u8 data); |
| |
| // |
| // HW setting map file operation |
| // |
| static void |
| efuse_ReadAllMap(struct net_device* dev,u8 *Efuse); |
| #ifdef TO_DO_LIST |
| static void |
| efuse_WriteAllMap(struct net_device* dev,u8 *eeprom,u32 eeprom_size); |
| static bool |
| efuse_ParsingMap(char* szStr,u32* pu4bVal,u32* pu4bMove); |
| #endif |
| // |
| // Reald Efuse R/W or other operation API. |
| // |
| static u8 |
| efuse_PgPacketRead( struct net_device* dev,u8 offset,u8 *data); |
| static u8 |
| efuse_PgPacketWrite(struct net_device* dev,u8 offset,u8 word_en,u8 *data); |
| static void |
| efuse_WordEnableDataRead( u8 word_en,u8 *sourdata,u8 *targetdata); |
| static u8 |
| efuse_WordEnableDataWrite( struct net_device* dev, u16 efuse_addr, u8 word_en, u8 *data); |
| static void |
| efuse_PowerSwitch(struct net_device* dev,u8 PwrState); |
| static u16 |
| efuse_GetCurrentSize(struct net_device* dev); |
| static u8 |
| efuse_CalculateWordCnts(u8 word_en); |
| // |
| // API for power on power off!!! |
| // |
| #ifdef TO_DO_LIST |
| static void efuse_reg_ctrl(struct net_device* dev, u8 bPowerOn); |
| #endif |
| /*--------------------Define function prototype-----------------------*/ |
| |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_Initialize |
| * |
| * Overview: Copy from WMAC fot EFUSE testing setting init. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 09/23/2008 MHC Copy from WMAC. |
| * |
| *---------------------------------------------------------------------------*/ |
| extern void |
| EFUSE_Initialize(struct net_device* dev) |
| { |
| u8 Bytetemp = {0x00}; |
| u8 temp = {0x00}; |
| |
| //Enable Digital Core Vdd : 0x2[13]=1 |
| Bytetemp = read_nic_byte(dev, SYS_FUNC_EN+1); |
| temp = Bytetemp | 0x20; |
| write_nic_byte(dev, SYS_FUNC_EN+1, temp); |
| |
| //EE loader to retention path1: attach 0x0[8]=0 |
| Bytetemp = read_nic_byte(dev, SYS_ISO_CTRL+1); |
| temp = Bytetemp & 0xFE; |
| write_nic_byte(dev, SYS_ISO_CTRL+1, temp); |
| |
| |
| //Enable E-fuse use 2.5V LDO : 0x37[7]=1 |
| Bytetemp = read_nic_byte(dev, EFUSE_TEST+3); |
| temp = Bytetemp | 0x80; |
| write_nic_byte(dev, EFUSE_TEST+3, temp); |
| |
| //E-fuse clk switch from 500k to 40M : 0x2F8[1:0]=11b |
| write_nic_byte(dev, 0x2F8, 0x3); |
| |
| //Set E-fuse program time & read time : 0x30[30:24]=1110010b |
| write_nic_byte(dev, EFUSE_CTRL+3, 0x72); |
| |
| } /* EFUSE_Initialize */ |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_Read1Byte |
| * |
| * Overview: Copy from WMAC fot EFUSE read 1 byte. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 09/23/2008 MHC Copy from WMAC. |
| * |
| *---------------------------------------------------------------------------*/ |
| extern u8 |
| EFUSE_Read1Byte(struct net_device* dev, u16 Address) |
| { |
| u8 data; |
| u8 Bytetemp = {0x00}; |
| u8 temp = {0x00}; |
| u32 k=0; |
| |
| if (Address < EFUSE_MAC_LEN) //E-fuse 512Byte |
| { |
| //Write E-fuse Register address bit0~7 |
| temp = Address & 0xFF; |
| write_nic_byte(dev, EFUSE_CTRL+1, temp); |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+2); |
| //Write E-fuse Register address bit8~9 |
| temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); |
| write_nic_byte(dev, EFUSE_CTRL+2, temp); |
| |
| //Write 0x30[31]=0 |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); |
| temp = Bytetemp & 0x7F; |
| write_nic_byte(dev, EFUSE_CTRL+3, temp); |
| |
| //Wait Write-ready (0x30[31]=1) |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); |
| while(!(Bytetemp & 0x80)) |
| { |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); |
| k++; |
| if(k==1000) |
| { |
| k=0; |
| break; |
| } |
| } |
| data=read_nic_byte(dev, EFUSE_CTRL); |
| return data; |
| } |
| else |
| return 0xFF; |
| |
| } /* EFUSE_Read1Byte */ |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_Write1Byte |
| * |
| * Overview: Copy from WMAC fot EFUSE write 1 byte. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 09/23/2008 MHC Copy from WMAC. |
| * |
| *---------------------------------------------------------------------------*/ |
| extern void |
| EFUSE_Write1Byte(struct net_device* dev, u16 Address,u8 Value) |
| { |
| //u8 data; |
| u8 Bytetemp = {0x00}; |
| u8 temp = {0x00}; |
| u32 k=0; |
| |
| //RT_TRACE(COMP_EFUSE, "Addr=%x Data =%x\n", Address, Value); |
| |
| if( Address < EFUSE_MAC_LEN) //E-fuse 512Byte |
| { |
| write_nic_byte(dev, EFUSE_CTRL, Value); |
| |
| //Write E-fuse Register address bit0~7 |
| temp = Address & 0xFF; |
| write_nic_byte(dev, EFUSE_CTRL+1, temp); |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+2); |
| |
| //Write E-fuse Register address bit8~9 |
| temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC); |
| write_nic_byte(dev, EFUSE_CTRL+2, temp); |
| |
| //Write 0x30[31]=1 |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); |
| temp = Bytetemp | 0x80; |
| write_nic_byte(dev, EFUSE_CTRL+3, temp); |
| |
| //Wait Write-ready (0x30[31]=0) |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); |
| while(Bytetemp & 0x80) |
| { |
| Bytetemp = read_nic_byte(dev, EFUSE_CTRL+3); |
| k++; |
| if(k==100) |
| { |
| k=0; |
| break; |
| } |
| } |
| } |
| |
| } /* EFUSE_Write1Byte */ |
| |
| |
| #ifdef EFUSE_FOR_92SU |
| // |
| // Description: |
| // 1. Process CR93C46 Data polling cycle. |
| // 2. Refered from SD1 Richard. |
| // |
| // Assumption: |
| // 1. Boot from E-Fuse and successfully auto-load. |
| // 2. PASSIVE_LEVEL (USB interface) |
| // |
| // Created by Roger, 2008.10.21. |
| // |
| void do_93c46(struct net_device* dev, u8 addorvalue) |
| { |
| //u8 clear[1] = {0x0}; // cs=0 , sk=0 , di=0 , do=0 |
| u8 cs[1] = {0x88}; // cs=1 , sk=0 , di=0 , do=0 |
| u8 cssk[1] = {0x8c}; // cs=1 , sk=1 , di=0 , do=0 |
| u8 csdi[1] = {0x8a}; // cs=1 , sk=0 , di=1 , do=0 |
| u8 csskdi[1] = {0x8e}; // cs=1 , sk=1 , di=1 , do=0 |
| //u8 di[1] = {0x82}; // cs=0 , sk=0 , di=1 , do=0 |
| u8 count; |
| |
| for(count=0 ; count<8 ; count++) |
| { |
| if((addorvalue&0x80)!=0) |
| { |
| write_nic_byte(dev, EPROM_CMD, csdi[0]); |
| write_nic_byte(dev, EPROM_CMD, csskdi[0]); |
| } |
| else |
| { |
| write_nic_byte(dev, EPROM_CMD, cs[0]); |
| write_nic_byte(dev, EPROM_CMD, cssk[0]); |
| } |
| addorvalue = addorvalue << 1; |
| } |
| } |
| |
| |
| // |
| // Description: |
| // Process CR93C46 Data read polling cycle. |
| // Refered from SD1 Richard. |
| // |
| // Assumption: |
| // 1. Boot from E-Fuse and successfully auto-load. |
| // 2. PASSIVE_LEVEL (USB interface) |
| // |
| // Created by Roger, 2008.10.21. |
| // |
| u16 Read93C46(struct net_device* dev, u16 Reg ) |
| { |
| |
| u8 clear[1] = {0x0}; // cs=0 , sk=0 , di=0 , do=0 |
| u8 cs[1] = {0x88}; // cs=1 , sk=0 , di=0 , do=0 |
| u8 cssk[1] = {0x8c}; // cs=1 , sk=1 , di=0 , do=0 |
| u8 csdi[1] = {0x8a}; // cs=1 , sk=0 , di=1 , do=0 |
| u8 csskdi[1] = {0x8e}; // cs=1 , sk=1 , di=1 , do=0 |
| //u8 di[1] = {0x82}; // cs=0 , sk=0 , di=1 , do=0 |
| u8 EepromSEL[1]={0x00}; |
| u8 address; |
| |
| u16 storedataF[1] = {0x0}; //93c46 data packet for 16bits |
| u8 t,data[1],storedata[1]; |
| |
| |
| address = (u8)Reg; |
| |
| // Suggested by SD1 Alex, 2008.10.20. Revised by Roger. |
| *EepromSEL= read_nic_byte(dev, EPROM_CMD); |
| |
| if((*EepromSEL & 0x10) == 0x10) // select 93c46 |
| { |
| address = address | 0x80; |
| |
| write_nic_byte(dev, EPROM_CMD, csdi[0]); |
| write_nic_byte(dev, EPROM_CMD, csskdi[0]); |
| do_93c46(dev, address); |
| } |
| |
| |
| for(t=0 ; t<16 ; t++) //if read 93c46 , t=16 |
| { |
| write_nic_byte(dev, EPROM_CMD, cs[0]); |
| write_nic_byte(dev, EPROM_CMD, cssk[0]); |
| *data= read_nic_byte(dev, EPROM_CMD); |
| |
| if(*data & 0x8d) //original code |
| { |
| *data = *data & 0x01; |
| *storedata = *data; |
| } |
| else |
| { |
| *data = *data & 0x01 ; |
| *storedata = *data; |
| } |
| *storedataF = (*storedataF << 1 ) + *storedata; |
| } |
| write_nic_byte(dev, EPROM_CMD, cs[0]); |
| write_nic_byte(dev, EPROM_CMD, clear[0]); |
| |
| return *storedataF; |
| } |
| |
| |
| // |
| // Description: |
| // Execute E-Fuse read byte operation. |
| // Refered from SD1 Richard. |
| // |
| // Assumption: |
| // 1. Boot from E-Fuse and successfully auto-load. |
| // 2. PASSIVE_LEVEL (USB interface) |
| // |
| // Created by Roger, 2008.10.21. |
| // |
| void |
| ReadEFuseByte(struct net_device* dev,u16 _offset, u8 *pbuf) |
| { |
| |
| //u16 indexk=0; |
| u32 value32; |
| u8 readbyte; |
| u16 retry; |
| |
| |
| //Write Address |
| write_nic_byte(dev, EFUSE_CTRL+1, (_offset & 0xff)); |
| readbyte = read_nic_byte(dev, EFUSE_CTRL+2); |
| write_nic_byte(dev, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc)); |
| |
| //Write bit 32 0 |
| readbyte = read_nic_byte(dev, EFUSE_CTRL+3); |
| write_nic_byte(dev, EFUSE_CTRL+3, (readbyte & 0x7f)); |
| |
| //Check bit 32 read-ready |
| retry = 0; |
| value32 = read_nic_dword(dev, EFUSE_CTRL); |
| //while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10)) |
| while(!(((value32 >> 24) & 0xff) & 0x80) && (retry<10000)) |
| { |
| value32 = read_nic_dword(dev, EFUSE_CTRL); |
| retry++; |
| } |
| *pbuf = (u8)(value32 & 0xff); |
| } |
| |
| |
| #define EFUSE_READ_SWITCH 1 |
| // |
| // Description: |
| // 1. Execute E-Fuse read byte operation according as map offset and |
| // save to E-Fuse table. |
| // 2. Refered from SD1 Richard. |
| // |
| // Assumption: |
| // 1. Boot from E-Fuse and successfully auto-load. |
| // 2. PASSIVE_LEVEL (USB interface) |
| // |
| // Created by Roger, 2008.10.21. |
| // |
| void |
| ReadEFuse(struct net_device* dev, u16 _offset, u16 _size_byte, u8 *pbuf) |
| { |
| |
| u8 efuseTbl[128]; |
| u8 rtemp8[1]; |
| u16 eFuse_Addr = 0; |
| u8 offset, wren; |
| u16 i, j; |
| u16 eFuseWord[16][4];// = {0xFF};//FIXLZM |
| |
| for(i=0; i<16; i++) |
| for(j=0; j<4; j++) |
| eFuseWord[i][j]=0xFF; |
| |
| // Do NOT excess total size of EFuse table. Added by Roger, 2008.11.10. |
| if((_offset + _size_byte)>128) |
| {// total E-Fuse table is 128bytes |
| //RT_TRACE(COMP_EFUSE, "ReadEFuse(): Invalid offset(%#x) with read bytes(%#x)!!\n",_offset, _size_byte); |
| printk("ReadEFuse(): Invalid offset with read bytes!!\n"); |
| return; |
| } |
| |
| // Refresh efuse init map as all oxFF. |
| for (i = 0; i < 128; i++) |
| efuseTbl[i] = 0xFF; |
| |
| #if (EFUSE_READ_SWITCH == 1) |
| ReadEFuseByte(dev, eFuse_Addr, rtemp8); |
| #else |
| rtemp8[0] = EFUSE_Read1Byte(dev, eFuse_Addr); |
| #endif |
| if(*rtemp8 != 0xFF) eFuse_Addr++; |
| while((*rtemp8 != 0xFF) && (eFuse_Addr < 512)){ |
| offset = ((*rtemp8 >> 4) & 0x0f); |
| if(offset <= 0x0F){ |
| wren = (*rtemp8 & 0x0f); |
| for(i=0; i<4; i++){ |
| if(!(wren & 0x01)){ |
| #if (EFUSE_READ_SWITCH == 1) |
| ReadEFuseByte(dev, eFuse_Addr, rtemp8); eFuse_Addr++; |
| #else |
| rtemp8[0] = EFUSE_Read1Byte(dev, eFuse_Addr); eFuse_Addr++; |
| #endif |
| eFuseWord[offset][i] = (*rtemp8 & 0xff); |
| if(eFuse_Addr >= 512) break; |
| #if (EFUSE_READ_SWITCH == 1) |
| ReadEFuseByte(dev, eFuse_Addr, rtemp8); eFuse_Addr++; |
| #else |
| rtemp8[0] = EFUSE_Read1Byte(dev, eFuse_Addr); eFuse_Addr++; |
| #endif |
| eFuseWord[offset][i] |= (((u16)*rtemp8 << 8) & 0xff00); |
| if(eFuse_Addr >= 512) break; |
| } |
| wren >>= 1; |
| } |
| } |
| #if (EFUSE_READ_SWITCH == 1) |
| ReadEFuseByte(dev, eFuse_Addr, rtemp8); |
| #else |
| rtemp8[0] = EFUSE_Read1Byte(dev, eFuse_Addr); eFuse_Addr++; |
| #endif |
| if(*rtemp8 != 0xFF && (eFuse_Addr < 512)) eFuse_Addr++; |
| } |
| |
| for(i=0; i<16; i++){ |
| for(j=0; j<4; j++){ |
| efuseTbl[(i*8)+(j*2)]=(eFuseWord[i][j] & 0xff); |
| efuseTbl[(i*8)+((j*2)+1)]=((eFuseWord[i][j] >> 8) & 0xff); |
| } |
| } |
| for(i=0; i<_size_byte; i++) |
| pbuf[i] = efuseTbl[_offset+i]; |
| } |
| #endif // #if (EFUSE_FOR_92SU == 1) |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_ShadowRead |
| * |
| * Overview: Read from efuse init map !!!!! |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/12/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| extern void |
| EFUSE_ShadowRead( struct net_device* dev, u8 Type, u16 Offset, u32 *Value) |
| { |
| //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); |
| |
| if (Type == 1) |
| efuse_ShadowRead1Byte(dev, Offset, (u8 *)Value); |
| else if (Type == 2) |
| efuse_ShadowRead2Byte(dev, Offset, (u16 *)Value); |
| else if (Type == 4) |
| efuse_ShadowRead4Byte(dev, Offset, (u32 *)Value); |
| |
| } // EFUSE_ShadowRead |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_ShadowWrite |
| * |
| * Overview: Write efuse modify map for later update operation to use!!!!! |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/12/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| extern void |
| EFUSE_ShadowWrite( struct net_device* dev, u8 Type, u16 Offset,u32 Value) |
| { |
| //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); |
| |
| if (Offset >= 0x18 && Offset <= 0x1F) |
| return; |
| |
| if (Type == 1) |
| efuse_ShadowWrite1Byte(dev, Offset, (u8)Value); |
| else if (Type == 2) |
| efuse_ShadowWrite2Byte(dev, Offset, (u16)Value); |
| else if (Type == 4) |
| efuse_ShadowWrite4Byte(dev, Offset, (u32)Value); |
| |
| } // EFUSE_ShadowWrite |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_ShadowUpdate |
| * |
| * Overview: Compare init and modify map to update Efuse!!!!! |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/12/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| extern void |
| EFUSE_ShadowUpdate(struct net_device* dev) |
| { |
| //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(pAdapter); |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| u16 i, offset, base = 0; |
| u8 word_en = 0x0F; |
| bool first_pg = false; |
| // For Efuse write action, we must enable LDO2.5V and 40MHZ clk. |
| efuse_PowerSwitch(dev, TRUE); |
| |
| // |
| // Efuse support 16 write are with PG header packet!!!! |
| // |
| for (offset = 0; offset < 16; offset++) |
| { |
| // Offset 0x18-1F are reserved now!!! |
| word_en = 0x0F; |
| base = offset * 8; |
| |
| // |
| // Decide Word Enable Bit for the Efuse section |
| // One section contain 4 words = 8 bytes!!!!! |
| // |
| for (i = 0; i < 8; i++) |
| { |
| if (offset == 0 && priv->EfuseMap[EFUSE_INIT_MAP][base+i] == 0xFF) |
| { |
| first_pg = TRUE; |
| } |
| |
| // 2008/12/11 MH HW autoload fail workaround for A/BCUT. |
| |
| if (first_pg == TRUE) |
| { |
| word_en &= ~(1<<(i/2)); |
| priv->EfuseMap[EFUSE_INIT_MAP][base+i] = |
| priv->EfuseMap[EFUSE_MODIFY_MAP][base+i]; |
| }else |
| { |
| if ( priv->EfuseMap[EFUSE_INIT_MAP][base+i] != |
| priv->EfuseMap[EFUSE_MODIFY_MAP][base+i]) |
| { |
| word_en &= ~(EFUSE_BIT(i/2)); |
| //RT_TRACE(COMP_EFUSE, "Offset=%d Addr%x %x ==> %x Word_En=%02x\n", |
| //offset, base+i, priv->EfuseMap[0][base+i], priv->EfuseMap[1][base+i],word_en); |
| |
| // Update init table!!! |
| priv->EfuseMap[EFUSE_INIT_MAP][base+i] = |
| priv->EfuseMap[EFUSE_MODIFY_MAP][base+i]; |
| } |
| } |
| } |
| |
| // |
| // Call Efuse real write section !!!! |
| // |
| if (word_en != 0x0F) |
| { |
| u8 tmpdata[8]; |
| |
| //FIXLZM |
| memcpy(tmpdata, &(priv->EfuseMap[EFUSE_MODIFY_MAP][base]), 8); |
| //RT_PRINT_DATA(COMP_INIT, DBG_LOUD, ("U-EFUSE\n"), tmpdata, 8); |
| efuse_PgPacketWrite(dev,(u8)offset,word_en,tmpdata); |
| } |
| |
| } |
| // 2008/12/01 MH For Efuse HW load bug workarounf method!!!! |
| // We will force write 0x10EC into address 10&11 after all Efuse content. |
| // |
| |
| |
| // For warm reboot, we must resume Efuse clock to 500K. |
| efuse_PowerSwitch(dev, FALSE); |
| // 2008/12/01 MH We update shadow content again!!!! |
| EFUSE_ShadowMapUpdate(dev); |
| |
| } // EFUSE_ShadowUpdate |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_ShadowMapUpdate |
| * |
| * Overview: Transfer current EFUSE content to shadow init and modify map. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/13/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| extern void EFUSE_ShadowMapUpdate(struct net_device* dev) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| |
| if (priv->AutoloadFailFlag == true){ |
| memset(&(priv->EfuseMap[EFUSE_INIT_MAP][0]), 0xff, 128); |
| }else{ |
| efuse_ReadAllMap(dev, &priv->EfuseMap[EFUSE_INIT_MAP][0]); |
| } |
| //PlatformMoveMemory(&priv->EfuseMap[EFUSE_MODIFY_MAP][0], |
| //&priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S);//FIXLZM |
| memcpy(&priv->EfuseMap[EFUSE_MODIFY_MAP][0], |
| &priv->EfuseMap[EFUSE_INIT_MAP][0], HWSET_MAX_SIZE_92S); |
| |
| } // EFUSE_ShadowMapUpdate |
| |
| extern void |
| EFUSE_ForceWriteVendorId( struct net_device* dev) |
| { |
| u8 tmpdata[8] = {0xFF, 0xFF, 0xEC, 0x10, 0xFF, 0xFF, 0xFF, 0xFF}; |
| |
| efuse_PowerSwitch(dev, TRUE); |
| |
| efuse_PgPacketWrite(dev, 1, 0xD, tmpdata); |
| |
| efuse_PowerSwitch(dev, FALSE); |
| |
| } // EFUSE_ForceWriteVendorId |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_ShadowRead1Byte |
| * efuse_ShadowRead2Byte |
| * efuse_ShadowRead4Byte |
| * |
| * Overview: Read from efuse init map by one/two/four bytes !!!!! |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/12/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| static void |
| efuse_ShadowRead1Byte(struct net_device* dev, u16 Offset, u8 *Value) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| |
| *Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset]; |
| |
| } // EFUSE_ShadowRead1Byte |
| |
| //---------------Read Two Bytes |
| static void |
| efuse_ShadowRead2Byte(struct net_device* dev, u16 Offset, u16 *Value) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| |
| *Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset]; |
| *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1]<<8; |
| |
| } // EFUSE_ShadowRead2Byte |
| |
| //---------------Read Four Bytes |
| static void |
| efuse_ShadowRead4Byte(struct net_device* dev, u16 Offset, u32 *Value) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| |
| *Value = priv->EfuseMap[EFUSE_MODIFY_MAP][Offset]; |
| *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1]<<8; |
| *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+2]<<16; |
| *Value |= priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+3]<<24; |
| |
| } // efuse_ShadowRead4Byte |
| |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_ShadowWrite1Byte |
| * efuse_ShadowWrite2Byte |
| * efuse_ShadowWrite4Byte |
| * |
| * Overview: Write efuse modify map by one/two/four byte. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/12/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| static void |
| efuse_ShadowWrite1Byte(struct net_device* dev, u16 Offset, u8 Value) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| |
| priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = Value; |
| |
| } // efuse_ShadowWrite1Byte |
| |
| //---------------Write Two Bytes |
| static void |
| efuse_ShadowWrite2Byte(struct net_device* dev, u16 Offset, u16 Value) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| |
| priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = Value&0x00FF; |
| priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1] = Value>>8; |
| |
| } // efuse_ShadowWrite1Byte |
| |
| //---------------Write Four Bytes |
| static void |
| efuse_ShadowWrite4Byte(struct net_device* dev, u16 Offset, u32 Value) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| |
| priv->EfuseMap[EFUSE_MODIFY_MAP][Offset] = (u8)(Value&0x000000FF); |
| priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+1] = (u8)((Value>>8)&0x0000FF); |
| priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+2] = (u8)((Value>>16)&0x00FF); |
| priv->EfuseMap[EFUSE_MODIFY_MAP][Offset+3] = (u8)((Value>>24)&0xFF); |
| |
| } // efuse_ShadowWrite1Byte |
| |
| |
| /* 11/16/2008 MH Read one byte from real Efuse. */ |
| static u8 |
| efuse_OneByteRead(struct net_device* dev, u16 addr,u8 *data) |
| { |
| u8 tmpidx = 0; |
| u8 bResult; |
| |
| // -----------------e-fuse reg ctrl --------------------------------- |
| //address |
| write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff)); |
| write_nic_byte(dev, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03) ) | |
| (read_nic_byte(dev, EFUSE_CTRL+2)&0xFC )); |
| |
| write_nic_byte(dev, EFUSE_CTRL+3, 0x72);//read cmd |
| |
| while(!(0x80 &read_nic_byte(dev, EFUSE_CTRL+3))&&(tmpidx<100)) |
| { |
| tmpidx++; |
| } |
| if(tmpidx<100) |
| { |
| *data=read_nic_byte(dev, EFUSE_CTRL); |
| bResult = TRUE; |
| } |
| else |
| { |
| *data = 0xff; |
| bResult = FALSE; |
| } |
| return bResult; |
| } // efuse_OneByteRead |
| |
| /* 11/16/2008 MH Write one byte to reald Efuse. */ |
| static u8 |
| efuse_OneByteWrite(struct net_device* dev, u16 addr, u8 data) |
| { |
| u8 tmpidx = 0; |
| u8 bResult; |
| |
| //RT_TRACE(COMP_EFUSE, "Addr = %x Data=%x\n", addr, data); |
| |
| //return 0; |
| |
| // -----------------e-fuse reg ctrl --------------------------------- |
| //address |
| write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff)); |
| write_nic_byte(dev, EFUSE_CTRL+2, |
| read_nic_byte(dev, EFUSE_CTRL+2)|(u8)((addr>>8)&0x03) ); |
| |
| write_nic_byte(dev, EFUSE_CTRL, data);//data |
| write_nic_byte(dev, EFUSE_CTRL+3, 0xF2);//write cmd |
| |
| while((0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){ |
| tmpidx++; |
| } |
| |
| if(tmpidx<100) |
| { |
| bResult = TRUE; |
| } |
| else |
| { |
| bResult = FALSE; |
| } |
| |
| return bResult; |
| } // efuse_OneByteWrite |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_ReadAllMap |
| * |
| * Overview: Read All Efuse content |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/11/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| static void |
| efuse_ReadAllMap(struct net_device* dev, u8 *Efuse) |
| { |
| //u8 pg_data[8]; |
| //u8 offset = 0; |
| //u8 tmpidx; |
| //static u8 index = 0; |
| |
| // |
| // We must enable clock and LDO 2.5V otherwise, read all map will be fail!!!! |
| // |
| efuse_PowerSwitch(dev, TRUE); |
| ReadEFuse(dev, 0, 128, Efuse); |
| efuse_PowerSwitch(dev, FALSE); |
| } // efuse_ReadAllMap |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_WriteAllMap |
| * |
| * Overview: Write All Efuse content |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/11/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| #ifdef TO_DO_LIST |
| static void |
| efuse_WriteAllMap(struct net_device* dev,u8 *eeprom, u32 eeprom_size) |
| { |
| unsigned char word_en = 0x00; |
| |
| unsigned char tmpdata[8]; |
| unsigned char offset; |
| |
| // For Efuse write action, we must enable LDO2.5V and 40MHZ clk. |
| efuse_PowerSwitch(dev, TRUE); |
| |
| //sdio contents |
| for(offset=0 ; offset< eeprom_size/PGPKT_DATA_SIZE ; offset++) |
| { |
| // 92S will only reserv 0x18-1F 8 bytes now. The 3rd efuse write area! |
| if (IS_HARDWARE_TYPE_8192SE(dev)) |
| { |
| // Refer to |
| // 0x18-1f Reserve >0x50 Reserve for tx power |
| if (offset == 3/* || offset > 9*/) |
| continue;//word_en = 0x0F; |
| //else if (offset == 9) // 0x4c-4f Reserve |
| //word_en = 0x0C; |
| else |
| word_en = 0x00; |
| } |
| //RT_TRACE(COMP_EFUSE, ("Addr=%d size=%d Word_En=%02x\n", offset, eeprom_size, word_en)); |
| |
| //memcpy(tmpdata,eeprom+(offset*PGPKT_DATA_SIZE),8); |
| memcpy(tmpdata, (eeprom+(offset*PGPKT_DATA_SIZE)), 8); |
| |
| //RT_PRINT_DATA(COMP_INIT, DBG_LOUD, ("EFUSE\t"), tmpdata, 8); |
| |
| efuse_PgPacketWrite(dev,offset,word_en,tmpdata); |
| |
| |
| } |
| |
| // For warm reboot, we must resume Efuse clock to 500K. |
| efuse_PowerSwitch(dev, FALSE); |
| |
| } // efuse_WriteAllMap |
| #endif |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_PgPacketRead |
| * |
| * Overview: Receive dedicated Efuse are content. For92s, we support 16 |
| * area now. It will return 8 bytes content for every area. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/16/2008 MHC Reorganize code Arch and assign as local API. |
| * |
| *---------------------------------------------------------------------------*/ |
| static u8 |
| efuse_PgPacketRead( struct net_device* dev, u8 offset, u8 *data) |
| { |
| u8 ReadState = PG_STATE_HEADER; |
| |
| bool bContinual = TRUE; |
| bool bDataEmpty = TRUE ; |
| |
| u8 efuse_data,word_cnts=0; |
| u16 efuse_addr = 0; |
| u8 hoffset=0,hworden=0; |
| u8 tmpidx=0; |
| u8 tmpdata[8]; |
| |
| if(data==NULL) return FALSE; |
| if(offset>15) return FALSE; |
| |
| //FIXLZM |
| //PlatformFillMemory((PVOID)data, sizeof(u8)*PGPKT_DATA_SIZE, 0xff); |
| //PlatformFillMemory((PVOID)tmpdata, sizeof(u8)*PGPKT_DATA_SIZE, 0xff); |
| memset(data, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); |
| memset(tmpdata, 0xff, sizeof(u8)*PGPKT_DATA_SIZE); |
| |
| //RT_PRINT_DATA(COMP_EFUSE, DBG_LOUD, ("efuse_PgPacketRead-1\n"), data, 8); |
| |
| //efuse_reg_ctrl(pAdapter,TRUE);//power on |
| while(bContinual && (efuse_addr < EFUSE_MAX_SIZE) ) |
| { |
| //------- Header Read ------------- |
| if(ReadState & PG_STATE_HEADER) |
| { |
| if(efuse_OneByteRead(dev, efuse_addr ,&efuse_data)&&(efuse_data!=0xFF)){ |
| hoffset = (efuse_data>>4) & 0x0F; |
| hworden = efuse_data & 0x0F; |
| word_cnts = efuse_CalculateWordCnts(hworden); |
| bDataEmpty = TRUE ; |
| |
| if(hoffset==offset){ |
| for(tmpidx = 0;tmpidx< word_cnts*2 ;tmpidx++){ |
| if(efuse_OneByteRead(dev, efuse_addr+1+tmpidx ,&efuse_data) ){ |
| tmpdata[tmpidx] = efuse_data; |
| if(efuse_data!=0xff){ |
| bDataEmpty = FALSE; |
| } |
| } |
| } |
| if(bDataEmpty==FALSE){ |
| ReadState = PG_STATE_DATA; |
| }else{//read next header |
| efuse_addr = efuse_addr + (word_cnts*2)+1; |
| ReadState = PG_STATE_HEADER; |
| } |
| } |
| else{//read next header |
| efuse_addr = efuse_addr + (word_cnts*2)+1; |
| ReadState = PG_STATE_HEADER; |
| } |
| |
| } |
| else{ |
| bContinual = FALSE ; |
| } |
| } |
| //------- Data section Read ------------- |
| else if(ReadState & PG_STATE_DATA) |
| { |
| efuse_WordEnableDataRead(hworden,tmpdata,data); |
| efuse_addr = efuse_addr + (word_cnts*2)+1; |
| ReadState = PG_STATE_HEADER; |
| } |
| |
| } |
| //efuse_reg_ctrl(pAdapter,FALSE);//power off |
| |
| //RT_PRINT_DATA(COMP_EFUSE, DBG_LOUD, ("efuse_PgPacketRead-2\n"), data, 8); |
| |
| if( (data[0]==0xff) &&(data[1]==0xff) && (data[2]==0xff) && (data[3]==0xff) && |
| (data[4]==0xff) &&(data[5]==0xff) && (data[6]==0xff) && (data[7]==0xff)) |
| return FALSE; |
| else |
| return TRUE; |
| |
| } // efuse_PgPacketRead |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_PgPacketWrite |
| * |
| * Overview: Send A G package for different section in real efuse area. |
| * For 92S, One PG package contain 8 bytes content and 4 word |
| * unit. PG header = 0x[bit7-4=offset][bit3-0word enable] |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/16/2008 MHC Reorganize code Arch and assign as local API. |
| * |
| *---------------------------------------------------------------------------*/ |
| static u8 efuse_PgPacketWrite(struct net_device* dev, u8 offset, u8 word_en,u8 *data) |
| { |
| u8 WriteState = PG_STATE_HEADER; |
| |
| bool bContinual = TRUE,bDataEmpty=TRUE, bResult = TRUE; |
| u16 efuse_addr = 0; |
| u8 efuse_data; |
| |
| u8 pg_header = 0; |
| |
| //u16 tmp_addr=0; |
| u8 tmp_word_cnts=0,target_word_cnts=0; |
| u8 tmp_header,match_word_en,tmp_word_en; |
| |
| //u8 efuse_clk_ori,efuse_clk_new; |
| |
| PGPKT_STRUCT target_pkt; |
| PGPKT_STRUCT tmp_pkt; |
| |
| u8 originaldata[sizeof(u8)*8]; |
| u8 tmpindex = 0,badworden = 0x0F; |
| |
| static u32 repeat_times = 0; |
| |
| if( efuse_GetCurrentSize(dev) >= EFUSE_MAX_SIZE) |
| { |
| printk("efuse_PgPacketWrite error \n"); |
| return FALSE; |
| } |
| |
| // Init the 8 bytes content as 0xff |
| target_pkt.offset = offset; |
| target_pkt.word_en= word_en; |
| |
| //PlatformFillMemory((PVOID)target_pkt.data, sizeof(u8)*8, 0xFF); |
| memset(target_pkt.data,0xFF,sizeof(u8)*8); |
| |
| efuse_WordEnableDataRead(word_en,data,target_pkt.data); |
| target_word_cnts = efuse_CalculateWordCnts(target_pkt.word_en); |
| |
| //efuse_reg_ctrl(pAdapter,TRUE);//power on |
| printk("EFUSE Power ON\n"); |
| |
| while( bContinual && (efuse_addr < EFUSE_MAX_SIZE) ) |
| { |
| |
| if(WriteState==PG_STATE_HEADER) |
| { |
| bDataEmpty=TRUE; |
| badworden = 0x0F; |
| //************ so ******************* |
| printk("EFUSE PG_STATE_HEADER\n"); |
| if ( efuse_OneByteRead(dev, efuse_addr ,&efuse_data) && |
| (efuse_data!=0xFF)) |
| { |
| tmp_header = efuse_data; |
| |
| tmp_pkt.offset = (tmp_header>>4) & 0x0F; |
| tmp_pkt.word_en = tmp_header & 0x0F; |
| tmp_word_cnts = efuse_CalculateWordCnts(tmp_pkt.word_en); |
| |
| //************ so-1 ******************* |
| if(tmp_pkt.offset != target_pkt.offset) |
| { |
| efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; //Next pg_packet |
| #if (EFUSE_ERROE_HANDLE == 1) |
| WriteState = PG_STATE_HEADER; |
| #endif |
| } |
| else |
| { |
| //************ so-2 ******************* |
| for(tmpindex=0 ; tmpindex<(tmp_word_cnts*2) ; tmpindex++) |
| { |
| if(efuse_OneByteRead(dev, (efuse_addr+1+tmpindex) ,&efuse_data)&&(efuse_data != 0xFF)){ |
| bDataEmpty = FALSE; |
| } |
| } |
| //************ so-2-1 ******************* |
| if(bDataEmpty == FALSE) |
| { |
| efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; //Next pg_packet |
| #if (EFUSE_ERROE_HANDLE == 1) |
| WriteState=PG_STATE_HEADER; |
| #endif |
| } |
| else |
| {//************ so-2-2 ******************* |
| match_word_en = 0x0F; |
| if( !( (target_pkt.word_en&BIT0)|(tmp_pkt.word_en&BIT0) )) |
| { |
| match_word_en &= (~BIT0); |
| } |
| if( !( (target_pkt.word_en&BIT1)|(tmp_pkt.word_en&BIT1) )) |
| { |
| match_word_en &= (~BIT1); |
| } |
| if( !( (target_pkt.word_en&BIT2)|(tmp_pkt.word_en&BIT2) )) |
| { |
| match_word_en &= (~BIT2); |
| } |
| if( !( (target_pkt.word_en&BIT3)|(tmp_pkt.word_en&BIT3) )) |
| { |
| match_word_en &= (~BIT3); |
| } |
| |
| //************ so-2-2-A ******************* |
| if((match_word_en&0x0F)!=0x0F) |
| { |
| badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1, tmp_pkt.word_en ,target_pkt.data); |
| |
| //************ so-2-2-A-1 ******************* |
| //############################ |
| if(0x0F != (badworden&0x0F)) |
| { |
| u8 reorg_offset = offset; |
| u8 reorg_worden=badworden; |
| efuse_PgPacketWrite(dev,reorg_offset,reorg_worden,originaldata); |
| } |
| //############################ |
| |
| tmp_word_en = 0x0F; |
| if( (target_pkt.word_en&BIT0)^(match_word_en&BIT0) ) |
| { |
| tmp_word_en &= (~BIT0); |
| } |
| if( (target_pkt.word_en&BIT1)^(match_word_en&BIT1) ) |
| { |
| tmp_word_en &= (~BIT1); |
| } |
| if( (target_pkt.word_en&BIT2)^(match_word_en&BIT2) ) |
| { |
| tmp_word_en &= (~BIT2); |
| } |
| if( (target_pkt.word_en&BIT3)^(match_word_en&BIT3) ) |
| { |
| tmp_word_en &=(~BIT3); |
| } |
| |
| //************ so-2-2-A-2 ******************* |
| if((tmp_word_en&0x0F)!=0x0F){ |
| //reorganize other pg packet |
| //efuse_addr = efuse_addr + (2*tmp_word_cnts) +1;//next pg packet addr |
| efuse_addr = efuse_GetCurrentSize(dev); |
| //=========================== |
| target_pkt.offset = offset; |
| target_pkt.word_en= tmp_word_en; |
| //=========================== |
| }else{ |
| bContinual = FALSE; |
| } |
| #if (EFUSE_ERROE_HANDLE == 1) |
| WriteState=PG_STATE_HEADER; |
| repeat_times++; |
| if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ |
| bContinual = FALSE; |
| bResult = FALSE; |
| } |
| #endif |
| } |
| else{//************ so-2-2-B ******************* |
| //reorganize other pg packet |
| efuse_addr = efuse_addr + (2*tmp_word_cnts) +1;//next pg packet addr |
| //=========================== |
| target_pkt.offset = offset; |
| target_pkt.word_en= target_pkt.word_en; |
| //=========================== |
| #if (EFUSE_ERROE_HANDLE == 1) |
| WriteState=PG_STATE_HEADER; |
| #endif |
| } |
| } |
| } |
| printk("EFUSE PG_STATE_HEADER-1\n"); |
| } |
| else //************ s1: header == oxff ******************* |
| { |
| pg_header = ((target_pkt.offset << 4)&0xf0) |target_pkt.word_en; |
| |
| efuse_OneByteWrite(dev,efuse_addr, pg_header); |
| efuse_OneByteRead(dev,efuse_addr, &tmp_header); |
| |
| if(tmp_header == pg_header) |
| { //************ s1-1******************* |
| WriteState = PG_STATE_DATA; |
| } |
| #if (EFUSE_ERROE_HANDLE == 1) |
| else if(tmp_header == 0xFF){//************ s1-3: if Write or read func doesn't work ******************* |
| //efuse_addr doesn't change |
| WriteState = PG_STATE_HEADER; |
| repeat_times++; |
| if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ |
| bContinual = FALSE; |
| bResult = FALSE; |
| } |
| } |
| #endif |
| else |
| {//************ s1-2 : fixed the header procedure ******************* |
| tmp_pkt.offset = (tmp_header>>4) & 0x0F; |
| tmp_pkt.word_en= tmp_header & 0x0F; |
| tmp_word_cnts = efuse_CalculateWordCnts(tmp_pkt.word_en); |
| |
| //************ s1-2-A :cover the exist data ******************* |
| memset(originaldata,0xff,sizeof(u8)*8); |
| //PlatformFillMemory((PVOID)originaldata, sizeof(u8)*8, 0xff); |
| |
| if(efuse_PgPacketRead( dev, tmp_pkt.offset,originaldata)) |
| { //check if data exist |
| //efuse_reg_ctrl(pAdapter,TRUE);//power on |
| badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1,tmp_pkt.word_en,originaldata); |
| //############################ |
| if(0x0F != (badworden&0x0F)) |
| { |
| u8 reorg_offset = tmp_pkt.offset; |
| u8 reorg_worden=badworden; |
| efuse_PgPacketWrite(dev,reorg_offset,reorg_worden,originaldata); |
| efuse_addr = efuse_GetCurrentSize(dev); |
| } |
| //############################ |
| else{ |
| efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; //Next pg_packet |
| } |
| } |
| //************ s1-2-B: wrong address******************* |
| else |
| { |
| efuse_addr = efuse_addr + (tmp_word_cnts*2) +1; //Next pg_packet |
| } |
| |
| #if (EFUSE_ERROE_HANDLE == 1) |
| WriteState=PG_STATE_HEADER; |
| repeat_times++; |
| if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ |
| bContinual = FALSE; |
| bResult = FALSE; |
| } |
| #endif |
| |
| printk("EFUSE PG_STATE_HEADER-2\n"); |
| } |
| |
| } |
| |
| } |
| //write data state |
| else if(WriteState==PG_STATE_DATA) |
| { //************ s1-1 ******************* |
| printk("EFUSE PG_STATE_DATA\n"); |
| badworden = 0x0f; |
| badworden = efuse_WordEnableDataWrite(dev,efuse_addr+1,target_pkt.word_en,target_pkt.data); |
| if((badworden&0x0F)==0x0F) |
| { //************ s1-1-A ******************* |
| bContinual = FALSE; |
| } |
| else |
| {//reorganize other pg packet //************ s1-1-B ******************* |
| efuse_addr = efuse_addr + (2*target_word_cnts) +1;//next pg packet addr |
| |
| //=========================== |
| target_pkt.offset = offset; |
| target_pkt.word_en= badworden; |
| target_word_cnts = efuse_CalculateWordCnts(target_pkt.word_en); |
| //=========================== |
| #if (EFUSE_ERROE_HANDLE == 1) |
| WriteState=PG_STATE_HEADER; |
| repeat_times++; |
| if(repeat_times>EFUSE_REPEAT_THRESHOLD_){ |
| bContinual = FALSE; |
| bResult = FALSE; |
| } |
| #endif |
| printk("EFUSE PG_STATE_HEADER-3\n"); |
| } |
| } |
| } |
| |
| //efuse_reg_ctrl(pAdapter,FALSE);//power off |
| |
| return TRUE; |
| } // efuse_PgPacketWrite |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_WordEnableDataRead |
| * |
| * Overview: Read allowed word in current efuse section data. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/16/2008 MHC Create Version 0. |
| * 11/21/2008 MHC Fix Write bug when we only enable late word. |
| * |
| *---------------------------------------------------------------------------*/ |
| static void |
| efuse_WordEnableDataRead( u8 word_en,u8 *sourdata,u8 *targetdata) |
| { |
| //u8 tmpindex = 0; |
| |
| //DbgPrint("efuse_WordEnableDataRead word_en = %x\n", word_en); |
| |
| //RT_PRINT_DATA(COMP_EFUSE, DBG_LOUD, ("sourdata\n"), sourdata, 8); |
| //RT_PRINT_DATA(COMP_EFUSE, DBG_LOUD, ("targetdata\n"), targetdata, 8); |
| |
| if (!(word_en&BIT0)) |
| { |
| targetdata[0] = sourdata[0];//sourdata[tmpindex++]; |
| targetdata[1] = sourdata[1];//sourdata[tmpindex++]; |
| } |
| if (!(word_en&BIT1)) |
| { |
| targetdata[2] = sourdata[2];//sourdata[tmpindex++]; |
| targetdata[3] = sourdata[3];//sourdata[tmpindex++]; |
| } |
| if (!(word_en&BIT2)) |
| { |
| targetdata[4] = sourdata[4];//sourdata[tmpindex++]; |
| targetdata[5] = sourdata[5];//sourdata[tmpindex++]; |
| } |
| if (!(word_en&BIT3)) |
| { |
| targetdata[6] = sourdata[6];//sourdata[tmpindex++]; |
| targetdata[7] = sourdata[7];//sourdata[tmpindex++]; |
| } |
| } // efuse_WordEnableDataRead |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_WordEnableDataWrite |
| * |
| * Overview: Write necessary word unit into current efuse section! |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/16/2008 MHC Reorganize Efuse operate flow!!. |
| * |
| *---------------------------------------------------------------------------*/ |
| static u8 |
| efuse_WordEnableDataWrite( struct net_device* dev, u16 efuse_addr, u8 word_en, u8 *data) |
| { |
| u16 tmpaddr = 0; |
| u16 start_addr = efuse_addr; |
| u8 badworden = 0x0F; |
| //u8 NextState; |
| u8 tmpdata[8]; |
| |
| memset(tmpdata,0xff,PGPKT_DATA_SIZE); |
| //PlatformFillMemory((PVOID)tmpdata, PGPKT_DATA_SIZE, 0xff); |
| |
| //RT_TRACE(COMP_EFUSE, "word_en = %x efuse_addr=%x\n", word_en, efuse_addr); |
| |
| //RT_PRINT_DATA(COMP_EFUSE, DBG_LOUD, ("U-EFUSE\n"), data, 8); |
| |
| if(!(word_en&BIT0)) |
| { |
| tmpaddr = start_addr; |
| efuse_OneByteWrite(dev,start_addr++, data[0]); |
| efuse_OneByteWrite(dev,start_addr++, data[1]); |
| |
| efuse_OneByteRead(dev,tmpaddr, &tmpdata[0]); |
| efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[1]); |
| if((data[0]!=tmpdata[0])||(data[1]!=tmpdata[1])){ |
| badworden &= (~BIT0); |
| } |
| } |
| if(!(word_en&BIT1)) |
| { |
| tmpaddr = start_addr; |
| efuse_OneByteWrite(dev,start_addr++, data[2]); |
| efuse_OneByteWrite(dev,start_addr++, data[3]); |
| |
| efuse_OneByteRead(dev,tmpaddr , &tmpdata[2]); |
| efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[3]); |
| if((data[2]!=tmpdata[2])||(data[3]!=tmpdata[3])){ |
| badworden &=( ~BIT1); |
| } |
| } |
| if(!(word_en&BIT2)) |
| { |
| tmpaddr = start_addr; |
| efuse_OneByteWrite(dev,start_addr++, data[4]); |
| efuse_OneByteWrite(dev,start_addr++, data[5]); |
| |
| efuse_OneByteRead(dev,tmpaddr, &tmpdata[4]); |
| efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[5]); |
| if((data[4]!=tmpdata[4])||(data[5]!=tmpdata[5])){ |
| badworden &=( ~BIT2); |
| } |
| } |
| if(!(word_en&BIT3)) |
| { |
| tmpaddr = start_addr; |
| efuse_OneByteWrite(dev,start_addr++, data[6]); |
| efuse_OneByteWrite(dev,start_addr++, data[7]); |
| |
| efuse_OneByteRead(dev,tmpaddr, &tmpdata[6]); |
| efuse_OneByteRead(dev,tmpaddr+1, &tmpdata[7]); |
| if((data[6]!=tmpdata[6])||(data[7]!=tmpdata[7])){ |
| badworden &=( ~BIT3); |
| } |
| } |
| return badworden; |
| } // efuse_WordEnableDataWrite |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_PowerSwitch |
| * |
| * Overview: When we want to enable write operation, we should change to |
| * pwr on state. When we stop write, we should switch to 500k mode |
| * and disable LDO 2.5V. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/17/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| static void |
| efuse_PowerSwitch(struct net_device* dev, u8 PwrState) |
| { |
| u8 tempval; |
| if (PwrState == TRUE) |
| { |
| // Enable LDO 2.5V for write action |
| tempval = read_nic_byte(dev, EFUSE_TEST+3); |
| write_nic_byte(dev, EFUSE_TEST+3, (tempval | 0x80)); |
| |
| // Change Efuse Clock for write action to 40MHZ |
| write_nic_byte(dev, EFUSE_CLK, 0x03); |
| } |
| else |
| { |
| // Enable LDO 2.5V for write action |
| tempval = read_nic_byte(dev, EFUSE_TEST+3); |
| write_nic_byte(dev, EFUSE_TEST+3, (tempval & 0x7F)); |
| |
| // Change Efuse Clock for write action to 500K |
| write_nic_byte(dev, EFUSE_CLK, 0x02); |
| } |
| |
| } /* efuse_PowerSwitch */ |
| |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_GetCurrentSize |
| * |
| * Overview: Get current efuse size!!! |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/16/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| static u16 |
| efuse_GetCurrentSize(struct net_device* dev) |
| { |
| bool bContinual = TRUE; |
| |
| u16 efuse_addr = 0; |
| u8 hoffset=0,hworden=0; |
| u8 efuse_data,word_cnts=0; |
| |
| //efuse_reg_ctrl(pAdapter,TRUE);//power on |
| |
| while ( bContinual && |
| efuse_OneByteRead(dev, efuse_addr ,&efuse_data) && |
| (efuse_addr < EFUSE_MAX_SIZE) ) |
| { |
| if(efuse_data!=0xFF) |
| { |
| hoffset = (efuse_data>>4) & 0x0F; |
| hworden = efuse_data & 0x0F; |
| word_cnts = efuse_CalculateWordCnts(hworden); |
| //read next header |
| efuse_addr = efuse_addr + (word_cnts*2)+1; |
| } |
| else |
| { |
| bContinual = FALSE ; |
| } |
| } |
| |
| //efuse_reg_ctrl(pAdapter,FALSE);//power off |
| |
| return efuse_addr; |
| |
| } // efuse_GetCurrentSize} |
| |
| |
| /* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */ |
| static u8 |
| efuse_CalculateWordCnts(u8 word_en) |
| { |
| u8 word_cnts = 0; |
| if(!(word_en & BIT0)) word_cnts++; // 0 : write enable |
| if(!(word_en & BIT1)) word_cnts++; |
| if(!(word_en & BIT2)) word_cnts++; |
| if(!(word_en & BIT3)) word_cnts++; |
| return word_cnts; |
| } // efuse_CalculateWordCnts |
| |
| /*----------------------------------------------------------------------------- |
| * Function: EFUSE_ProgramMap |
| * |
| * Overview: Read EFUSE map file and execute PG. |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/10/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| #ifdef TO_DO_LIST |
| extern bool // 0=Shadow 1=Real Efuse |
| EFUSE_ProgramMap(struct net_device* dev, char* pFileName,u8 TableType) |
| { |
| struct r8192_priv *priv = ieee80211_priv(dev); |
| s4Byte nLinesRead, ithLine; |
| RT_STATUS rtStatus = RT_STATUS_SUCCESS; |
| char* szLine; |
| u32 u4bRegValue, u4RegMask; |
| u32 u4bMove; |
| u16 index = 0; |
| u16 i; |
| u8 eeprom[HWSET_MAX_SIZE_92S]; |
| |
| rtStatus = PlatformReadFile( |
| dev, |
| pFileName, |
| (u8*)(priv->BufOfLines), |
| MAX_LINES_HWCONFIG_TXT, |
| MAX_BYTES_LINE_HWCONFIG_TXT, |
| &nLinesRead |
| ); |
| |
| if(rtStatus == RT_STATUS_SUCCESS) |
| { |
| memcp(pHalData->BufOfLines3, pHalData->BufOfLines, |
| nLinesRead*MAX_BYTES_LINE_HWCONFIG_TXT); |
| pHalData->nLinesRead3 = nLinesRead; |
| } |
| |
| if(rtStatus == RT_STATUS_SUCCESS) |
| { |
| printk("szEepromFile(): read %s ok\n", pFileName); |
| for(ithLine = 0; ithLine < nLinesRead; ithLine++) |
| { |
| szLine = pHalData->BufOfLines[ithLine]; |
| printk("Line-%d String =%s\n", ithLine, szLine); |
| |
| if(!IsCommentString(szLine)) |
| { |
| // EEPROM map one line has 8 words content. |
| for (i = 0; i < 8; i++) |
| { |
| u32 j; |
| |
| //GetHexValueFromString(szLine, &u4bRegValue, &u4bMove); |
| efuse_ParsingMap(szLine, &u4bRegValue, &u4bMove); |
| |
| // Get next hex value as EEPROM value. |
| szLine += u4bMove; |
| //WriteEEprom(dev, (u16)(ithLine*8+i), (u16)u4bRegValue); |
| eeprom[index++] = (u8)(u4bRegValue&0xff); |
| eeprom[index++] = (u8)((u4bRegValue>>8)&0xff); |
| |
| printk("Addr-%d = %x\n", (ithLine*8+i), u4bRegValue); |
| } |
| } |
| |
| } |
| |
| } |
| else |
| { |
| printk("szEepromFile(): Fail read%s\n", pFileName); |
| return RT_STATUS_FAILURE; |
| } |
| |
| |
| //RT_PRINT_DATA(COMP_EFUSE, DBG_LOUD, ("EFUSE "), eeprom, HWSET_MAX_SIZE_92S); |
| |
| // Use map file to update real Efuse or shadow modify table. |
| if (TableType == 1) |
| { |
| efuse_WriteAllMap(dev, eeprom, HWSET_MAX_SIZE_92S); |
| } |
| else |
| { |
| // Modify shadow table. |
| for (i = 0; i < HWSET_MAX_SIZE_92S; i++) |
| EFUSE_ShadowWrite(dev, 1, i, (u32)eeprom[i]); |
| } |
| |
| return rtStatus; |
| } /* EFUSE_ProgramMap */ |
| |
| #endif |
| |
| // |
| // Description: |
| // Return TRUE if chTmp is represent for hex digit and |
| // FALSE otherwise. |
| // |
| // |
| bool IsHexDigit( char chTmp) |
| { |
| if( (chTmp >= '0' && chTmp <= '9') || |
| (chTmp >= 'a' && chTmp <= 'f') || |
| (chTmp >= 'A' && chTmp <= 'F') ) |
| { |
| return TRUE; |
| } |
| else |
| { |
| return FALSE; |
| } |
| } |
| |
| // |
| // Description: |
| // Translate a character to hex digit. |
| // |
| u32 MapCharToHexDigit(char chTmp) |
| { |
| if(chTmp >= '0' && chTmp <= '9') |
| return (chTmp - '0'); |
| else if(chTmp >= 'a' && chTmp <= 'f') |
| return (10 + (chTmp - 'a')); |
| else if(chTmp >= 'A' && chTmp <= 'F') |
| return (10 + (chTmp - 'A')); |
| else |
| return 0; |
| } |
| |
| /*----------------------------------------------------------------------------- |
| * Function: efuse_ParsingMap |
| * |
| * Overview: |
| * |
| * Input: NONE |
| * |
| * Output: NONE |
| * |
| * Return: NONE |
| * |
| * Revised History: |
| * When Who Remark |
| * 11/08/2008 MHC Create Version 0. |
| * |
| *---------------------------------------------------------------------------*/ |
| #ifdef TO_DO_LIST |
| static bool |
| efuse_ParsingMap(char* szStr,u32* pu4bVal,u32* pu4bMove) |
| { |
| char* szScan = szStr; |
| |
| // Check input parameter. |
| if(szStr == NULL || pu4bVal == NULL || pu4bMove == NULL) |
| { |
| //RT_TRACE(COMP_EFUSE, |
| //"eeprom_ParsingMap(): Invalid IN args! szStr: %p, pu4bVal: %p, pu4bMove: %p\n", |
| //szStr, pu4bVal, pu4bMove); |
| return FALSE; |
| } |
| |
| // Initialize output. |
| *pu4bMove = 0; |
| *pu4bVal = 0; |
| |
| // Skip leading space. |
| while( *szScan != '\0' && |
| (*szScan == ' ' || *szScan == '\t') ) |
| { |
| szScan++; |
| (*pu4bMove)++; |
| } |
| |
| // Check if szScan is now pointer to a character for hex digit, |
| // if not, it means this is not a valid hex number. |
| if(!IsHexDigit(*szScan)) |
| { |
| return FALSE; |
| } |
| |
| // Parse each digit. |
| do |
| { |
| (*pu4bVal) <<= 4; |
| *pu4bVal += MapCharToHexDigit(*szScan); |
| |
| szScan++; |
| (*pu4bMove)++; |
| } while(IsHexDigit(*szScan)); |
| |
| return TRUE; |
| |
| } /* efuse_ParsingMap */ |
| #endif |
| |
| // |
| // Useless Section Code Now!!!!!! |
| // |
| // Porting from 8712 SDIO |
| int efuse_one_byte_rw(struct net_device* dev, u8 bRead, u16 addr, u8 *data) |
| { |
| u32 bResult; |
| //u8 efuse_ctlreg,tmpidx = 0; |
| u8 tmpidx = 0; |
| u8 tmpv8=0; |
| |
| // -----------------e-fuse reg ctrl --------------------------------- |
| |
| write_nic_byte(dev, EFUSE_CTRL+1, (u8)(addr&0xff)); //address |
| tmpv8 = ((u8)((addr>>8) &0x03) ) | (read_nic_byte(dev, EFUSE_CTRL+2)&0xFC ); |
| write_nic_byte(dev, EFUSE_CTRL+2, tmpv8); |
| |
| if(TRUE==bRead){ |
| |
| write_nic_byte(dev, EFUSE_CTRL+3, 0x72);//read cmd |
| |
| while(!(0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){ |
| tmpidx++; |
| } |
| if(tmpidx<100){ |
| *data=read_nic_byte(dev, EFUSE_CTRL); |
| bResult = TRUE; |
| } |
| else |
| { |
| *data = 0; |
| bResult = FALSE; |
| } |
| |
| } |
| else{ |
| //return 0; |
| write_nic_byte(dev, EFUSE_CTRL, *data);//data |
| |
| write_nic_byte(dev, EFUSE_CTRL+3, 0xF2);//write cmd |
| |
| while((0x80 & read_nic_byte(dev, EFUSE_CTRL+3)) && (tmpidx<100) ){ |
| tmpidx++; |
| } |
| if(tmpidx<100) |
| { |
| *data=read_nic_byte(dev, EFUSE_CTRL); |
| bResult = TRUE; |
| } |
| else |
| { |
| *data = 0; |
| bResult = FALSE; |
| } |
| |
| } |
| return bResult; |
| } |
| //------------------------------------------------------------------------------ |
| void efuse_access(struct net_device* dev, u8 bRead,u16 start_addr, u8 cnts, u8 *data) |
| { |
| u8 efuse_clk_ori,efuse_clk_new;//,tmp8; |
| u32 i = 0; |
| |
| if(start_addr>0x200) return; |
| //RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_, |
| // ("\n ===> efuse_access [start_addr=0x%x cnts:%d dataarray:0x%08x Query Efuse].\n",start_addr,cnts,data)); |
| // -----------------SYS_FUNC_EN Digital Core Vdd enable --------------------------------- |
| efuse_clk_ori = read_nic_byte(dev,SYS_FUNC_EN+1); |
| efuse_clk_new = efuse_clk_ori|0x20; |
| |
| if(efuse_clk_new!= efuse_clk_ori){ |
| //RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x10250003=====\n")); |
| write_nic_byte(dev, SYS_FUNC_EN+1, efuse_clk_new); |
| } |
| #ifdef _POWERON_DELAY_ |
| mdelay(10); |
| #endif |
| // -----------------e-fuse pwr & clk reg ctrl --------------------------------- |
| write_nic_byte(dev, EFUSE_TEST+3, (read_nic_byte(dev, EFUSE_TEST+3)|0x80)); |
| write_nic_byte(dev, EFUSE_CLK_CTRL, (read_nic_byte(dev, EFUSE_CLK_CTRL)|0x03)); |
| |
| #ifdef _PRE_EXECUTE_READ_CMD_ |
| { |
| unsigned char tmpdata; |
| efuse_OneByteRead(dev, 0,&tmpdata); |
| } |
| #endif |
| |
| //-----------------e-fuse one byte read / write ------------------------------ |
| for(i=0;i<cnts;i++){ |
| efuse_one_byte_rw(dev,bRead, start_addr+i , data+i); |
| ////RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("==>efuse_access addr:0x%02x value:0x%02x\n",data+i,*(data+i))); |
| } |
| // -----------------e-fuse pwr & clk reg ctrl --------------------------------- |
| write_nic_byte(dev, EFUSE_TEST+3, read_nic_byte(dev, EFUSE_TEST+3)&0x7f); |
| write_nic_byte(dev, EFUSE_CLK_CTRL, read_nic_byte(dev, EFUSE_CLK_CTRL)&0xfd); |
| |
| // -----------------SYS_FUNC_EN Digital Core Vdd disable --------------------------------- |
| if(efuse_clk_new != efuse_clk_ori) write_nic_byte(dev, 0x10250003, efuse_clk_ori); |
| |
| } |
| //------------------------------------------------------------------------------ |
| //------------------------------------------------------------------------------ |
| |
| #ifdef TO_DO_LIST |
| static void efuse_reg_ctrl(struct net_device* dev, u8 bPowerOn) |
| { |
| if(TRUE==bPowerOn){ |
| // -----------------SYS_FUNC_EN Digital Core Vdd enable --------------------------------- |
| write_nic_byte(dev, SYS_FUNC_EN+1, read_nic_byte(dev,SYS_FUNC_EN+1)|0x20); |
| #ifdef _POWERON_DELAY_ |
| mdelay(10); |
| #endif |
| // -----------------e-fuse pwr & clk reg ctrl --------------------------------- |
| write_nic_byte(dev, EFUSE_TEST+4, (read_nic_byte(dev, EFUSE_TEST+4)|0x80)); |
| write_nic_byte(dev, EFUSE_CLK_CTRL, (read_nic_byte(dev, EFUSE_CLK_CTRL)|0x03)); |
| #ifdef _PRE_EXECUTE_READ_CMD_ |
| { |
| unsigned char tmpdata; |
| efuse_OneByteRead(dev, 0,&tmpdata); |
| } |
| |
| #endif |
| } |
| else{ |
| // -----------------e-fuse pwr & clk reg ctrl --------------------------------- |
| write_nic_byte(dev, EFUSE_TEST+4, read_nic_byte(dev, EFUSE_TEST+4)&0x7f); |
| write_nic_byte(dev, EFUSE_CLK_CTRL, read_nic_byte(dev, EFUSE_CLK_CTRL)&0xfd); |
| // -----------------SYS_FUNC_EN Digital Core Vdd disable --------------------------------- |
| |
| //write_nic_byte(pAdapter, SYS_FUNC_EN+1, read_nic_byte(pAdapter,SYS_FUNC_EN+1)&0xDF); |
| } |
| |
| |
| } |
| #endif |
| //------------------------------------------------------------------------------ |
| |
| //------------------------------------------------------------------------------ |
| void efuse_read_data(struct net_device* dev,u8 efuse_read_item,u8 *data,u32 data_size) |
| { |
| u8 offset, word_start,byte_start,byte_cnts; |
| u8 efusedata[EFUSE_MAC_LEN]; |
| u8 *tmpdata = NULL; |
| |
| u8 pg_pkt_cnts ; |
| |
| u8 tmpidx; |
| u8 pg_data[8]; |
| //u8 temp_value[8] = {0xff}; |
| |
| if(efuse_read_item> (sizeof(RTL8712_SDIO_EFUSE_TABLE)/sizeof(EFUSE_MAP))){ |
| //error msg |
| return ; |
| } |
| |
| offset = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].offset ; |
| word_start = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].word_start; |
| byte_start = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].byte_start; |
| byte_cnts = RTL8712_SDIO_EFUSE_TABLE[efuse_read_item].byte_cnts; |
| |
| if(data_size!=byte_cnts){ |
| //error msg |
| return; |
| } |
| |
| pg_pkt_cnts = (byte_cnts /PGPKT_DATA_SIZE) +1; |
| |
| if(pg_pkt_cnts > 1){ |
| //tmpdata = _malloc(pg_pkt_cnts*PGPKT_DATA_SIZE); |
| tmpdata = efusedata; |
| |
| if(tmpdata!=NULL) |
| { |
| memset(tmpdata,0xff,pg_pkt_cnts*PGPKT_DATA_SIZE); |
| //PlatformFillMemory((PVOID)pg_data, pg_pkt_cnts*PGPKT_DATA_SIZE, 0xff); |
| |
| for(tmpidx=0;tmpidx<pg_pkt_cnts;tmpidx++) |
| { |
| memset(pg_data,0xff,PGPKT_DATA_SIZE); |
| //PlatformFillMemory((PVOID)pg_data, PGPKT_DATA_SIZE, 0xff); |
| if(TRUE== efuse_PgPacketRead(dev,offset+tmpidx,pg_data)) |
| { |
| memcpy(tmpdata+(PGPKT_DATA_SIZE*tmpidx),pg_data,PGPKT_DATA_SIZE); |
| //PlatformMoveMemory((PVOID)(tmpdata+(PGPKT_DATA_SIZE*tmpidx)), (PVOID)pg_data, PGPKT_DATA_SIZE); |
| } |
| } |
| memcpy(data,(tmpdata+ (2*word_start)+byte_start ),data_size); |
| //PlatformMoveMemory((PVOID)data, (PVOID)(tmpdata+ (2*word_start)+byte_start ), data_size); |
| //_mfree(tmpdata, pg_pkt_cnts*PGPKT_DATA_SIZE); |
| } |
| } |
| else |
| { |
| memset(pg_data,0xff,PGPKT_DATA_SIZE); |
| //PlatformFillMemory((PVOID)pg_data, PGPKT_DATA_SIZE, 0xff); |
| if(TRUE==efuse_PgPacketRead(dev,offset,pg_data)){ |
| memcpy(data,pg_data+ (2*word_start)+byte_start ,data_size); |
| //PlatformMoveMemory((PVOID)data, (PVOID)(pg_data+ (2*word_start)+byte_start), data_size); |
| } |
| } |
| |
| } |
| //------------------------------------------------------------------------------ |
| //per interface doesn't alike |
| void efuse_write_data(struct net_device* dev,u8 efuse_write_item,u8 *data,u32 data_size,u32 bWordUnit) |
| { |
| u8 offset, word_start,byte_start,byte_cnts; |
| u8 word_en = 0x0f,word_cnts; |
| u8 pg_pkt_cnts ; |
| |
| u8 tmpidx,tmpbitmask; |
| u8 pg_data[8],tmpbytes=0; |
| |
| if(efuse_write_item> (sizeof(RTL8712_SDIO_EFUSE_TABLE)/sizeof(EFUSE_MAP))){ |
| //error msg |
| return ; |
| } |
| |
| offset = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].offset ; |
| word_start = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].word_start; |
| byte_start = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].byte_start; |
| byte_cnts = RTL8712_SDIO_EFUSE_TABLE[efuse_write_item].byte_cnts; |
| |
| if(data_size > byte_cnts){ |
| //error msg |
| return; |
| } |
| pg_pkt_cnts = (byte_cnts /PGPKT_DATA_SIZE) +1; |
| word_cnts = byte_cnts /2 ; |
| |
| if(byte_cnts %2){ |
| word_cnts+=1; |
| } |
| if((byte_start==1)||((byte_cnts%2)==1)){//situation A |
| |
| if((efuse_write_item==EFUSE_F0CIS)||(efuse_write_item==EFUSE_F1CIS)){ |
| memset(pg_data,0xff,PGPKT_DATA_SIZE); |
| //PlatformFillMemory((PVOID)pg_data, PGPKT_DATA_SIZE, 0xff); |
| efuse_PgPacketRead(dev,offset,pg_data); |
| |
| if(efuse_write_item==EFUSE_F0CIS){ |
| word_en = 0x07; |
| memcpy(pg_data+word_start*2+byte_start,data,sizeof(u8)*2); |
| //PlatformMoveMemory((PVOID)(pg_data+word_start*2+byte_start), (PVOID)data, sizeof(u8)*2); |
| efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2)); |
| |
| word_en = 0x00; |
| efuse_PgPacketWrite(dev,(offset+1),word_en,data+2); |
| |
| word_en = 0x00; |
| efuse_PgPacketRead(dev,offset+2,pg_data); |
| memcpy(pg_data,data+2+8,sizeof(u8)*7); |
| //PlatformMoveMemory((PVOID)(pg_data), (PVOID)(data+2+8), sizeof(u8)*7); |
| |
| efuse_PgPacketWrite(dev,(offset+2),word_en,pg_data); |
| } |
| else if(efuse_write_item==EFUSE_F1CIS){ |
| word_en = 0x07; |
| efuse_PgPacketRead(dev,offset,pg_data); |
| pg_data[7] = data[0]; |
| efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2)); |
| |
| word_en = 0x00; |
| for(tmpidx = 0 ;tmpidx<(word_cnts/4);tmpidx++){ |
| efuse_PgPacketWrite(dev,(offset+1+tmpidx),word_en,data+1+(tmpidx*PGPKT_DATA_SIZE)); |
| } |
| } |
| |
| } |
| else{ |
| memset(pg_data,0xff,PGPKT_DATA_SIZE); |
| //PlatformFillMemory((PVOID)pg_data, PGPKT_DATA_SIZE, 0xff); |
| if((efuse_write_item==EFUSE_SDIO_SETTING)||(efuse_write_item==EFUSE_CCCR)){ |
| word_en = 0x0e ; |
| tmpbytes = 2; |
| } |
| else if(efuse_write_item == EFUSE_SDIO_MODE){ |
| word_en = 0x0d ; |
| tmpbytes = 2; |
| } |
| else if(efuse_write_item == EFUSE_OCR){ |
| word_en = 0x09 ; |
| tmpbytes = 4; |
| } |
| else if((efuse_write_item == EFUSE_EEPROM_VER)||(efuse_write_item==EFUSE_CHAN_PLAN)){ |
| word_en = 0x07 ; |
| tmpbytes = 2; |
| } |
| if(bWordUnit==TRUE){ |
| memcpy(pg_data+word_start*2 ,data,sizeof(u8)*tmpbytes); |
| //PlatformMoveMemory((PVOID)(pg_data+word_start*2), (PVOID)(data), sizeof(u8)*tmpbytes); |
| } |
| else{ |
| efuse_PgPacketRead(dev,offset,pg_data); |
| memcpy(pg_data+(2*word_start)+byte_start,data,sizeof(u8)*byte_cnts); |
| //PlatformMoveMemory((PVOID)(pg_data+(2*word_start)+byte_start), (PVOID)(data), sizeof(u8)*byte_cnts); |
| } |
| |
| efuse_PgPacketWrite(dev,offset,word_en,pg_data+(word_start*2)); |
| |
| } |
| |
| } |
| //======================================================================== |
| else if(pg_pkt_cnts>1){//situation B |
| if(word_start==0){ |
| word_en = 0x00; |
| for(tmpidx = 0 ;tmpidx<(word_cnts/4);tmpidx++) |
| { |
| efuse_PgPacketWrite(dev,(offset+tmpidx),word_en,data+(tmpidx*PGPKT_DATA_SIZE)); |
| } |
| word_en = 0x0f; |
| for(tmpidx= 0; tmpidx<(word_cnts%4) ; tmpidx++) |
| { |
| tmpbitmask =tmpidx; |
| word_en &= (~(EFUSE_BIT(tmpbitmask))); |
| //BIT0 |
| } |
| efuse_PgPacketWrite(dev,offset+(word_cnts/4),word_en,data+((word_cnts/4)*PGPKT_DATA_SIZE)); |
| }else |
| { |
| |
| } |
| } |
| //======================================================================== |
| else{//situation C |
| word_en = 0x0f; |
| for(tmpidx= 0; tmpidx<word_cnts ; tmpidx++) |
| { |
| tmpbitmask = word_start + tmpidx ; |
| word_en &= (~(EFUSE_BIT(tmpbitmask))); |
| } |
| efuse_PgPacketWrite(dev,offset,word_en,data); |
| } |
| |
| } |
| //------------------------------------------------------------------------------ |
| |
| void efuset_test_func_read(struct net_device* dev) |
| { |
| u8 chipid[2]; |
| u8 ocr[3]; |
| u8 macaddr[6]; |
| u8 txpowertable[28]; |
| |
| memset(chipid,0,sizeof(u8)*2); |
| efuse_read_data(dev,EFUSE_CHIP_ID,chipid,sizeof(chipid)); |
| |
| memset(ocr,0,sizeof(u8)*3); |
| efuse_read_data(dev,EFUSE_CCCR,ocr,sizeof(ocr)); |
| |
| memset(macaddr,0,sizeof(u8)*6); |
| efuse_read_data(dev,EFUSE_MAC_ADDR,macaddr,sizeof(macaddr)); |
| |
| memset(txpowertable,0,sizeof(u8)*28); |
| efuse_read_data(dev,EFUSE_TXPW_TAB,txpowertable,sizeof(txpowertable)); |
| } |
| //------------------------------------------------------------------------------ |
| |
| void efuset_test_func_write(struct net_device* dev) |
| { |
| u32 bWordUnit = TRUE; |
| u8 CCCR=0x02,SDIO_SETTING = 0xFF; |
| u8 tmpdata[2]; |
| |
| u8 macaddr[6] = {0x00,0xe0,0x4c,0x87,0x12,0x66}; |
| efuse_write_data(dev,EFUSE_MAC_ADDR,macaddr,sizeof(macaddr),bWordUnit); |
| |
| bWordUnit = FALSE; |
| efuse_write_data(dev,EFUSE_CCCR,&CCCR,sizeof(u8),bWordUnit); |
| |
| bWordUnit = FALSE; |
| efuse_write_data(dev,EFUSE_SDIO_SETTING,&SDIO_SETTING,sizeof(u8),bWordUnit); |
| |
| bWordUnit = TRUE; |
| tmpdata[0] =SDIO_SETTING ; |
| tmpdata[1] =CCCR ; |
| efuse_write_data(dev,EFUSE_SDIO_SETTING,tmpdata,sizeof(tmpdata),bWordUnit); |
| |
| } |
| //------------------------------------------------------------------------------ |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| /* End of Efuse.c */ |
| |
| |
| |
| |