summaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_eeprom.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_eeprom.c')
-rw-r--r--target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_eeprom.c579
1 files changed, 579 insertions, 0 deletions
diff --git a/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_eeprom.c b/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_eeprom.c
new file mode 100644
index 000000000..bd9ff86a5
--- /dev/null
+++ b/target/linux/realtek/files/drivers/net/wireless/rtl8192cd/8192cd_eeprom.c
@@ -0,0 +1,579 @@
+/*
+ * Routines to read and write eeprom
+ *
+ * $Id: 8192cd_eeprom.c,v 1.1 2009/11/06 12:26:48 victoryman Exp $
+ *
+ * Copyright (c) 2009 Realtek Semiconductor Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define _8192CD_EEPROM_C_
+
+#ifdef __KERNEL__
+#include <linux/config.h>
+#include <linux/module.h>
+#endif
+
+#include "./8192cd_cfg.h"
+#include "./8192cd.h"
+#include "./8192cd_hw.h"
+#include "./8192cd_util.h"
+#include "./8192cd_debug.h"
+
+#if 0
+
+#define VOID void
+#define EEPROM_MAX_SIZE 256
+#define CSR_EEPROM_CONTROL_REG _9346CR_
+#define CLOCK_RATE 50 //100us
+
+
+static VOID ShiftOutBits(struct rtl8192cd_priv *priv, USHORT data, USHORT count);
+static USHORT ShiftInBits(struct rtl8192cd_priv *priv);
+static VOID RaiseClock(struct rtl8192cd_priv *priv, USHORT *x);
+static VOID LowerClock(struct rtl8192cd_priv *priv, USHORT *x);
+static VOID EEpromCleanup(struct rtl8192cd_priv *priv);
+static USHORT WaitEEPROMCmdDone(struct rtl8192cd_priv *priv);
+static VOID StandBy(struct rtl8192cd_priv *priv);
+
+
+//*****************************************************************************
+//
+// I/O based Read EEPROM Routines
+//
+//*****************************************************************************
+//-----------------------------------------------------------------------------
+// Procedure: ReadEEprom
+//
+// Description: This routine serially reads one word out of the EEPROM.
+//
+// Arguments:
+// Reg - EEPROM word to read.
+//
+// Returns:
+// Contents of EEPROM word (Reg).
+//-----------------------------------------------------------------------------
+static USHORT
+ReadEEprom(
+ struct rtl8192cd_priv *priv,
+ UCHAR AddressSize,
+ USHORT Reg)
+{
+ USHORT x;
+ USHORT data;
+
+ // select EEPROM, reset bits, set EECS
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+
+ x &= ~(EEDI | EEDO | EESK | CR9346_EEM0);
+ x |= CR9346_EEM1 | EECS;
+ RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x);
+
+ // write the read opcode and register number in that order
+ // The opcode is 3bits in length, reg is 6 bits long
+ ShiftOutBits(priv, EEPROM_READ_OPCODE, 3);
+ ShiftOutBits(priv, Reg, AddressSize);
+
+ // Now read the data (16 bits) in from the selected EEPROM word
+ data = ShiftInBits(priv);
+
+ EEpromCleanup(priv);
+ return data;
+}
+
+//-----------------------------------------------------------------------------
+// Procedure: ShiftOutBits
+//
+// Description: This routine shifts data bits out to the EEPROM.
+//
+// Arguments:
+// data - data to send to the EEPROM.
+// count - number of data bits to shift out.
+//
+// Returns: (none)
+//-----------------------------------------------------------------------------
+
+static VOID
+ShiftOutBits(
+ struct rtl8192cd_priv *priv,
+ USHORT data,
+ USHORT count)
+{
+ USHORT x,mask;
+
+ mask = 0x01 << (count - 1);
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+
+ x &= ~(EEDO | EEDI);
+
+ do
+ {
+ x &= ~EEDI;
+ if(data & mask)
+ x |= EEDI;
+
+ RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x);
+ delay_us(CLOCK_RATE);
+ RaiseClock(priv, &x);
+ LowerClock(priv, &x);
+ mask = mask >> 1;
+ } while(mask);
+
+ x &= ~EEDI;
+ RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x);
+}
+
+//-----------------------------------------------------------------------------
+// Procedure: ShiftInBits
+//
+// Description: This routine shifts data bits in from the EEPROM.
+//
+// Arguments:
+//
+// Returns:
+// The contents of that particular EEPROM word
+//-----------------------------------------------------------------------------
+
+static USHORT
+ShiftInBits(
+ struct rtl8192cd_priv *priv)
+{
+ USHORT x,d,i;
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+
+ x &= ~( EEDO | EEDI);
+ d = 0;
+
+ for(i=0; i<16; i++)
+ {
+ d = d << 1;
+ RaiseClock(priv, &x);
+
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+
+ x &= ~(EEDI);
+ if(x & EEDO)
+ d |= 1;
+
+ LowerClock(priv, &x);
+ }
+
+ return d;
+}
+
+//-----------------------------------------------------------------------------
+// Procedure: RaiseClock
+//
+// Description: This routine raises the EEPOM's clock input (EESK)
+//
+// Arguments:
+// x - Ptr to the EEPROM control register's current value
+//
+// Returns: (none)
+//-----------------------------------------------------------------------------
+
+static VOID
+RaiseClock(
+ struct rtl8192cd_priv *priv,
+ USHORT *x)
+{
+ *x = *x | EESK;
+ RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)(*x));
+ delay_us(CLOCK_RATE);
+}
+
+
+//-----------------------------------------------------------------------------
+// Procedure: LowerClock
+//
+// Description: This routine lower's the EEPOM's clock input (EESK)
+//
+// Arguments:
+// x - Ptr to the EEPROM control register's current value
+//
+// Returns: (none)
+//-----------------------------------------------------------------------------
+
+static VOID
+LowerClock(
+ struct rtl8192cd_priv *priv,
+ USHORT *x)
+{
+ *x = *x & ~EESK;
+ RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)(*x));
+ delay_us(CLOCK_RATE);
+}
+
+//-----------------------------------------------------------------------------
+// Procedure: EEpromCleanup
+//
+// Description: This routine returns the EEPROM to an idle state
+//
+// Arguments:
+//
+// Returns: (none)
+//-----------------------------------------------------------------------------
+
+static VOID
+EEpromCleanup(
+ struct rtl8192cd_priv *priv)
+{
+ USHORT x;
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+
+ x &= ~(EECS | EEDI);
+ RTL_W8(CSR_EEPROM_CONTROL_REG, (UCHAR)x);
+
+ RaiseClock(priv, &x);
+ LowerClock(priv, &x);
+}
+
+//*****************************************************************************
+//
+// EEPROM Write Routines
+//
+//*****************************************************************************
+
+//-----------------------------------------------------------------------------
+// Procedure: D100UpdateChecksum
+//
+// Description: Calculates the checksum and writes it to the EEProm. This
+// routine assumes that the checksum word is the last word in
+// a 64 word EEPROM. It calculates the checksum accroding to
+// the formula: Checksum = 0xBABA - (sum of first 63 words).
+//
+// Arguments:
+// Adapter - Ptr to this card's adapter data structure
+//
+// Returns: (none)
+//-----------------------------------------------------------------------------
+
+/*static VOID
+UpdateChecksum(
+ struct rtl8192cd_priv *priv)
+{
+ USHORT Checksum=0;
+// USHORT Iter;
+
+// for (Iter = 0; Iter < 0x3F; Iter++)
+// Checksum += ReadEEprom( CSRBaseIoAddress, Iter );
+
+ Checksum = (USHORT)0xBABA - Checksum;
+// WriteEEprom( CSRBaseIoAddress, 0x3F, Checksum );
+}*/
+
+//-----------------------------------------------------------------------------
+// Procedure: WriteEEprom
+//
+// Description: This routine writes a word to a specific EEPROM location.
+//
+// Arguments:
+// Adapter - Ptr to this card's adapter data structure.
+// reg - The EEPROM word that we are going to write to.
+// data - The data (word) that we are going to write to the EEPROM.
+//
+// Returns: (none)
+//-----------------------------------------------------------------------------
+
+static VOID
+WriteEEprom(
+ struct rtl8192cd_priv *priv,
+ UCHAR AddressSize,
+ USHORT reg,
+ USHORT data)
+{
+ UCHAR x;
+
+ // select EEPROM, mask off ASIC and reset bits, set EECS
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+
+ x &= ~(EEDI | EEDO | EESK | CR9346_EEM0);
+ x |= CR9346_EEM1 | EECS;
+ RTL_W8(CSR_EEPROM_CONTROL_REG, x);
+
+ ShiftOutBits(priv, EEPROM_EWEN_OPCODE, 5);
+ /////ShiftOutBits(CSRBaseIoAddress, reg, 4);
+ ShiftOutBits(priv, 0, 6);
+
+ StandBy(priv);
+
+ // Erase this particular word. Write the erase opcode and register
+ // number in that order. The opcode is 3bits in length; reg is 6 bits long.
+ ShiftOutBits(priv, EEPROM_ERASE_OPCODE, 3);
+ ShiftOutBits(priv, reg, AddressSize);
+
+ if (WaitEEPROMCmdDone(priv) == FALSE)
+ {
+ return;
+ }
+
+ StandBy(priv);
+
+ // write the new word to the EEPROM
+
+ // send the write opcode the EEPORM
+ ShiftOutBits(priv, EEPROM_WRITE_OPCODE, 3);
+
+ // select which word in the EEPROM that we are writing to.
+ ShiftOutBits(priv, reg, AddressSize);
+
+ // write the data to the selected EEPROM word.
+ ShiftOutBits(priv, data, 16);
+
+ if (WaitEEPROMCmdDone(priv) == FALSE)
+ {
+// DbgPrint("D100: Failed EEPROM Write");
+ return;
+ }
+
+ StandBy(priv);
+
+ ShiftOutBits(priv, EEPROM_EWDS_OPCODE, 5);
+ ShiftOutBits(priv, reg, 4);
+
+ EEpromCleanup(priv);
+ return;
+}
+
+//-----------------------------------------------------------------------------
+// Procedure: WaitEEPROMCmdDone
+//
+// Description: This routine waits for the the EEPROM to finish its command.
+// Specifically, it waits for EEDO (data out) to go high.
+//
+// Arguments:
+// Adapter - Ptr to this card's adapter data structure.
+//
+// Returns:
+// TRUE - If the command finished
+// FALSE - If the command never finished (EEDO stayed low)
+//-----------------------------------------------------------------------------
+
+static USHORT
+WaitEEPROMCmdDone(
+ struct rtl8192cd_priv *priv)
+{
+ UCHAR x;
+ USHORT i;
+
+ StandBy(priv);
+ for (i=0; i<200; i++)
+ {
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+ if (x & EEDO)
+ return (TRUE);
+ delay_us(CLOCK_RATE);
+ }
+ return FALSE;
+}
+
+
+//-----------------------------------------------------------------------------
+// Procedure: StandBy
+//
+// Description: This routine lowers the EEPROM chip select (EECS) for a few
+// microseconds.
+//
+// Arguments:
+// Adapter - Ptr to this card's adapter data structure.
+//
+// Returns: (none)
+//-----------------------------------------------------------------------------
+
+static VOID
+StandBy(
+ struct rtl8192cd_priv *priv)
+{
+ UCHAR x;
+
+ x = RTL_R8(CSR_EEPROM_CONTROL_REG);
+
+ x &= ~(EECS | EESK);
+ RTL_W8(CSR_EEPROM_CONTROL_REG, x);
+
+ delay_us(CLOCK_RATE);
+ x |= EECS;
+ RTL_W8(CSR_EEPROM_CONTROL_REG, x);
+ delay_us(CLOCK_RATE);
+}
+
+
+//*****************************************************************************
+//
+// Main routines to read and write EEPROM
+//
+//*****************************************************************************
+#define NUM_11A_CHANNEL 46
+const UCHAR ChannelNumberListOf11a[] = {
+ 26, 28, 30, 32,
+ 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64,
+ 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86,
+ 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140,
+ 149, 153, 157, 161
+};
+#define READ_EEPROM(addr) ReadEEprom(priv, EepromAddressSize, addr)
+#define WRITE_EEPROM(a,d) WriteEEprom(priv, EepromAddressSize, a, d)
+
+int ReadAdapterInfo(struct rtl8192cd_priv *priv, int entry_id, void *data)
+{
+ USHORT Index;
+ USHORT usValue;
+ ULONG curRCR;
+ UCHAR EepromAddressSize;
+ UCHAR TxPowerLevel[64];
+
+ if (!priv->EE_Cached)
+ {
+ curRCR = RTL_R32(_RCR_);
+ EepromAddressSize = (curRCR & _9356SEL_)? 8 : 6;
+
+ // ID
+ priv->EE_ID = (unsigned int)READ_EEPROM(EEPROM_ID);
+ DEBUG_INFO("ID 0x%04X\n", (USHORT)priv->EE_ID);
+ if (priv->EE_ID != RTL8180_EEPROM_ID) {
+ DEBUG_INFO("ID is invalid\n");
+ priv->EE_AutoloadFail = TRUE;
+ }
+ else
+ priv->EE_AutoloadFail = FALSE;
+
+ // Version
+// priv->EE_Version = (unsigned int)READ_EEPROM((USHORT)(EEPROM_VERSION >> 1));
+ usValue = READ_EEPROM(0x7C >> 1);
+ priv->EE_Version = ((usValue&0xff00)>>8);
+ DEBUG_INFO("Version 0x%x\n", (USHORT)priv->EE_Version);
+
+ // MAC address
+ for (Index = 0; Index < 6; Index += 2) {
+ usValue = READ_EEPROM((USHORT)((EEPROM_NODE_ADDRESS_BYTE_0 + Index)>>1));
+ priv->EE_Mac[Index] = usValue & 0xff;
+ priv->EE_Mac[Index+1] = ((usValue&0xff00) >> 8);
+ }
+ DEBUG_INFO("Mac %02X-%02X-%02X-%02X-%02X-%02X\n",
+ priv->EE_Mac[0], priv->EE_Mac[1], priv->EE_Mac[2], priv->EE_Mac[3],
+ priv->EE_Mac[4], priv->EE_Mac[5]);
+
+ // for identifying empty EEPROM
+ if (!priv->EE_AutoloadFail)
+ {
+ // Tx Power Level
+ memset(priv->EE_TxPower_CCK, 0, sizeof(priv->EE_TxPower_CCK));
+ for (Index = 0; Index < MAX_CCK_CHANNEL_NUM; Index += 2) {
+ usValue = READ_EEPROM((USHORT)((EEPROM_TX_POWER_LEVEL_0 + Index) >> 1));
+ *((USHORT *)(&priv->EE_TxPower_CCK[Index])) = usValue;
+ }
+
+ memset(priv->EE_TxPower_OFDM, 0, sizeof(priv->EE_TxPower_OFDM));
+ for (Index = 0; Index < NUM_11A_CHANNEL; Index += 2) {
+ usValue = READ_EEPROM((USHORT)((EEPROM_11A_CHANNEL_TX_POWER_LEVEL_OFFSET + Index) >> 1));
+ *((USHORT *)(&TxPowerLevel[Index])) = usValue;
+ }
+ for (Index = 0; Index < NUM_11A_CHANNEL; Index++)
+ priv->EE_TxPower_OFDM[ChannelNumberListOf11a[Index] - 1] = TxPowerLevel[Index];
+
+ for (Index = 0; Index < MAX_CCK_CHANNEL_NUM; Index += 2) {
+ usValue = READ_EEPROM((USHORT)((EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET + Index) >> 1));
+ *((USHORT *)(&TxPowerLevel[Index])) = usValue;
+ }
+ for (Index = 0; Index < MAX_CCK_CHANNEL_NUM; Index++)
+ priv->EE_TxPower_OFDM[Index] = TxPowerLevel[Index];
+
+ #ifdef _DEBUG_RTL8192CD_
+ if (rtl8192cd_debug_info & _MODULE_DEFINE) {
+ extern void debug_out(char *label, unsigned char *data, int data_length);
+ debug_out("EEProm CCK TxPower", priv->EE_TxPower_CCK, MAX_CCK_CHANNEL_NUM);
+ debug_out("EEProm OFDM TxPower", priv->EE_TxPower_OFDM, MAX_OFDM_CHANNEL_NUM);
+ }
+ #endif
+
+ // RF chip id
+// priv->EE_RFTypeID = (unsigned int)(READ_EEPROM((USHORT)(EEPROM_RF_CHIP_ID >> 1)) & 0x00f);
+ priv->EE_RFTypeID = (unsigned int)(READ_EEPROM((USHORT)(0x28 >> 1)) & 0x80 ) >> 7;
+ DEBUG_INFO("RF ID 0x%02X\n", (UCHAR)priv->EE_RFTypeID);
+
+ // AnaParm
+ usValue = READ_EEPROM((USHORT)((EEPROM_ANA_PARM + 2) >> 1));
+ priv->EE_AnaParm = (unsigned int)(usValue << 16);
+ usValue = READ_EEPROM((USHORT)(EEPROM_ANA_PARM >> 1));
+ priv->EE_AnaParm |= usValue;
+ DEBUG_INFO("AnaParm 0x%08X\n", priv->EE_AnaParm);
+ usValue = READ_EEPROM((USHORT)((EEPROM_ANA_PARM2 + 2) >> 1));
+ priv->EE_AnaParm2 = (unsigned int)(usValue << 16);
+ usValue = READ_EEPROM((USHORT)(EEPROM_ANA_PARM2 >> 1));
+ priv->EE_AnaParm2 |= usValue;
+ DEBUG_INFO("AnaParm2 0x%08X\n", priv->EE_AnaParm2);
+ //add CrystalCap, joshua 20080502
+ priv->EE_CrystalCap = (((unsigned int) READ_EEPROM( 0x2A >> 1)) & 0xf000) >> 12;
+ priv->pmib->dot11RFEntry.crystalCap = priv->EE_CrystalCap;
+ DEBUG_INFO("CrystalCap 0x%08X\n", priv->EE_CrystalCap);
+ }
+
+ priv->EE_Cached = 1;
+ }
+
+ if ((data != NULL) && (!priv->EE_AutoloadFail))
+ {
+ switch(entry_id)
+ {
+ case EEPROM_RF_CHIP_ID:
+ *((UCHAR *)data) = (UCHAR)priv->EE_RFTypeID;
+ break;
+
+ case EEPROM_NODE_ADDRESS_BYTE_0:
+ memcpy(data, priv->EE_Mac, MACADDRLEN);
+ break;
+
+ case EEPROM_TX_POWER_LEVEL_0:
+ memcpy(data, priv->EE_TxPower_CCK, MAX_CCK_CHANNEL_NUM);
+ break;
+
+ case EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET:
+ memcpy(data, priv->EE_TxPower_OFDM, MAX_OFDM_CHANNEL_NUM);
+ break;
+
+ default:
+ DEBUG_INFO("not support this id yet\n");
+ return 0;
+ }
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+int WriteAdapterInfo(struct rtl8192cd_priv *priv, int entry_id, void *data)
+{
+ USHORT Index;
+ USHORT usValue;
+ ULONG curRCR;
+ UCHAR EepromAddressSize;
+
+ priv->EE_Cached = 0;
+ curRCR = RTL_R32(_RCR_);
+ EepromAddressSize = (curRCR & _9356SEL_)? 8 : 6;
+
+ switch(entry_id)
+ {
+ case EEPROM_TX_POWER_LEVEL_0:
+ Index = ((USHORT)((int)data)) & 0xfffe;
+ usValue = *((USHORT *)(&priv->EE_TxPower_CCK[Index]));
+ WRITE_EEPROM((USHORT)((EEPROM_TX_POWER_LEVEL_0 + Index) >> 1), usValue);
+ break;
+
+ case EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET:
+ Index = ((USHORT)((int)data)) & 0xfffe;
+ usValue = *((USHORT *)(&priv->EE_TxPower_OFDM[Index]));
+ WRITE_EEPROM((USHORT)((EEPROM_11G_CHANNEL_OFDM_TX_POWER_LEVEL_OFFSET + Index) >> 1), usValue);
+ break;
+
+ default:
+ return 0;
+ }
+ return 1;
+}
+#endif
+