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/* IRQL = PASSIVE_LEVEL */ 41static inline void RaiseClock(struct rt_rtmp_adapter *pAd, u32 * x) 42{ 43 *x = *x | EESK; 44 RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); 45 RTMPusecDelay(1); /* Max frequency = 1MHz in Spec. definition */ 46} 47 48/* IRQL = PASSIVE_LEVEL */ 49static inline void LowerClock(struct rt_rtmp_adapter *pAd, u32 * x) 50{ 51 *x = *x & ~EESK; 52 RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x); 53 RTMPusecDelay(1); 54} 55 56/* IRQL = PASSIVE_LEVEL */ 57static inline u16 ShiftInBits(struct rt_rtmp_adapter *pAd) 58{ 59 u32 x, i; 60 u16 data = 0; 61 62 RTMP_IO_READ32(pAd, E2PROM_CSR, &x); 63 64 x &= ~(EEDO | EEDI); 65 66 for (i = 0; i < 16; i++) { 67 data = data << 1; 68 RaiseClock(pAd, &x); 69 70 RTMP_IO_READ32(pAd, E2PROM_CSR, &x); 71 LowerClock(pAd, &x); /*prevent read failed */ 72 73 x &= ~(EEDI); 74 if (x & EEDO) 75 data |= 1; 76 } 77 78 return data; 79} 80 81/* IRQL = PASSIVE_LEVEL */ 82static inline void ShiftOutBits(struct rt_rtmp_adapter *pAd, 83 u16 data, u16 count) 84{ 85 u32 x, mask; 86 87 mask = 0x01 << (count - 1); 88 RTMP_IO_READ32(pAd, E2PROM_CSR, &x); 89 90 x &= ~(EEDO | EEDI); 91 92 do { 93 x &= ~EEDI; 94 if (data & mask) 95 x |= EEDI; 96 97 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); 98 99 RaiseClock(pAd, &x); 100 LowerClock(pAd, &x); 101 102 mask = mask >> 1; 103 } while (mask); 104 105 x &= ~EEDI; 106 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); 107} 108 109/* IRQL = PASSIVE_LEVEL */ 110static inline void EEpromCleanup(struct rt_rtmp_adapter *pAd) 111{ 112 u32 x; 113 114 RTMP_IO_READ32(pAd, E2PROM_CSR, &x); 115 116 x &= ~(EECS | EEDI); 117 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); 118 119 RaiseClock(pAd, &x); 120 LowerClock(pAd, &x); 121} 122 123static inline void EWEN(struct rt_rtmp_adapter *pAd) 124{ 125 u32 x; 126 127 /* reset bits and set EECS */ 128 RTMP_IO_READ32(pAd, E2PROM_CSR, &x); 129 x &= ~(EEDI | EEDO | EESK); 130 x |= EECS; 131 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); 132 133 /* kick a pulse */ 134 RaiseClock(pAd, &x); 135 LowerClock(pAd, &x); 136 137 /* output the read_opcode and six pulse in that order */ 138 ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5); 139 ShiftOutBits(pAd, 0, 6); 140 141 EEpromCleanup(pAd); 142} 143 144static inline void EWDS(struct rt_rtmp_adapter *pAd) 145{ 146 u32 x; 147 148 /* reset bits and set EECS */ 149 RTMP_IO_READ32(pAd, E2PROM_CSR, &x); 150 x &= ~(EEDI | EEDO | EESK); 151 x |= EECS; 152 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); 153 154 /* kick a pulse */ 155 RaiseClock(pAd, &x); 156 LowerClock(pAd, &x); 157 158 /* output the read_opcode and six pulse in that order */ 159 ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5); 160 ShiftOutBits(pAd, 0, 6); 161 162 EEpromCleanup(pAd); 163} 164 165/* IRQL = PASSIVE_LEVEL */ 166int rtmp_ee_prom_read16(struct rt_rtmp_adapter *pAd, 167 u16 Offset, u16 * pValue) 168{ 169 u32 x; 170 u16 data; 171 172 Offset /= 2; 173 /* reset bits and set EECS */ 174 RTMP_IO_READ32(pAd, E2PROM_CSR, &x); 175 x &= ~(EEDI | EEDO | EESK); 176 x |= EECS; 177 RTMP_IO_WRITE32(pAd, E2PROM_CSR, x); 178 179 /* patch can not access e-Fuse issue */ 180 if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) { 181 /* kick a pulse */ 182 RaiseClock(pAd, &x); 183 LowerClock(pAd, &x); 184 } 185 /* output the read_opcode and register number in that order */ 186 ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3); 187 ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum); 188 189 /* Now read the data (16 bits) in from the selected EEPROM word */ 190 data = ShiftInBits(pAd); 191 192 EEpromCleanup(pAd); 193 194 *pValue = data; 195 196 return NDIS_STATUS_SUCCESS; 197} 198