blob: 2083740a844bb29cce3e9927f37cfd235cc46197 [file] [log] [blame]
/*
*************************************************************************
* Ralink Tech Inc.
* 5F., No.36, Taiyuan St., Jhubei City,
* Hsinchu County 302,
* Taiwan, R.O.C.
*
* (c) Copyright 2002-2007, Ralink Technology, Inc.
*
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
*************************************************************************
Module Name:
ee_prom.c
Abstract:
Miniport generic portion header file
Revision History:
Who When What
-------- ---------- ----------------------------------------------
*/
#include "../rt_config.h"
/* IRQL = PASSIVE_LEVEL */
static inline void RaiseClock(struct rt_rtmp_adapter *pAd, u32 * x)
{
*x = *x | EESK;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
RTMPusecDelay(1); /* Max frequency = 1MHz in Spec. definition */
}
/* IRQL = PASSIVE_LEVEL */
static inline void LowerClock(struct rt_rtmp_adapter *pAd, u32 * x)
{
*x = *x & ~EESK;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, *x);
RTMPusecDelay(1);
}
/* IRQL = PASSIVE_LEVEL */
static inline u16 ShiftInBits(struct rt_rtmp_adapter *pAd)
{
u32 x, i;
u16 data = 0;
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDO | EEDI);
for (i = 0; i < 16; i++) {
data = data << 1;
RaiseClock(pAd, &x);
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
LowerClock(pAd, &x); /*prevent read failed */
x &= ~(EEDI);
if (x & EEDO)
data |= 1;
}
return data;
}
/* IRQL = PASSIVE_LEVEL */
static inline void ShiftOutBits(struct rt_rtmp_adapter *pAd,
u16 data, u16 count)
{
u32 x, mask;
mask = 0x01 << (count - 1);
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDO | EEDI);
do {
x &= ~EEDI;
if (data & mask)
x |= EEDI;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
mask = mask >> 1;
} while (mask);
x &= ~EEDI;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
}
/* IRQL = PASSIVE_LEVEL */
static inline void EEpromCleanup(struct rt_rtmp_adapter *pAd)
{
u32 x;
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EECS | EEDI);
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
}
static inline void EWEN(struct rt_rtmp_adapter *pAd)
{
u32 x;
/* reset bits and set EECS */
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
/* kick a pulse */
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
/* output the read_opcode and six pulse in that order */
ShiftOutBits(pAd, EEPROM_EWEN_OPCODE, 5);
ShiftOutBits(pAd, 0, 6);
EEpromCleanup(pAd);
}
static inline void EWDS(struct rt_rtmp_adapter *pAd)
{
u32 x;
/* reset bits and set EECS */
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
/* kick a pulse */
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
/* output the read_opcode and six pulse in that order */
ShiftOutBits(pAd, EEPROM_EWDS_OPCODE, 5);
ShiftOutBits(pAd, 0, 6);
EEpromCleanup(pAd);
}
/* IRQL = PASSIVE_LEVEL */
int rtmp_ee_prom_read16(struct rt_rtmp_adapter *pAd,
u16 Offset, u16 * pValue)
{
u32 x;
u16 data;
Offset /= 2;
/* reset bits and set EECS */
RTMP_IO_READ32(pAd, E2PROM_CSR, &x);
x &= ~(EEDI | EEDO | EESK);
x |= EECS;
RTMP_IO_WRITE32(pAd, E2PROM_CSR, x);
/* patch can not access e-Fuse issue */
if (!(IS_RT3090(pAd) || IS_RT3572(pAd) || IS_RT3390(pAd))) {
/* kick a pulse */
RaiseClock(pAd, &x);
LowerClock(pAd, &x);
}
/* output the read_opcode and register number in that order */
ShiftOutBits(pAd, EEPROM_READ_OPCODE, 3);
ShiftOutBits(pAd, Offset, pAd->EEPROMAddressNum);
/* Now read the data (16 bits) in from the selected EEPROM word */
data = ShiftInBits(pAd);
EEpromCleanup(pAd);
*pValue = data;
return NDIS_STATUS_SUCCESS;
}