Commit 16a9013b authored by Naveen Krishna Ch's avatar Naveen Krishna Ch Committed by Sylwester Nawrocki

clk: samsung: Factor out the common code to clk.c

While adding clock support for Exynos5260, the infrastructure to
register multiple clock controllers was introduced. Factor out the
support for registering multiple clock controller from Exynos5260
clock code to common samsung clock code so that it can be used by
other Exynos SoC which have multiple clock controllers.
Signed-off-by: default avatarNaveen Krishna Ch <naveenkrishna.ch@gmail.com>
Signed-off-by: default avatarAbhilash Kesavan <a.kesavan@samsung.com>
Reviewed-by: default avatarThomas Abraham <thomas.ab@samsung.com>
Tested-by: default avatarThomas Abraham <thomas.ab@samsung.com>
Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
parent 0c23e2af
This diff is collapsed.
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/syscore_ops.h> #include <linux/syscore_ops.h>
#include "clk.h" #include "clk.h"
static LIST_HEAD(clock_reg_cache_list);
void samsung_clk_save(void __iomem *base, void samsung_clk_save(void __iomem *base,
struct samsung_clk_reg_dump *rd, struct samsung_clk_reg_dump *rd,
unsigned int num_regs) unsigned int num_regs)
...@@ -313,3 +315,96 @@ unsigned long _get_rate(const char *clk_name) ...@@ -313,3 +315,96 @@ unsigned long _get_rate(const char *clk_name)
return clk_get_rate(clk); return clk_get_rate(clk);
} }
#ifdef CONFIG_PM_SLEEP
static int samsung_clk_suspend(void)
{
struct samsung_clock_reg_cache *reg_cache;
list_for_each_entry(reg_cache, &clock_reg_cache_list, node)
samsung_clk_save(reg_cache->reg_base, reg_cache->rdump,
reg_cache->rd_num);
return 0;
}
static void samsung_clk_resume(void)
{
struct samsung_clock_reg_cache *reg_cache;
list_for_each_entry(reg_cache, &clock_reg_cache_list, node)
samsung_clk_restore(reg_cache->reg_base, reg_cache->rdump,
reg_cache->rd_num);
}
static struct syscore_ops samsung_clk_syscore_ops = {
.suspend = samsung_clk_suspend,
.resume = samsung_clk_resume,
};
static void samsung_clk_sleep_init(void __iomem *reg_base,
const unsigned long *rdump,
unsigned long nr_rdump)
{
struct samsung_clock_reg_cache *reg_cache;
reg_cache = kzalloc(sizeof(struct samsung_clock_reg_cache),
GFP_KERNEL);
if (!reg_cache)
panic("could not allocate register reg_cache.\n");
reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump);
if (!reg_cache->rdump)
panic("could not allocate register dump storage.\n");
if (list_empty(&clock_reg_cache_list))
register_syscore_ops(&samsung_clk_syscore_ops);
reg_cache->reg_base = reg_base;
reg_cache->rd_num = nr_rdump;
list_add_tail(&reg_cache->node, &clock_reg_cache_list);
}
#else
static void samsung_clk_sleep_init(void __iomem *reg_base,
const unsigned long *rdump,
unsigned long nr_rdump) {}
#endif
/*
* Common function which registers plls, muxes, dividers and gates
* for each CMU. It also add CMU register list to register cache.
*/
void __init samsung_cmu_register_one(struct device_node *np,
struct samsung_cmu_info *cmu)
{
void __iomem *reg_base;
struct samsung_clk_provider *ctx;
reg_base = of_iomap(np, 0);
if (!reg_base)
panic("%s: failed to map registers\n", __func__);
ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids);
if (!ctx)
panic("%s: unable to alllocate ctx\n", __func__);
if (cmu->pll_clks)
samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks,
reg_base);
if (cmu->mux_clks)
samsung_clk_register_mux(ctx, cmu->mux_clks,
cmu->nr_mux_clks);
if (cmu->div_clks)
samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks);
if (cmu->gate_clks)
samsung_clk_register_gate(ctx, cmu->gate_clks,
cmu->nr_gate_clks);
if (cmu->fixed_clks)
samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks,
cmu->nr_fixed_clks);
if (cmu->clk_regs)
samsung_clk_sleep_init(reg_base, cmu->clk_regs,
cmu->nr_clk_regs);
samsung_clk_of_add_provider(np, ctx);
}
...@@ -324,6 +324,37 @@ struct samsung_pll_clock { ...@@ -324,6 +324,37 @@ struct samsung_pll_clock {
__PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \
_lock, _con, _rtable, _alias) _lock, _con, _rtable, _alias)
struct samsung_clock_reg_cache {
struct list_head node;
void __iomem *reg_base;
struct samsung_clk_reg_dump *rdump;
unsigned int rd_num;
};
struct samsung_cmu_info {
/* list of pll clocks and respective count */
struct samsung_pll_clock *pll_clks;
unsigned int nr_pll_clks;
/* list of mux clocks and respective count */
struct samsung_mux_clock *mux_clks;
unsigned int nr_mux_clks;
/* list of div clocks and respective count */
struct samsung_div_clock *div_clks;
unsigned int nr_div_clks;
/* list of gate clocks and respective count */
struct samsung_gate_clock *gate_clks;
unsigned int nr_gate_clks;
/* list of fixed clocks and respective count */
struct samsung_fixed_rate_clock *fixed_clks;
unsigned int nr_fixed_clks;
/* total number of clocks with IDs assigned*/
unsigned int nr_clk_ids;
/* list and number of clocks registers */
unsigned long *clk_regs;
unsigned int nr_clk_regs;
};
extern struct samsung_clk_provider *__init samsung_clk_init( extern struct samsung_clk_provider *__init samsung_clk_init(
struct device_node *np, void __iomem *base, struct device_node *np, void __iomem *base,
unsigned long nr_clks); unsigned long nr_clks);
...@@ -362,6 +393,9 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, ...@@ -362,6 +393,9 @@ extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx,
struct samsung_pll_clock *pll_list, struct samsung_pll_clock *pll_list,
unsigned int nr_clk, void __iomem *base); unsigned int nr_clk, void __iomem *base);
extern void __init samsung_cmu_register_one(struct device_node *,
struct samsung_cmu_info *);
extern unsigned long _get_rate(const char *clk_name); extern unsigned long _get_rate(const char *clk_name);
extern void samsung_clk_save(void __iomem *base, extern void samsung_clk_save(void __iomem *base,
......
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