|
@@ -7,6 +7,7 @@
|
|
|
*
|
|
|
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
|
|
|
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
|
|
|
+ * Copyright(c) 2016 Intel Deutschland GmbH
|
|
|
*
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
@@ -69,6 +70,7 @@
|
|
|
#include "iwl-drv.h"
|
|
|
#include "iwl-modparams.h"
|
|
|
#include "iwl-nvm-parse.h"
|
|
|
+#include "iwl-prph.h"
|
|
|
|
|
|
/* NVM offsets (in words) definitions */
|
|
|
enum wkp_nvm_offsets {
|
|
@@ -522,27 +524,11 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg,
|
|
|
data->valid_rx_ant = NVM_RF_CFG_RX_ANT_MSK_FAMILY_8000(radio_cfg);
|
|
|
}
|
|
|
|
|
|
-static void iwl_set_hw_address(const struct iwl_cfg *cfg,
|
|
|
- struct iwl_nvm_data *data,
|
|
|
- const __le16 *nvm_sec)
|
|
|
-{
|
|
|
- const u8 *hw_addr = (const u8 *)(nvm_sec + HW_ADDR);
|
|
|
-
|
|
|
- /* The byte order is little endian 16 bit, meaning 214365 */
|
|
|
- data->hw_addr[0] = hw_addr[1];
|
|
|
- data->hw_addr[1] = hw_addr[0];
|
|
|
- data->hw_addr[2] = hw_addr[3];
|
|
|
- data->hw_addr[3] = hw_addr[2];
|
|
|
- data->hw_addr[4] = hw_addr[5];
|
|
|
- data->hw_addr[5] = hw_addr[4];
|
|
|
-}
|
|
|
-
|
|
|
-static void iwl_set_hw_address_family_8000(struct device *dev,
|
|
|
+static void iwl_set_hw_address_family_8000(struct iwl_trans *trans,
|
|
|
const struct iwl_cfg *cfg,
|
|
|
struct iwl_nvm_data *data,
|
|
|
const __le16 *mac_override,
|
|
|
- const __le16 *nvm_hw,
|
|
|
- __le32 mac_addr0, __le32 mac_addr1)
|
|
|
+ const __le16 *nvm_hw)
|
|
|
{
|
|
|
const u8 *hw_addr;
|
|
|
|
|
@@ -568,11 +554,16 @@ static void iwl_set_hw_address_family_8000(struct device *dev,
|
|
|
memcmp(reserved_mac, hw_addr, ETH_ALEN) != 0)
|
|
|
return;
|
|
|
|
|
|
- IWL_ERR_DEV(dev,
|
|
|
- "mac address from nvm override section is not valid\n");
|
|
|
+ IWL_ERR(trans,
|
|
|
+ "mac address from nvm override section is not valid\n");
|
|
|
}
|
|
|
|
|
|
if (nvm_hw) {
|
|
|
+ /* read the mac address from WFMP registers */
|
|
|
+ __le32 mac_addr0 = cpu_to_le32(iwl_trans_read_prph(trans,
|
|
|
+ WFMP_MAC_ADDR_0));
|
|
|
+ __le32 mac_addr1 = cpu_to_le32(iwl_trans_read_prph(trans,
|
|
|
+ WFMP_MAC_ADDR_1));
|
|
|
/* read the MAC address from HW resisters */
|
|
|
hw_addr = (const u8 *)&mac_addr0;
|
|
|
data->hw_addr[0] = hw_addr[3];
|
|
@@ -585,28 +576,50 @@ static void iwl_set_hw_address_family_8000(struct device *dev,
|
|
|
data->hw_addr[5] = hw_addr[0];
|
|
|
|
|
|
if (!is_valid_ether_addr(data->hw_addr))
|
|
|
- IWL_ERR_DEV(dev,
|
|
|
- "mac address (%pM) from hw section is not valid\n",
|
|
|
- data->hw_addr);
|
|
|
+ IWL_ERR(trans,
|
|
|
+ "mac address (%pM) from hw section is not valid\n",
|
|
|
+ data->hw_addr);
|
|
|
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- IWL_ERR_DEV(dev, "mac address is not found\n");
|
|
|
+ IWL_ERR(trans, "mac address is not found\n");
|
|
|
+}
|
|
|
+
|
|
|
+static void iwl_set_hw_address(struct iwl_trans *trans,
|
|
|
+ const struct iwl_cfg *cfg,
|
|
|
+ struct iwl_nvm_data *data, const __le16 *nvm_hw,
|
|
|
+ const __le16 *mac_override)
|
|
|
+{
|
|
|
+ if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
|
|
+ const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR);
|
|
|
+
|
|
|
+ /* The byte order is little endian 16 bit, meaning 214365 */
|
|
|
+ data->hw_addr[0] = hw_addr[1];
|
|
|
+ data->hw_addr[1] = hw_addr[0];
|
|
|
+ data->hw_addr[2] = hw_addr[3];
|
|
|
+ data->hw_addr[3] = hw_addr[2];
|
|
|
+ data->hw_addr[4] = hw_addr[5];
|
|
|
+ data->hw_addr[5] = hw_addr[4];
|
|
|
+ } else {
|
|
|
+ iwl_set_hw_address_family_8000(trans, cfg, data,
|
|
|
+ mac_override, nvm_hw);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
struct iwl_nvm_data *
|
|
|
-iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
|
|
+iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg,
|
|
|
const __le16 *nvm_hw, const __le16 *nvm_sw,
|
|
|
const __le16 *nvm_calib, const __le16 *regulatory,
|
|
|
const __le16 *mac_override, const __le16 *phy_sku,
|
|
|
- u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
|
|
|
- __le32 mac_addr0, __le32 mac_addr1)
|
|
|
+ u8 tx_chains, u8 rx_chains, bool lar_fw_supported)
|
|
|
{
|
|
|
+ struct device *dev = trans->dev;
|
|
|
struct iwl_nvm_data *data;
|
|
|
- u32 sku;
|
|
|
- u32 radio_cfg;
|
|
|
+ bool lar_enabled;
|
|
|
+ u32 sku, radio_cfg;
|
|
|
u16 lar_config;
|
|
|
+ const __le16 *ch_section;
|
|
|
|
|
|
if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
|
|
|
data = kzalloc(sizeof(*data) +
|
|
@@ -645,21 +658,16 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
|
|
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
|
|
/* Checking for required sections */
|
|
|
if (!nvm_calib) {
|
|
|
- IWL_ERR_DEV(dev,
|
|
|
- "Can't parse empty Calib NVM sections\n");
|
|
|
+ IWL_ERR(trans,
|
|
|
+ "Can't parse empty Calib NVM sections\n");
|
|
|
kfree(data);
|
|
|
return NULL;
|
|
|
}
|
|
|
/* in family 8000 Xtal calibration values moved to OTP */
|
|
|
data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB);
|
|
|
data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1);
|
|
|
- }
|
|
|
-
|
|
|
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {
|
|
|
- iwl_set_hw_address(cfg, data, nvm_hw);
|
|
|
-
|
|
|
- iwl_init_sbands(dev, cfg, data, nvm_sw,
|
|
|
- tx_chains, rx_chains, lar_fw_supported);
|
|
|
+ lar_enabled = true;
|
|
|
+ ch_section = nvm_sw;
|
|
|
} else {
|
|
|
u16 lar_offset = data->nvm_version < 0xE39 ?
|
|
|
NVM_LAR_OFFSET_FAMILY_8000_OLD :
|
|
@@ -668,16 +676,13 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
|
|
|
lar_config = le16_to_cpup(regulatory + lar_offset);
|
|
|
data->lar_enabled = !!(lar_config &
|
|
|
NVM_LAR_ENABLED_FAMILY_8000);
|
|
|
-
|
|
|
- /* MAC address in family 8000 */
|
|
|
- iwl_set_hw_address_family_8000(dev, cfg, data, mac_override,
|
|
|
- nvm_hw, mac_addr0, mac_addr1);
|
|
|
-
|
|
|
- iwl_init_sbands(dev, cfg, data, regulatory,
|
|
|
- tx_chains, rx_chains,
|
|
|
- lar_fw_supported && data->lar_enabled);
|
|
|
+ lar_enabled = data->lar_enabled;
|
|
|
+ ch_section = regulatory;
|
|
|
}
|
|
|
|
|
|
+ iwl_set_hw_address(trans, cfg, data, nvm_hw, mac_override);
|
|
|
+ iwl_init_sbands(dev, cfg, data, ch_section, tx_chains, rx_chains,
|
|
|
+ lar_fw_supported && lar_enabled);
|
|
|
data->calib_version = 255;
|
|
|
|
|
|
return data;
|