mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-15 05:11:32 +00:00
clk: tegra: Add super clock mux/divider
Add a super clock type which implements both mux and divider. This is used for aclk. Signed-off-by: Peter De Schrijver <pdeschrijver@nvidia.com> Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com> Tested-by: Mikko Perttunen <mperttunen@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
6cfc8bc9ee
commit
e827ba1840
@ -121,9 +121,50 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct clk_ops tegra_clk_super_mux_ops = {
|
||||||
|
.get_parent = clk_super_get_parent,
|
||||||
|
.set_parent = clk_super_set_parent,
|
||||||
|
};
|
||||||
|
|
||||||
|
static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *parent_rate)
|
||||||
|
{
|
||||||
|
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
|
||||||
|
struct clk_hw *div_hw = &super->frac_div.hw;
|
||||||
|
|
||||||
|
__clk_hw_set_clk(div_hw, hw);
|
||||||
|
|
||||||
|
return super->div_ops->round_rate(div_hw, rate, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long clk_super_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
|
||||||
|
struct clk_hw *div_hw = &super->frac_div.hw;
|
||||||
|
|
||||||
|
__clk_hw_set_clk(div_hw, hw);
|
||||||
|
|
||||||
|
return super->div_ops->recalc_rate(div_hw, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
|
||||||
|
struct clk_hw *div_hw = &super->frac_div.hw;
|
||||||
|
|
||||||
|
__clk_hw_set_clk(div_hw, hw);
|
||||||
|
|
||||||
|
return super->div_ops->set_rate(div_hw, rate, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
const struct clk_ops tegra_clk_super_ops = {
|
const struct clk_ops tegra_clk_super_ops = {
|
||||||
.get_parent = clk_super_get_parent,
|
.get_parent = clk_super_get_parent,
|
||||||
.set_parent = clk_super_set_parent,
|
.set_parent = clk_super_set_parent,
|
||||||
|
.set_rate = clk_super_set_rate,
|
||||||
|
.round_rate = clk_super_round_rate,
|
||||||
|
.recalc_rate = clk_super_recalc_rate,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clk *tegra_clk_register_super_mux(const char *name,
|
struct clk *tegra_clk_register_super_mux(const char *name,
|
||||||
@ -136,13 +177,11 @@ struct clk *tegra_clk_register_super_mux(const char *name,
|
|||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
|
|
||||||
super = kzalloc(sizeof(*super), GFP_KERNEL);
|
super = kzalloc(sizeof(*super), GFP_KERNEL);
|
||||||
if (!super) {
|
if (!super)
|
||||||
pr_err("%s: could not allocate super clk\n", __func__);
|
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
|
||||||
|
|
||||||
init.name = name;
|
init.name = name;
|
||||||
init.ops = &tegra_clk_super_ops;
|
init.ops = &tegra_clk_super_mux_ops;
|
||||||
init.flags = flags;
|
init.flags = flags;
|
||||||
init.parent_names = parent_names;
|
init.parent_names = parent_names;
|
||||||
init.num_parents = num_parents;
|
init.num_parents = num_parents;
|
||||||
@ -163,3 +202,43 @@ struct clk *tegra_clk_register_super_mux(const char *name,
|
|||||||
|
|
||||||
return clk;
|
return clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct clk *tegra_clk_register_super_clk(const char *name,
|
||||||
|
const char * const *parent_names, u8 num_parents,
|
||||||
|
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
||||||
|
spinlock_t *lock)
|
||||||
|
{
|
||||||
|
struct tegra_clk_super_mux *super;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk_init_data init;
|
||||||
|
|
||||||
|
super = kzalloc(sizeof(*super), GFP_KERNEL);
|
||||||
|
if (!super)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
init.name = name;
|
||||||
|
init.ops = &tegra_clk_super_ops;
|
||||||
|
init.flags = flags;
|
||||||
|
init.parent_names = parent_names;
|
||||||
|
init.num_parents = num_parents;
|
||||||
|
|
||||||
|
super->reg = reg;
|
||||||
|
super->lock = lock;
|
||||||
|
super->width = 4;
|
||||||
|
super->flags = clk_super_flags;
|
||||||
|
super->frac_div.reg = reg + 4;
|
||||||
|
super->frac_div.shift = 16;
|
||||||
|
super->frac_div.width = 8;
|
||||||
|
super->frac_div.frac_width = 1;
|
||||||
|
super->frac_div.lock = lock;
|
||||||
|
super->div_ops = &tegra_clk_frac_div_ops;
|
||||||
|
|
||||||
|
/* Data in .init is copied by clk_register(), so stack variable OK */
|
||||||
|
super->hw.init = &init;
|
||||||
|
|
||||||
|
clk = clk_register(NULL, &super->hw);
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
kfree(super);
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
}
|
||||||
|
@ -686,6 +686,8 @@ struct tegra_periph_init_data {
|
|||||||
struct tegra_clk_super_mux {
|
struct tegra_clk_super_mux {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
void __iomem *reg;
|
void __iomem *reg;
|
||||||
|
struct tegra_clk_frac_div frac_div;
|
||||||
|
const struct clk_ops *div_ops;
|
||||||
u8 width;
|
u8 width;
|
||||||
u8 flags;
|
u8 flags;
|
||||||
u8 div2_index;
|
u8 div2_index;
|
||||||
@ -702,7 +704,10 @@ struct clk *tegra_clk_register_super_mux(const char *name,
|
|||||||
const char **parent_names, u8 num_parents,
|
const char **parent_names, u8 num_parents,
|
||||||
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
||||||
u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock);
|
u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock);
|
||||||
|
struct clk *tegra_clk_register_super_clk(const char *name,
|
||||||
|
const char * const *parent_names, u8 num_parents,
|
||||||
|
unsigned long flags, void __iomem *reg, u8 clk_super_flags,
|
||||||
|
spinlock_t *lock);
|
||||||
/**
|
/**
|
||||||
* struct clk_init_table - clock initialization table
|
* struct clk_init_table - clock initialization table
|
||||||
* @clk_id: clock id as mentioned in device tree bindings
|
* @clk_id: clock id as mentioned in device tree bindings
|
||||||
|
Loading…
Reference in New Issue
Block a user