Commit 80cbb224 authored by Tero Kristo's avatar Tero Kristo

ARM: OMAP2+: clock: add low-level support for regmap

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: default avatarTero Kristo <t-kristo@ti.com>
parent 219595b6
...@@ -23,7 +23,9 @@ ...@@ -23,7 +23,9 @@
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/regmap.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/bootmem.h>
#include <asm/cpu.h> #include <asm/cpu.h>
#include <trace/events/power.h> #include <trace/events/power.h>
...@@ -73,20 +75,37 @@ struct ti_clk_features ti_clk_features; ...@@ -73,20 +75,37 @@ struct ti_clk_features ti_clk_features;
static bool clkdm_control = true; static bool clkdm_control = true;
static LIST_HEAD(clk_hw_omap_clocks); 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) static void clk_memmap_writel(u32 val, void __iomem *reg)
{ {
struct clk_omap_reg *r = (struct clk_omap_reg *)&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) static u32 clk_memmap_readl(void __iomem *reg)
{ {
u32 val;
struct clk_omap_reg *r = (struct clk_omap_reg *)&reg; 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) 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 = { ...@@ -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 * @match_table: DT device table to match for devices to init
* @np: device node pointer for the this clock provider * @np: device node pointer for the this clock provider
* @index: index for the 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 * Initializes a clock provider module (CM/PRM etc.), registering
* the memory mapping at specified index and initializing the * the memory mapping at specified index and initializing the
* low level driver infrastructure. Returns 0 in success. * low level driver infrastructure. Returns 0 in success.
*/ */
int __init omap2_clk_provider_init(struct device_node *np, int index, 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; 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); ti_dt_clk_init_provider(np, index);
...@@ -142,9 +170,15 @@ int __init omap2_clk_provider_init(struct device_node *np, int 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) void __init omap2_clk_legacy_provider_init(int index, void __iomem *mem)
{ {
struct clk_iomap *io;
ti_clk_ll_ops = &omap_clk_ll_ops; 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;
} }
/* /*
......
...@@ -274,8 +274,10 @@ extern const struct clksel_rate div31_1to31_rates[]; ...@@ -274,8 +274,10 @@ extern const struct clksel_rate div31_1to31_rates[];
extern int omap2_clkops_enable_clkdm(struct clk_hw *hw); extern int omap2_clkops_enable_clkdm(struct clk_hw *hw);
extern void omap2_clkops_disable_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, 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 omap2_clk_legacy_provider_init(int index, void __iomem *mem);
void __init ti_clk_init_features(void); void __init ti_clk_init_features(void);
......
...@@ -361,7 +361,7 @@ int __init omap_cm_init(void) ...@@ -361,7 +361,7 @@ int __init omap_cm_init(void)
if (data->flags & CM_NO_CLOCKS) if (data->flags & CM_NO_CLOCKS)
continue; continue;
ret = omap2_clk_provider_init(np, data->index, data->mem); ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
if (ret) if (ret)
return ret; return ret;
} }
......
...@@ -676,7 +676,7 @@ int __init omap_control_init(void) ...@@ -676,7 +676,7 @@ int __init omap_control_init(void)
for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) { for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
data = match->data; 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) if (ret)
return ret; return ret;
} }
......
...@@ -798,7 +798,7 @@ int __init omap_prcm_init(void) ...@@ -798,7 +798,7 @@ int __init omap_prcm_init(void)
for_each_matching_node_and_match(np, omap_prcm_dt_match_table, &match) { for_each_matching_node_and_match(np, omap_prcm_dt_match_table, &match) {
data = match->data; 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) if (ret)
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment