Talk:Intel Centrino Advanced-N 6205

From WikiDevi.Wi-Cat.RU
Jump to navigation Jump to search

Intel 5150 AGX/6205 AGN - 802.11n

%NIC_MPCIEX_6205AGN_2x2_HMC% = Install_MPCIEX_GEN_6205_AGN_2x2_HMC_XP_MOW , PCI\VEN_8086&DEV_0082&SUBSYS_13018086 ; MOW
%NIC_MPCIEX_6205AGN_2x2_HMC% = Install_MPCIEX_GEN_6205_AGN_2x2_HMC_XP_ABG , PCI\VEN_8086&DEV_0082&SUBSYS_13068086 ; ABG
%NIC_MPCIEX_6205AGN_2x2_HMC% = Install_MPCIEX_GEN_6205_AGN_2x2_HMC_XP_BG7 , PCI\VEN_8086&DEV_0082&SUBSYS_13078086 ; BG7
%NIC_MPCIEX_6205AGN_2x2_HMC% = Install_MPCIEX_GEN_6205_AGN_2x2_HMC_XP_MOW1 , PCI\VEN_8086&DEV_0082&SUBSYS_13048086 ; MOW1
%NIC_MPCIEX_6205AGN_2x2_HMC% = Install_MPCIEX_GEN_6205_AGN_2x2_HMC_XP_MOW2 , PCI\VEN_8086&DEV_0082&SUBSYS_13058086 ; MOW2
  • CONFIG_IWLWIFI_DEBUG: iwlwifi debug=0x41
Some Intel Wi-Fi hardware has 80211N disabled by firmware.
Patch EEPROM shadow copy to enable it on the 6xxx series.
 
This code based on http://forum.ixbt.com/topic.cgi?id=14:51214:326#326
and https://github.com/0x90/iwleeprom
 
Signed-off-by: Sergei A. Trusov <sergei.a.trusov@yandex.ru>
---
 drivers/net/wireless/intel/iwlwifi/cfg/6000.c      |  30 ++--
 .../net/wireless/intel/iwlwifi/iwl-eeprom-read.c   | 169 +++++++++++++++++++++
 2 files changed, 189 insertions(+), 10 deletions(-)
 
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
index 39335b7b0c16..2e37877d5643 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/6000.c
@@ -144,13 +144,15 @@ const struct iwl_cfg iwl6005_2agn_cfg = {
 };
 
 const struct iwl_cfg iwl6005_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG+N",
 	IWL_DEVICE_6005,
+	.ht_params = &iwl6000_ht_params,
 };
 
 const struct iwl_cfg iwl6005_2bg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
+	.name = "Intel(R) Centrino(R) Advanced-N 6205 BG+N",
 	IWL_DEVICE_6005,
+	.ht_params = &iwl6000_ht_params,
 };
 
 const struct iwl_cfg iwl6005_2agn_sff_cfg = {
@@ -198,8 +200,9 @@ const struct iwl_cfg iwl6030_2agn_cfg = {
 };
 
 const struct iwl_cfg iwl6030_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG+N",
 	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
 };
 
 const struct iwl_cfg iwl6030_2bgn_cfg = {
@@ -209,8 +212,9 @@ const struct iwl_cfg iwl6030_2bgn_cfg = {
 };
 
 const struct iwl_cfg iwl6030_2bg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
+	.name = "Intel(R) Centrino(R) Advanced-N 6230 BG+N",
 	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
 };
 
 #define IWL_DEVICE_6035						\
@@ -246,8 +250,9 @@ const struct iwl_cfg iwl1030_bgn_cfg = {
 };
 
 const struct iwl_cfg iwl1030_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
+	.name = "Intel(R) Centrino(R) Wireless-N 1030 BG+N",
 	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
 };
 
 const struct iwl_cfg iwl130_bgn_cfg = {
@@ -258,8 +263,9 @@ const struct iwl_cfg iwl130_bgn_cfg = {
 };
 
 const struct iwl_cfg iwl130_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
+	.name = "Intel(R) Centrino(R) Wireless-N 130 BG+N",
 	IWL_DEVICE_6030,
+	.ht_params = &iwl6000_ht_params,
 	.rx_with_siso_diversity = true,
 };
 
@@ -289,13 +295,15 @@ const struct iwl_cfg iwl6000i_2agn_cfg = {
 };
 
 const struct iwl_cfg iwl6000i_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
+	.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG+N",
 	IWL_DEVICE_6000i,
+	.ht_params = &iwl6000_ht_params,
 };
 
 const struct iwl_cfg iwl6000i_2bg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
+	.name = "Intel(R) Centrino(R) Advanced-N 6200 BG+N",
 	IWL_DEVICE_6000i,
+	.ht_params = &iwl6000_ht_params,
 };
 
 #define IWL_DEVICE_6050						\
