davinci: Add support for multiple PSCs
authorMark A. Greer <mgreer@mvista.com>
Wed, 15 Apr 2009 19:39:33 +0000 (12:39 -0700)
committerKevin Hilman <khilman@deeprootsystems.com>
Tue, 26 May 2009 15:16:46 +0000 (08:16 -0700)
The current code to support the DaVinci Power and Sleep Controller (PSC)
assumes that there is only one controller.  This assumption is no longer
valid so expand the support to allow greater than one PSC.

To accomplish this, put the base addresses for the PSCs in the SoC
infrastructure so it can be referenced by the PSC code.  This also
requires adding an extra parameter to davinci_psc_config() to specify
the PSC that is to be enabled/disabled.

Signed-off-by: Mark A. Greer <mgreer@mvista.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
arch/arm/mach-davinci/clock.c
arch/arm/mach-davinci/clock.h
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-davinci/include/mach/common.h
arch/arm/mach-davinci/include/mach/psc.h
arch/arm/mach-davinci/psc.c

index f0baaa15a57e661c2991fe85d883376eb35dd11f..39bf321d70a274a4c0514e7f41619df4e188fad5 100644 (file)
@@ -42,7 +42,8 @@ static void __clk_enable(struct clk *clk)
        if (clk->parent)
                __clk_enable(clk->parent);
        if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
-               davinci_psc_config(psc_domain(clk), clk->lpsc, 1);
+               davinci_psc_config(psc_domain(clk), clk->psc_ctlr,
+                               clk->lpsc, 1);
 }
 
 static void __clk_disable(struct clk *clk)
@@ -50,7 +51,8 @@ static void __clk_disable(struct clk *clk)
        if (WARN_ON(clk->usecount == 0))
                return;
        if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
-               davinci_psc_config(psc_domain(clk), clk->lpsc, 0);
+               davinci_psc_config(psc_domain(clk), clk->psc_ctlr,
+                               clk->lpsc, 0);
        if (clk->parent)
                __clk_disable(clk->parent);
 }
@@ -164,11 +166,11 @@ static int __init clk_disable_unused(void)
                        continue;
 
                /* ignore if in Disabled or SwRstDisable states */
-               if (!davinci_psc_is_clk_active(ck->lpsc))
+               if (!davinci_psc_is_clk_active(ck->psc_ctlr, ck->lpsc))
                        continue;
 
                pr_info("Clocks: disable unused %s\n", ck->name);
-               davinci_psc_config(psc_domain(ck), ck->lpsc, 0);
+               davinci_psc_config(psc_domain(ck), ck->psc_ctlr, ck->lpsc, 0);
        }
        spin_unlock_irq(&clockfw_lock);
 
index 584494a32070464d49450eafd79e78fa2889f56a..27233cb4a2fbeeaca1e66a9bff1a1d96f4e36734 100644 (file)
@@ -67,6 +67,7 @@ struct clk {
        u8                      usecount;
        u8                      flags;
        u8                      lpsc;
+       u8                      psc_ctlr;
        struct clk              *parent;
        struct pll_data         *pll_data;
        u32                     div_reg;
index e93840a814ed6f97bb22c65392e229cd7b28c290..37f20a7214bea71156ba1a4c85815c72191079e5 100644 (file)
@@ -545,6 +545,10 @@ static struct davinci_id dm355_ids[] = {
        },
 };
 
+static void __iomem *dm355_psc_bases[] = {
+       IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
+};
+
 static struct davinci_soc_info davinci_soc_info_dm355 = {
        .io_desc                = dm355_io_desc,
        .io_desc_num            = ARRAY_SIZE(dm355_io_desc),
@@ -552,6 +556,8 @@ static struct davinci_soc_info davinci_soc_info_dm355 = {
        .ids                    = dm355_ids,
        .ids_num                = ARRAY_SIZE(dm355_ids),
        .cpu_clks               = dm355_clks,
+       .psc_bases              = dm355_psc_bases,
+       .psc_bases_num          = ARRAY_SIZE(dm355_psc_bases),
 };
 
 void __init dm355_init(void)
index 648160c2960d823518b1b6f4d84c706b6b20bfb2..7b15faba56ed2520fa2baec6481d88433c1f0a82 100644 (file)
@@ -485,6 +485,10 @@ static struct davinci_id dm644x_ids[] = {
        },
 };
 
