Merge branch 'cleanup/io-pci' into next/cleanups
[pandora-kernel.git] / arch / arm / mach-kirkwood / common.c
index 55e4d79..31d9f40 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/clk-provider.h>
 #include <linux/spinlock.h>
+#include <linux/mv643xx_i2c.h>
 #include <net/dsa.h>
 #include <asm/page.h>
 #include <asm/timex.h>
@@ -57,6 +58,14 @@ void __init kirkwood_map_io(void)
  * CLK tree
  ****************************************************************************/
 
+static void enable_sata0(void)
+{
+       /* Enable PLL and IVREF */
+       writel(readl(SATA0_PHY_MODE_2) | 0xf, SATA0_PHY_MODE_2);
+       /* Enable PHY */
+       writel(readl(SATA0_IF_CTRL) & ~0x200, SATA0_IF_CTRL);
+}
+
 static void disable_sata0(void)
 {
        /* Disable PLL and IVREF */
@@ -65,6 +74,14 @@ static void disable_sata0(void)
        writel(readl(SATA0_IF_CTRL) | 0x200, SATA0_IF_CTRL);
 }
 
+static void enable_sata1(void)
+{
+       /* Enable PLL and IVREF */
+       writel(readl(SATA1_PHY_MODE_2) | 0xf, SATA1_PHY_MODE_2);
+       /* Enable PHY */
+       writel(readl(SATA1_IF_CTRL) & ~0x200, SATA1_IF_CTRL);
+}
+
 static void disable_sata1(void)
 {
        /* Disable PLL and IVREF */
@@ -97,23 +114,38 @@ static void disable_pcie1(void)
        }
 }
 
-/* An extended version of the gated clk. This calls fn() before
- * disabling the clock. We use this to turn off PHYs etc. */
+/* An extended version of the gated clk. This calls fn_en()/fn_dis
+ * before enabling/disabling the clock.  We use this to turn on/off
+ * PHYs etc.  */
 struct clk_gate_fn {
        struct clk_gate gate;
-       void (*fn)(void);
+       void (*fn_en)(void);
+       void (*fn_dis)(void);
 };
 
 #define to_clk_gate_fn(_gate) container_of(_gate, struct clk_gate_fn, gate)
 #define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
 
+static int clk_gate_fn_enable(struct clk_hw *hw)
+{
+       struct clk_gate *gate = to_clk_gate(hw);
+       struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
+       int ret;
+
+       ret = clk_gate_ops.enable(hw);
+       if (!ret && gate_fn->fn_en)
+               gate_fn->fn_en();
+
+       return ret;
+}
+
 static void clk_gate_fn_disable(struct clk_hw *hw)
 {
        struct clk_gate *gate = to_clk_gate(hw);
        struct clk_gate_fn *gate_fn = to_clk_gate_fn(gate);
 
-       if (gate_fn->fn)
-               gate_fn->fn();
+       if (gate_fn->fn_dis)
+               gate_fn->fn_dis();
 
        clk_gate_ops.disable(hw);
 }
@@ -125,7 +157,7 @@ static struct clk __init *clk_register_gate_fn(struct device *dev,
                const char *parent_name, unsigned long flags,
                void __iomem *reg, u8 bit_idx,
                u8 clk_gate_flags, spinlock_t *lock,
-               void (*fn)(void))
+               void (*fn_en)(void), void (*fn_dis)(void))
 {
        struct clk_gate_fn *gate_fn;
        struct clk *clk;
@@ -149,11 +181,14 @@ static struct clk __init *clk_register_gate_fn(struct device *dev,
        gate_fn->gate.flags = clk_gate_flags;
        gate_fn->gate.lock = lock;
        gate_fn->gate.hw.init = &init;
-       gate_fn->fn = fn;
+       gate_fn->fn_en = fn_en;
+       gate_fn->fn_dis = fn_dis;
 
-       /* ops is the gate ops, but with our disable function */
-       if (clk_gate_fn_ops.disable != clk_gate_fn_disable) {
+       /* ops is the gate ops, but with our enable/disable functions */
+       if (clk_gate_fn_ops.enable != clk_gate_fn_enable ||
+           clk_gate_fn_ops.disable != clk_gate_fn_disable) {
                clk_gate_fn_ops = clk_gate_ops;
+               clk_gate_fn_ops.enable = clk_gate_fn_enable;
                clk_gate_fn_ops.disable = clk_gate_fn_disable;
        }
 
@@ -177,11 +212,12 @@ static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
 
 static struct clk __init *kirkwood_register_gate_fn(const char *name,
                                                    u8 bit_idx,
-                                                   void (*fn)(void))
+                                                   void (*fn_en)(void),
+                                                   void (*fn_dis)(void))
 {
        return clk_register_gate_fn(NULL, name, "tclk", 0,
                                    (void __iomem *)CLOCK_GATING_CTRL,
-                                   bit_idx, 0, &gating_lock, fn);
+                                   bit_idx, 0, &gating_lock, fn_en, fn_dis);
 }
 
 static struct clk *ge0, *ge1;
@@ -198,18 +234,18 @@ void __init kirkwood_clk_init(void)
        ge0 = kirkwood_register_gate("ge0",    CGC_BIT_GE0);
        ge1 = kirkwood_register_gate("ge1",    CGC_BIT_GE1);
        sata0 = kirkwood_register_gate_fn("sata0",  CGC_BIT_SATA0,
-                                         disable_sata0);
+                                         enable_sata0, disable_sata0);
        sata1 = kirkwood_register_gate_fn("sata1",  CGC_BIT_SATA1,
-                                         disable_sata1);
+                                         enable_sata1, disable_sata1);
        usb0 = kirkwood_register_gate("usb0",   CGC_BIT_USB0);
        sdio = kirkwood_register_gate("sdio",   CGC_BIT_SDIO);
        crypto = kirkwood_register_gate("crypto", CGC_BIT_CRYPTO);
        xor0 = kirkwood_register_gate("xor0",   CGC_BIT_XOR0);
        xor1 = kirkwood_register_gate("xor1",   CGC_BIT_XOR1);
        pex0 = kirkwood_register_gate_fn("pex0",   CGC_BIT_PEX0,
-                                        disable_pcie0);
+                                        NULL, disable_pcie0);
        pex1 = kirkwood_register_gate_fn("pex1",   CGC_BIT_PEX1,
-                                        disable_pcie1);
+                                        NULL, disable_pcie1);
        audio = kirkwood_register_gate("audio",  CGC_BIT_AUDIO);
        kirkwood_register_gate("tdm",    CGC_BIT_TDM);
        kirkwood_register_gate("tsu",    CGC_BIT_TSU);
@@ -231,6 +267,12 @@ void __init kirkwood_clk_init(void)
        orion_clkdev_add("0", "pcie", pex0);
        orion_clkdev_add("1", "pcie", pex1);
        orion_clkdev_add(NULL, "kirkwood-i2s", audio);
+       orion_clkdev_add(NULL, MV64XXX_I2C_CTLR_NAME ".0", runit);
+
+       /* Marvell says runit is used by SPI, UART, NAND, TWSI, ...,
+        * so should never be gated.
+        */
+       clk_prepare_enable(runit);
 }
 
 /*****************************************************************************