@@ -322,8 +330,9 @@ const struct iwl_cfg iwl6050_2agn_cfg = {
 };
 
 const struct iwl_cfg iwl6050_2abg_cfg = {
-	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
+	.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG+N",
 	IWL_DEVICE_6050,
+	.ht_params = &iwl6000_ht_params,
 };
 
 #define IWL_DEVICE_6150						\
@@ -348,8 +357,9 @@ const struct iwl_cfg iwl6150_bgn_cfg = {
 };
 
 const struct iwl_cfg iwl6150_bg_cfg = {
-	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG",
+	.name = "Intel(R) Centrino(R) Wireless-N + WiMAX 6150 BG+N",
 	IWL_DEVICE_6150,
+	.ht_params = &iwl6000_ht_params,
 };
 
 const struct iwl_cfg iwl6000_3agn_cfg = {
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c
index f2cea1c7befc..bb72f4e6ed87 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-eeprom-read.c
@@ -347,6 +347,160 @@ static int iwl_find_otp_image(struct iwl_trans *trans,
 	return -EINVAL;
 }
 
+/*
+ * The following regulatory items and supporting code are from:
+ * iwleeprom - EEPROM reader/writer for intel wifi cards.
+ */
+struct regulatory_item
+{
+	unsigned addr;
+	u16	 data;
+	u16	 chn;
+};
+
+#define HT40 0x100
+struct regulatory_item regulatory[] =
+{
+	/*
+	 * BAND 2.4GHz (@15e-179 with regulatory base @156)
+	 * enabling channels 12-14 (1-11 should be enabled on all cards)
+	 */
+	{ 0x1E, 0x0f21, 12 },
+	{ 0x20, 0x0f21, 13 },
+	{ 0x22, 0x0f21, 14 },
+
+	/* BAND 5GHz */
+
+	/* subband 5170-5320 MHz (@198-1af) */
+//	{ 0x42, 0x0fe1, 34 },
+	{ 0x44, 0x0fe1, 36 },
+//	{ 0x46, 0x0fe1, 38 },
+	{ 0x48, 0x0fe1, 40 },
+//	{ 0x4a, 0x0fe1, 42 },
+	{ 0x4c, 0x0fe1, 44 },
+//	{ 0x4e, 0x0fe1, 46 },
+	{ 0x50, 0x0fe1, 48 },
+	{ 0x52, 0x0f31, 52 },
+	{ 0x54, 0x0f31, 56 },
+	{ 0x56, 0x0f31, 60 },
+	{ 0x58, 0x0f31, 64 },
+
+	/* subband 5500-5700 MHz (@1b2-1c7) */
+	{ 0x5c, 0x0f31, 100 },
+	{ 0x5e, 0x0f31, 104 },
+	{ 0x60, 0x0f31, 108 },
+	{ 0x62, 0x0f31, 112 },
+	{ 0x64, 0x0f31, 116 },
+	{ 0x66, 0x0f31, 120 },
+	{ 0x68, 0x0f31, 124 },
+	{ 0x6a, 0x0f31, 128 },
+	{ 0x6c, 0x0f31, 132 },
+	{ 0x6e, 0x0f31, 136 },
+	{ 0x70, 0x0f31, 140 },
+
+	/* subband 5725-5825 MHz (@1ca-1d5) */
+//	{ 0x74, 0x0fa1, 145 },
+	{ 0x76, 0x0fa1, 149 },
+	{ 0x78, 0x0fa1, 153 },
+	{ 0x7a, 0x0fa1, 157 },
+	{ 0x7c, 0x0fa1, 161 },
+	{ 0x7e, 0x0fa1, 165 },
+
+	/* BAND 2.4GHz, HT40 channels (@1d8-1e5) */
+	{ 0x82, 0x0e6f, HT40 + 1 },
+	{ 0x84, 0x0f6f, HT40 + 2 },
+	{ 0x86, 0x0f6f, HT40 + 3 },
+	{ 0x88, 0x0f6f, HT40 + 4 },
+	{ 0x8a, 0x0f6f, HT40 + 5 },
+	{ 0x8c, 0x0f6f, HT40 + 6 },
+	{ 0x8e, 0x0f6f, HT40 + 7 },
+
+	/* BAND 5GHz, HT40 channels (@1e8-1fd) */
+	{ 0x92, 0x0fe1, HT40 +  36 },
+	{ 0x94, 0x0fe1, HT40 +  44 },
+	{ 0x96, 0x0f31, HT40 +  52 },
+	{ 0x98, 0x0f31, HT40 +  60 },
+	{ 0x9a, 0x0f31, HT40 + 100 },
+	{ 0x9c, 0x0f31, HT40 + 108 },
+	{ 0x9e, 0x0f31, HT40 + 116 },
+	{ 0xa0, 0x0f31, HT40 + 124 },
+	{ 0xa2, 0x0f31, HT40 + 132 },
+	{ 0xa4, 0x0f61, HT40 + 149 },
+	{ 0xa6, 0x0f61, HT40 + 157 },
+
+	{ 0, 0}
+};
+
+/* This and bellow one are an EEPROM copy acessors actually */
+u16 iwl_eeprom_read16(__le16 *base, unsigned addr)
+{
+	return base[addr >> 1];
+}
+
+void iwl_eeprom_write16(__le16 *base, unsigned addr, u16 value)
+{
+	base[addr >> 1] = value;
+}
+
+/* We get here whith EEPROM semaphore aquired */
+void iwl_eeprom_patch11n(struct iwl_trans *trans, __le16 *eeprom)
+{
+	uint16_t value;
+	unsigned reg_offs;
+	int idx;
+
+	IWL_DEBUG_EEPROM(trans->dev, "Patching card EEPROM shadow RAM...\n");
+
+	/* This seems redundand but let's be intact with the original code */
+	IWL_DEBUG_EEPROM(trans->dev, "-> Changing subdev ID\n");
+	/* The magic number is EEPROM_SUBSYSTEM_ID from iwl-eeprom-parse.c */
+	value = iwl_eeprom_read16(eeprom, 0x14);
+	if ((value & 0x000F) == 0x0006) {
+		iwl_eeprom_write16(eeprom, 0x14, (value & 0xFFF0) | 0x0001);
+	}
+	/*
+	 * enabling .11n
+	 * W @8A << 00F0 (00B0) <- xxxx xxxx x1xx xxxx
+	 * W @8C << 103E (603F) <- x001 xxxx xxxx xxx0
+	 */
+	IWL_DEBUG_EEPROM(trans->dev, "-> Enabling 11n mode\n");
+
+	/* SKU_CAP */
+	value = iwl_eeprom_read16(eeprom, 0x8A);
+	if ((value & 0x0040) != 0x0040) {
+		IWL_DEBUG_EEPROM(trans->dev, "  SKU CAP\n");
+		iwl_eeprom_write16(eeprom, 0x8A, value | 0x0040);
+	}
+
+	/* OEM_MODE */
+	value = iwl_eeprom_read16(eeprom, 0x8C);
+	if ((value & 0x7001) != 0x1000) {
+		IWL_DEBUG_EEPROM(trans->dev, "  OEM MODE\n");
+		iwl_eeprom_write16(eeprom, 0x8C, (value & 0x9FFE) | 0x1000);
+	}
+
+	/* writing SKU ID - 'MoW' signature */
+	if (iwl_eeprom_read16(eeprom, 0x158) != 0x6f4d)
+		iwl_eeprom_write16(eeprom, 0x158, 0x6f4d);
+	if (iwl_eeprom_read16(eeprom, 0x15A) != 0x0057)
+		iwl_eeprom_write16(eeprom, 0x15A, 0x0057);
+
+	IWL_DEBUG_EEPROM(trans->dev, "-> Checking and adding channels...\n");
+	/* reading regulatory offset */
+	reg_offs = 2 * iwl_eeprom_read16(eeprom, 0xCC);
+	IWL_DEBUG_EEPROM(trans->dev, "Regulatory base: %04x\n", reg_offs);
+
+	/*writing channels regulatory.*/
+	for (idx=0; regulatory[idx].addr; idx++) {
+		if (iwl_eeprom_read16(eeprom, reg_offs + regulatory[idx].addr) != regulatory[idx].data) {
+			IWL_DEBUG_EEPROM(trans->dev, "  %d%s\n", regulatory[idx].chn & ~HT40, (regulatory[idx].chn & HT40) ? " (HT40)" : "");
+			iwl_eeprom_write16(eeprom, reg_offs + regulatory[idx].addr, regulatory[idx].data);
+		}
+	}
+
+	IWL_DEBUG_EEPROM(trans->dev, "\nCard EEPROM shadow RAM patched successfully\n");
+}
+
 /**
  * iwl_read_eeprom - read EEPROM contents
  *
@@ -448,6 +602,21 @@ int iwl_read_eeprom(struct iwl_trans *trans, u8 **eeprom, size_t *eeprom_size)
 	IWL_DEBUG_EEPROM(trans->dev, "NVM Type: %s\n",
 			 nvm_is_otp ? "OTP" : "EEPROM");
 
+#if IS_ENABLED(CONFIG_IWLDVM)
+	/* Hack EEPROM shadow to enable N mode on disabled hardware */
+	if (trans->cfg == &iwl6005_2abg_cfg ||
+	    trans->cfg == &iwl6005_2bg_cfg ||
+	    trans->cfg == &iwl6030_2abg_cfg ||
+	    trans->cfg == &iwl6030_2bg_cfg ||
+	    trans->cfg == &iwl1030_bg_cfg ||
+	    trans->cfg == &iwl130_bg_cfg ||
+	    trans->cfg == &iwl6000i_2abg_cfg ||
+	    trans->cfg == &iwl6000i_2bg_cfg ||
+	    trans->cfg == &iwl6050_2abg_cfg ||
+	    trans->cfg == &iwl6150_bg_cfg)
+		iwl_eeprom_patch11n(trans, e);
+#endif
+
 	iwl_eeprom_release_semaphore(trans);
 
 	*eeprom_size = sz;