Commit 70d3ca86 authored by Luca Coelho's avatar Luca Coelho Committed by Kalle Valo

iwlwifi: mvm: ring the doorbell and wait for PNVM load completion

When we receive a non-zero SKU_ID in the alive notification, we need
to ring the doorbell and wait for the FW to send us a PNVM load
complete notification before we continue the init phase.
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20201008180656.a10e8b6bbcf9.Ib5d10b3d508a4d2d4e6b7b629af89d76f4f03d81@changeid
parent 7ef3e224
...@@ -90,6 +90,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids { ...@@ -90,6 +90,11 @@ enum iwl_regulatory_and_nvm_subcmd_ids {
* @TAS_CONFIG: &struct iwl_tas_config_cmd * @TAS_CONFIG: &struct iwl_tas_config_cmd
*/ */
TAS_CONFIG = 0x3, TAS_CONFIG = 0x3,
/**
* @PNVM_INIT_COMPLETE_NTFY: &struct iwl_pnvm_init_complete_ntfy
*/
PNVM_INIT_COMPLETE_NTFY = 0xFE,
}; };
/** /**
...@@ -476,4 +481,12 @@ struct iwl_lari_config_change_cmd { ...@@ -476,4 +481,12 @@ struct iwl_lari_config_change_cmd {
__le32 config_bitmap; __le32 config_bitmap;
} __packed; /* LARI_CHANGE_CONF_CMD_S_VER_1 */ } __packed; /* LARI_CHANGE_CONF_CMD_S_VER_1 */
/**
* struct iwl_pnvm_init_complete_ntfy - PNVM initialization complete
* @status: PNVM image loading status
*/
struct iwl_pnvm_init_complete_ntfy {
__le32 status;
} __packed; /* PNVM_INIT_COMPLETE_NTFY_S_VER_1 */
#endif /* __iwl_fw_api_nvm_reg_h__ */ #endif /* __iwl_fw_api_nvm_reg_h__ */
...@@ -460,6 +460,7 @@ enum { ...@@ -460,6 +460,7 @@ enum {
#define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0) #define UREG_DOORBELL_TO_ISR6_NMI_BIT BIT(0)
#define UREG_DOORBELL_TO_ISR6_SUSPEND BIT(18) #define UREG_DOORBELL_TO_ISR6_SUSPEND BIT(18)
#define UREG_DOORBELL_TO_ISR6_RESUME BIT(19) #define UREG_DOORBELL_TO_ISR6_RESUME BIT(19)
#define UREG_DOORBELL_TO_ISR6_PNVM BIT(20)
#define FSEQ_ERROR_CODE 0xA340C8 #define FSEQ_ERROR_CODE 0xA340C8
#define FSEQ_TOP_INIT_VERSION 0xA34038 #define FSEQ_TOP_INIT_VERSION 0xA34038
......
...@@ -79,6 +79,7 @@ ...@@ -79,6 +79,7 @@
#define MVM_UCODE_ALIVE_TIMEOUT HZ #define MVM_UCODE_ALIVE_TIMEOUT HZ
#define MVM_UCODE_CALIB_TIMEOUT (2*HZ) #define MVM_UCODE_CALIB_TIMEOUT (2*HZ)
#define MVM_UCODE_PNVM_TIMEOUT (HZ / 10)
#define UCODE_VALID_OK cpu_to_le32(0x1) #define UCODE_VALID_OK cpu_to_le32(0x1)
...@@ -305,6 +306,20 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, ...@@ -305,6 +306,20 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
return true; return true;
} }
static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_mvm *mvm =
container_of(notif_wait, struct iwl_mvm, notif_wait);
struct iwl_pnvm_init_complete_ntfy *pnvm_ntf = (void *)pkt->data;
IWL_DEBUG_FW(mvm,
"PNVM complete notification received with status %d\n",
le32_to_cpu(pnvm_ntf->status));
return true;
}
static bool iwl_wait_init_complete(struct iwl_notif_wait_data *notif_wait, static bool iwl_wait_init_complete(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data) struct iwl_rx_packet *pkt, void *data)
{ {
...@@ -328,6 +343,35 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait, ...@@ -328,6 +343,35 @@ static bool iwl_wait_phy_db_entry(struct iwl_notif_wait_data *notif_wait,
return false; return false;
} }
static int iwl_mvm_load_pnvm(struct iwl_mvm *mvm)
{
struct iwl_notification_wait pnvm_wait;
static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP,
PNVM_INIT_COMPLETE_NTFY) };
/* if the SKU_ID is empty, there's nothing to do */
if (!mvm->trans->sku_id[0] &&
!mvm->trans->sku_id[1] &&
!mvm->trans->sku_id[2])
return 0;
/*
* TODO: phase 2: load the pnvm file, find the right section,
* load it and set the right DMA pointer.
*/
iwl_init_notification_wait(&mvm->notif_wait, &pnvm_wait,
ntf_cmds, ARRAY_SIZE(ntf_cmds),
iwl_pnvm_complete_fn, NULL);
/* kick the doorbell */
iwl_write_umac_prph(mvm->trans, UREG_DOORBELL_TO_ISR6,
UREG_DOORBELL_TO_ISR6_PNVM);
return iwl_wait_notification(&mvm->notif_wait, &pnvm_wait,
MVM_UCODE_PNVM_TIMEOUT);
}
static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
enum iwl_ucode_type ucode_type) enum iwl_ucode_type ucode_type)
{ {
...@@ -416,6 +460,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, ...@@ -416,6 +460,13 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return -EIO; return -EIO;
} }
ret = iwl_mvm_load_pnvm(mvm);
if (ret) {
IWL_ERR(mvm, "Timeout waiting for PNVM load!\n");
iwl_fw_set_current_image(&mvm->fwrt, old_type);
return ret;
}
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr); iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment