mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 17:54:13 +08:00
clk: ti: divider: add support for legacy divider init
Legacy clock data is initialized slightly differently compared to DT clocks, thus add support for this. Signed-off-by: Tero Kristo <t-kristo@ti.com> Acked-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Michael Turquette <mturquette@linaro.org>
This commit is contained in:
parent
06524fa428
commit
d96f774b25
@ -214,6 +214,9 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
|
||||
case TI_CLK_MUX:
|
||||
clk = ti_clk_register_mux(setup);
|
||||
break;
|
||||
case TI_CLK_DIVIDER:
|
||||
clk = ti_clk_register_divider(setup);
|
||||
break;
|
||||
case TI_CLK_FIXED_FACTOR:
|
||||
fixed_factor = setup->data;
|
||||
|
||||
|
@ -156,7 +156,9 @@ struct ti_clk_dpll {
|
||||
struct clk *ti_clk_register_gate(struct ti_clk *setup);
|
||||
struct clk *ti_clk_register_interface(struct ti_clk *setup);
|
||||
struct clk *ti_clk_register_mux(struct ti_clk *setup);
|
||||
struct clk *ti_clk_register_divider(struct ti_clk *setup);
|
||||
|
||||
struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup);
|
||||
struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup);
|
||||
struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/clk/ti.h>
|
||||
#include "clock.h"
|
||||
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) "%s: " fmt, __func__
|
||||
@ -300,6 +301,134 @@ static struct clk *_register_divider(struct device *dev, const char *name,
|
||||
return clk;
|
||||
}
|
||||
|
||||
static struct clk_div_table *
|
||||
_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
|
||||
{
|
||||
int valid_div = 0;
|
||||
struct clk_div_table *table;
|
||||
int i;
|
||||
int div;
|
||||
u32 val;
|
||||
u8 flags;
|
||||
|
||||
if (!setup->num_dividers) {
|
||||
/* Clk divider table not provided, determine min/max divs */
|
||||
flags = setup->flags;
|
||||
|
||||
if (flags & CLKF_INDEX_STARTS_AT_ONE)
|
||||
val = 1;
|
||||
else
|
||||
val = 0;
|
||||
|
||||
div = 1;
|
||||
|
||||
while (div < setup->max_div) {
|
||||
if (flags & CLKF_INDEX_POWER_OF_TWO)
|
||||
div <<= 1;
|
||||
else
|
||||
div++;
|
||||
val++;
|
||||
}
|
||||
|
||||
*width = fls(val);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < setup->num_dividers; i++)
|
||||
if (setup->dividers[i])
|
||||
valid_div++;
|
||||
|
||||
table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
|
||||
if (!table)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
valid_div = 0;
|
||||
*width = 0;
|
||||
|
||||
for (i = 0; i < setup->num_dividers; i++)
|
||||
if (setup->dividers[i]) {
|
||||
table[valid_div].div = setup->dividers[i];
|
||||
table[valid_div].val = i;
|
||||
valid_div++;
|
||||
*width = i;
|
||||
}
|
||||
|
||||
*width = fls(*width);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
|
||||
{
|
||||
struct clk_divider *div;
|
||||
struct clk_omap_reg *reg;
|
||||
|
||||
if (!setup)
|
||||
return NULL;
|
||||
|
||||
div = kzalloc(sizeof(*div), GFP_KERNEL);
|
||||
if (!div)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
reg = (struct clk_omap_reg *)&div->reg;
|
||||
reg->index = setup->module;
|
||||
reg->offset = setup->reg;
|
||||
|
||||
if (setup->flags & CLKF_INDEX_STARTS_AT_ONE)
|
||||
div->flags |= CLK_DIVIDER_ONE_BASED;
|
||||
|
||||
if (setup->flags & CLKF_INDEX_POWER_OF_TWO)
|
||||
div->flags |= CLK_DIVIDER_POWER_OF_TWO;
|
||||
|
||||
div->table = _get_div_table_from_setup(setup, &div->width);
|
||||
|
||||
div->shift = setup->bit_shift;
|
||||
|
||||
return &div->hw;
|
||||
}
|
||||
|
||||
struct clk *ti_clk_register_divider(struct ti_clk *setup)
|
||||
{
|
||||
struct ti_clk_divider *div;
|
||||
struct clk_omap_reg *reg_setup;
|
||||
u32 reg;
|
||||
u8 width;
|
||||
u32 flags = 0;
|
||||
u8 div_flags = 0;
|
||||
struct clk_div_table *table;
|
||||
struct clk *clk;
|
||||
|
||||
div = setup->data;
|
||||
|
||||
reg_setup = (struct clk_omap_reg *)®
|
||||
|
||||
reg_setup->index = div->module;
|
||||
reg_setup->offset = div->reg;
|
||||
|
||||
if (div->flags & CLKF_INDEX_STARTS_AT_ONE)
|
||||
div_flags |= CLK_DIVIDER_ONE_BASED;
|
||||
|
||||
if (div->flags & CLKF_INDEX_POWER_OF_TWO)
|
||||
div_flags |= CLK_DIVIDER_POWER_OF_TWO;
|
||||
|
||||
if (div->flags & CLKF_SET_RATE_PARENT)
|
||||
flags |= CLK_SET_RATE_PARENT;
|
||||
|
||||
table = _get_div_table_from_setup(div, &width);
|
||||
if (IS_ERR(table))
|
||||
return (struct clk *)table;
|
||||
|
||||
clk = _register_divider(NULL, setup->name, div->parent,
|
||||
flags, (void __iomem *)reg, div->bit_shift,
|
||||
width, div_flags, table, NULL);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
kfree(table);
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
static struct clk_div_table *
|
||||
__init ti_clk_get_div_table(struct device_node *node)
|
||||
{
|
||||
@ -455,7 +584,8 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
|
||||
goto cleanup;
|
||||
|
||||
clk = _register_divider(NULL, node->name, parent_name, flags, reg,
|
||||
shift, width, clk_divider_flags, table, NULL);
|
||||
shift, width, clk_divider_flags, table,
|
||||
NULL);
|
||||
|
||||
if (!IS_ERR(clk)) {
|
||||
of_clk_add_provider(node, of_clk_src_simple_get, clk);
|
||||
|
Loading…
Reference in New Issue
Block a user