Talk:Intel Centrino Advanced-N 6205

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
 * http://forum.ixbt.com/topic.cgi?id=14:51214:2172#2172

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  --- 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, }; @@ -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, }; @@ -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, }; @@ -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;
 * CONFIG_IWLWIFI_DEBUG: iwlwifi debug=0x41
 * 1) define IWL_DEVICE_6035						\
 * 1) define IWL_DEVICE_6050						\
 * 1) define IWL_DEVICE_6150						\