mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 11:37:06 +02:00
soc: qcom: rpmh-rsc: Attach RSC to CPU cluster PM domain
RSC is part the CPU subsystem and powers off the CPU domains when all the CPUs and no RPMH transactions are pending from any of the drivers. The RSC needs to flush the 'sleep' and 'wake' votes that are critical for saving power when all the CPUs are in idle. Doing this every time a CPU powers down, increases latency to enter idle state. So, we want to do this, only when it makes sense - when the last CPU is powering down. Let's make RSC part of the CPU PM domains, by attaching it to the cluster PD (defined in DT). Registering for PM domain notifications, RSC driver can be notified that the last CPU is powering down. When the last CPU is powering down the domain, let's flush the 'sleep' and 'wake' votes that are stored in the data buffers into the hardware. Change-Id: Id748413f0f86a4ac73c37e0780b2b22a143a1e61 Signed-off-by: Lina Iyer <ilina@codeaurora.org> Signed-off-by: Maulik Shah <quic_mkshah@quicinc.com>
This commit is contained in:
parent
5a1e88f0c5
commit
7466fd9c13
|
|
@ -119,6 +119,8 @@ struct rpmh_ctrlr {
|
|||
* @tcs_wait: Wait queue used to wait for @tcs_in_use to free up a
|
||||
* slot
|
||||
* @client: Handle to the DRV's client.
|
||||
* @genpd_nb: PM Domain notifier
|
||||
* @dev: RSC device
|
||||
*/
|
||||
struct rsc_drv {
|
||||
const char *name;
|
||||
|
|
@ -134,6 +136,8 @@ struct rsc_drv {
|
|||
spinlock_t lock;
|
||||
wait_queue_head_t tcs_wait;
|
||||
struct rpmh_ctrlr client;
|
||||
struct notifier_block genpd_nb;
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
extern bool rpmh_standalone;
|
||||
|
|
|
|||
|
|
@ -14,10 +14,13 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wait.h>
|
||||
|
|
@ -1054,6 +1057,32 @@ static int rpmh_probe_tcs_config(struct platform_device *pdev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rpmh_rsc_pd_cb(struct notifier_block *nb,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
struct rsc_drv *drv = container_of(nb, struct rsc_drv, genpd_nb);
|
||||
|
||||
/* We don't need to lock as domin on/off are serialized */
|
||||
if ((action == GENPD_NOTIFY_PRE_OFF) &&
|
||||
(rpmh_rsc_ctrlr_is_busy(drv) || rpmh_flush(&drv->client)))
|
||||
return NOTIFY_BAD;
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
static int rpmh_rsc_pd_attach(struct rsc_drv *drv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pm_runtime_enable(drv->dev);
|
||||
ret = dev_pm_domain_attach(drv->dev, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drv->genpd_nb.notifier_call = rpmh_rsc_pd_cb;
|
||||
return dev_pm_genpd_add_notifier(drv->dev, &drv->genpd_nb);
|
||||
}
|
||||
|
||||
static int rpmh_rsc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
|
|
@ -1117,6 +1146,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
drv->dev = &pdev->dev;
|
||||
/*
|
||||
* CPU PM notification are not required for controllers that support
|
||||
* 'HW solver' mode where they can be in autonomous mode executing low
|
||||
|
|
@ -1125,7 +1155,13 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
|
|||
solver_config = readl_relaxed(base + DRV_SOLVER_CONFIG);
|
||||
solver_config &= DRV_HW_SOLVER_MASK << DRV_HW_SOLVER_SHIFT;
|
||||
solver_config = solver_config >> DRV_HW_SOLVER_SHIFT;
|
||||
if (!solver_config) {
|
||||
if (of_find_property(dn, "power-domains", NULL)) {
|
||||
ret = rpmh_rsc_pd_attach(drv);
|
||||
if (ret == -EPROBE_DEFER) {
|
||||
pr_err("Failed to attach RSC %s to domain ret=%d\n", drv->name, ret);
|
||||
return ret;
|
||||
}
|
||||
} else if (!solver_config) {
|
||||
drv->rsc_pm.notifier_call = rpmh_rsc_cpu_pm_callback;
|
||||
cpu_pm_register_notifier(&drv->rsc_pm);
|
||||
drv->client.flags &= ~SOLVER_PRESENT;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user