Skip to content

Commit 4a1ae04

Browse files
tlebbebarino
authored andcommitted
clk: eyeq: add fixed factor clocks infrastructure
Driver can currently host two types of clocks: - PLLs derived directly from the main crystal (taken using a fwhandle). - Divider clocks derived from those PLLs. PLLs can be instantiated from of_clk_init() or platform device probe, using two separate clock providers. Divider clocks are all instantiated at platform device probe. Add a third type of clocks: fixed factors. Those can be instantiated at both stages. They can be parented to any clock from the driver. Early match data and match data store the list of fixed factor clocks. Signed-off-by: Théo Lebrun <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent d75fbc8 commit 4a1ae04

File tree

1 file changed

+73
-8
lines changed

1 file changed

+73
-8
lines changed

drivers/clk/clk-eyeq.c

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
/*
33
* PLL clock driver for the Mobileye EyeQ5, EyeQ6L and EyeQ6H platforms.
44
*
5-
* This controller handles read-only PLLs, all derived from the same main
6-
* crystal clock. It also exposes divider clocks, those are children to PLLs.
7-
* Parent clock is expected to be constant. This driver's registers live in
8-
* a shared region called OLB. Some PLLs are initialised early by of_clk_init();
9-
* if so, two clk providers are registered.
5+
* This controller handles:
6+
* - Read-only PLLs, all derived from the same main crystal clock.
7+
* - It also exposes divider clocks, those are children to PLLs.
8+
* - Fixed factor clocks, children to PLLs.
9+
*
10+
* Parent clock is expected to be constant. This driver's registers live in a
11+
* shared region called OLB. Some PLLs and fixed-factors are initialised early
12+
* by of_clk_init(); if so, two clk providers are registered.
1013
*
1114
* We use eqc_ as prefix, as-in "EyeQ Clock", but way shorter.
1215
*
@@ -86,13 +89,24 @@ struct eqc_div {
8689
u8 width;
8790
};
8891

92+
struct eqc_fixed_factor {
93+
unsigned int index;
94+
const char *name;
95+
unsigned int mult;
96+
unsigned int div;
97+
unsigned int parent;
98+
};
99+
89100
struct eqc_match_data {
90101
unsigned int pll_count;
91102
const struct eqc_pll *plls;
92103

93104
unsigned int div_count;
94105
const struct eqc_div *divs;
95106

107+
unsigned int fixed_factor_count;
108+
const struct eqc_fixed_factor *fixed_factors;
109+
96110
const char *reset_auxdev_name;
97111
const char *pinctrl_auxdev_name;
98112

@@ -103,6 +117,9 @@ struct eqc_early_match_data {
103117
unsigned int early_pll_count;
104118
const struct eqc_pll *early_plls;
105119

120+
unsigned int early_fixed_factor_count;
121+
const struct eqc_fixed_factor *early_fixed_factors;
122+
106123
/*
107124
* We want our of_xlate callback to EPROBE_DEFER instead of dev_err()
108125
* and EINVAL. For that, we must know the total clock count.
@@ -276,6 +293,35 @@ static void eqc_probe_init_divs(struct device *dev, const struct eqc_match_data
276293
}
277294
}
278295

296+
static void eqc_probe_init_fixed_factors(struct device *dev,
297+
const struct eqc_match_data *data,
298+
struct clk_hw_onecell_data *cells)
299+
{
300+
const struct eqc_fixed_factor *ff;
301+
struct clk_hw *hw, *parent_hw;
302+
unsigned int i;
303+
304+
for (i = 0; i < data->fixed_factor_count; i++) {
305+
ff = &data->fixed_factors[i];
306+
parent_hw = cells->hws[ff->parent];
307+
308+
if (IS_ERR(parent_hw)) {
309+
/* Parent is in early clk provider. */
310+
hw = clk_hw_register_fixed_factor_index(dev, ff->name,
311+
ff->parent, 0, ff->mult, ff->div);
312+
} else {
313+
/* Avoid clock lookup when we already have the hw reference. */
314+
hw = clk_hw_register_fixed_factor_parent_hw(dev, ff->name,
315+
parent_hw, 0, ff->mult, ff->div);
316+
}
317+
318+
cells->hws[ff->index] = hw;
319+
if (IS_ERR(hw))
320+
dev_warn(dev, "failed registering %s: %pe\n",
321+
ff->name, hw);
322+
}
323+
}
324+
279325
static void eqc_auxdev_release(struct device *dev)
280326
{
281327
struct auxiliary_device *adev = to_auxiliary_dev(dev);
@@ -349,10 +395,11 @@ static int eqc_probe(struct platform_device *pdev)
349395
KBUILD_MODNAME, data->pinctrl_auxdev_name, ret);
350396
}
351397

352-
if (data->pll_count + data->div_count == 0)
398+
if (data->pll_count + data->div_count + data->fixed_factor_count == 0)
353399
return 0; /* Zero clocks, we are done. */
354400

355-
clk_count = data->pll_count + data->div_count + data->early_clk_count;
401+
clk_count = data->pll_count + data->div_count +
402+
data->fixed_factor_count + data->early_clk_count;
356403
cells = kzalloc(struct_size(cells, hws, clk_count), GFP_KERNEL);
357404
if (!cells)
358405
return -ENOMEM;
@@ -367,6 +414,8 @@ static int eqc_probe(struct platform_device *pdev)
367414

368415
eqc_probe_init_divs(dev, data, base, cells);
369416

417+
eqc_probe_init_fixed_factors(dev, data, cells);
418+
370419
return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, cells);
371420
}
372421

@@ -580,7 +629,8 @@ static void __init eqc_early_init(struct device_node *np,
580629
void __iomem *base;
581630
int ret;
582631

583-
clk_count = early_data->early_pll_count + early_data->late_clk_count;
632+
clk_count = early_data->early_pll_count + early_data->early_fixed_factor_count +
633+
early_data->late_clk_count;
584634
cells = kzalloc(struct_size(cells, hws, clk_count), GFP_KERNEL);
585635
if (!cells) {
586636
ret = -ENOMEM;
@@ -633,6 +683,21 @@ static void __init eqc_early_init(struct device_node *np,
633683
}
634684
}
635685

686+
for (i = 0; i < early_data->early_fixed_factor_count; i++) {
687+
const struct eqc_fixed_factor *ff = &early_data->early_fixed_factors[i];
688+
struct clk_hw *parent_hw = cells->hws[ff->parent];
689+
struct clk_hw *hw;
690+
691+
hw = clk_hw_register_fixed_factor_parent_hw(NULL, ff->name,
692+
parent_hw, 0, ff->mult, ff->div);
693+
cells->hws[ff->index] = hw;
694+
if (IS_ERR(hw)) {
695+
pr_err("failed registering %s: %pe\n", ff->name, hw);
696+
ret = PTR_ERR(hw);
697+
goto err;
698+
}
699+
}
700+
636701
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, cells);
637702
if (ret) {
638703
pr_err("failed registering clk provider: %d\n", ret);

0 commit comments

Comments
 (0)