1/* 2 ************************************************************************* 3 * Ralink Tech Inc. 4 * 5F., No.36, Taiyuan St., Jhubei City, 5 * Hsinchu County 302, 6 * Taiwan, R.O.C. 7 * 8 * (c) Copyright 2002-2007, Ralink Technology, Inc. 9 * 10 * This program is free software; you can redistribute it and/or modify * 11 * it under the terms of the GNU General Public License as published by * 12 * the Free Software Foundation; either version 2 of the License, or * 13 * (at your option) any later version. * 14 * * 15 * This program is distributed in the hope that it will be useful, * 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 18 * GNU General Public License for more details. * 19 * * 20 * You should have received a copy of the GNU General Public License * 21 * along with this program; if not, write to the * 22 * Free Software Foundation, Inc., * 23 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 24 * * 25 ************************************************************************* 26 27 Module Name: 28 ee_efuse.c 29 30 Abstract: 31 Miniport generic portion header file 32 33 Revision History: 34 Who When What 35 -------- ---------- ---------------------------------------------- 36*/ 37 38#include "../rt_config.h" 39 40#define EFUSE_USAGE_MAP_START 0x2d0 41#define EFUSE_USAGE_MAP_END 0x2fc 42#define EFUSE_USAGE_MAP_SIZE 45 43 44#define EFUSE_EEPROM_DEFULT_FILE "RT30xxEEPROM.bin" 45#define MAX_EEPROM_BIN_FILE_SIZE 1024 46 47#define EFUSE_TAG 0x2fe 48 49typedef union _EFUSE_CTRL_STRUC { 50 struct { 51 u32 EFSROM_AOUT:6; 52 u32 EFSROM_MODE:2; 53 u32 EFSROM_LDO_OFF_TIME:6; 54 u32 EFSROM_LDO_ON_TIME:2; 55 u32 EFSROM_AIN:10; 56 u32 RESERVED:4; 57 u32 EFSROM_KICK:1; 58 u32 SEL_EFUSE:1; 59 } field; 60 u32 word; 61} EFUSE_CTRL_STRUC, *PEFUSE_CTRL_STRUC; 62 63/* 64======================================================================== 65 66 Routine Description: 67 68 Arguments: 69 70 Return Value: 71 72 Note: 73 74======================================================================== 75*/ 76u8 eFuseReadRegisters(struct rt_rtmp_adapter *pAd, 77 u16 Offset, u16 Length, u16 * pData) 78{ 79 EFUSE_CTRL_STRUC eFuseCtrlStruc; 80 int i; 81 u16 efuseDataOffset; 82 u32 data; 83 84 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); 85 86 /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. */ 87 /*Use the eeprom logical address and covert to address to block number */ 88 eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; 89 90 /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 0. */ 91 eFuseCtrlStruc.field.EFSROM_MODE = 0; 92 93 /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */ 94 eFuseCtrlStruc.field.EFSROM_KICK = 1; 95 96 NdisMoveMemory(&data, &eFuseCtrlStruc, 4); 97 RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); 98 99 /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */ 100 i = 0; 101 while (i < 500) { 102 /*rtmp.HwMemoryReadDword(EFUSE_CTRL, (DWORD *) &eFuseCtrlStruc, 4); */ 103 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); 104 if (eFuseCtrlStruc.field.EFSROM_KICK == 0) { 105 break; 106 } 107 RTMPusecDelay(2); 108 i++; 109 } 110 111 /*if EFSROM_AOUT is not found in physical address, write 0xffff */ 112 if (eFuseCtrlStruc.field.EFSROM_AOUT == 0x3f) { 113 for (i = 0; i < Length / 2; i++) 114 *(pData + 2 * i) = 0xffff; 115 } else { 116 /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x590-0x59C) */ 117 efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC); 118 /*data hold 4 bytes data. */ 119 /*In RTMP_IO_READ32 will automatically execute 32-bytes swapping */ 120 RTMP_IO_READ32(pAd, efuseDataOffset, &data); 121 /*Decide the upper 2 bytes or the bottom 2 bytes. */ 122 /* Little-endian S | S Big-endian */ 123 /* addr 3 2 1 0 | 0 1 2 3 */ 124 /* Ori-V D C B A | A B C D */ 125 /*After swapping */ 126 /* D C B A | D C B A */ 127 /*Return 2-bytes */ 128 /*The return byte statrs from S. Therefore, the little-endian will return BA, the Big-endian will return DC. */ 129 /*For returning the bottom 2 bytes, the Big-endian should shift right 2-bytes. */ 130 data = data >> (8 * (Offset & 0x3)); 131 132 NdisMoveMemory(pData, &data, Length); 133 } 134 135 return (u8)eFuseCtrlStruc.field.EFSROM_AOUT; 136 137} 138 139/* 140======================================================================== 141 142 Routine Description: 143 144 Arguments: 145 146 Return Value: 147 148 Note: 149 150======================================================================== 151*/ 152void eFusePhysicalReadRegisters(struct rt_rtmp_adapter *pAd, 153 u16 Offset, 154 u16 Length, u16 * pData) 155{ 156 EFUSE_CTRL_STRUC eFuseCtrlStruc; 157 int i; 158 u16 efuseDataOffset; 159 u32 data; 160 161 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); 162 163 /*Step0. Write 10-bit of address to EFSROM_AIN (0x580, bit25:bit16). The address must be 16-byte alignment. */ 164 eFuseCtrlStruc.field.EFSROM_AIN = Offset & 0xfff0; 165 166 /*Step1. Write EFSROM_MODE (0x580, bit7:bit6) to 1. */ 167 /*Read in physical view */ 168 eFuseCtrlStruc.field.EFSROM_MODE = 1; 169 170 /*Step2. Write EFSROM_KICK (0x580, bit30) to 1 to kick-off physical read procedure. */ 171 eFuseCtrlStruc.field.EFSROM_KICK = 1; 172 173 NdisMoveMemory(&data, &eFuseCtrlStruc, 4); 174 RTMP_IO_WRITE32(pAd, EFUSE_CTRL, data); 175 176 /*Step3. Polling EFSROM_KICK(0x580, bit30) until it become 0 again. */ 177 i = 0; 178 while (i < 500) { 179 RTMP_IO_READ32(pAd, EFUSE_CTRL, &eFuseCtrlStruc.word); 180 if (eFuseCtrlStruc.field.EFSROM_KICK == 0) 181 break; 182 RTMPusecDelay(2); 183 i++; 184 } 185 186 /*Step4. Read 16-byte of data from EFUSE_DATA0-3 (0x59C-0x590) */ 187 /*Because the size of each EFUSE_DATA is 4 Bytes, the size of address of each is 2 bits. */ 188 /*The previous 2 bits is the EFUSE_DATA number, the last 2 bits is used to decide which bytes */ 189 /*Decide which EFUSE_DATA to read */ 190 /*590:F E D C */ 191 /*594:B A 9 8 */ 192 /*598:7 6 5 4 */ 193 /*59C:3 2 1 0 */ 194 efuseDataOffset = EFUSE_DATA3 - (Offset & 0xC); 195 196 RTMP_IO_READ32(pAd, efuseDataOffset, &data); 197 198 data = data >> (8 * (Offset & 0x3)); 199 200 NdisMoveMemory(pData, &data, Length); 201 202} 203 204/* 205======================================================================== 206 207 Routine Description: 208 209 Arguments: 210 211 Return Value: 212 213 Note: 214 215======================================================================== 216*/ 217static void eFuseReadPhysical(struct rt_rtmp_adapter *pAd, 218 u16 *lpInBuffer, 219 unsigned long nInBufferSize, 220 u16 *lpOutBuffer, unsigned long nOutBufferSize) 221{ 222 u16 *pInBuf = (u16 *) lpInBuffer; 223 u16 *pOutBuf = (u16 *) lpOutBuffer; 224 225 u16 Offset = pInBuf[0]; /*addr */ 226 u16 Length = pInBuf[1]; /*length */ 227 int i; 228 229 for (i = 0; i < Length; i += 2) { 230 eFusePhysicalReadRegisters(pAd, Offset + i, 2, &pOutBuf[i / 2]); 231 } 232} 233 234/* 235======================================================================== 236 237 Routine Description: 238 239 Arguments: 240 241 Return Value: 242 243 Note: 244 245======================================================================== 246*/ 247int set_eFuseGetFreeBlockCount_Proc(struct rt_rtmp_adapter *pAd, char *arg) 248{ 249 u16 i; 250 u16 LogicalAddress; 251 u16 efusefreenum = 0; 252 if (!pAd->bUseEfuse) 253 return FALSE; 254 for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) { 255 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); 256 if ((LogicalAddress & 0xff) == 0) { 257 efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i + 1); 258 break; 259 } else if (((LogicalAddress >> 8) & 0xff) == 0) { 260 efusefreenum = (u8)(EFUSE_USAGE_MAP_END - i); 261 break; 262 } 263 264 if (i == EFUSE_USAGE_MAP_END) 265 efusefreenum = 0; 266 } 267 printk("efuseFreeNumber is %d\n", efusefreenum); 268 return TRUE; 269} 270 271int set_eFusedump_Proc(struct rt_rtmp_adapter *pAd, char *arg) 272{ 273 u16 InBuf[3]; 274 int i = 0; 275 if (!pAd->bUseEfuse) 276 return FALSE; 277 for (i = 0; i < EFUSE_USAGE_MAP_END / 2; i++) { 278 InBuf[0] = 2 * i; 279 InBuf[1] = 2; 280 InBuf[2] = 0x0; 281 282 eFuseReadPhysical(pAd, &InBuf[0], 4, &InBuf[2], 2); 283 if (i % 4 == 0) 284 printk("\nBlock %x:", i / 8); 285 printk("%04x ", InBuf[2]); 286 } 287 return TRUE; 288} 289 290int rtmp_ee_efuse_read16(struct rt_rtmp_adapter *pAd, 291 u16 Offset, u16 * pValue) 292{ 293 eFuseReadRegisters(pAd, Offset, 2, pValue); 294 return (*pValue); 295} 296 297int RtmpEfuseSupportCheck(struct rt_rtmp_adapter *pAd) 298{ 299 u16 value; 300 301 if (IS_RT30xx(pAd)) { 302 eFusePhysicalReadRegisters(pAd, EFUSE_TAG, 2, &value); 303 pAd->EFuseTag = (value & 0xff); 304 } 305 return 0; 306} 307 308void eFuseGetFreeBlockCount(struct rt_rtmp_adapter *pAd, u32 *EfuseFreeBlock) 309{ 310 u16 i; 311 u16 LogicalAddress; 312 if (!pAd->bUseEfuse) { 313 DBGPRINT(RT_DEBUG_TRACE, 314 ("eFuseGetFreeBlockCount Only supports efuse Mode\n")); 315 return; 316 } 317 for (i = EFUSE_USAGE_MAP_START; i <= EFUSE_USAGE_MAP_END; i += 2) { 318 eFusePhysicalReadRegisters(pAd, i, 2, &LogicalAddress); 319 if ((LogicalAddress & 0xff) == 0) { 320 *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i + 1); 321 break; 322 } else if (((LogicalAddress >> 8) & 0xff) == 0) { 323 *EfuseFreeBlock = (u8)(EFUSE_USAGE_MAP_END - i); 324 break; 325 } 326 327 if (i == EFUSE_USAGE_MAP_END) 328 *EfuseFreeBlock = 0; 329 } 330 DBGPRINT(RT_DEBUG_TRACE, 331 ("eFuseGetFreeBlockCount is 0x%x\n", *EfuseFreeBlock)); 332} 333 334int eFuse_init(struct rt_rtmp_adapter *pAd) 335{ 336 u32 EfuseFreeBlock = 0; 337 DBGPRINT(RT_DEBUG_ERROR, 338 ("NVM is Efuse and its size =%x[%x-%x] \n", 339 EFUSE_USAGE_MAP_SIZE, EFUSE_USAGE_MAP_START, 340 EFUSE_USAGE_MAP_END)); 341 eFuseGetFreeBlockCount(pAd, &EfuseFreeBlock); 342 343 return 0; 344} 345