Loading Documentation/devicetree/bindings/cnss/icnss.txt +1 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ Optional properties: - qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass - qcom,wlan-msa-fixed-region: phandle, specifier pairs to children of /reserved-memory - qcom,hyp_disabled: Boolean context flag to disable hyperviser - qcom,clk-monitor-enable: Boolean context flag to enable monitoring external clock WLAN SMP2P sub nodes Loading drivers/soc/qcom/icnss.c +96 −2 Original line number Diff line number Diff line Loading @@ -70,6 +70,9 @@ #define ICNSS_QUIRKS_DEFAULT BIT(FW_REJUVENATE_ENABLE) #define ICNSS_MAX_PROBE_CNT 2 #define SUBSYS_INTERNAL_MODEM_NAME "modem" #define SUBSYS_EXTERNAL_MODEM_NAME "esoc0" #define PROBE_TIMEOUT 5000 static struct icnss_priv *penv; Loading Loading @@ -964,6 +967,13 @@ static int icnss_driver_event_server_arrive(void *data) set_bit(ICNSS_WLFW_CONNECTED, &penv->state); if (penv->clk_monitor_enable && !test_bit(ICNSS_CLK_UP, &penv->state)) { reinit_completion(&penv->clk_complete); icnss_pr_dbg("Waiting for CLK up notification\n"); wait_for_completion(&penv->clk_complete); } ret = icnss_hw_power_on(penv); if (ret) goto clear_server; Loading Loading @@ -1560,6 +1570,68 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, return NOTIFY_OK; } static int icnss_ext_modem_notifier_nb(struct notifier_block *nb, unsigned long code, void *data) { struct icnss_priv *priv = container_of(nb, struct icnss_priv, ext_modem_ssr_nb); icnss_pr_vdbg("EXT-Modem-Notify: event %lu\n", code); if (code == SUBSYS_AFTER_POWERUP) { set_bit(ICNSS_CLK_UP, &priv->state); complete(&priv->clk_complete); } return NOTIFY_OK; } static int icnss_ext_modem_ssr_register_notifier(struct icnss_priv *priv) { int ret = 0; priv->ext_modem_ssr_nb.notifier_call = icnss_ext_modem_notifier_nb; priv->ext_modem_notify_handler = subsys_notif_register_notifier(SUBSYS_EXTERNAL_MODEM_NAME, &priv->ext_modem_ssr_nb); if (IS_ERR_OR_NULL(priv->ext_modem_notify_handler)) { ret = PTR_ERR(priv->ext_modem_notify_handler); icnss_pr_err("External Modem register notifier failed %d\n", ret); priv->ext_modem_notify_handler = NULL; /* In NULL case */ if (ret == 0) ret = -EINVAL; return ret; } init_completion(&priv->clk_complete); return ret; } static int icnss_ext_modem_ssr_unregister_notifier(struct icnss_priv *priv) { int ret = 0; if (!priv->ext_modem_notify_handler) return 0; complete_all(&priv->clk_complete); ret = subsys_notif_unregister_notifier(priv->ext_modem_notify_handler, &priv->ext_modem_ssr_nb); if (ret) icnss_pr_err("Fail to unregister external Modem notifier %d\n", ret); priv->ext_modem_notify_handler = NULL; return 0; } static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv) { int ret = 0; Loading @@ -1567,7 +1639,8 @@ static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv) priv->modem_ssr_nb.notifier_call = icnss_modem_notifier_nb; priv->modem_notify_handler = subsys_notif_register_notifier("modem", &priv->modem_ssr_nb); subsys_notif_register_notifier(SUBSYS_INTERNAL_MODEM_NAME, &priv->modem_ssr_nb); if (IS_ERR(priv->modem_notify_handler)) { ret = PTR_ERR(priv->modem_notify_handler); Loading Loading @@ -2826,6 +2899,10 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) continue; case ICNSS_PDR: seq_puts(s, "PDR TRIGGERED"); continue; case ICNSS_CLK_UP: seq_puts(s, "CLK UP"); continue; } seq_printf(s, "UNKNOWN-%d", i); Loading Loading @@ -3492,6 +3569,19 @@ static int icnss_probe(struct platform_device *pdev) } } if (of_property_read_bool(pdev->dev.of_node, "qcom,clk-monitor-enable")) { priv->clk_monitor_enable = true; icnss_pr_dbg("CLK monitor is enabled\n"); } if (priv->clk_monitor_enable) { ret = icnss_ext_modem_ssr_register_notifier(priv); if (ret) goto out_smmu_deinit; } spin_lock_init(&priv->event_lock); spin_lock_init(&priv->on_off_lock); mutex_init(&priv->dev_lock); Loading @@ -3500,7 +3590,7 @@ static int icnss_probe(struct platform_device *pdev) if (!priv->event_wq) { icnss_pr_err("Workqueue creation failed\n"); ret = -EFAULT; goto out_smmu_deinit; goto out_unregister_ext_modem; } INIT_WORK(&priv->event_work, icnss_driver_event_work); Loading Loading @@ -3533,6 +3623,8 @@ static int icnss_probe(struct platform_device *pdev) out_destroy_wq: destroy_workqueue(priv->event_wq); out_unregister_ext_modem: icnss_ext_modem_ssr_unregister_notifier(priv); out_smmu_deinit: icnss_smmu_deinit(priv); out: Loading Loading @@ -3563,6 +3655,8 @@ static int icnss_remove(struct platform_device *pdev) if (penv->event_wq) destroy_workqueue(penv->event_wq); icnss_ext_modem_ssr_unregister_notifier(penv); icnss_hw_power_off(penv); icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_HLOS_ALL); Loading drivers/soc/qcom/icnss_private.h +5 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,7 @@ enum icnss_driver_state { ICNSS_MODE_ON, ICNSS_BLOCK_SHUTDOWN, ICNSS_PDR, ICNSS_CLK_UP, }; struct ce_irq_list { Loading Loading @@ -373,6 +374,10 @@ struct icnss_priv { struct kobject *icnss_kobject; atomic_t is_shutdown; bool is_ssr; bool clk_monitor_enable; void *ext_modem_notify_handler; struct notifier_block ext_modem_ssr_nb; struct completion clk_complete; }; int icnss_call_driver_uevent(struct icnss_priv *priv, Loading Loading
Documentation/devicetree/bindings/cnss/icnss.txt +1 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ Optional properties: - qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass - qcom,wlan-msa-fixed-region: phandle, specifier pairs to children of /reserved-memory - qcom,hyp_disabled: Boolean context flag to disable hyperviser - qcom,clk-monitor-enable: Boolean context flag to enable monitoring external clock WLAN SMP2P sub nodes Loading
drivers/soc/qcom/icnss.c +96 −2 Original line number Diff line number Diff line Loading @@ -70,6 +70,9 @@ #define ICNSS_QUIRKS_DEFAULT BIT(FW_REJUVENATE_ENABLE) #define ICNSS_MAX_PROBE_CNT 2 #define SUBSYS_INTERNAL_MODEM_NAME "modem" #define SUBSYS_EXTERNAL_MODEM_NAME "esoc0" #define PROBE_TIMEOUT 5000 static struct icnss_priv *penv; Loading Loading @@ -964,6 +967,13 @@ static int icnss_driver_event_server_arrive(void *data) set_bit(ICNSS_WLFW_CONNECTED, &penv->state); if (penv->clk_monitor_enable && !test_bit(ICNSS_CLK_UP, &penv->state)) { reinit_completion(&penv->clk_complete); icnss_pr_dbg("Waiting for CLK up notification\n"); wait_for_completion(&penv->clk_complete); } ret = icnss_hw_power_on(penv); if (ret) goto clear_server; Loading Loading @@ -1560,6 +1570,68 @@ static int icnss_modem_notifier_nb(struct notifier_block *nb, return NOTIFY_OK; } static int icnss_ext_modem_notifier_nb(struct notifier_block *nb, unsigned long code, void *data) { struct icnss_priv *priv = container_of(nb, struct icnss_priv, ext_modem_ssr_nb); icnss_pr_vdbg("EXT-Modem-Notify: event %lu\n", code); if (code == SUBSYS_AFTER_POWERUP) { set_bit(ICNSS_CLK_UP, &priv->state); complete(&priv->clk_complete); } return NOTIFY_OK; } static int icnss_ext_modem_ssr_register_notifier(struct icnss_priv *priv) { int ret = 0; priv->ext_modem_ssr_nb.notifier_call = icnss_ext_modem_notifier_nb; priv->ext_modem_notify_handler = subsys_notif_register_notifier(SUBSYS_EXTERNAL_MODEM_NAME, &priv->ext_modem_ssr_nb); if (IS_ERR_OR_NULL(priv->ext_modem_notify_handler)) { ret = PTR_ERR(priv->ext_modem_notify_handler); icnss_pr_err("External Modem register notifier failed %d\n", ret); priv->ext_modem_notify_handler = NULL; /* In NULL case */ if (ret == 0) ret = -EINVAL; return ret; } init_completion(&priv->clk_complete); return ret; } static int icnss_ext_modem_ssr_unregister_notifier(struct icnss_priv *priv) { int ret = 0; if (!priv->ext_modem_notify_handler) return 0; complete_all(&priv->clk_complete); ret = subsys_notif_unregister_notifier(priv->ext_modem_notify_handler, &priv->ext_modem_ssr_nb); if (ret) icnss_pr_err("Fail to unregister external Modem notifier %d\n", ret); priv->ext_modem_notify_handler = NULL; return 0; } static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv) { int ret = 0; Loading @@ -1567,7 +1639,8 @@ static int icnss_modem_ssr_register_notifier(struct icnss_priv *priv) priv->modem_ssr_nb.notifier_call = icnss_modem_notifier_nb; priv->modem_notify_handler = subsys_notif_register_notifier("modem", &priv->modem_ssr_nb); subsys_notif_register_notifier(SUBSYS_INTERNAL_MODEM_NAME, &priv->modem_ssr_nb); if (IS_ERR(priv->modem_notify_handler)) { ret = PTR_ERR(priv->modem_notify_handler); Loading Loading @@ -2826,6 +2899,10 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) continue; case ICNSS_PDR: seq_puts(s, "PDR TRIGGERED"); continue; case ICNSS_CLK_UP: seq_puts(s, "CLK UP"); continue; } seq_printf(s, "UNKNOWN-%d", i); Loading Loading @@ -3492,6 +3569,19 @@ static int icnss_probe(struct platform_device *pdev) } } if (of_property_read_bool(pdev->dev.of_node, "qcom,clk-monitor-enable")) { priv->clk_monitor_enable = true; icnss_pr_dbg("CLK monitor is enabled\n"); } if (priv->clk_monitor_enable) { ret = icnss_ext_modem_ssr_register_notifier(priv); if (ret) goto out_smmu_deinit; } spin_lock_init(&priv->event_lock); spin_lock_init(&priv->on_off_lock); mutex_init(&priv->dev_lock); Loading @@ -3500,7 +3590,7 @@ static int icnss_probe(struct platform_device *pdev) if (!priv->event_wq) { icnss_pr_err("Workqueue creation failed\n"); ret = -EFAULT; goto out_smmu_deinit; goto out_unregister_ext_modem; } INIT_WORK(&priv->event_work, icnss_driver_event_work); Loading Loading @@ -3533,6 +3623,8 @@ static int icnss_probe(struct platform_device *pdev) out_destroy_wq: destroy_workqueue(priv->event_wq); out_unregister_ext_modem: icnss_ext_modem_ssr_unregister_notifier(priv); out_smmu_deinit: icnss_smmu_deinit(priv); out: Loading Loading @@ -3563,6 +3655,8 @@ static int icnss_remove(struct platform_device *pdev) if (penv->event_wq) destroy_workqueue(penv->event_wq); icnss_ext_modem_ssr_unregister_notifier(penv); icnss_hw_power_off(penv); icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_HLOS_ALL); Loading
drivers/soc/qcom/icnss_private.h +5 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,7 @@ enum icnss_driver_state { ICNSS_MODE_ON, ICNSS_BLOCK_SHUTDOWN, ICNSS_PDR, ICNSS_CLK_UP, }; struct ce_irq_list { Loading Loading @@ -373,6 +374,10 @@ struct icnss_priv { struct kobject *icnss_kobject; atomic_t is_shutdown; bool is_ssr; bool clk_monitor_enable; void *ext_modem_notify_handler; struct notifier_block ext_modem_ssr_nb; struct completion clk_complete; }; int icnss_call_driver_uevent(struct icnss_priv *priv, Loading