diff --git a/icnss2/debug.c b/icnss2/debug.c index 44308f1a05..ac1c9d72e6 100644 --- a/icnss2/debug.c +++ b/icnss2/debug.c @@ -475,7 +475,7 @@ static int icnss_stats_show(struct seq_file *s, void *data) ICNSS_STATS_DUMP(s, priv, pm_stay_awake); ICNSS_STATS_DUMP(s, priv, pm_relax); - if (priv->device_id != WCN6750_DEVICE_ID) { + if (priv->device_id == ADRASTEA_DEVICE_ID) { seq_puts(s, "\n<------------------ MSA stats ------------------->\n"); ICNSS_STATS_DUMP(s, priv, msa_info_req); ICNSS_STATS_DUMP(s, priv, msa_info_resp); diff --git a/icnss2/main.c b/icnss2/main.c index 4a037aeee7..b254558966 100644 --- a/icnss2/main.c +++ b/icnss2/main.c @@ -896,7 +896,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv, } } - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { if (!icnss_get_temperature(priv, &temp)) { icnss_pr_dbg("Temperature: %d\n", temp); if (temp < WLAN_EN_TEMP_THRESHOLD) @@ -938,7 +939,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv, if (ret) goto fail; - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { ret = wlfw_device_info_send_msg(priv); if (ret < 0) { ignore_assert = true; @@ -978,7 +980,8 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv, goto device_info_failure; } - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { if (!priv->fw_soc_wake_ack_irq) register_soc_wake_notif(&priv->pdev->dev); @@ -1163,7 +1166,8 @@ static int icnss_driver_event_fw_ready_ind(struct icnss_priv *priv, void *data) clear_bit(ICNSS_MODE_ON, &priv->state); atomic_set(&priv->soc_wake_ref_count, 0); - if (priv->device_id == WCN6750_DEVICE_ID) + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) icnss_free_qdss_mem(priv); icnss_pr_info("WLAN FW is ready: 0x%lx\n", priv->state); @@ -1598,7 +1602,8 @@ static int icnss_driver_event_pd_service_down(struct icnss_priv *priv, if (priv->force_err_fatal) ICNSS_ASSERT(0); - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { icnss_send_smp2p(priv, ICNSS_RESET_MSG, ICNSS_SMP2P_OUT_SOC_WAKE); icnss_send_smp2p(priv, ICNSS_RESET_MSG, @@ -2614,7 +2619,8 @@ static int icnss_register_ramdump_devices(struct icnss_priv *priv) return -ENOMEM; } - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { priv->m3_dump_phyareg = icnss_create_ramdump_device(priv, ICNSS_M3_SEGMENT( ICNSS_M3_SEGMENT_PHYAREG)); @@ -2970,7 +2976,7 @@ out: } EXPORT_SYMBOL(icnss_unregister_driver); -static struct icnss_msi_config msi_config = { +static struct icnss_msi_config msi_config_wcn6750 = { .total_vectors = 28, .total_users = 2, .users = (struct icnss_msi_user[]) { @@ -2979,9 +2985,20 @@ static struct icnss_msi_config msi_config = { }, }; +static struct icnss_msi_config msi_config_wcn6450 = { + .total_vectors = 10, + .total_users = 1, + .users = (struct icnss_msi_user[]) { + { .name = "CE", .num_vectors = 10, .base_vector = 0 }, + }, +}; + static int icnss_get_msi_assignment(struct icnss_priv *priv) { - priv->msi_config = &msi_config; + if (priv->device_id == WCN6750_DEVICE_ID) + priv->msi_config = &msi_config_wcn6750; + else + priv->msi_config = &msi_config_wcn6450; return 0; } @@ -3918,7 +3935,7 @@ static ssize_t wlan_en_delay_store(struct device *dev, struct icnss_priv *priv = dev_get_drvdata(dev); uint32_t wlan_en_delay = 0; - if (priv->device_id != WCN6750_DEVICE_ID) + if (priv->device_id == ADRASTEA_DEVICE_ID) return count; if (sscanf(buf, "%du", &wlan_en_delay) != 1) { @@ -4085,7 +4102,8 @@ static int icnss_resource_parse(struct icnss_priv *priv) priv->is_slate_rfa = true; icnss_pr_err("SLATE rfa is enabled\n"); } - } else if (priv->device_id == WCN6750_DEVICE_ID) { + } else if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "msi_addr"); if (!res) { @@ -4122,7 +4140,7 @@ static int icnss_resource_parse(struct icnss_priv *priv) priv->msi_base_data, int_prop); icnss_get_msi_assignment(priv); - for (i = 0; i < msi_config.total_vectors; i++) { + for (i = 0; i < priv->msi_config->total_vectors; i++) { res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i); if (!res) { @@ -4273,7 +4291,8 @@ static int icnss_smmu_dt_parse(struct icnss_priv *priv) if (!ret && !strcmp("fastmap", iommu_dma_type)) { icnss_pr_dbg("SMMU S1 stage enabled\n"); priv->smmu_s1_enable = true; - if (priv->device_id == WCN6750_DEVICE_ID) + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) iommu_set_fault_handler(priv->iommu_domain, icnss_smmu_fault_handler, priv); @@ -4339,16 +4358,19 @@ void icnss_add_fw_prefix_name(struct icnss_priv *priv, char *prefix_name, if (priv->device_id == ADRASTEA_DEVICE_ID) scnprintf(prefix_name, ICNSS_MAX_FILE_NAME, ADRASTEA_PATH_PREFIX "%s", name); - else + else if (priv->device_id == WCN6750_DEVICE_ID) scnprintf(prefix_name, ICNSS_MAX_FILE_NAME, QCA6750_PATH_PREFIX "%s", name); - + else if (priv->device_id == WCN6450_DEVICE_ID) + scnprintf(prefix_name, ICNSS_MAX_FILE_NAME, + WCN6450_PATH_PREFIX "%s", name); icnss_pr_dbg("File added with prefix: %s\n", prefix_name); } static const struct platform_device_id icnss_platform_id_table[] = { { .name = "wcn6750", .driver_data = WCN6750_DEVICE_ID, }, { .name = "adrastea", .driver_data = ADRASTEA_DEVICE_ID, }, + { .name = "wcn6450", .driver_data = WCN6450_DEVICE_ID, }, { }, }; @@ -4359,6 +4381,9 @@ static const struct of_device_id icnss_dt_match[] = { { .compatible = "qcom,icnss", .data = (void *)&icnss_platform_id_table[1]}, + { + .compatible = "qcom,wcn6450", + .data = (void *)&icnss_platform_id_table[2]}, { }, }; @@ -4532,7 +4557,8 @@ static int icnss_probe(struct platform_device *pdev) if (priv->is_slate_rfa) init_completion(&priv->slate_boot_complete); - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { priv->soc_wake_wq = alloc_workqueue("icnss_soc_wake_event", WQ_UNBOUND|WQ_HIGHPRI, 1); if (!priv->soc_wake_wq) { @@ -4654,7 +4680,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_pdr_unregister_notifier(priv); } - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { icnss_genl_exit(); icnss_runtime_pm_deinit(priv); if (!IS_ERR_OR_NULL(priv->mbox_chan)) @@ -4727,7 +4754,8 @@ static int icnss_pm_suspend(struct device *dev) ret = priv->ops->pm_suspend(dev); if (ret == 0) { - if (priv->device_id == WCN6750_DEVICE_ID) { + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { if (test_bit(ICNSS_PD_RESTART, &priv->state) || !test_bit(ICNSS_MODE_ON, &priv->state)) return 0; @@ -4836,7 +4864,7 @@ static int icnss_pm_runtime_suspend(struct device *dev) struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; - if (priv->device_id != WCN6750_DEVICE_ID) { + if (priv->device_id == ADRASTEA_DEVICE_ID) { icnss_pr_err("Ignore runtime suspend:\n"); goto out; } @@ -4870,8 +4898,8 @@ static int icnss_pm_runtime_resume(struct device *dev) struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; - if (priv->device_id != WCN6750_DEVICE_ID) { - icnss_pr_err("Ignore runtime resume:\n"); + if (priv->device_id == ADRASTEA_DEVICE_ID) { + icnss_pr_err("Ignore runtime resume\n"); goto out; } @@ -4897,8 +4925,8 @@ static int icnss_pm_runtime_idle(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); - if (priv->device_id != WCN6750_DEVICE_ID) { - icnss_pr_err("Ignore runtime idle:\n"); + if (priv->device_id == ADRASTEA_DEVICE_ID) { + icnss_pr_err("Ignore runtime idle\n"); goto out; } diff --git a/icnss2/main.h b/icnss2/main.h index d7b0c6f404..48bebcf7d2 100644 --- a/icnss2/main.h +++ b/icnss2/main.h @@ -22,12 +22,14 @@ #include #define WCN6750_DEVICE_ID 0x6750 +#define WCN6450_DEVICE_ID 0x6450 #define ADRASTEA_DEVICE_ID 0xabcd #define THERMAL_NAME_LENGTH 20 #define ICNSS_SMEM_VALUE_MASK 0xFFFFFFFF #define ICNSS_SMEM_SEQ_NO_POS 16 #define QCA6750_PATH_PREFIX "qca6750/" #define ADRASTEA_PATH_PREFIX "adrastea/" +#define WCN6450_PATH_PREFIX "wcn6450/" #define ICNSS_MAX_FILE_NAME 35 #define ICNSS_PCI_EP_WAKE_OFFSET 4 #define ICNSS_DISABLE_M3_SSR 0 diff --git a/icnss2/power.c b/icnss2/power.c index adbea8329b..d45fb8adaf 100644 --- a/icnss2/power.c +++ b/icnss2/power.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include @@ -38,6 +39,13 @@ static struct icnss_battery_level icnss_battery_level[] = { {0, 2850000}, }; +static struct icnss_vreg_cfg icnss_wcn6450_vreg_list[] = { + {"vdd-cx-mx", 824000, 952000, 0, 0, 0, false, true}, + {"vdd-1.8-xo", 1872000, 1872000, 0, 0, 0, false, true}, + {"vdd-1.3-rfa", 1256000, 1352000, 0, 0, 0, false, true}, + {"vdd-aon", 1256000, 1352000, 0, 0, 0, false, true}, +}; + static struct icnss_clk_cfg icnss_clk_list[] = { {"rf_clk", 0, 0}, }; @@ -48,6 +56,7 @@ static struct icnss_clk_cfg icnss_adrestea_clk_list[] = { #define ICNSS_VREG_LIST_SIZE ARRAY_SIZE(icnss_wcn6750_vreg_list) #define ICNSS_VREG_ADRESTEA_LIST_SIZE ARRAY_SIZE(icnss_adrestea_vreg_list) +#define ICNSS_VREG_EVROS_LIST_SIZE ARRAY_SIZE(icnss_wcn6450_vreg_list) #define ICNSS_CLK_LIST_SIZE ARRAY_SIZE(icnss_clk_list) #define ICNSS_CLK_ADRESTEA_LIST_SIZE ARRAY_SIZE(icnss_adrestea_clk_list) @@ -311,6 +320,10 @@ static struct icnss_vreg_cfg *get_vreg_list(u32 *vreg_list_size, *vreg_list_size = ICNSS_VREG_ADRESTEA_LIST_SIZE; return icnss_adrestea_vreg_list; + case WCN6450_DEVICE_ID: + *vreg_list_size = ICNSS_VREG_EVROS_LIST_SIZE; + return icnss_wcn6450_vreg_list; + default: icnss_pr_err("Unsupported device_id 0x%x\n", device_id); *vreg_list_size = 0; @@ -524,7 +537,8 @@ int icnss_get_clk(struct icnss_priv *priv) if (priv->device_id == ADRASTEA_DEVICE_ID) { clk_cfg = icnss_adrestea_clk_list; clk_list_size = ICNSS_CLK_ADRESTEA_LIST_SIZE; - } else if (priv->device_id == WCN6750_DEVICE_ID) { + } else if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { clk_cfg = icnss_clk_list; clk_list_size = ICNSS_CLK_LIST_SIZE; } diff --git a/icnss2/qmi.c b/icnss2/qmi.c index 5ee261f709..63d8526e82 100644 --- a/icnss2/qmi.c +++ b/icnss2/qmi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #define pr_fmt(fmt) "icnss2_qmi: " fmt @@ -55,6 +55,9 @@ #define DMS_MAC_NOT_PROVISIONED 16 #define BDWLAN_SIZE 6 #define UMC_CHIP_ID 0x4320 +#define MAX_SHADOW_REG_RESERVED 2 +#define MAX_NUM_SHADOW_REG_V3 (QMI_WLFW_MAX_NUM_SHADOW_REG_V3_USAGE_V01 - \ + MAX_SHADOW_REG_RESERVED) #ifdef CONFIG_ICNSS2_DEBUG bool ignore_fw_timeout; @@ -546,7 +549,8 @@ int wlfw_ind_register_send_sync_msg(struct icnss_priv *priv) req->rejuvenate_enable_valid = 1; req->rejuvenate_enable = 1; } - } else if (priv->device_id == WCN6750_DEVICE_ID) { + } else if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) { req->fw_init_done_enable_valid = 1; req->fw_init_done_enable = 1; req->cal_done_enable_valid = 1; @@ -2969,7 +2973,8 @@ int icnss_register_fw_service(struct icnss_priv *priv) if (ret < 0) return ret; - if (priv->device_id == WCN6750_DEVICE_ID) + if (priv->device_id == WCN6750_DEVICE_ID || + priv->device_id == WCN6450_DEVICE_ID) ret = qmi_add_lookup(&priv->qmi, WLFW_SERVICE_ID_V01, WLFW_SERVICE_VERS_V01, WLFW_SERVICE_WCN_INS_ID_V01); @@ -3060,6 +3065,17 @@ int icnss_send_wlan_enable_to_fw(struct icnss_priv *priv, memcpy(req.shadow_reg, config->shadow_reg_cfg, sizeof(struct wlfw_msi_cfg_s_v01) * req.shadow_reg_len); + } else if (priv->device_id == WCN6450_DEVICE_ID) { + req.shadow_reg_v3_valid = 1; + if (config->num_shadow_reg_v3_cfg > + MAX_NUM_SHADOW_REG_V3) + req.shadow_reg_v3_len = MAX_NUM_SHADOW_REG_V3; + else + req.shadow_reg_v3_len = config->num_shadow_reg_v3_cfg; + + memcpy(req.shadow_reg_v3, config->shadow_reg_v3_cfg, + sizeof(struct wlfw_shadow_reg_v3_cfg_s_v01) + * req.shadow_reg_v3_len); } ret = wlfw_wlan_cfg_send_sync_msg(priv, &req); diff --git a/inc/icnss2.h b/inc/icnss2.h index 51e4e39f22..c32bec8f4e 100644 --- a/inc/icnss2.h +++ b/inc/icnss2.h @@ -95,6 +95,10 @@ struct icnss_shadow_reg_v2_cfg { u32 addr; }; +struct icnss_shadow_reg_v3_cfg { + u32 addr; +}; + struct icnss_rri_over_ddr_cfg { u32 base_addr_low; u32 base_addr_high; @@ -109,6 +113,8 @@ struct icnss_wlan_enable_cfg { struct icnss_shadow_reg_cfg *shadow_reg_cfg; u32 num_shadow_reg_v2_cfg; struct icnss_shadow_reg_v2_cfg *shadow_reg_v2_cfg; + u32 num_shadow_reg_v3_cfg; + struct icnss_shadow_reg_v3_cfg *shadow_reg_v3_cfg; bool rri_over_ddr_cfg_valid; struct icnss_rri_over_ddr_cfg rri_over_ddr_cfg; };