linux/drivers/staging/rt2860/common/ee_efuse.c
<<
>>
Prefs
   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
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.