#include <dt-bindings/power/jh7110-power.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
PMU_INT_HW_REQ | \
PMU_INT_FAIL_MASK)
+#define DELAY_US 10
+#define TIMEOUT_US 100000
+
struct jh7110_power_dev {
struct generic_pm_domain genpd;
struct jh7110_pmu *power;
if (!pmd->mask)
return -EINVAL;
+
ret = jh7110_pmu_get_state(pmd, &is_on);
if (ret)
dev_info(pmu->pdev, "unable to get current state for %s\n",
pmd->genpd.name);
if (is_on == on) {
- dev_info(pmu->pdev, "pm domain is already %sable status.\n",
- on ? "en" : "dis");
+ dev_info(pmu->pdev, "pm domain [%s] is already %sable status.\n",
+ pmd->genpd.name, on ? "en" : "dis");
return 0;
}
encourage_hi = SW_MODE_ENCOURAGE_DIS_HI;
}
- val = __raw_readl(pmu->base + mode);
- val |= pmd->mask;
- __raw_writel(val, pmu->base + mode);
+ __raw_writel(pmd->mask, pmu->base + mode);
/* write SW_ENCOURAGE to make the configuration take effect */
__raw_writel(SW_MODE_ENCOURAGE_ON, pmu->base + SW_ENCOURAGE);
spin_unlock_irqrestore(&pmu->lock, flags);
+ if (on) {
+ ret = readl_poll_timeout_atomic(pmu->base + CURR_POWER_MODE, val,
+ val & pmd->mask, DELAY_US,
+ TIMEOUT_US);
+ if (ret) {
+ dev_err(pmu->pdev, "%s power_on failed", pmd->genpd.name);
+ return -ETIMEDOUT;
+ }
+ } else {
+ ret = readl_poll_timeout_atomic(pmu->base + CURR_POWER_MODE, val,
+ !(val & pmd->mask), DELAY_US,
+ TIMEOUT_US);
+ if (ret) {
+ dev_err(pmu->pdev, "%s power_off failed", pmd->genpd.name);
+ return -ETIMEDOUT;
+ }
+ }
+
return 0;
}
};
builtin_platform_driver(jh7110_pmu_driver);
-MODULE_AUTHOR("Walker Chen <walker.chen@starfivetech.com>");
+MODULE_AUTHOR("Walker Chen <walker.chen@linux.starfivetech.com>");
MODULE_DESCRIPTION("Starfive JH7110 Power Domain Driver");
MODULE_LICENSE("GPL");