linux/drivers/staging/rt3090/common/ee_prom.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_prom.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
  41// IRQL = PASSIVE_LEVEL
  42static inline VOID RaiseClock(
  43    IN  PRTMP_ADAPTER   pAd,
  44    IN  UINT32 *x)
  45{
  46        *x = *x | EESK;
  47        RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
  48        RTMPusecDelay(1);                               // Max frequency = 1MHz in Spec. definition
  49}
  50
  51// IRQL = PASSIVE_LEVEL
  52static inline VOID LowerClock(
  53    IN  PRTMP_ADAPTER   pAd,
  54    IN  UINT32 *x)
  55{
  56        *x = *x & ~EESK;
  57        RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
  58        RTMPusecDelay(1);
  59}
  60
  61// IRQL = PASSIVE_LEVEL
  62static inline USHORT ShiftInBits(
  63        IN PRTMP_ADAPTER        pAd)
  64{
  65        UINT32          x,i;
  66        USHORT      data=0;
  67
  68        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
  69
  70        x &= ~( EEDO | EEDI);
  71
  72        for(i=0; i<16; i++)
  73        {
  74                data = data << 1;
  75                RaiseClock(pAd, &x);
  76
  77                RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
  78                LowerClock(pAd, &x); //prevent read failed
  79
  80                x &= ~(EEDI);
  81                if(x & EEDO)
  82                    data |= 1;
  83        }
  84
  85        return data;
  86}
  87
  88
  89// IRQL = PASSIVE_LEVEL
  90static inline VOID ShiftOutBits(
  91        IN PRTMP_ADAPTER        pAd,
  92        IN USHORT                       data,
  93        IN USHORT                       count)
  94{
  95        UINT32       x,mask;
  96
  97        mask = 0x01 << (count - 1);
  98        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
  99
 100        x &= ~(EEDO | EEDI);
 101
 102        do
 103        {
 104            x &= ~EEDI;
 105            if(data & mask)             x |= EEDI;
 106
 107            RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 108
 109            RaiseClock(pAd, &x);
 110            LowerClock(pAd, &x);
 111
 112            mask = mask >> 1;
 113        } while(mask);
 114
 115        x &= ~EEDI;
 116        RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 117}
 118
 119
 120// IRQL = PASSIVE_LEVEL
 121static inline VOID EEpromCleanup(
 122        IN PRTMP_ADAPTER        pAd)
 123{
 124        UINT32 x;
 125
 126        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
 127
 128        x &= ~(EECS | EEDI);
 129        RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 130
 131        RaiseClock(pAd, &x);
 132        LowerClock(pAd, &x);
 133}
 134
 135
 136static inline VOID EWEN(
 137        IN PRTMP_ADAPTER        pAd)
 138{
 139        UINT32  x;
 140
 141        // reset bits and set EECS
 142        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
 143        x &= ~(EEDI | EEDO | EESK);
 144        x |= EECS;
 145        RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 146
 147        // kick a pulse
 148        RaiseClock(pAd, &x);
 149        LowerClock(pAd, &x);
 150
 151        // output the read_opcode and six pulse in that order
 152        ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
 153        ShiftOutBits(pAd, 0, 6);
 154
 155        EEpromCleanup(pAd);
 156}
 157
 158
 159static inline VOID EWDS(
 160        IN PRTMP_ADAPTER        pAd)
 161{
 162        UINT32  x;
 163
 164        // reset bits and set EECS
 165        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
 166        x &= ~(EEDI | EEDO | EESK);
 167        x |= EECS;
 168        RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 169
 170        // kick a pulse
 171        RaiseClock(pAd, &x);
 172        LowerClock(pAd, &x);
 173
 174        // output the read_opcode and six pulse in that order
 175        ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
 176        ShiftOutBits(pAd, 0, 6);
 177
 178        EEpromCleanup(pAd);
 179}
 180
 181
 182// IRQL = PASSIVE_LEVEL
 183int rtmp_ee_prom_read16(
 184        IN PRTMP_ADAPTER        pAd,
 185        IN USHORT                       Offset,
 186        OUT USHORT                      *pValue)
 187{
 188        UINT32          x;
 189        USHORT          data;
 190
 191#ifdef RT30xx
 192#ifdef ANT_DIVERSITY_SUPPORT
 193        if (pAd->NicConfig2.field.AntDiversity)
 194        {
 195                pAd->EepromAccess = TRUE;
 196        }
 197#endif // ANT_DIVERSITY_SUPPORT //
 198#endif // RT30xx //
 199
 200        Offset /= 2;
 201        // reset bits and set EECS
 202        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
 203        x &= ~(EEDI | EEDO | EESK);
 204        x |= EECS;
 205        RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 206
 207        // patch can not access e-Fuse issue
 208        if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
 209        {
 210                // kick a pulse
 211                RaiseClock(pAd, &x);
 212                LowerClock(pAd, &x);
 213        }
 214
 215        // output the read_opcode and register number in that order
 216        ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
 217        ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
 218
 219        // Now read the data (16 bits) in from the selected EEPROM word
 220        data = ShiftInBits(pAd);
 221
 222        EEpromCleanup(pAd);
 223
 224#ifdef RT30xx
 225#ifdef ANT_DIVERSITY_SUPPORT
 226        // Antenna and EEPROM access are both using EESK pin,
 227        // Therefor we should avoid accessing EESK at the same time
 228        // Then restore antenna after EEPROM access
 229        if ((pAd->NicConfig2.field.AntDiversity)/* || (pAd->RfIcType == RFIC_3020)*/)
 230        {
 231                pAd->EepromAccess = FALSE;
 232                AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
 233        }
 234#endif // ANT_DIVERSITY_SUPPORT //
 235#endif // RT30xx //
 236
 237        *pValue = data;
 238
 239        return NDIS_STATUS_SUCCESS;
 240}
 241
 242
 243int rtmp_ee_prom_write16(
 244    IN  PRTMP_ADAPTER   pAd,
 245    IN  USHORT Offset,
 246    IN  USHORT Data)
 247{
 248        UINT32 x;
 249
 250#ifdef RT30xx
 251#ifdef ANT_DIVERSITY_SUPPORT
 252        if (pAd->NicConfig2.field.AntDiversity)
 253        {
 254                pAd->EepromAccess = TRUE;
 255        }
 256#endif // ANT_DIVERSITY_SUPPORT //
 257#endif // RT30xx //
 258
 259        Offset /= 2;
 260
 261        EWEN(pAd);
 262
 263        // reset bits and set EECS
 264        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
 265        x &= ~(EEDI | EEDO | EESK);
 266        x |= EECS;
 267        RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
 268
 269        // patch can not access e-Fuse issue
 270        if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd)))
 271        {
 272                // kick a pulse
 273                RaiseClock(pAd, &x);
 274                LowerClock(pAd, &x);
 275        }
 276
 277        // output the read_opcode ,register number and data in that order
 278        ShiftOutBits(pAd, EEPROM_WRITE_OPCODE, 3);
 279        ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
 280        ShiftOutBits(pAd, Data, 16);            // 16-bit access
 281
 282        // read DO status
 283        RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
 284
 285        EEpromCleanup(pAd);
 286
 287        RTMPusecDelay(10000);   //delay for twp(MAX)=10ms
 288
 289        EWDS(pAd);
 290
 291        EEpromCleanup(pAd);
 292
 293#ifdef RT30xx
 294#ifdef ANT_DIVERSITY_SUPPORT
 295        // Antenna and EEPROM access are both using EESK pin,
 296        // Therefor we should avoid accessing EESK at the same time
 297        // Then restore antenna after EEPROM access
 298        if ((pAd->NicConfig2.field.AntDiversity) /*|| (pAd->RfIcType == RFIC_3020)*/)
 299        {
 300                pAd->EepromAccess = FALSE;
 301                AsicSetRxAnt(pAd, pAd->RxAnt.Pair1PrimaryRxAnt);
 302        }
 303#endif // ANT_DIVERSITY_SUPPORT //
 304#endif // RT30xx //
 305
 306        return NDIS_STATUS_SUCCESS;
 307
 308}
 309