Loading soc/swr-mstr-ctrl.c +197 −18 Original line number Diff line number Diff line Loading @@ -33,7 +33,8 @@ #include "swr-mstr-ctrl.h" #include "swrm_port_config.h" #define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700 #define SWRM_SYS_SUSPEND_WAIT 1 #define SWR_BROADCAST_CMD_ID 0x0F #define SWR_AUTO_SUSPEND_DELAY 3 /* delay in sec */ #define SWR_DEV_ID_MASK 0xFFFFFFFF Loading Loading @@ -89,6 +90,8 @@ static struct dentry *debugfs_poke; static struct dentry *debugfs_reg_dump; static unsigned int read_data; static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm); static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm); static bool swrm_is_msm_variant(int val) { Loading Loading @@ -1269,6 +1272,10 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev) struct swr_device *swr_dev; struct swr_master *mstr = &swrm->master; if (unlikely(swrm_lock_sleep(swrm) == false)) { dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); return IRQ_NONE; } mutex_lock(&swrm->reslock); swrm_clk_request(swrm, true); Loading Loading @@ -1419,6 +1426,7 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev) mutex_lock(&swrm->reslock); swrm_clk_request(swrm, false); mutex_unlock(&swrm->reslock); swrm_unlock_sleep(swrm); return ret; } Loading Loading @@ -1462,12 +1470,19 @@ static void swrm_wakeup_work(struct work_struct *work) mutex_lock(&swrm->devlock); if (!swrm->dev_up) { mutex_unlock(&swrm->devlock); return; goto exit; } mutex_unlock(&swrm->devlock); if (unlikely(swrm_lock_sleep(swrm) == false)) { dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); goto exit; } pm_runtime_get_sync(swrm->dev); pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); swrm_unlock_sleep(swrm); exit: pm_relax(swrm->dev); } static int swrm_get_device_status(struct swr_mstr_ctrl *swrm, u8 devnum) Loading Loading @@ -1553,6 +1568,10 @@ static void swrm_device_wakeup_vote(struct swr_master *mstr) __func__); return; } if (unlikely(swrm_lock_sleep(swrm) == false)) { dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); return; } pm_runtime_get_sync(swrm->dev); } Loading @@ -1567,6 +1586,7 @@ static void swrm_device_wakeup_unvote(struct swr_master *mstr) } pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); swrm_unlock_sleep(swrm); } static int swrm_master_init(struct swr_mstr_ctrl *swrm) Loading Loading @@ -1647,6 +1667,7 @@ static int swrm_event_notify(struct notifier_block *self, case SWR_WAKE_IRQ_EVENT: if (swrm->ipc_wakeup && !swrm->ipc_wakeup_triggered) { swrm->ipc_wakeup_triggered = true; pm_stay_awake(swrm->dev); schedule_work(&swrm->wakeup_work); } break; Loading Loading @@ -1753,6 +1774,21 @@ static int swrm_probe(struct platform_device *pdev) &swrm->clk_stop_mode0_supp)) { swrm->clk_stop_mode0_supp = FALSE; } ret = of_property_read_u32(swrm->dev->of_node, "qcom,swr-num-dev", &swrm->num_dev); if (ret) { dev_dbg(&pdev->dev, "%s: Looking up %s property failed\n", __func__, "qcom,swr-num-dev"); } else { if (swrm->num_dev > SWR_MAX_SLAVE_DEVICES) { dev_err(&pdev->dev, "%s: num_dev %d > max limit %d\n", __func__, swrm->num_dev, SWR_MAX_SLAVE_DEVICES); ret = -EINVAL; goto err_pdata_fail; } } /* Parse soundwire port mapping */ ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr-num-ports", &num_ports); Loading Loading @@ -1835,24 +1871,17 @@ static int swrm_probe(struct platform_device *pdev) mutex_init(&swrm->iolock); mutex_init(&swrm->clklock); mutex_init(&swrm->devlock); mutex_init(&swrm->pm_lock); swrm->wlock_holders = 0; swrm->pm_state = SWRM_PM_SLEEPABLE; init_waitqueue_head(&swrm->pm_wq); pm_qos_add_request(&swrm->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++) INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list); ret = of_property_read_u32(swrm->dev->of_node, "qcom,swr-num-dev", &swrm->num_dev); if (ret) { dev_dbg(&pdev->dev, "%s: Looking up %s property failed\n", __func__, "qcom,swr-num-dev"); } else { if (swrm->num_dev > SWR_MAX_SLAVE_DEVICES) { dev_err(&pdev->dev, "%s: num_dev %d > max limit %d\n", __func__, swrm->num_dev, SWR_MAX_SLAVE_DEVICES); ret = -EINVAL; goto err_pdata_fail; } } if (swrm->reg_irq) { ret = swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_REGISTER); Loading Loading @@ -1948,6 +1977,9 @@ static int swrm_probe(struct platform_device *pdev) mutex_destroy(&swrm->force_down_lock); mutex_destroy(&swrm->iolock); mutex_destroy(&swrm->clklock); mutex_destroy(&swrm->pm_lock); pm_qos_remove_request(&swrm->pm_qos_req); err_pdata_fail: err_memory_fail: return ret; Loading @@ -1964,7 +1996,7 @@ static int swrm_remove(struct platform_device *pdev) free_irq(swrm->irq, swrm); else if (swrm->wake_irq > 0) free_irq(swrm->wake_irq, swrm); cancel_work_sync(&swrm->wakeup_work); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); swr_unregister_master(&swrm->master); Loading @@ -1974,6 +2006,8 @@ static int swrm_remove(struct platform_device *pdev) mutex_destroy(&swrm->iolock); mutex_destroy(&swrm->clklock); mutex_destroy(&swrm->force_down_lock); mutex_destroy(&swrm->pm_lock); pm_qos_remove_request(&swrm->pm_qos_req); devm_kfree(&pdev->dev, swrm); return 0; } Loading Loading @@ -2309,6 +2343,94 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) } EXPORT_SYMBOL(swrm_wcd_notify); /* * swrm_pm_cmpxchg: * Check old state and exchange with pm new state * if old state matches with current state * * @swrm: pointer to wcd core resource * @o: pm old state * @n: pm new state * * Returns old state */ static enum swrm_pm_state swrm_pm_cmpxchg( struct swr_mstr_ctrl *swrm, enum swrm_pm_state o, enum swrm_pm_state n) { enum swrm_pm_state old; if (!swrm) return o; mutex_lock(&swrm->pm_lock); old = swrm->pm_state; if (old == o) swrm->pm_state = n; mutex_unlock(&swrm->pm_lock); return old; } static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm) { enum swrm_pm_state os; /* * swrm_{lock/unlock}_sleep will be called by swr irq handler * and slave wake up requests.. * * If system didn't resume, we can simply return false so * IRQ handler can return without handling IRQ. */ mutex_lock(&swrm->pm_lock); if (swrm->wlock_holders++ == 0) { dev_dbg(swrm->dev, "%s: holding wake lock\n", __func__); pm_qos_update_request(&swrm->pm_qos_req, msm_cpuidle_get_deep_idle_latency()); pm_stay_awake(swrm->dev); } mutex_unlock(&swrm->pm_lock); if (!wait_event_timeout(swrm->pm_wq, ((os = swrm_pm_cmpxchg(swrm, SWRM_PM_SLEEPABLE, SWRM_PM_AWAKE)) == SWRM_PM_SLEEPABLE || (os == SWRM_PM_AWAKE)), msecs_to_jiffies( SWRM_SYSTEM_RESUME_TIMEOUT_MS))) { dev_err(swrm->dev, "%s: system didn't resume within %dms, s %d, w %d\n", __func__, SWRM_SYSTEM_RESUME_TIMEOUT_MS, swrm->pm_state, swrm->wlock_holders); swrm_unlock_sleep(swrm); return false; } wake_up_all(&swrm->pm_wq); return true; } static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm) { mutex_lock(&swrm->pm_lock); if (--swrm->wlock_holders == 0) { dev_dbg(swrm->dev, "%s: releasing wake lock pm_state %d -> %d\n", __func__, swrm->pm_state, SWRM_PM_SLEEPABLE); /* * if swrm_lock_sleep failed, pm_state would be still * swrm_PM_ASLEEP, don't overwrite */ if (likely(swrm->pm_state == SWRM_PM_AWAKE)) swrm->pm_state = SWRM_PM_SLEEPABLE; pm_qos_update_request(&swrm->pm_qos_req, PM_QOS_DEFAULT_VALUE); pm_relax(swrm->dev); } mutex_unlock(&swrm->pm_lock); wake_up_all(&swrm->pm_wq); } #ifdef CONFIG_PM_SLEEP static int swrm_suspend(struct device *dev) { Loading @@ -2317,7 +2439,49 @@ static int swrm_suspend(struct device *dev) struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); dev_dbg(dev, "%s: system suspend, state: %d\n", __func__, swrm->state); if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) { mutex_lock(&swrm->pm_lock); if (swrm->pm_state == SWRM_PM_SLEEPABLE) { dev_dbg(swrm->dev, "%s: suspending system, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); swrm->pm_state = SWRM_PM_ASLEEP; } else if (swrm->pm_state == SWRM_PM_AWAKE) { /* * unlock to wait for pm_state == SWRM_PM_SLEEPABLE * then set to SWRM_PM_ASLEEP */ dev_dbg(swrm->dev, "%s: waiting to suspend system, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); mutex_unlock(&swrm->pm_lock); if (!(wait_event_timeout(swrm->pm_wq, swrm_pm_cmpxchg( swrm, SWRM_PM_SLEEPABLE, SWRM_PM_ASLEEP) == SWRM_PM_SLEEPABLE, msecs_to_jiffies( SWRM_SYS_SUSPEND_WAIT)))) { dev_dbg(swrm->dev, "%s: suspend failed state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); return -EBUSY; } else { dev_dbg(swrm->dev, "%s: done, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); } mutex_lock(&swrm->pm_lock); } else if (swrm->pm_state == SWRM_PM_ASLEEP) { dev_dbg(swrm->dev, "%s: system is already suspended, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); } mutex_unlock(&swrm->pm_lock); if ((!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev))) { ret = swrm_runtime_suspend(dev); if (!ret) { /* Loading Loading @@ -2363,6 +2527,21 @@ static int swrm_resume(struct device *dev) pm_request_autosuspend(dev); } } mutex_lock(&swrm->pm_lock); if (swrm->pm_state == SWRM_PM_ASLEEP) { dev_dbg(swrm->dev, "%s: resuming system, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); swrm->pm_state = SWRM_PM_SLEEPABLE; } else { dev_dbg(swrm->dev, "%s: system is already awake, state %d wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); } mutex_unlock(&swrm->pm_lock); wake_up_all(&swrm->pm_wq); return ret; } #endif /* CONFIG_PM_SLEEP */ Loading soc/swr-mstr-ctrl.h +13 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #define _SWR_WCD_CTRL_H #include <linux/module.h> #include <soc/swr-wcd.h> #include <linux/pm_qos.h> #include <soc/qcom/pm.h> #define SWR_ROW_48 0 #define SWR_ROW_50 1 Loading Loading @@ -42,6 +44,12 @@ enum { SWR_MSTR_SSR, }; enum swrm_pm_state { SWRM_PM_SLEEPABLE, SWRM_PM_AWAKE, SWRM_PM_ASLEEP, }; enum { SWR_IRQ_FREE, SWR_IRQ_REGISTER, Loading Loading @@ -118,6 +126,7 @@ struct swr_mstr_ctrl { struct mutex devlock; struct mutex mlock; struct mutex reslock; struct mutex pm_lock; u32 swrm_base_reg; char __iomem *swrm_dig_base; u8 rcmd_id; Loading Loading @@ -156,6 +165,10 @@ struct swr_mstr_ctrl { u32 ipc_wakeup; bool dev_up; bool ipc_wakeup_triggered; struct pm_qos_request pm_qos_req; enum swrm_pm_state pm_state; wait_queue_head_t pm_wq; int wlock_holders; }; #endif /* _SWR_WCD_CTRL_H */ Loading
soc/swr-mstr-ctrl.c +197 −18 Original line number Diff line number Diff line Loading @@ -33,7 +33,8 @@ #include "swr-mstr-ctrl.h" #include "swrm_port_config.h" #define SWRM_SYSTEM_RESUME_TIMEOUT_MS 700 #define SWRM_SYS_SUSPEND_WAIT 1 #define SWR_BROADCAST_CMD_ID 0x0F #define SWR_AUTO_SUSPEND_DELAY 3 /* delay in sec */ #define SWR_DEV_ID_MASK 0xFFFFFFFF Loading Loading @@ -89,6 +90,8 @@ static struct dentry *debugfs_poke; static struct dentry *debugfs_reg_dump; static unsigned int read_data; static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm); static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm); static bool swrm_is_msm_variant(int val) { Loading Loading @@ -1269,6 +1272,10 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev) struct swr_device *swr_dev; struct swr_master *mstr = &swrm->master; if (unlikely(swrm_lock_sleep(swrm) == false)) { dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); return IRQ_NONE; } mutex_lock(&swrm->reslock); swrm_clk_request(swrm, true); Loading Loading @@ -1419,6 +1426,7 @@ static irqreturn_t swr_mstr_interrupt(int irq, void *dev) mutex_lock(&swrm->reslock); swrm_clk_request(swrm, false); mutex_unlock(&swrm->reslock); swrm_unlock_sleep(swrm); return ret; } Loading Loading @@ -1462,12 +1470,19 @@ static void swrm_wakeup_work(struct work_struct *work) mutex_lock(&swrm->devlock); if (!swrm->dev_up) { mutex_unlock(&swrm->devlock); return; goto exit; } mutex_unlock(&swrm->devlock); if (unlikely(swrm_lock_sleep(swrm) == false)) { dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); goto exit; } pm_runtime_get_sync(swrm->dev); pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); swrm_unlock_sleep(swrm); exit: pm_relax(swrm->dev); } static int swrm_get_device_status(struct swr_mstr_ctrl *swrm, u8 devnum) Loading Loading @@ -1553,6 +1568,10 @@ static void swrm_device_wakeup_vote(struct swr_master *mstr) __func__); return; } if (unlikely(swrm_lock_sleep(swrm) == false)) { dev_err(swrm->dev, "%s Failed to hold suspend\n", __func__); return; } pm_runtime_get_sync(swrm->dev); } Loading @@ -1567,6 +1586,7 @@ static void swrm_device_wakeup_unvote(struct swr_master *mstr) } pm_runtime_mark_last_busy(swrm->dev); pm_runtime_put_autosuspend(swrm->dev); swrm_unlock_sleep(swrm); } static int swrm_master_init(struct swr_mstr_ctrl *swrm) Loading Loading @@ -1647,6 +1667,7 @@ static int swrm_event_notify(struct notifier_block *self, case SWR_WAKE_IRQ_EVENT: if (swrm->ipc_wakeup && !swrm->ipc_wakeup_triggered) { swrm->ipc_wakeup_triggered = true; pm_stay_awake(swrm->dev); schedule_work(&swrm->wakeup_work); } break; Loading Loading @@ -1753,6 +1774,21 @@ static int swrm_probe(struct platform_device *pdev) &swrm->clk_stop_mode0_supp)) { swrm->clk_stop_mode0_supp = FALSE; } ret = of_property_read_u32(swrm->dev->of_node, "qcom,swr-num-dev", &swrm->num_dev); if (ret) { dev_dbg(&pdev->dev, "%s: Looking up %s property failed\n", __func__, "qcom,swr-num-dev"); } else { if (swrm->num_dev > SWR_MAX_SLAVE_DEVICES) { dev_err(&pdev->dev, "%s: num_dev %d > max limit %d\n", __func__, swrm->num_dev, SWR_MAX_SLAVE_DEVICES); ret = -EINVAL; goto err_pdata_fail; } } /* Parse soundwire port mapping */ ret = of_property_read_u32(pdev->dev.of_node, "qcom,swr-num-ports", &num_ports); Loading Loading @@ -1835,24 +1871,17 @@ static int swrm_probe(struct platform_device *pdev) mutex_init(&swrm->iolock); mutex_init(&swrm->clklock); mutex_init(&swrm->devlock); mutex_init(&swrm->pm_lock); swrm->wlock_holders = 0; swrm->pm_state = SWRM_PM_SLEEPABLE; init_waitqueue_head(&swrm->pm_wq); pm_qos_add_request(&swrm->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++) INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list); ret = of_property_read_u32(swrm->dev->of_node, "qcom,swr-num-dev", &swrm->num_dev); if (ret) { dev_dbg(&pdev->dev, "%s: Looking up %s property failed\n", __func__, "qcom,swr-num-dev"); } else { if (swrm->num_dev > SWR_MAX_SLAVE_DEVICES) { dev_err(&pdev->dev, "%s: num_dev %d > max limit %d\n", __func__, swrm->num_dev, SWR_MAX_SLAVE_DEVICES); ret = -EINVAL; goto err_pdata_fail; } } if (swrm->reg_irq) { ret = swrm->reg_irq(swrm->handle, swr_mstr_interrupt, swrm, SWR_IRQ_REGISTER); Loading Loading @@ -1948,6 +1977,9 @@ static int swrm_probe(struct platform_device *pdev) mutex_destroy(&swrm->force_down_lock); mutex_destroy(&swrm->iolock); mutex_destroy(&swrm->clklock); mutex_destroy(&swrm->pm_lock); pm_qos_remove_request(&swrm->pm_qos_req); err_pdata_fail: err_memory_fail: return ret; Loading @@ -1964,7 +1996,7 @@ static int swrm_remove(struct platform_device *pdev) free_irq(swrm->irq, swrm); else if (swrm->wake_irq > 0) free_irq(swrm->wake_irq, swrm); cancel_work_sync(&swrm->wakeup_work); pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); swr_unregister_master(&swrm->master); Loading @@ -1974,6 +2006,8 @@ static int swrm_remove(struct platform_device *pdev) mutex_destroy(&swrm->iolock); mutex_destroy(&swrm->clklock); mutex_destroy(&swrm->force_down_lock); mutex_destroy(&swrm->pm_lock); pm_qos_remove_request(&swrm->pm_qos_req); devm_kfree(&pdev->dev, swrm); return 0; } Loading Loading @@ -2309,6 +2343,94 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data) } EXPORT_SYMBOL(swrm_wcd_notify); /* * swrm_pm_cmpxchg: * Check old state and exchange with pm new state * if old state matches with current state * * @swrm: pointer to wcd core resource * @o: pm old state * @n: pm new state * * Returns old state */ static enum swrm_pm_state swrm_pm_cmpxchg( struct swr_mstr_ctrl *swrm, enum swrm_pm_state o, enum swrm_pm_state n) { enum swrm_pm_state old; if (!swrm) return o; mutex_lock(&swrm->pm_lock); old = swrm->pm_state; if (old == o) swrm->pm_state = n; mutex_unlock(&swrm->pm_lock); return old; } static bool swrm_lock_sleep(struct swr_mstr_ctrl *swrm) { enum swrm_pm_state os; /* * swrm_{lock/unlock}_sleep will be called by swr irq handler * and slave wake up requests.. * * If system didn't resume, we can simply return false so * IRQ handler can return without handling IRQ. */ mutex_lock(&swrm->pm_lock); if (swrm->wlock_holders++ == 0) { dev_dbg(swrm->dev, "%s: holding wake lock\n", __func__); pm_qos_update_request(&swrm->pm_qos_req, msm_cpuidle_get_deep_idle_latency()); pm_stay_awake(swrm->dev); } mutex_unlock(&swrm->pm_lock); if (!wait_event_timeout(swrm->pm_wq, ((os = swrm_pm_cmpxchg(swrm, SWRM_PM_SLEEPABLE, SWRM_PM_AWAKE)) == SWRM_PM_SLEEPABLE || (os == SWRM_PM_AWAKE)), msecs_to_jiffies( SWRM_SYSTEM_RESUME_TIMEOUT_MS))) { dev_err(swrm->dev, "%s: system didn't resume within %dms, s %d, w %d\n", __func__, SWRM_SYSTEM_RESUME_TIMEOUT_MS, swrm->pm_state, swrm->wlock_holders); swrm_unlock_sleep(swrm); return false; } wake_up_all(&swrm->pm_wq); return true; } static void swrm_unlock_sleep(struct swr_mstr_ctrl *swrm) { mutex_lock(&swrm->pm_lock); if (--swrm->wlock_holders == 0) { dev_dbg(swrm->dev, "%s: releasing wake lock pm_state %d -> %d\n", __func__, swrm->pm_state, SWRM_PM_SLEEPABLE); /* * if swrm_lock_sleep failed, pm_state would be still * swrm_PM_ASLEEP, don't overwrite */ if (likely(swrm->pm_state == SWRM_PM_AWAKE)) swrm->pm_state = SWRM_PM_SLEEPABLE; pm_qos_update_request(&swrm->pm_qos_req, PM_QOS_DEFAULT_VALUE); pm_relax(swrm->dev); } mutex_unlock(&swrm->pm_lock); wake_up_all(&swrm->pm_wq); } #ifdef CONFIG_PM_SLEEP static int swrm_suspend(struct device *dev) { Loading @@ -2317,7 +2439,49 @@ static int swrm_suspend(struct device *dev) struct swr_mstr_ctrl *swrm = platform_get_drvdata(pdev); dev_dbg(dev, "%s: system suspend, state: %d\n", __func__, swrm->state); if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) { mutex_lock(&swrm->pm_lock); if (swrm->pm_state == SWRM_PM_SLEEPABLE) { dev_dbg(swrm->dev, "%s: suspending system, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); swrm->pm_state = SWRM_PM_ASLEEP; } else if (swrm->pm_state == SWRM_PM_AWAKE) { /* * unlock to wait for pm_state == SWRM_PM_SLEEPABLE * then set to SWRM_PM_ASLEEP */ dev_dbg(swrm->dev, "%s: waiting to suspend system, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); mutex_unlock(&swrm->pm_lock); if (!(wait_event_timeout(swrm->pm_wq, swrm_pm_cmpxchg( swrm, SWRM_PM_SLEEPABLE, SWRM_PM_ASLEEP) == SWRM_PM_SLEEPABLE, msecs_to_jiffies( SWRM_SYS_SUSPEND_WAIT)))) { dev_dbg(swrm->dev, "%s: suspend failed state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); return -EBUSY; } else { dev_dbg(swrm->dev, "%s: done, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); } mutex_lock(&swrm->pm_lock); } else if (swrm->pm_state == SWRM_PM_ASLEEP) { dev_dbg(swrm->dev, "%s: system is already suspended, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); } mutex_unlock(&swrm->pm_lock); if ((!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev))) { ret = swrm_runtime_suspend(dev); if (!ret) { /* Loading Loading @@ -2363,6 +2527,21 @@ static int swrm_resume(struct device *dev) pm_request_autosuspend(dev); } } mutex_lock(&swrm->pm_lock); if (swrm->pm_state == SWRM_PM_ASLEEP) { dev_dbg(swrm->dev, "%s: resuming system, state %d, wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); swrm->pm_state = SWRM_PM_SLEEPABLE; } else { dev_dbg(swrm->dev, "%s: system is already awake, state %d wlock %d\n", __func__, swrm->pm_state, swrm->wlock_holders); } mutex_unlock(&swrm->pm_lock); wake_up_all(&swrm->pm_wq); return ret; } #endif /* CONFIG_PM_SLEEP */ Loading
soc/swr-mstr-ctrl.h +13 −0 Original line number Diff line number Diff line Loading @@ -14,6 +14,8 @@ #define _SWR_WCD_CTRL_H #include <linux/module.h> #include <soc/swr-wcd.h> #include <linux/pm_qos.h> #include <soc/qcom/pm.h> #define SWR_ROW_48 0 #define SWR_ROW_50 1 Loading Loading @@ -42,6 +44,12 @@ enum { SWR_MSTR_SSR, }; enum swrm_pm_state { SWRM_PM_SLEEPABLE, SWRM_PM_AWAKE, SWRM_PM_ASLEEP, }; enum { SWR_IRQ_FREE, SWR_IRQ_REGISTER, Loading Loading @@ -118,6 +126,7 @@ struct swr_mstr_ctrl { struct mutex devlock; struct mutex mlock; struct mutex reslock; struct mutex pm_lock; u32 swrm_base_reg; char __iomem *swrm_dig_base; u8 rcmd_id; Loading Loading @@ -156,6 +165,10 @@ struct swr_mstr_ctrl { u32 ipc_wakeup; bool dev_up; bool ipc_wakeup_triggered; struct pm_qos_request pm_qos_req; enum swrm_pm_state pm_state; wait_queue_head_t pm_wq; int wlock_holders; }; #endif /* _SWR_WCD_CTRL_H */