summaryrefslogtreecommitdiff
path: root/drivers/staging/rt2860/common/ee_prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/rt2860/common/ee_prom.c')
-rw-r--r--drivers/staging/rt2860/common/ee_prom.c197
1 files changed, 197 insertions, 0 deletions
diff --git a/drivers/staging/rt2860/common/ee_prom.c b/drivers/staging/rt2860/common/ee_prom.c
new file mode 100644
index 000000000000..2083740a844b
--- /dev/null
+++ b/drivers/staging/rt2860/common/ee_prom.c
@@ -0,0 +1,197 @@
+/*
+ *************************************************************************
+ * 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;
+}