Loading drivers/soc/qcom/icnss.c +156 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ #define MAX_PROP_SIZE 32 #define NUM_LOG_PAGES 10 #define NUM_REG_LOG_PAGES 4 #define ICNSS_MAGIC 0x5abc5abc /* * Registers: MPM2_PSHOLD Loading Loading @@ -269,6 +270,8 @@ enum icnss_driver_state { ICNSS_DRIVER_PROBED, ICNSS_FW_TEST_MODE, ICNSS_SUSPEND, ICNSS_PM_SUSPEND, ICNSS_PM_SUSPEND_NOIRQ, ICNSS_SSR_ENABLED, ICNSS_PDR_ENABLED, ICNSS_PD_RESTART, Loading Loading @@ -324,6 +327,15 @@ struct icnss_stats { uint32_t disable; } ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS]; uint32_t pm_suspend; uint32_t pm_suspend_err; uint32_t pm_resume; uint32_t pm_resume_err; uint32_t pm_suspend_noirq; uint32_t pm_suspend_noirq_err; uint32_t pm_resume_noirq; uint32_t pm_resume_noirq_err; uint32_t ind_register_req; uint32_t ind_register_resp; uint32_t ind_register_err; Loading @@ -350,6 +362,7 @@ struct icnss_stats { }; static struct icnss_priv { uint32_t magic; struct platform_device *pdev; struct icnss_driver_ops *ops; struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS]; Loading Loading @@ -3302,6 +3315,12 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) case ICNSS_FW_TEST_MODE: seq_puts(s, "FW TEST MODE"); continue; case ICNSS_PM_SUSPEND: seq_puts(s, "PM SUSPEND"); continue; case ICNSS_PM_SUSPEND_NOIRQ: seq_puts(s, "PM SUSPEND_NOIRQ"); continue; case ICNSS_SSR_ENABLED: seq_puts(s, "SSR ENABLED"); continue; Loading Loading @@ -3402,6 +3421,16 @@ static int icnss_stats_show(struct seq_file *s, void *data) ICNSS_STATS_DUMP(s, priv, ini_resp); ICNSS_STATS_DUMP(s, priv, ini_req_err); seq_puts(s, "\n<------------------ PM stats ------------------->\n"); ICNSS_STATS_DUMP(s, priv, pm_suspend); ICNSS_STATS_DUMP(s, priv, pm_suspend_err); ICNSS_STATS_DUMP(s, priv, pm_resume); ICNSS_STATS_DUMP(s, priv, pm_resume_err); ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq); ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq_err); ICNSS_STATS_DUMP(s, priv, pm_resume_noirq); ICNSS_STATS_DUMP(s, priv, pm_resume_noirq_err); icnss_stats_show_irqs(s, priv); icnss_stats_show_capability(s, priv); Loading Loading @@ -3477,6 +3506,7 @@ static int icnss_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; priv->magic = ICNSS_MAGIC; dev_set_drvdata(dev, priv); priv->pdev = pdev; Loading Loading @@ -3725,6 +3755,131 @@ out: return ret; } #ifdef CONFIG_PM_SLEEP static int icnss_pm_suspend(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm suspend: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM Suspend, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->pm_suspend || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->pm_suspend(dev); out: if (ret == 0) { priv->stats.pm_suspend++; set_bit(ICNSS_PM_SUSPEND, &priv->state); } else { priv->stats.pm_suspend_err++; } return ret; } static int icnss_pm_resume(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm resume: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM resume, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->pm_resume || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->pm_resume(dev); out: if (ret == 0) { priv->stats.pm_resume++; clear_bit(ICNSS_PM_SUSPEND, &priv->state); } else { priv->stats.pm_resume_err++; } return ret; } static int icnss_pm_suspend_noirq(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm suspend_noirq: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM suspend_noirq, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->suspend_noirq || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->suspend_noirq(dev); out: if (ret == 0) { priv->stats.pm_suspend_noirq++; set_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state); } else { priv->stats.pm_suspend_noirq_err++; } return ret; } static int icnss_pm_resume_noirq(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm resume_noirq: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM resume_noirq, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->resume_noirq || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->resume_noirq(dev); out: if (ret == 0) { priv->stats.pm_resume_noirq++; clear_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state); } else { priv->stats.pm_resume_noirq_err++; } return ret; } #endif static const struct dev_pm_ops icnss_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend, icnss_pm_resume) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend_noirq, icnss_pm_resume_noirq) }; static const struct of_device_id icnss_dt_match[] = { {.compatible = "qcom,icnss"}, {} Loading @@ -3739,6 +3894,7 @@ static struct platform_driver icnss_driver = { .resume = icnss_resume, .driver = { .name = "icnss", .pm = &icnss_pm_ops, .owner = THIS_MODULE, .of_match_table = icnss_dt_match, }, Loading include/soc/qcom/icnss.h +4 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ struct icnss_driver_ops { void (*crash_shutdown)(void *pdev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); int (*pm_suspend)(struct device *dev); int (*pm_resume)(struct device *dev); int (*suspend_noirq)(struct device *dev); int (*resume_noirq)(struct device *dev); }; Loading Loading
drivers/soc/qcom/icnss.c +156 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ #define MAX_PROP_SIZE 32 #define NUM_LOG_PAGES 10 #define NUM_REG_LOG_PAGES 4 #define ICNSS_MAGIC 0x5abc5abc /* * Registers: MPM2_PSHOLD Loading Loading @@ -269,6 +270,8 @@ enum icnss_driver_state { ICNSS_DRIVER_PROBED, ICNSS_FW_TEST_MODE, ICNSS_SUSPEND, ICNSS_PM_SUSPEND, ICNSS_PM_SUSPEND_NOIRQ, ICNSS_SSR_ENABLED, ICNSS_PDR_ENABLED, ICNSS_PD_RESTART, Loading Loading @@ -324,6 +327,15 @@ struct icnss_stats { uint32_t disable; } ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS]; uint32_t pm_suspend; uint32_t pm_suspend_err; uint32_t pm_resume; uint32_t pm_resume_err; uint32_t pm_suspend_noirq; uint32_t pm_suspend_noirq_err; uint32_t pm_resume_noirq; uint32_t pm_resume_noirq_err; uint32_t ind_register_req; uint32_t ind_register_resp; uint32_t ind_register_err; Loading @@ -350,6 +362,7 @@ struct icnss_stats { }; static struct icnss_priv { uint32_t magic; struct platform_device *pdev; struct icnss_driver_ops *ops; struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS]; Loading Loading @@ -3302,6 +3315,12 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv) case ICNSS_FW_TEST_MODE: seq_puts(s, "FW TEST MODE"); continue; case ICNSS_PM_SUSPEND: seq_puts(s, "PM SUSPEND"); continue; case ICNSS_PM_SUSPEND_NOIRQ: seq_puts(s, "PM SUSPEND_NOIRQ"); continue; case ICNSS_SSR_ENABLED: seq_puts(s, "SSR ENABLED"); continue; Loading Loading @@ -3402,6 +3421,16 @@ static int icnss_stats_show(struct seq_file *s, void *data) ICNSS_STATS_DUMP(s, priv, ini_resp); ICNSS_STATS_DUMP(s, priv, ini_req_err); seq_puts(s, "\n<------------------ PM stats ------------------->\n"); ICNSS_STATS_DUMP(s, priv, pm_suspend); ICNSS_STATS_DUMP(s, priv, pm_suspend_err); ICNSS_STATS_DUMP(s, priv, pm_resume); ICNSS_STATS_DUMP(s, priv, pm_resume_err); ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq); ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq_err); ICNSS_STATS_DUMP(s, priv, pm_resume_noirq); ICNSS_STATS_DUMP(s, priv, pm_resume_noirq_err); icnss_stats_show_irqs(s, priv); icnss_stats_show_capability(s, priv); Loading Loading @@ -3477,6 +3506,7 @@ static int icnss_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; priv->magic = ICNSS_MAGIC; dev_set_drvdata(dev, priv); priv->pdev = pdev; Loading Loading @@ -3725,6 +3755,131 @@ out: return ret; } #ifdef CONFIG_PM_SLEEP static int icnss_pm_suspend(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm suspend: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM Suspend, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->pm_suspend || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->pm_suspend(dev); out: if (ret == 0) { priv->stats.pm_suspend++; set_bit(ICNSS_PM_SUSPEND, &priv->state); } else { priv->stats.pm_suspend_err++; } return ret; } static int icnss_pm_resume(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm resume: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM resume, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->pm_resume || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->pm_resume(dev); out: if (ret == 0) { priv->stats.pm_resume++; clear_bit(ICNSS_PM_SUSPEND, &priv->state); } else { priv->stats.pm_resume_err++; } return ret; } static int icnss_pm_suspend_noirq(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm suspend_noirq: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM suspend_noirq, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->suspend_noirq || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->suspend_noirq(dev); out: if (ret == 0) { priv->stats.pm_suspend_noirq++; set_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state); } else { priv->stats.pm_suspend_noirq_err++; } return ret; } static int icnss_pm_resume_noirq(struct device *dev) { struct icnss_priv *priv = dev_get_drvdata(dev); int ret = 0; if (priv->magic != ICNSS_MAGIC) { icnss_pr_err("Invalid drvdata for pm resume_noirq: dev %p, data %p, magic 0x%x\n", dev, priv, priv->magic); return -EINVAL; } icnss_pr_dbg("PM resume_noirq, state: 0x%lx\n", priv->state); if (!priv->ops || !priv->ops->resume_noirq || !test_bit(ICNSS_DRIVER_PROBED, &priv->state)) goto out; ret = priv->ops->resume_noirq(dev); out: if (ret == 0) { priv->stats.pm_resume_noirq++; clear_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state); } else { priv->stats.pm_resume_noirq_err++; } return ret; } #endif static const struct dev_pm_ops icnss_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend, icnss_pm_resume) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend_noirq, icnss_pm_resume_noirq) }; static const struct of_device_id icnss_dt_match[] = { {.compatible = "qcom,icnss"}, {} Loading @@ -3739,6 +3894,7 @@ static struct platform_driver icnss_driver = { .resume = icnss_resume, .driver = { .name = "icnss", .pm = &icnss_pm_ops, .owner = THIS_MODULE, .of_match_table = icnss_dt_match, }, Loading
include/soc/qcom/icnss.h +4 −0 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ struct icnss_driver_ops { void (*crash_shutdown)(void *pdev); int (*suspend)(struct device *dev, pm_message_t state); int (*resume)(struct device *dev); int (*pm_suspend)(struct device *dev); int (*pm_resume)(struct device *dev); int (*suspend_noirq)(struct device *dev); int (*resume_noirq)(struct device *dev); }; Loading