]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/mach-omap2/clock.c
ARM: OMAP: clk_disable_unused: init section mismatch
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / clock.c
index 7c18a14f5ee7e5062309834c848cd8492f760a1c..668560dba557b81057fd7f192ee3db4dc5be5acb 100644 (file)
@@ -19,6 +19,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#undef DEBUG
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -31,6 +33,7 @@
 
 #include <asm/arch/clock.h>
 #include <asm/arch/sram.h>
+#include <asm/arch/cpu.h>
 #include <asm/div64.h>
 
 #include "memory.h"
@@ -41,9 +44,7 @@
 #include "cm.h"
 #include "cm_regbits_24xx.h"
 
-#undef DEBUG
-
-#define MAX_PLL_LOCK_WAIT              100000
+#define MAX_CLOCK_ENABLE_WAIT          100000
 
 u8 cpu_mask;
 
@@ -73,8 +74,7 @@ void omap2_init_clksel_parent(struct clk *clk)
        if (!clk->clksel)
                return;
 
-       /* XXX Should be __raw_readl for non-CM 3430 clocks ? */
-       r = cm_read_reg(clk->clksel_reg) & clk->clksel_mask;
+       r = __raw_readl(clk->clksel_reg) & clk->clksel_mask;
        r >>= mask_to_shift(clk->clksel_mask);
 
        for (clks = clk->clksel; clks->parent && !found; clks++) {
@@ -84,7 +84,7 @@ void omap2_init_clksel_parent(struct clk *clk)
                                        pr_debug("clock: inited %s parent "
                                                 "to %s (was %s)\n",
                                                 clk->name, clks->parent->name,
-                                                ((clk->parent->name) ?
+                                                ((clk->parent) ?
                                                  clk->parent->name : "NULL"));
                                        clk->parent = clks->parent;
                                };
@@ -121,6 +121,14 @@ u32 omap2_get_dpll_rate(struct clk *clk)
        dpll_clk = (long long)clk->parent->rate * dpll_mult;
        do_div(dpll_clk, dpll_div + 1);
 
+       /* 34XX only */
+       if (dd->div2_reg) {
+               dpll = cm_read_reg(dd->div2_reg);
+               dpll_div = dpll & dd->div2_mask;
+               dpll_div >>= mask_to_shift(dd->div2_mask);
+               do_div(dpll_clk, dpll_div + 1);
+       }
+
        return dpll_clk;
 }
 
@@ -138,38 +146,61 @@ void omap2_fixed_divisor_recalc(struct clk *clk)
                propagate_rate(clk);
 }
 
-/*
- * omap2_wait_clock_ready - wait for PLL to lock
+/**
+ * omap2_wait_clock_ready - wait for clock to enable
+ * @reg: physical address of clock IDLEST register
+ * @mask: value to mask against to determine if the clock is active
+ * @name: name of the clock (for printk)
  *
- * Returns 1 if the PLL locked, 0 if it failed to lock.
+ * Returns 1 if the clock enabled in time, or 0 if it failed to enable
+ * in roughly MAX_CLOCK_ENABLE_WAIT microseconds.
  */
-int omap2_wait_clock_ready(void __iomem *reg, u32 cval, const char *name)
+int omap2_wait_clock_ready(void __iomem *reg, u32 mask, const char *name)
 {
        int i = 0;
+       int ena = 0;
+
+       /*
+        * 24xx uses 0 to indicate not ready, and 1 to indicate ready.
+        * 34xx reverses this, just to keep us on our toes
+        */
+       if (cpu_mask & (RATE_IN_242X | RATE_IN_243X)) {
+               ena = mask;
+       } else if (cpu_mask & RATE_IN_343X) {
+               ena = 0;
+       }
 
        /* Wait for lock */
-       while (!(cm_read_reg(reg) & cval)) {
-               ++i;
+       while (((cm_read_reg(reg) & mask) != ena) &&
+              (i++ < MAX_CLOCK_ENABLE_WAIT)) {
                udelay(1);
-               if (i == MAX_PLL_LOCK_WAIT) {
-                       printk(KERN_ERR "Clock %s didn't lock in %d tries\n",
-                              name, MAX_PLL_LOCK_WAIT);
-                       break;
-               }
        }
 
-       if (i)
+       if (i < MAX_CLOCK_ENABLE_WAIT)
                pr_debug("Clock %s stable after %d loops\n", name, i);
+       else
+               printk(KERN_ERR "Clock %s didn't enable in %d tries\n",
+                      name, MAX_CLOCK_ENABLE_WAIT);
+
 
-       return (i < MAX_PLL_LOCK_WAIT) ? 1 : 0;
+       return (i < MAX_CLOCK_ENABLE_WAIT) ? 1 : 0;
 };
 
 
+/*
+ * Note: We don't need special code here for INVERT_ENABLE
+ * for the time being since INVERT_ENABLE only applies to clocks enabled by
+ * CM_CLKEN_PLL
+ */
 static void omap2_clk_wait_ready(struct clk *clk)
 {
        void __iomem *reg, *other_reg, *st_reg;
        u32 bit;
 
+       /*
+        * REVISIT: This code is pretty ugly.  It would be nice to generalize
+        * it and pull it into struct clk itself somehow.
+        */
        reg = clk->enable_reg;
        if (reg == OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1) ||
            reg == OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2))
