clk: ti: divider: add driver internal API for parsing divider data
This can be used from the divider itself, and also from the clkctrl clocks once this is introduced. Signed-off-by: Tero Kristo <t-kristo@ti.com> Acked-by: Tony Lindgren <tony@atomide.com>
This commit is contained in:
Родитель
6dbde94756
Коммит
4f6be5655d
|
@ -220,6 +220,10 @@ 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_gate(struct ti_clk_gate *setup);
|
||||||
struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
|
struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
|
||||||
|
|
||||||
|
int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
|
||||||
|
u8 flags, u8 *width,
|
||||||
|
const struct clk_div_table **table);
|
||||||
|
|
||||||
void ti_clk_patch_legacy_clks(struct ti_clk **patch);
|
void ti_clk_patch_legacy_clks(struct ti_clk **patch);
|
||||||
struct clk *ti_clk_register_clk(struct ti_clk *setup);
|
struct clk *ti_clk_register_clk(struct ti_clk *setup);
|
||||||
int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
|
int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
|
||||||
|
|
|
@ -319,20 +319,17 @@ static struct clk *_register_divider(struct device *dev, const char *name,
|
||||||
return clk;
|
return clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct clk_div_table *
|
int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
|
||||||
_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
|
u8 flags, u8 *width,
|
||||||
|
const struct clk_div_table **table)
|
||||||
{
|
{
|
||||||
int valid_div = 0;
|
int valid_div = 0;
|
||||||
struct clk_div_table *table;
|
|
||||||
int i;
|
|
||||||
int div;
|
|
||||||
u32 val;
|
u32 val;
|
||||||
u8 flags;
|
int div;
|
||||||
|
int i;
|
||||||
if (!setup->num_dividers) {
|
struct clk_div_table *tmp;
|
||||||
/* Clk divider table not provided, determine min/max divs */
|
|
||||||
flags = setup->flags;
|
|
||||||
|
|
||||||
|
if (!div_table) {
|
||||||
if (flags & CLKF_INDEX_STARTS_AT_ONE)
|
if (flags & CLKF_INDEX_STARTS_AT_ONE)
|
||||||
val = 1;
|
val = 1;
|
||||||
else
|
else
|
||||||
|
@ -340,7 +337,7 @@ _get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
|
||||||
|
|
||||||
div = 1;
|
div = 1;
|
||||||
|
|
||||||
while (div < setup->max_div) {
|
while (div < max_div) {
|
||||||
if (flags & CLKF_INDEX_POWER_OF_TWO)
|
if (flags & CLKF_INDEX_POWER_OF_TWO)
|
||||||
div <<= 1;
|
div <<= 1;
|
||||||
else
|
else
|
||||||
|
@ -349,30 +346,52 @@ _get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
|
||||||
}
|
}
|
||||||
|
|
||||||
*width = fls(val);
|
*width = fls(val);
|
||||||
|
*table = NULL;
|
||||||
|
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < setup->num_dividers; i++)
|
i = 0;
|
||||||
if (setup->dividers[i])
|
|
||||||
valid_div++;
|
|
||||||
|
|
||||||
table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
|
while (!num_dividers || i < num_dividers) {
|
||||||
if (!table)
|
if (div_table[i] == -1)
|
||||||
return ERR_PTR(-ENOMEM);
|
break;
|
||||||
|
if (div_table[i])
|
||||||
|
valid_div++;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_dividers = i;
|
||||||
|
|
||||||
|
tmp = kzalloc(sizeof(*tmp) * (valid_div + 1), GFP_KERNEL);
|
||||||
|
if (!tmp)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
valid_div = 0;
|
valid_div = 0;
|
||||||
*width = 0;
|
*width = 0;
|
||||||
|
|
||||||
for (i = 0; i < setup->num_dividers; i++)
|
for (i = 0; i < num_dividers; i++)
|
||||||
if (setup->dividers[i]) {
|
if (div_table[i] > 0) {
|
||||||
table[valid_div].div = setup->dividers[i];
|
tmp[valid_div].div = div_table[i];
|
||||||
table[valid_div].val = i;
|
tmp[valid_div].val = i;
|
||||||
valid_div++;
|
valid_div++;
|
||||||
*width = i;
|
*width = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
*width = fls(*width);
|
*width = fls(*width);
|
||||||
|
*table = tmp;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clk_div_table *
|
||||||
|
_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
|
||||||
|
{
|
||||||
|
const struct clk_div_table *table = NULL;
|
||||||
|
|
||||||
|
ti_clk_parse_divider_data(setup->dividers, setup->num_dividers,
|
||||||
|
setup->max_div, setup->flags, width,
|
||||||
|
&table);
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
@ -414,7 +433,7 @@ struct clk *ti_clk_register_divider(struct ti_clk *setup)
|
||||||
u8 width;
|
u8 width;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
u8 div_flags = 0;
|
u8 div_flags = 0;
|
||||||
struct clk_div_table *table;
|
const struct clk_div_table *table;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
div = setup->data;
|
div = setup->data;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче