Merge tag 'omap-for-v4.1/prcm-dts' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / arch / arm / mach-omap2 / clock.c
index 6ad5b4d..a699d71 100644 (file)
@@ -23,7 +23,9 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
-#include <linux/clk-private.h>
+#include <linux/regmap.h>
+#include <linux/of_address.h>
+#include <linux/bootmem.h>
 #include <asm/cpu.h>
 
 #include <trace/events/power.h>
@@ -73,30 +75,110 @@ struct ti_clk_features ti_clk_features;
 static bool clkdm_control = true;
 
 static LIST_HEAD(clk_hw_omap_clocks);
-void __iomem *clk_memmaps[CLK_MAX_MEMMAPS];
+
+struct clk_iomap {
+       struct regmap *regmap;
+       void __iomem *mem;
+};
+
+static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
+
+static void clk_memmap_writel(u32 val, void __iomem *reg)
+{
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_write(io->regmap, r->offset, val);
+       else
+               writel_relaxed(val, io->mem + r->offset);
+}
+
+static u32 clk_memmap_readl(void __iomem *reg)
+{
+       u32 val;
+       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
+       struct clk_iomap *io = clk_memmaps[r->index];
+
+       if (io->regmap)
+               regmap_read(io->regmap, r->offset, &val);
+       else
+               val = readl_relaxed(io->mem + r->offset);
+
+       return val;
+}
 
 void omap2_clk_writel(u32 val, struct clk_hw_omap *clk, void __iomem *reg)
 {
-       if (clk->flags & MEMMAP_ADDRESSING) {
-               struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-               writel_relaxed(val, clk_memmaps[r->index] + r->offset);
-       } else {
+       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
                writel_relaxed(val, reg);
-       }
+       else
+               clk_memmap_writel(val, reg);
 }
 
 u32 omap2_clk_readl(struct clk_hw_omap *clk, void __iomem *reg)
 {
-       u32 val;
+       if (WARN_ON_ONCE(!(clk->flags & MEMMAP_ADDRESSING)))
+               return readl_relaxed(reg);
+       else
+               return clk_memmap_readl(reg);
+}
 
-       if (clk->flags & MEMMAP_ADDRESSING) {
-               struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-               val = readl_relaxed(clk_memmaps[r->index] + r->offset);
-       } else {
-               val = readl_relaxed(reg);
-       }
+static struct ti_clk_ll_ops omap_clk_ll_ops = {
+       .clk_readl = clk_memmap_readl,
+       .clk_writel = clk_memmap_writel,
+};
 
-       return val;
+/**
+ * omap2_clk_provider_init - initialize a clock provider
+ * @match_table: DT device table to match for devices to init
+ * @np: device node pointer for the this clock provider
+ * @index: index for the clock provider
+ + @syscon: syscon regmap pointer
+ * @mem: iomem pointer for the clock provider memory area, only used if
+ *      syscon is not provided
+ *
+ * Initializes a clock provider module (CM/PRM etc.), registering
+ * the memory mapping at specified index and initializing the
+ * low level driver infrastructure. Returns 0 in success.
+ */
+int __init omap2_clk_provider_init(struct device_node *np, int index,
+                                  struct regmap *syscon, void __iomem *mem)
+{
+       struct clk_iomap *io;
+
+       ti_clk_ll_ops = &omap_clk_ll_ops;
+
+       io = kzalloc(sizeof(*io), GFP_KERNEL);
+
+       io->regmap = syscon;
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
+
+       ti_dt_clk_init_provider(np, index);
+
+       return 0;
+}
+
+/**
+ * omap2_clk_legacy_provider_init - initialize a legacy clock provider
+ * @index: index for the clock provider
+ * @mem: iomem pointer for the clock provider memory area
+ *
+ * Initializes a legacy clock provider memory mapping.
+ */
+void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
+{
+       struct clk_iomap *io;
+
+       ti_clk_ll_ops = &omap_clk_ll_ops;
+
+       io = memblock_virt_alloc(sizeof(*io), 0);
+
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
 }
 
 /*
@@ -620,6 +702,9 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
 
        for (i = 0; i < num_clocks; i++) {
                init_clk = clk_get(NULL, clk_names[i]);
+               if (WARN(IS_ERR(init_clk), "could not find init clock %s\n",
+                               clk_names[i]))
+                       continue;
                clk_prepare_enable(init_clk);
        }
 }
@@ -629,21 +714,6 @@ const struct clk_hw_omap_ops clkhwops_wait = {
        .find_companion = omap2_clk_dflt_find_companion,
 };
 
-/**
- * omap_clocks_register - register an array of omap_clk
- * @ocs: pointer to an array of omap_clk to register
- */
-void __init omap_clocks_register(struct omap_clk oclks[], int cnt)
-{
-       struct omap_clk *c;
-
-       for (c = oclks; c < oclks + cnt; c++) {
-               clkdev_add(&c->lk);
-               if (!__clk_init(NULL, c->lk.clk))
-                       omap2_init_clk_hw_omap_clocks(c->lk.clk);
-       }
-}
-
 /**
  * omap2_clk_switch_mpurate_at_boot - switch ARM MPU rate by boot-time argument
  * @mpurate_ck_name: clk name of the clock to change rate