@@ -180,8 +211,9 @@ static void omap2_clk_wait_ready(struct clk *clk)
        else
                return;
 
+       /* REVISIT: What are the appropriate exclusions for 34XX? */
        /* No check for DSS or cam clocks */
-       if (((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */
+       if (cpu_is_omap24xx() && ((u32)reg & 0x0f) == 0) { /* CM_{F,I}CLKEN1 */
                if (clk->enable_bit == OMAP24XX_EN_DSS2_SHIFT ||
                    clk->enable_bit == OMAP24XX_EN_DSS1_SHIFT ||
                    clk->enable_bit == OMAP24XX_EN_CAM_SHIFT)
@@ -214,11 +246,14 @@ int _omap2_clk_enable(struct clk *clk)
        if (unlikely(clk->enable_reg == 0)) {
                printk(KERN_ERR "clock.c: Enable for %s without enable code\n",
                       clk->name);
-               return -EINVAL;
+               return 0; /* REVISIT: -EINVAL */
        }
 
        regval32 = cm_read_reg(clk->enable_reg);
-       regval32 |= (1 << clk->enable_bit);
+       if (clk->flags & INVERT_ENABLE)
+               regval32 &= ~(1 << clk->enable_bit);
+       else
+               regval32 |= (1 << clk->enable_bit);
        cm_write_reg(regval32, clk->enable_reg);
        wmb();
 
@@ -251,7 +286,10 @@ void _omap2_clk_disable(struct clk *clk)
        }
 
        regval32 = cm_read_reg(clk->enable_reg);
-       regval32 &= ~(1 << clk->enable_bit);
+       if (clk->flags & INVERT_ENABLE)
+               regval32 |= (1 << clk->enable_bit);
+       else
+               regval32 &= ~(1 << clk->enable_bit);
        cm_write_reg(regval32, clk->enable_reg);
        wmb();
 }
@@ -574,7 +612,7 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
 
        clk->rate = clk->parent->rate / new_div;
 
-       if (clk->flags & DELAYED_APP) {
+       if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
                prm_write_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_PRCM_CLKCFG_CTRL);
                wmb();
        }
@@ -670,7 +708,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
        __raw_writel(reg_val, src_addr);
        wmb();
 
-       if (clk->flags & DELAYED_APP) {
+       if (clk->flags & DELAYED_APP && cpu_is_omap24xx()) {
                prm_write_reg(OMAP24XX_VALID_CONFIG,
                              OMAP24XX_PRCM_CLKCFG_CTRL);
                wmb();
@@ -701,12 +739,14 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
  *-------------------------------------------------------------------------*/
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
-void __init omap2_clk_disable_unused(struct clk *clk)
+void omap2_clk_disable_unused(struct clk *clk)
 {
-       u32 regval32;
+       u32 regval32, v;
+
+       v = (clk->flags & INVERT_ENABLE) ? (1 << clk->enable_bit) : 0;
 
        regval32 = cm_read_reg(clk->enable_reg);
-       if ((regval32 & (1 << clk->enable_bit)) == 0)
+       if ((regval32 & (1 << clk->enable_bit)) == v)
                return;
 
        printk(KERN_INFO "Disabling unused clock \"%s\"\n", clk->name);