soc: rockchip: power-domain: add panic when wait status timeout

Change-Id: Ic0ce83068091313942f9277ba56abffa525da1d2
Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
This commit is contained in:
Elaine Zhang
2018-04-25 15:47:36 +08:00
committed by Tao Huang
parent deb5bade24
commit a8dd883a2a

View File

@@ -160,7 +160,7 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
unsigned int target_ack;
unsigned int val;
bool is_idle;
int ret;
int ret = 0;
if (pd_info->req_mask == 0)
return 0;
@@ -181,21 +181,24 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
0, 10000);
if (ret) {
dev_err(pmu->dev,
"failed to get ack on domain '%s', val=0x%x\n",
genpd->name, val);
return ret;
"failed to get ack on domain '%s', target_idle = %d, target_ack = %d, val=0x%x\n",
genpd->name, idle, target_ack, val);
goto error;
}
ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_idle, pd,
is_idle, is_idle == idle, 0, 10000);
if (ret) {
dev_err(pmu->dev,
"failed to set idle on domain '%s', val=%d\n",
genpd->name, is_idle);
return ret;
"failed to set idle on domain '%s', target_idle = %d, val=%d\n",
genpd->name, idle, is_idle);
goto error;
}
return 0;
return ret;
error:
panic("panic_on_set_idle set ...\n");
return ret;
}
int rockchip_pmu_idle_request(struct device *dev, bool idle)
@@ -331,15 +334,16 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
return !(val & pd->info->status_mask);
}
static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
bool on)
static int rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
bool on)
{
struct rockchip_pmu *pmu = pd->pmu;
struct generic_pm_domain *genpd = &pd->genpd;
bool is_on;
int ret = 0;
if (pd->info->pwr_mask == 0)
return;
return 0;
else if (pd->info->pwr_w_mask)
regmap_write(pmu->regmap, pmu->info->pwr_offset,
on ? pd->info->pwr_w_mask :
@@ -350,19 +354,26 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
dsb(sy);
if (readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
is_on == on, 0, 10000)) {
ret = readx_poll_timeout_atomic(rockchip_pmu_domain_is_on, pd, is_on,
is_on == on, 0, 10000);
if (ret) {
dev_err(pmu->dev,
"failed to set domain '%s', val=%d\n",
genpd->name, is_on);
return;
"failed to set domain '%s', target_on= %d, val=%d\n",
genpd->name, on, is_on);
goto error;
}
return ret;
error:
panic("panic_on_set_domain set ...\n");
return ret;
}
static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
{
struct rockchip_pmu *pmu = pd->pmu;
int ret;
int ret = 0;
struct generic_pm_domain *genpd = &pd->genpd;
mutex_lock(&pmu->mutex);
@@ -379,24 +390,40 @@ static int rockchip_pd_power(struct rockchip_pm_domain *pd, bool power_on)
pd->is_qos_saved = true;
/* if powering down, idle request to NIU first */
rockchip_pmu_set_idle_request(pd, true);
ret = rockchip_pmu_set_idle_request(pd, true);
if (ret) {
dev_err(pd->pmu->dev, "failed to set idle request '%s',\n",
genpd->name);
goto out;
}
}
rockchip_do_pmu_set_power_domain(pd, power_on);
ret = rockchip_do_pmu_set_power_domain(pd, power_on);
if (ret) {
dev_err(pd->pmu->dev, "failed to set power '%s' = %d,\n",
genpd->name, power_on);
goto out;
}
if (power_on) {
/* if powering up, leave idle mode */
rockchip_pmu_set_idle_request(pd, false);
ret = rockchip_pmu_set_idle_request(pd, false);
if (ret) {
dev_err(pd->pmu->dev, "failed to set deidle request '%s',\n",
genpd->name);
goto out;
}
if (pd->is_qos_saved)
rockchip_pmu_restore_qos(pd);
}
out:
clk_bulk_disable(pd->num_clks, pd->clks);
}
mutex_unlock(&pmu->mutex);
return 0;
return ret;
}
static int rockchip_pd_power_on(struct generic_pm_domain *domain)
@@ -709,6 +736,30 @@ err_out:
return error;
}
static void __iomem *pd_base;
void rockchip_dump_pmu(void)
{
if (pd_base) {
pr_warn("PMU:\n");
print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET,
32, 4, pd_base,
0x100, false);
}
}
EXPORT_SYMBOL_GPL(rockchip_dump_pmu);
static int rockchip_pmu_panic(struct notifier_block *this,
unsigned long ev, void *ptr)
{
rockchip_dump_pmu();
return NOTIFY_DONE;
}
static struct notifier_block pmu_panic_block = {
.notifier_call = rockchip_pmu_panic,
};
static int rockchip_pm_domain_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -719,6 +770,7 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
const struct of_device_id *match;
const struct rockchip_pmu_info *pmu_info;
int error;
void __iomem *reg_base;
if (!np) {
dev_err(dev, "device tree node not found\n");
@@ -759,6 +811,14 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
return PTR_ERR(pmu->regmap);
}
reg_base = of_iomap(parent->of_node, 0);
if (!reg_base) {
dev_err(dev, "%s: could not map pmu region\n", __func__);
return -ENOMEM;
}
pd_base = reg_base;
/*
* Configure power up and down transition delays for CORE
* and GPU domains.
@@ -801,6 +861,9 @@ static int rockchip_pm_domain_probe(struct platform_device *pdev)
goto err_out;
}
atomic_notifier_chain_register(&panic_notifier_list,
&pmu_panic_block);
return 0;
err_out: