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 f0baaa1..39bf321 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 584494a..27233cb 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 e93840a..37f20a7 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 648160c..7b15fab 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 7cf9705..3c61543 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 97782a7..7851d56 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 55a90d4..ab8a258 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 84171ab..a78b657 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;