Commit f6fba5f6 authored by Heiko Stuebner's avatar Heiko Stuebner

clk: rockchip: add new clock-type for the cpuclk

When changing the armclk on Rockchip SoCs it is supposed to be reparented
to an alternate parent before changing the underlying pll and back after
the change. Additionally there exist clocks that are very tightly bound to
the armclk whose divider values are set according to the armclk rate.

Add a special clock-type to handle all that. The rate table and divider
values will be supplied from the soc-specific clock controllers.
Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
Reviewed-by: default avatarDoug Anderson <dianders@chromium.org>
On a rk3288-board:
Tested-by: default avatarDoug Anderson <dianders@chromium.org>
parent 2b9bceea
......@@ -5,6 +5,7 @@
obj-y += clk-rockchip.o
obj-y += clk.o
obj-y += clk-pll.o
obj-y += clk-cpu.o
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
obj-y += clk-rk3188.o
......
This diff is collapsed.
......@@ -297,6 +297,27 @@ void __init rockchip_clk_register_branches(
}
}
void __init rockchip_clk_register_armclk(unsigned int lookup_id,
const char *name, const char **parent_names,
u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
int nrates)
{
struct clk *clk;
clk = rockchip_clk_register_cpuclk(name, parent_names, num_parents,
reg_data, rates, nrates, reg_base,
&clk_lock);
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s: %ld\n",
__func__, name, PTR_ERR(clk));
return;
}
rockchip_clk_add_lookup(clk, lookup_id);
}
void __init rockchip_clk_protect_critical(const char *clocks[], int nclocks)
{
int i;
......
......@@ -120,6 +120,38 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
struct rockchip_pll_rate_table *rate_table,
spinlock_t *lock);
struct rockchip_cpuclk_clksel {
int reg;
u32 val;
};
#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 2
struct rockchip_cpuclk_rate_table {
unsigned long prate;
struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
};
/**
* struct rockchip_cpuclk_reg_data: describes register offsets and masks of the cpuclock
* @core_reg: register offset of the core settings register
* @div_core_shift: core divider offset used to divide the pll value
* @div_core_mask: core divider mask
* @mux_core_shift: offset of the core multiplexer
*/
struct rockchip_cpuclk_reg_data {
int core_reg;
u8 div_core_shift;
u32 div_core_mask;
int mux_core_reg;
u8 mux_core_shift;
};
struct clk *rockchip_clk_register_cpuclk(const char *name,
const char **parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
int nrates, void __iomem *reg_base, spinlock_t *lock);
#define PNAME(x) static const char *x[] __initconst
enum rockchip_clk_branch_type {
......@@ -329,6 +361,11 @@ void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list,
unsigned int nr_clk);
void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list,
unsigned int nr_pll, int grf_lock_offset);
void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
const char **parent_names, u8 num_parents,
const struct rockchip_cpuclk_reg_data *reg_data,
const struct rockchip_cpuclk_rate_table *rates,
int nrates);
void rockchip_clk_protect_critical(const char *clocks[], int nclocks);
#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
......
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