diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-nvm-parse.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 270 |
1 files changed, 197 insertions, 73 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 725e954d8475..6be30c698506 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | |||
@@ -71,7 +71,7 @@ enum wkp_nvm_offsets { | |||
71 | /* NVM HW-Section offset (in words) definitions */ | 71 | /* NVM HW-Section offset (in words) definitions */ |
72 | HW_ADDR = 0x15, | 72 | HW_ADDR = 0x15, |
73 | 73 | ||
74 | /* NVM SW-Section offset (in words) definitions */ | 74 | /* NVM SW-Section offset (in words) definitions */ |
75 | NVM_SW_SECTION = 0x1C0, | 75 | NVM_SW_SECTION = 0x1C0, |
76 | NVM_VERSION = 0, | 76 | NVM_VERSION = 0, |
77 | RADIO_CFG = 1, | 77 | RADIO_CFG = 1, |
@@ -79,11 +79,32 @@ enum wkp_nvm_offsets { | |||
79 | N_HW_ADDRS = 3, | 79 | N_HW_ADDRS = 3, |
80 | NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION, | 80 | NVM_CHANNELS = 0x1E0 - NVM_SW_SECTION, |
81 | 81 | ||
82 | /* NVM calibration section offset (in words) definitions */ | 82 | /* NVM calibration section offset (in words) definitions */ |
83 | NVM_CALIB_SECTION = 0x2B8, | 83 | NVM_CALIB_SECTION = 0x2B8, |
84 | XTAL_CALIB = 0x316 - NVM_CALIB_SECTION | 84 | XTAL_CALIB = 0x316 - NVM_CALIB_SECTION |
85 | }; | 85 | }; |
86 | 86 | ||
87 | enum family_8000_nvm_offsets { | ||
88 | /* NVM HW-Section offset (in words) definitions */ | ||
89 | HW_ADDR0_FAMILY_8000 = 0x12, | ||
90 | HW_ADDR1_FAMILY_8000 = 0x16, | ||
91 | MAC_ADDRESS_OVERRIDE_FAMILY_8000 = 1, | ||
92 | |||
93 | /* NVM SW-Section offset (in words) definitions */ | ||
94 | NVM_SW_SECTION_FAMILY_8000 = 0x1C0, | ||
95 | NVM_VERSION_FAMILY_8000 = 0, | ||
96 | RADIO_CFG_FAMILY_8000 = 2, | ||
97 | SKU_FAMILY_8000 = 4, | ||
98 | N_HW_ADDRS_FAMILY_8000 = 5, | ||
99 | |||
100 | /* NVM REGULATORY -Section offset (in words) definitions */ | ||
101 | NVM_CHANNELS_FAMILY_8000 = 0, | ||
102 | |||
103 | /* NVM calibration section offset (in words) definitions */ | ||
104 | NVM_CALIB_SECTION_FAMILY_8000 = 0x2B8, | ||
105 | XTAL_CALIB_FAMILY_8000 = 0x316 - NVM_CALIB_SECTION_FAMILY_8000 | ||
106 | }; | ||
107 | |||
87 | /* SKU Capabilities (actual values from NVM definition) */ | 108 | /* SKU Capabilities (actual values from NVM definition) */ |
88 | enum nvm_sku_bits { | 109 | enum nvm_sku_bits { |
89 | NVM_SKU_CAP_BAND_24GHZ = BIT(0), | 110 | NVM_SKU_CAP_BAND_24GHZ = BIT(0), |
@@ -92,14 +113,6 @@ enum nvm_sku_bits { | |||
92 | NVM_SKU_CAP_11AC_ENABLE = BIT(3), | 113 | NVM_SKU_CAP_11AC_ENABLE = BIT(3), |
93 | }; | 114 | }; |
94 | 115 | ||
95 | /* radio config bits (actual values from NVM definition) */ | ||
96 | #define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */ | ||
97 | #define NVM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ | ||
98 | #define NVM_RF_CFG_TYPE_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ | ||
99 | #define NVM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ | ||
100 | #define NVM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ | ||
101 | #define NVM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ | ||
102 | |||
103 | /* | 116 | /* |
104 | * These are the channel numbers in the order that they are stored in the NVM | 117 | * These are the channel numbers in the order that they are stored in the NVM |
105 | */ | 118 | */ |
@@ -112,7 +125,17 @@ static const u8 iwl_nvm_channels[] = { | |||
112 | 149, 153, 157, 161, 165 | 125 | 149, 153, 157, 161, 165 |
113 | }; | 126 | }; |
114 | 127 | ||
128 | static const u8 iwl_nvm_channels_family_8000[] = { | ||
129 | /* 2.4 GHz */ | ||
130 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, | ||
131 | /* 5 GHz */ | ||
132 | 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92, | ||
133 | 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, | ||
134 | 149, 153, 157, 161, 165, 169, 173, 177, 181 | ||
135 | }; | ||
136 | |||
115 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) | 137 | #define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels) |
138 | #define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000) | ||
116 | #define NUM_2GHZ_CHANNELS 14 | 139 | #define NUM_2GHZ_CHANNELS 14 |
117 | #define FIRST_2GHZ_HT_MINUS 5 | 140 | #define FIRST_2GHZ_HT_MINUS 5 |
118 | #define LAST_2GHZ_HT_PLUS 9 | 141 | #define LAST_2GHZ_HT_PLUS 9 |
@@ -179,8 +202,18 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
179 | struct ieee80211_channel *channel; | 202 | struct ieee80211_channel *channel; |
180 | u16 ch_flags; | 203 | u16 ch_flags; |
181 | bool is_5ghz; | 204 | bool is_5ghz; |
205 | int num_of_ch; | ||
206 | const u8 *nvm_chan; | ||
207 | |||
208 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { | ||
209 | num_of_ch = IWL_NUM_CHANNELS; | ||
210 | nvm_chan = &iwl_nvm_channels[0]; | ||
211 | } else { | ||
212 | num_of_ch = IWL_NUM_CHANNELS_FAMILY_8000; | ||
213 | nvm_chan = &iwl_nvm_channels_family_8000[0]; | ||
214 | } | ||
182 | 215 | ||
183 | for (ch_idx = 0; ch_idx < IWL_NUM_CHANNELS; ch_idx++) { | 216 | for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { |
184 | ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); | 217 | ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); |
185 | 218 | ||
186 | if (ch_idx >= NUM_2GHZ_CHANNELS && | 219 | if (ch_idx >= NUM_2GHZ_CHANNELS && |
@@ -190,7 +223,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
190 | if (!(ch_flags & NVM_CHANNEL_VALID)) { | 223 | if (!(ch_flags & NVM_CHANNEL_VALID)) { |
191 | IWL_DEBUG_EEPROM(dev, | 224 | IWL_DEBUG_EEPROM(dev, |
192 | "Ch. %d Flags %x [%sGHz] - No traffic\n", | 225 | "Ch. %d Flags %x [%sGHz] - No traffic\n", |
193 | iwl_nvm_channels[ch_idx], | 226 | nvm_chan[ch_idx], |
194 | ch_flags, | 227 | ch_flags, |
195 | (ch_idx >= NUM_2GHZ_CHANNELS) ? | 228 | (ch_idx >= NUM_2GHZ_CHANNELS) ? |
196 | "5.2" : "2.4"); | 229 | "5.2" : "2.4"); |
@@ -200,7 +233,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
200 | channel = &data->channels[n_channels]; | 233 | channel = &data->channels[n_channels]; |
201 | n_channels++; | 234 | n_channels++; |
202 | 235 | ||
203 | channel->hw_value = iwl_nvm_channels[ch_idx]; | 236 | channel->hw_value = nvm_chan[ch_idx]; |
204 | channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ? | 237 | channel->band = (ch_idx < NUM_2GHZ_CHANNELS) ? |
205 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | 238 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; |
206 | channel->center_freq = | 239 | channel->center_freq = |
@@ -211,11 +244,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
211 | channel->flags = IEEE80211_CHAN_NO_HT40; | 244 | channel->flags = IEEE80211_CHAN_NO_HT40; |
212 | if (ch_idx < NUM_2GHZ_CHANNELS && | 245 | if (ch_idx < NUM_2GHZ_CHANNELS && |
213 | (ch_flags & NVM_CHANNEL_40MHZ)) { | 246 | (ch_flags & NVM_CHANNEL_40MHZ)) { |
214 | if (iwl_nvm_channels[ch_idx] <= LAST_2GHZ_HT_PLUS) | 247 | if (nvm_chan[ch_idx] <= LAST_2GHZ_HT_PLUS) |
215 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | 248 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; |
216 | if (iwl_nvm_channels[ch_idx] >= FIRST_2GHZ_HT_MINUS) | 249 | if (nvm_chan[ch_idx] >= FIRST_2GHZ_HT_MINUS) |
217 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; | 250 | channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; |
218 | } else if (iwl_nvm_channels[ch_idx] <= LAST_5GHZ_HT && | 251 | } else if (nvm_chan[ch_idx] <= LAST_5GHZ_HT && |
219 | (ch_flags & NVM_CHANNEL_40MHZ)) { | 252 | (ch_flags & NVM_CHANNEL_40MHZ)) { |
220 | if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) | 253 | if ((ch_idx - NUM_2GHZ_CHANNELS) % 2 == 0) |
221 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; | 254 | channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; |
@@ -266,9 +299,11 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, | |||
266 | 299 | ||
267 | static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | 300 | static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, |
268 | struct iwl_nvm_data *data, | 301 | struct iwl_nvm_data *data, |
269 | struct ieee80211_sta_vht_cap *vht_cap) | 302 | struct ieee80211_sta_vht_cap *vht_cap, |
303 | u8 tx_chains, u8 rx_chains) | ||
270 | { | 304 | { |
271 | int num_ants = num_of_ant(data->valid_rx_ant); | 305 | int num_rx_ants = num_of_ant(rx_chains); |
306 | int num_tx_ants = num_of_ant(tx_chains); | ||
272 | 307 | ||
273 | vht_cap->vht_supported = true; | 308 | vht_cap->vht_supported = true; |
274 | 309 | ||
@@ -278,8 +313,10 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
278 | 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | | 313 | 3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT | |
279 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; | 314 | 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; |
280 | 315 | ||
281 | if (num_ants > 1) | 316 | if (num_tx_ants > 1) |
282 | vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; | 317 | vht_cap->cap |= IEEE80211_VHT_CAP_TXSTBC; |
318 | else | ||
319 | vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
283 | 320 | ||
284 | if (iwlwifi_mod_params.amsdu_size_8K) | 321 | if (iwlwifi_mod_params.amsdu_size_8K) |
285 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; | 322 | vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; |
@@ -294,10 +331,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
294 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | | 331 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | |
295 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); | 332 | IEEE80211_VHT_MCS_NOT_SUPPORTED << 14); |
296 | 333 | ||
297 | if (num_ants == 1 || | 334 | if (num_rx_ants == 1 || cfg->rx_with_siso_diversity) { |
298 | cfg->rx_with_siso_diversity) { | 335 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN; |
299 | vht_cap->cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN | | ||
300 | IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; | ||
301 | /* this works because NOT_SUPPORTED == 3 */ | 336 | /* this works because NOT_SUPPORTED == 3 */ |
302 | vht_cap->vht_mcs.rx_mcs_map |= | 337 | vht_cap->vht_mcs.rx_mcs_map |= |
303 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); | 338 | cpu_to_le16(IEEE80211_VHT_MCS_NOT_SUPPORTED << 2); |
@@ -307,14 +342,23 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, | |||
307 | } | 342 | } |
308 | 343 | ||
309 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | 344 | static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, |
310 | struct iwl_nvm_data *data, const __le16 *nvm_sw, | 345 | struct iwl_nvm_data *data, |
311 | bool enable_vht, u8 tx_chains, u8 rx_chains) | 346 | const __le16 *ch_section, bool enable_vht, |
347 | u8 tx_chains, u8 rx_chains) | ||
312 | { | 348 | { |
313 | int n_channels = iwl_init_channel_map(dev, cfg, data, | 349 | int n_channels; |
314 | &nvm_sw[NVM_CHANNELS]); | ||
315 | int n_used = 0; | 350 | int n_used = 0; |
316 | struct ieee80211_supported_band *sband; | 351 | struct ieee80211_supported_band *sband; |
317 | 352 | ||
353 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
354 | n_channels = iwl_init_channel_map( | ||
355 | dev, cfg, data, | ||
356 | &ch_section[NVM_CHANNELS]); | ||
357 | else | ||
358 | n_channels = iwl_init_channel_map( | ||
359 | dev, cfg, data, | ||
360 | &ch_section[NVM_CHANNELS_FAMILY_8000]); | ||
361 | |||
318 | sband = &data->bands[IEEE80211_BAND_2GHZ]; | 362 | sband = &data->bands[IEEE80211_BAND_2GHZ]; |
319 | sband->band = IEEE80211_BAND_2GHZ; | 363 | sband->band = IEEE80211_BAND_2GHZ; |
320 | sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; | 364 | sband->bitrates = &iwl_cfg80211_rates[RATES_24_OFFS]; |
@@ -333,80 +377,160 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, | |||
333 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, | 377 | iwl_init_ht_hw_capab(cfg, data, &sband->ht_cap, IEEE80211_BAND_5GHZ, |
334 | tx_chains, rx_chains); | 378 | tx_chains, rx_chains); |
335 | if (enable_vht) | 379 | if (enable_vht) |
336 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap); | 380 | iwl_init_vht_hw_capab(cfg, data, &sband->vht_cap, |
381 | tx_chains, rx_chains); | ||
337 | 382 | ||
338 | if (n_channels != n_used) | 383 | if (n_channels != n_used) |
339 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", | 384 | IWL_ERR_DEV(dev, "NVM: used only %d of %d channels\n", |
340 | n_used, n_channels); | 385 | n_used, n_channels); |
341 | } | 386 | } |
342 | 387 | ||
388 | static int iwl_get_sku(const struct iwl_cfg *cfg, | ||
389 | const __le16 *nvm_sw) | ||
390 | { | ||
391 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
392 | return le16_to_cpup(nvm_sw + SKU); | ||
393 | else | ||
394 | return le32_to_cpup((__le32 *)(nvm_sw + SKU_FAMILY_8000)); | ||
395 | } | ||
396 | |||
397 | static int iwl_get_nvm_version(const struct iwl_cfg *cfg, | ||
398 | const __le16 *nvm_sw) | ||
399 | { | ||
400 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
401 | return le16_to_cpup(nvm_sw + NVM_VERSION); | ||
402 | else | ||
403 | return le32_to_cpup((__le32 *)(nvm_sw + | ||
404 | NVM_VERSION_FAMILY_8000)); | ||
405 | } | ||
406 | |||
407 | static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, | ||
408 | const __le16 *nvm_sw) | ||
409 | { | ||
410 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
411 | return le16_to_cpup(nvm_sw + RADIO_CFG); | ||
412 | else | ||
413 | return le32_to_cpup((__le32 *)(nvm_sw + RADIO_CFG_FAMILY_8000)); | ||
414 | } | ||
415 | |||
416 | #define N_HW_ADDRS_MASK_FAMILY_8000 0xF | ||
417 | static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, | ||
418 | const __le16 *nvm_sw) | ||
419 | { | ||
420 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
421 | return le16_to_cpup(nvm_sw + N_HW_ADDRS); | ||
422 | else | ||
423 | return le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000)) | ||
424 | & N_HW_ADDRS_MASK_FAMILY_8000; | ||
425 | } | ||
426 | |||
427 | static void iwl_set_radio_cfg(const struct iwl_cfg *cfg, | ||
428 | struct iwl_nvm_data *data, | ||
429 | u32 radio_cfg) | ||
430 | { | ||
431 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { | ||
432 | data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg); | ||
433 | data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg); | ||
434 | data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg); | ||
435 | data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg); | ||
436 | return; | ||
437 | } | ||
438 | |||
439 | /* set the radio configuration for family 8000 */ | ||
440 | data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK_FAMILY_8000(radio_cfg); | ||
441 | data->radio_cfg_step = NVM_RF_CFG_STEP_MSK_FAMILY_8000(radio_cfg); | ||
442 | data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK_FAMILY_8000(radio_cfg); | ||
443 | data->radio_cfg_pnum = NVM_RF_CFG_FLAVOR_MSK_FAMILY_8000(radio_cfg); | ||
444 | } | ||
445 | |||
446 | static void iwl_set_hw_address(const struct iwl_cfg *cfg, | ||
447 | struct iwl_nvm_data *data, | ||
448 | const __le16 *nvm_sec) | ||
449 | { | ||
450 | u8 hw_addr[ETH_ALEN]; | ||
451 | |||
452 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) | ||
453 | memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN); | ||
454 | else | ||
455 | memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000, | ||
456 | ETH_ALEN); | ||
457 | |||
458 | /* The byte order is little endian 16 bit, meaning 214365 */ | ||
459 | data->hw_addr[0] = hw_addr[1]; | ||
460 | data->hw_addr[1] = hw_addr[0]; | ||
461 | data->hw_addr[2] = hw_addr[3]; | ||
462 | data->hw_addr[3] = hw_addr[2]; | ||
463 | data->hw_addr[4] = hw_addr[5]; | ||
464 | data->hw_addr[5] = hw_addr[4]; | ||
465 | } | ||
466 | |||
343 | struct iwl_nvm_data * | 467 | struct iwl_nvm_data * |
344 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, | 468 | iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, |
345 | const __le16 *nvm_hw, const __le16 *nvm_sw, | 469 | const __le16 *nvm_hw, const __le16 *nvm_sw, |
346 | const __le16 *nvm_calib, u8 tx_chains, u8 rx_chains) | 470 | const __le16 *nvm_calib, const __le16 *regulatory, |
471 | const __le16 *mac_override, u8 tx_chains, u8 rx_chains) | ||
347 | { | 472 | { |
348 | struct iwl_nvm_data *data; | 473 | struct iwl_nvm_data *data; |
349 | u8 hw_addr[ETH_ALEN]; | 474 | u32 sku; |
350 | u16 radio_cfg, sku; | 475 | u32 radio_cfg; |
351 | 476 | ||
352 | data = kzalloc(sizeof(*data) + | 477 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) |
353 | sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, | 478 | data = kzalloc(sizeof(*data) + |
354 | GFP_KERNEL); | 479 | sizeof(struct ieee80211_channel) * |
480 | IWL_NUM_CHANNELS, | ||
481 | GFP_KERNEL); | ||
482 | else | ||
483 | data = kzalloc(sizeof(*data) + | ||
484 | sizeof(struct ieee80211_channel) * | ||
485 | IWL_NUM_CHANNELS_FAMILY_8000, | ||
486 | GFP_KERNEL); | ||
355 | if (!data) | 487 | if (!data) |
356 | return NULL; | 488 | return NULL; |
357 | 489 | ||
358 | data->nvm_version = le16_to_cpup(nvm_sw + NVM_VERSION); | 490 | data->nvm_version = iwl_get_nvm_version(cfg, nvm_sw); |
359 | 491 | ||
360 | radio_cfg = le16_to_cpup(nvm_sw + RADIO_CFG); | 492 | radio_cfg = iwl_get_radio_cfg(cfg, nvm_sw); |
361 | data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg); | 493 | iwl_set_radio_cfg(cfg, data, radio_cfg); |
362 | data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg); | ||
363 | data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg); | ||
364 | data->radio_cfg_pnum = NVM_RF_CFG_PNUM_MSK(radio_cfg); | ||
365 | data->valid_tx_ant = NVM_RF_CFG_TX_ANT_MSK(radio_cfg); | ||
366 | data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK(radio_cfg); | ||
367 | 494 | ||
368 | sku = le16_to_cpup(nvm_sw + SKU); | 495 | sku = iwl_get_sku(cfg, nvm_sw); |
369 | data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; | 496 | data->sku_cap_band_24GHz_enable = sku & NVM_SKU_CAP_BAND_24GHZ; |
370 | data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; | 497 | data->sku_cap_band_52GHz_enable = sku & NVM_SKU_CAP_BAND_52GHZ; |
371 | data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; | 498 | data->sku_cap_11n_enable = sku & NVM_SKU_CAP_11N_ENABLE; |
499 | data->sku_cap_11ac_enable = sku & NVM_SKU_CAP_11AC_ENABLE; | ||
372 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) | 500 | if (iwlwifi_mod_params.disable_11n & IWL_DISABLE_HT_ALL) |
373 | data->sku_cap_11n_enable = false; | 501 | data->sku_cap_11n_enable = false; |
374 | 502 | ||
375 | /* check overrides (some devices have wrong NVM) */ | 503 | data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); |
376 | if (cfg->valid_tx_ant) | ||
377 | data->valid_tx_ant = cfg->valid_tx_ant; | ||
378 | if (cfg->valid_rx_ant) | ||
379 | data->valid_rx_ant = cfg->valid_rx_ant; | ||
380 | 504 | ||
381 | if (!data->valid_tx_ant || !data->valid_rx_ant) { | 505 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
382 | IWL_ERR_DEV(dev, "invalid antennas (0x%x, 0x%x)\n", | 506 | /* Checking for required sections */ |
383 | data->valid_tx_ant, data->valid_rx_ant); | 507 | if (!nvm_calib) { |
384 | kfree(data); | 508 | IWL_ERR_DEV(dev, |
385 | return NULL; | 509 | "Can't parse empty Calib NVM sections\n"); |
510 | kfree(data); | ||
511 | return NULL; | ||
512 | } | ||
513 | /* in family 8000 Xtal calibration values moved to OTP */ | ||
514 | data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); | ||
515 | data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); | ||
386 | } | 516 | } |
387 | 517 | ||
388 | data->n_hw_addrs = le16_to_cpup(nvm_sw + N_HW_ADDRS); | 518 | if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { |
519 | iwl_set_hw_address(cfg, data, nvm_hw); | ||
389 | 520 | ||
390 | data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); | 521 | iwl_init_sbands(dev, cfg, data, nvm_sw, |
391 | data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); | 522 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, |
523 | rx_chains); | ||
524 | } else { | ||
525 | /* MAC address in family 8000 */ | ||
526 | iwl_set_hw_address(cfg, data, mac_override); | ||
392 | 527 | ||
393 | /* The byte order is little endian 16 bit, meaning 214365 */ | 528 | iwl_init_sbands(dev, cfg, data, regulatory, |
394 | memcpy(hw_addr, nvm_hw + HW_ADDR, ETH_ALEN); | 529 | sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains, |
395 | data->hw_addr[0] = hw_addr[1]; | 530 | rx_chains); |
396 | data->hw_addr[1] = hw_addr[0]; | 531 | } |
397 | data->hw_addr[2] = hw_addr[3]; | ||
398 | data->hw_addr[3] = hw_addr[2]; | ||
399 | data->hw_addr[4] = hw_addr[5]; | ||
400 | data->hw_addr[5] = hw_addr[4]; | ||
401 | |||
402 | iwl_init_sbands(dev, cfg, data, nvm_sw, sku & NVM_SKU_CAP_11AC_ENABLE, | ||
403 | tx_chains, rx_chains); | ||
404 | 532 | ||
405 | data->calib_version = 255; /* TODO: | 533 | data->calib_version = 255; |
406 | this value will prevent some checks from | ||
407 | failing, we need to check if this | ||
408 | field is still needed, and if it does, | ||
409 | where is it in the NVM*/ | ||
410 | 534 | ||
411 | return data; | 535 | return data; |
412 | } | 536 | } |