|
|
@@ -13,14 +13,11 @@
|
|
|
#include <linux/err.h>
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/pm_domain.h>
|
|
|
-#include <linux/clk.h>
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/of_address.h>
|
|
|
#include <linux/of_platform.h>
|
|
|
#include <linux/sched.h>
|
|
|
|
|
|
-#define MAX_CLK_PER_DOMAIN 4
|
|
|
-
|
|
|
struct exynos_pm_domain_config {
|
|
|
/* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
|
|
|
u32 local_pwr_cfg;
|
|
|
@@ -33,10 +30,6 @@ struct exynos_pm_domain {
|
|
|
void __iomem *base;
|
|
|
bool is_off;
|
|
|
struct generic_pm_domain pd;
|
|
|
- struct clk *oscclk;
|
|
|
- struct clk *clk[MAX_CLK_PER_DOMAIN];
|
|
|
- struct clk *pclk[MAX_CLK_PER_DOMAIN];
|
|
|
- struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
|
|
|
u32 local_pwr_cfg;
|
|
|
};
|
|
|
|
|
|
@@ -46,29 +39,10 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
|
|
void __iomem *base;
|
|
|
u32 timeout, pwr;
|
|
|
char *op;
|
|
|
- int i;
|
|
|
|
|
|
pd = container_of(domain, struct exynos_pm_domain, pd);
|
|
|
base = pd->base;
|
|
|
|
|
|
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
|
|
- if (IS_ERR(pd->asb_clk[i]))
|
|
|
- break;
|
|
|
- clk_prepare_enable(pd->asb_clk[i]);
|
|
|
- }
|
|
|
-
|
|
|
- /* Set oscclk before powering off a domain*/
|
|
|
- if (!power_on) {
|
|
|
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
|
|
- if (IS_ERR(pd->clk[i]))
|
|
|
- break;
|
|
|
- pd->pclk[i] = clk_get_parent(pd->clk[i]);
|
|
|
- if (clk_set_parent(pd->clk[i], pd->oscclk))
|
|
|
- pr_err("%s: error setting oscclk as parent to clock %d\n",
|
|
|
- domain->name, i);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
pwr = power_on ? pd->local_pwr_cfg : 0;
|
|
|
writel_relaxed(pwr, base);
|
|
|
|
|
|
@@ -86,26 +60,6 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
|
|
|
usleep_range(80, 100);
|
|
|
}
|
|
|
|
|
|
- /* Restore clocks after powering on a domain*/
|
|
|
- if (power_on) {
|
|
|
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
|
|
- if (IS_ERR(pd->clk[i]))
|
|
|
- break;
|
|
|
-
|
|
|
- if (IS_ERR(pd->pclk[i]))
|
|
|
- continue; /* Skip on first power up */
|
|
|
- if (clk_set_parent(pd->clk[i], pd->pclk[i]))
|
|
|
- pr_err("%s: error setting parent to clock%d\n",
|
|
|
- domain->name, i);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
|
|
- if (IS_ERR(pd->asb_clk[i]))
|
|
|
- break;
|
|
|
- clk_disable_unprepare(pd->asb_clk[i]);
|
|
|
- }
|
|
|
-
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -147,12 +101,6 @@ static __init const char *exynos_get_domain_name(struct device_node *node)
|
|
|
return kstrdup_const(name, GFP_KERNEL);
|
|
|
}
|
|
|
|
|
|
-static const char *soc_force_no_clk[] = {
|
|
|
- "samsung,exynos5250-clock",
|
|
|
- "samsung,exynos5420-clock",
|
|
|
- "samsung,exynos5800-clock",
|
|
|
-};
|
|
|
-
|
|
|
static __init int exynos4_pm_init_power_domain(void)
|
|
|
{
|
|
|
struct device_node *np;
|
|
|
@@ -161,7 +109,7 @@ static __init int exynos4_pm_init_power_domain(void)
|
|
|
for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
|
|
|
const struct exynos_pm_domain_config *pm_domain_cfg;
|
|
|
struct exynos_pm_domain *pd;
|
|
|
- int on, i;
|
|
|
+ int on;
|
|
|
|
|
|
pm_domain_cfg = match->data;
|
|
|
|
|
|
@@ -189,42 +137,6 @@ static __init int exynos4_pm_init_power_domain(void)
|
|
|
pd->pd.power_on = exynos_pd_power_on;
|
|
|
pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
|
|
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(soc_force_no_clk); i++)
|
|
|
- if (of_find_compatible_node(NULL, NULL,
|
|
|
- soc_force_no_clk[i]))
|
|
|
- goto no_clk;
|
|
|
-
|
|
|
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
|
|
- char clk_name[8];
|
|
|
-
|
|
|
- snprintf(clk_name, sizeof(clk_name), "asb%d", i);
|
|
|
- pd->asb_clk[i] = of_clk_get_by_name(np, clk_name);
|
|
|
- if (IS_ERR(pd->asb_clk[i]))
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- pd->oscclk = of_clk_get_by_name(np, "oscclk");
|
|
|
- if (IS_ERR(pd->oscclk))
|
|
|
- goto no_clk;
|
|
|
-
|
|
|
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
|
|
|
- char clk_name[8];
|
|
|
-
|
|
|
- snprintf(clk_name, sizeof(clk_name), "clk%d", i);
|
|
|
- pd->clk[i] = of_clk_get_by_name(np, clk_name);
|
|
|
- if (IS_ERR(pd->clk[i]))
|
|
|
- break;
|
|
|
- /*
|
|
|
- * Skip setting parent on first power up.
|
|
|
- * The parent at this time may not be useful at all.
|
|
|
- */
|
|
|
- pd->pclk[i] = ERR_PTR(-EINVAL);
|
|
|
- }
|
|
|
-
|
|
|
- if (IS_ERR(pd->clk[0]))
|
|
|
- clk_put(pd->oscclk);
|
|
|
-
|
|
|
-no_clk:
|
|
|
on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
|
|
|
|
|
|
pm_genpd_init(&pd->pd, NULL, !on);
|