ARM: OMAP2+: clock: add low-level support for regmap
authorTero Kristo <t-kristo@ti.com>
Fri, 6 Feb 2015 14:00:32 +0000 (16:00 +0200)
committerTero Kristo <t-kristo@ti.com>
Tue, 31 Mar 2015 18:26:55 +0000 (21:26 +0300)
Some of the TI clock providers will be converted to use syscon, thus
low-level regmap support is needed for the clock drivers also. This
patch adds this support, which can be enabled for individual drivers
in later patches.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/cm_common.c
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/prm_common.c

index 94080fba02f603e4a50bf801052f58d0db484e03..a699d716930746d4f37bd603be865b248d5986bc 100644 (file)
@@ -23,7 +23,9 @@
 #include <linux/clk-provider.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <linux/regmap.h>
 #include <linux/of_address.h>
+#include <linux/bootmem.h>
 #include <asm/cpu.h>
 
 #include <trace/events/power.h>
@@ -73,20 +75,37 @@ struct ti_clk_features ti_clk_features;
 static bool clkdm_control = true;
 
 static LIST_HEAD(clk_hw_omap_clocks);
-static 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];
 
-       writel_relaxed(val, clk_memmaps[r->index] + r->offset);
+       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];
 
-       return readl_relaxed(clk_memmaps[r->index] + r->offset);
+       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)
@@ -115,18 +134,27 @@ static struct ti_clk_ll_ops omap_clk_ll_ops = {
  * @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
- * @mem: iomem pointer for the clock provider memory area
+ + @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,
-                                  void __iomem *mem)
+                                  struct regmap *syscon, void __iomem *mem)
 {
+       struct clk_iomap *io;
+
        ti_clk_ll_ops = &omap_clk_ll_ops;
 
-       clk_memmaps[index] = mem;
+       io = kzalloc(sizeof(*io), GFP_KERNEL);
+
+       io->regmap = syscon;
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
 
        ti_dt_clk_init_provider(np, index);
 
@@ -142,9 +170,15 @@ int __init omap2_clk_provider_init(struct device_node *np, int index,
  */
 void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
 {
+       struct clk_iomap *io;
+
        ti_clk_ll_ops = &omap_clk_ll_ops;
 
-       clk_memmaps[index] = mem;
+       io = memblock_virt_alloc(sizeof(*io), 0);
+
+       io->mem = mem;
+
+       clk_memmaps[index] = io;
 }
 
 /*
index b6433fc284cee5d67cad4717755c9f324dc018f4..652ed0ab86ec022cffdb55271e3c1e9fb6a78e0c 100644 (file)
@@ -274,8 +274,10 @@ extern const struct clksel_rate div31_1to31_rates[];
 extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 extern void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 
+struct regmap;
+
 int __init omap2_clk_provider_init(struct device_node *np, int index,
-                                  void __iomem *mem);
+                                  struct regmap *syscon, void __iomem *mem);
 void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem);
 
 void __init ti_clk_init_features(void);
index ff24fdfb3bb2fbd735153c83e2bfb4767c85b8eb..23e8bcec34e33c89d7f9f196badb57136db57378 100644 (file)
@@ -361,7 +361,7 @@ int __init omap_cm_init(void)
                if (data->flags & CM_NO_CLOCKS)
                        continue;
 
-               ret = omap2_clk_provider_init(np, data->index, data->mem);
+               ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
                if (ret)
                        return ret;
        }
index 21ff32c6001a4c5e67c385246acd03499a7a0ef4..4b4094685087c6bb3f6d3fc4d178b095e91b7438 100644 (file)
@@ -676,7 +676,7 @@ int __init omap_control_init(void)
        for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
                data = match->data;
 
-               ret = omap2_clk_provider_init(np, data->index, data->mem);
+               ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
                if (ret)
                        return ret;
        }
index 6832a31e9a70ba4b61beae31c8257966ebac8f51..7add7994dbfcf01496eec5182500833ab26cdd5f 100644 (file)
@@ -798,7 +798,7 @@ int __init omap_prcm_init(void)
        for_each_matching_node_and_match(np, omap_prcm_dt_match_table, &match) {
                data = match->data;
 
-               ret = omap2_clk_provider_init(np, data->index, data->mem);
+               ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
                if (ret)
                        return ret;
        }