+static void __iomem *dm644x_psc_bases[] = {
+       IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
+};
+
 static struct davinci_soc_info davinci_soc_info_dm644x = {
        .io_desc                = dm644x_io_desc,
        .io_desc_num            = ARRAY_SIZE(dm644x_io_desc),
@@ -492,6 +496,8 @@ static struct davinci_soc_info davinci_soc_info_dm644x = {
        .ids                    = dm644x_ids,
        .ids_num                = ARRAY_SIZE(dm644x_ids),
        .cpu_clks               = dm644x_clks,
+       .psc_bases              = dm644x_psc_bases,
+       .psc_bases_num          = ARRAY_SIZE(dm644x_psc_bases),
 };
 
 void __init dm644x_init(void)
index 7cf9705be9ce55229b856fc5aba773e0bb332cb7..3c61543c7cfa979ac5900ad6ce4b2282aa76a01c 100644 (file)
@@ -465,6 +465,10 @@ static struct davinci_id dm646x_ids[] = {
        },
 };
 
+static void __iomem *dm646x_psc_bases[] = {
+       IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE),
+};
+
 static struct davinci_soc_info davinci_soc_info_dm646x = {
        .io_desc                = dm646x_io_desc,
        .io_desc_num            = ARRAY_SIZE(dm646x_io_desc),
@@ -472,6 +476,8 @@ static struct davinci_soc_info davinci_soc_info_dm646x = {
        .ids                    = dm646x_ids,
        .ids_num                = ARRAY_SIZE(dm646x_ids),
        .cpu_clks               = dm646x_clks,
+       .psc_bases              = dm646x_psc_bases,
+       .psc_bases_num          = ARRAY_SIZE(dm646x_psc_bases),
 };
 
 void __init dm646x_init(void)
index 97782a76588229ef6569bfda06cc5338f9ad772f..7851d5680c13722f34aad0272b3f24c0f5f977af 100644 (file)
@@ -34,6 +34,8 @@ struct davinci_soc_info {
        struct davinci_id               *ids;
        unsigned long                   ids_num;
        struct davinci_clk              *cpu_clks;
+       void __iomem                    **psc_bases;
+       unsigned long                   psc_bases_num;
 };
 
 extern struct davinci_soc_info davinci_soc_info;
index 55a90d419fac2b17dc62732b98365e531c8a56a9..ab8a2586d1cc7e2767043166f2c40ed4bb5cd052 100644 (file)
@@ -27,6 +27,8 @@
 #ifndef __ASM_ARCH_PSC_H
 #define __ASM_ARCH_PSC_H
 
+#define        DAVINCI_PWR_SLEEP_CNTRL_BASE    0x01C41000
+
 /* Power and Sleep Controller (PSC) Domains */
 #define DAVINCI_GPSC_ARMDOMAIN      0
 #define DAVINCI_GPSC_DSPDOMAIN      1
 #define DM646X_LPSC_TIMER1         35
 #define DM646X_LPSC_ARM_INTC       45
 
-extern int davinci_psc_is_clk_active(unsigned int id);
-extern void davinci_psc_config(unsigned int domain, unsigned int id,
-                              char enable);
+extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
+extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
+               unsigned int id, char enable);
 
 #endif /* __ASM_ARCH_PSC_H */
index 84171abf5f7b25453af26092006939617ac99237..a78b657e916e9c44425e8c913e6160bc833089bc 100644 (file)
@@ -28,8 +28,6 @@
 #include <mach/psc.h>
 #include <mach/mux.h>
 
-#define DAVINCI_PWR_SLEEP_CNTRL_BASE 0x01C41000
-
 /* PSC register offsets */
 #define EPCPR          0x070
 #define PTCMD          0x120
 #define MDSTAT_STATE_MASK 0x1f
 
 /* Return nonzero iff the domain's clock is active */
-int __init davinci_psc_is_clk_active(unsigned int id)
+int __init davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id)
 {
-       void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
-       u32 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
+       void __iomem *psc_base;
+       u32 mdstat;
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+       if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
+               pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
+                               (int)soc_info->psc_bases, ctlr);
+               return 0;
+       }
+
+       psc_base = soc_info->psc_bases[ctlr];
+       mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
 
        /* if clocked, state can be "Enable" or "SyncReset" */
        return mdstat & BIT(12);
 }
 
 /* Enable or disable a PSC domain */
-void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
+void davinci_psc_config(unsigned int domain, unsigned int ctlr,
+               unsigned int id, char enable)
 {
        u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
-       void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
+       void __iomem *psc_base;
+       struct davinci_soc_info *soc_info = &davinci_soc_info;
        u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */
 
+       if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
+               pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
+                               (int)soc_info->psc_bases, ctlr);
+               return;
+       }
+
+       psc_base = soc_info->psc_bases[ctlr];
+
        mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
        mdctl &= ~MDSTAT_STATE_MASK;
        mdctl |= next_state;