* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
*
* 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
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
};
/**
+ * struct iwl_phy_specific_cfg - specific PHY filter configuration
+ *
+ * Sent as part of the phy configuration command (v3) to configure specific FW
+ * defined PHY filters that can be applied to each antenna.
+ *
+ * @filter_cfg_chain_a: filter config id for LMAC1 chain A
+ * @filter_cfg_chain_b: filter config id for LMAC1 chain B
+ * @filter_cfg_chain_c: filter config id for LMAC2 chain A
+ * @filter_cfg_chain_d: filter config id for LMAC2 chain B
+ * values: 0 - no filter; 0xffffffff - reserved; otherwise - filter id
+ */
+struct iwl_phy_specific_cfg {
+ __le32 filter_cfg_chain_a;
+ __le32 filter_cfg_chain_b;
+ __le32 filter_cfg_chain_c;
+ __le32 filter_cfg_chain_d;
+} __packed; /* PHY_SPECIFIC_CONFIGURATION_API_VER_1*/
+
+/**
* struct iwl_phy_cfg_cmd - Phy configuration command
+ *
* @phy_cfg: PHY configuration value, uses &enum iwl_fw_phy_cfg
* @calib_control: calibration control data
*/
-struct iwl_phy_cfg_cmd {
+struct iwl_phy_cfg_cmd_v1 {
__le32 phy_cfg;
struct iwl_calib_ctrl calib_control;
} __packed;
+/**
+ * struct iwl_phy_cfg_cmd_v3 - Phy configuration command (v3)
+ *
+ * @phy_cfg: PHY configuration value, uses &enum iwl_fw_phy_cfg
+ * @calib_control: calibration control data
+ * @phy_specific_cfg: configure predefined PHY filters
+ */
+struct iwl_phy_cfg_cmd_v3 {
+ __le32 phy_cfg;
+ struct iwl_calib_ctrl calib_control;
+ struct iwl_phy_specific_cfg phy_specific_cfg;
+} __packed; /* PHY_CONFIGURATION_CMD_API_S_VER_3 */
+
/*
* enum iwl_dc2dc_config_id - flag ids
*
#define IWL_MVM_USE_TWT false
#define IWL_MVM_AMPDU_CONSEC_DROPS_DELBA 10
#define IWL_MVM_USE_NSSN_SYNC 0
+#define IWL_MVM_PHY_FILTER_CHAIN_A 0
+#define IWL_MVM_PHY_FILTER_CHAIN_B 0
+#define IWL_MVM_PHY_FILTER_CHAIN_C 0
+#define IWL_MVM_PHY_FILTER_CHAIN_D 0
#endif /* __MVM_CONSTANTS_H */
return ret;
}
+#ifdef CONFIG_ACPI
+static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
+ struct iwl_phy_specific_cfg *phy_filters)
+{
+ /*
+ * TODO: read specific phy config from BIOS
+ * ACPI table for this feature has not been defined yet,
+ * so for now we use hardcoded values.
+ */
+
+ if (IWL_MVM_PHY_FILTER_CHAIN_A) {
+ phy_filters->filter_cfg_chain_a =
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_A);
+ }
+ if (IWL_MVM_PHY_FILTER_CHAIN_B) {
+ phy_filters->filter_cfg_chain_b =
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_B);
+ }
+ if (IWL_MVM_PHY_FILTER_CHAIN_C) {
+ phy_filters->filter_cfg_chain_c =
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_C);
+ }
+ if (IWL_MVM_PHY_FILTER_CHAIN_D) {
+ phy_filters->filter_cfg_chain_d =
+ cpu_to_le32(IWL_MVM_PHY_FILTER_CHAIN_D);
+ }
+}
+
+#else /* CONFIG_ACPI */
+
+static void iwl_mvm_phy_filter_init(struct iwl_mvm *mvm,
+ struct iwl_phy_specific_cfg *phy_filters)
+{
+}
+#endif /* CONFIG_ACPI */
+
static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
{
- struct iwl_phy_cfg_cmd phy_cfg_cmd;
+ struct iwl_phy_cfg_cmd_v3 phy_cfg_cmd;
enum iwl_ucode_type ucode_type = mvm->fwrt.cur_fw_img;
+ struct iwl_phy_specific_cfg phy_filters = {};
+ u8 cmd_ver;
+ size_t cmd_size;
if (iwl_mvm_has_unified_ucode(mvm) &&
!mvm->trans->cfg->tx_with_siso_diversity)
phy_cfg_cmd.calib_control.flow_trigger =
mvm->fw->default_calib[ucode_type].flow_trigger;
+ cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP,
+ PHY_CONFIGURATION_CMD);
+ if (cmd_ver == 3) {
+ iwl_mvm_phy_filter_init(mvm, &phy_filters);
+ memcpy(&phy_cfg_cmd.phy_specific_cfg, &phy_filters,
+ sizeof(struct iwl_phy_specific_cfg));
+ }
+
IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
phy_cfg_cmd.phy_cfg);
-
+ cmd_size = (cmd_ver == 3) ? sizeof(struct iwl_phy_cfg_cmd_v3) :
+ sizeof(struct iwl_phy_cfg_cmd_v1);
return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0,
- sizeof(phy_cfg_cmd), &phy_cfg_cmd);
+ cmd_size, &phy_cfg_cmd);
}
int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)