Skip to content

Commit fc0c209

Browse files
committed
clk: Allow parents to be specified without string names
The common clk framework is lacking in ability to describe the clk topology without specifying strings for every possible parent-child link. There are a few drawbacks to the current approach: 1) String comparisons are used for everything, including describing topologies that are 'local' to a single clock controller. 2) clk providers (e.g. i2c clk drivers) need to create globally unique clk names to avoid collisions in the clk namespace, leading to awkward name generation code in various clk drivers. 3) DT bindings may not fully describe the clk topology and linkages between clk controllers because drivers can easily rely on globally unique strings to describe connections between clks. This leads to confusing DT bindings, complicated clk name generation code, and inefficient string comparisons during clk registration just so that the clk framework can detect the topology of the clk tree. Furthermore, some drivers call clk_get() and then __clk_get_name() to extract the globally unique clk name just so they can specify the parent of the clk they're registering. We have of_clk_parent_fill() but that mostly only works for single clks registered from a DT node, which isn't the norm. Let's simplify this all by introducing two new ways of specifying clk parents. The first method is an array of pointers to clk_hw structures corresponding to the parents at that index. This works for clks that are registered when we have access to all the clk_hw pointers for the parents. The second method is a mix of clk_hw pointers and strings of local and global parent clk names. If the .fw_name member of the map is set we'll look for that clk by performing a DT based lookup of the device the clk is registered with and the .name specified in the map. If that fails, we'll fallback to the .name member and perform a global clk name lookup like we've always done before. Using either one of these new methods is entirely optional. Existing drivers will continue to work, and they can migrate to this new approach as they see fit. Eventually, we'll want to get rid of the 'parent_names' array in struct clk_init_data and use one of these new methods instead. Cc: Miquel Raynal <miquel.raynal@bootlin.com> Cc: Jerome Brunet <jbrunet@baylibre.com> Cc: Russell King <linux@armlinux.org.uk> Cc: Michael Turquette <mturquette@baylibre.com> Cc: Jeffrey Hugo <jhugo@codeaurora.org> Cc: Chen-Yu Tsai <wens@csie.org> Cc: Rob Herring <robh@kernel.org> Tested-by: Jeffrey Hugo <jhugo@codeaurora.org> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent 89a5ddc commit fc0c209

File tree

2 files changed

+219
-62
lines changed

2 files changed

+219
-62
lines changed

drivers/clk/clk.c

Lines changed: 200 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ static LIST_HEAD(clk_notifier_list);
3939

4040
/*** private data structures ***/
4141

42+
struct clk_parent_map {
43+
const struct clk_hw *hw;
44+
struct clk_core *core;
45+
const char *fw_name;
46+
const char *name;
47+
};
48+
4249
struct clk_core {
4350
const char *name;
4451
const struct clk_ops *ops;
@@ -47,8 +54,7 @@ struct clk_core {
4754
struct device *dev;
4855
struct device_node *of_node;
4956
struct clk_core *parent;
50-
const char **parent_names;
51-
struct clk_core **parents;
57+
struct clk_parent_map *parents;
5258
u8 num_parents;
5359
u8 new_parent_index;
5460
unsigned long rate;
@@ -317,17 +323,92 @@ static struct clk_core *clk_core_lookup(const char *name)
317323
return NULL;
318324
}
319325

326+
/**
327+
* clk_core_get - Find the parent of a clk using a clock specifier in DT
328+
* @core: clk to find parent of
329+
* @name: name to search for in 'clock-names' of device providing clk
330+
*
331+
* This is the preferred method for clk providers to find the parent of a
332+
* clk when that parent is external to the clk controller. The parent_names
333+
* array is indexed and treated as a local name matching a string in the device
334+
* node's 'clock-names' property. This allows clk providers to use their own
335+
* namespace instead of looking for a globally unique parent string.
336+
*
337+
* For example the following DT snippet would allow a clock registered by the
338+
* clock-controller@c001 that has a clk_init_data::parent_data array
339+
* with 'xtal' in the 'name' member to find the clock provided by the
340+
* clock-controller@f00abcd without needing to get the globally unique name of
341+
* the xtal clk.
342+
*
343+
* parent: clock-controller@f00abcd {
344+
* reg = <0xf00abcd 0xabcd>;
345+
* #clock-cells = <0>;
346+
* };
347+
*
348+
* clock-controller@c001 {
349+
* reg = <0xc001 0xf00d>;
350+
* clocks = <&parent>;
351+
* clock-names = "xtal";
352+
* #clock-cells = <1>;
353+
* };
354+
*
355+
* Returns: -ENOENT when the provider can't be found or the clk doesn't
356+
* exist in the provider. -EINVAL when the name can't be found. NULL when the
357+
* provider knows about the clk but it isn't provided on this system.
358+
* A valid clk_core pointer when the clk can be found in the provider.
359+
*/
360+
static struct clk_core *clk_core_get(struct clk_core *core, const char *name)
361+
{
362+
struct clk_hw *hw;
363+
struct device_node *np = core->of_node;
364+
365+
if (!np)
366+
return ERR_PTR(-ENOENT);
367+
368+
/* TODO: Support clkdev clk_lookups */
369+
hw = of_clk_get_hw(np, -1, name);
370+
if (IS_ERR_OR_NULL(hw))
371+
return ERR_CAST(hw);
372+
373+
return hw->core;
374+
}
375+
376+
static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
377+
{
378+
struct clk_parent_map *entry = &core->parents[index];
379+
struct clk_core *parent = ERR_PTR(-ENOENT);
380+
381+
if (entry->hw) {
382+
parent = entry->hw->core;
383+
/*
384+
* We have a direct reference but it isn't registered yet?
385+
* Orphan it and let clk_reparent() update the orphan status
386+
* when the parent is registered.
387+
*/
388+
if (!parent)
389+
parent = ERR_PTR(-EPROBE_DEFER);
390+
} else {
391+
if (entry->fw_name)
392+
parent = clk_core_get(core, entry->fw_name);
393+
if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT)
394+
parent = clk_core_lookup(entry->name);
395+
}
396+
397+
/* Only cache it if it's not an error */
398+
if (!IS_ERR(parent))
399+
entry->core = parent;
400+
}
401+
320402
static struct clk_core *clk_core_get_parent_by_index(struct clk_core *core,
321403
u8 index)
322404
{
323-
if (!core || index >= core->num_parents)
405+
if (!core || index >= core->num_parents || !core->parents)
324406
return NULL;
325407

326-
if (!core->parents[index])
327-
core->parents[index] =
328-
clk_core_lookup(core->parent_names[index]);
408+
if (!core->parents[index].core)
409+
clk_core_fill_parent_index(core, index);
329410

330-
return core->parents[index];
411+
return core->parents[index].core;
331412
}
332413

333414
struct clk_hw *
@@ -1520,15 +1601,15 @@ static int clk_fetch_parent_index(struct clk_core *core,
15201601
return -EINVAL;
15211602

15221603
for (i = 0; i < core->num_parents; i++) {
1523-
if (core->parents[i] == parent)
1604+
if (core->parents[i].core == parent)
15241605
return i;
15251606

1526-
if (core->parents[i])
1607+
if (core->parents[i].core)
15271608
continue;
15281609

15291610
/* Fallback to comparing globally unique names */
1530-
if (!strcmp(parent->name, core->parent_names[i])) {
1531-
core->parents[i] = parent;
1611+
if (!strcmp(parent->name, core->parents[i].name)) {
1612+
core->parents[i].core = parent;
15321613
return i;
15331614
}
15341615
}
@@ -2294,6 +2375,7 @@ void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
22942375
bool clk_has_parent(struct clk *clk, struct clk *parent)
22952376
{
22962377
struct clk_core *core, *parent_core;
2378+
int i;
22972379

22982380
/* NULL clocks should be nops, so return success if either is NULL. */
22992381
if (!clk || !parent)
@@ -2306,8 +2388,11 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
23062388
if (core->parent == parent_core)
23072389
return true;
23082390

2309-
return match_string(core->parent_names, core->num_parents,
2310-
parent_core->name) >= 0;
2391+
for (i = 0; i < core->num_parents; i++)
2392+
if (!strcmp(core->parents[i].name, parent_core->name))
2393+
return true;
2394+
2395+
return false;
23112396
}
23122397
EXPORT_SYMBOL_GPL(clk_has_parent);
23132398

@@ -2890,9 +2975,9 @@ static int possible_parents_show(struct seq_file *s, void *data)
28902975
int i;
28912976

28922977
for (i = 0; i < core->num_parents - 1; i++)
2893-
seq_printf(s, "%s ", core->parent_names[i]);
2978+
seq_printf(s, "%s ", core->parents[i].name);
28942979

2895-
seq_printf(s, "%s\n", core->parent_names[i]);
2980+
seq_printf(s, "%s\n", core->parents[i].name);
28962981

28972982
return 0;
28982983
}
@@ -3026,7 +3111,7 @@ static inline void clk_debug_unregister(struct clk_core *core)
30263111
*/
30273112
static int __clk_core_init(struct clk_core *core)
30283113
{
3029-
int i, ret;
3114+
int ret;
30303115
struct clk_core *orphan;
30313116
struct hlist_node *tmp2;
30323117
unsigned long rate;
@@ -3080,12 +3165,6 @@ static int __clk_core_init(struct clk_core *core)
30803165
goto out;
30813166
}
30823167

3083-
/* throw a WARN if any entries in parent_names are NULL */
3084-
for (i = 0; i < core->num_parents; i++)
3085-
WARN(!core->parent_names[i],
3086-
"%s: invalid NULL in %s's .parent_names\n",
3087-
__func__, core->name);
3088-
30893168
core->parent = __clk_init_parent(core);
30903169

30913170
/*
@@ -3314,10 +3393,102 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw,
33143393
return clk;
33153394
}
33163395

3396+
static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
3397+
{
3398+
const char *dst;
3399+
3400+
if (!src) {
3401+
if (must_exist)
3402+
return -EINVAL;
3403+
return 0;
3404+
}
3405+
3406+
*dst_p = dst = kstrdup_const(src, GFP_KERNEL);
3407+
if (!dst)
3408+
return -ENOMEM;
3409+
3410+
return 0;
3411+
}
3412+
3413+
static int clk_core_populate_parent_map(struct clk_core *core)
3414+
{
3415+
const struct clk_init_data *init = core->hw->init;
3416+
u8 num_parents = init->num_parents;
3417+
const char * const *parent_names = init->parent_names;
3418+
const struct clk_hw **parent_hws = init->parent_hws;
3419+
const struct clk_parent_data *parent_data = init->parent_data;
3420+
int i, ret = 0;
3421+
struct clk_parent_map *parents, *parent;
3422+
3423+
if (!num_parents)
3424+
return 0;
3425+
3426+
/*
3427+
* Avoid unnecessary string look-ups of clk_core's possible parents by
3428+
* having a cache of names/clk_hw pointers to clk_core pointers.
3429+
*/
3430+
parents = kcalloc(num_parents, sizeof(*parents), GFP_KERNEL);
3431+
core->parents = parents;
3432+
if (!parents)
3433+
return -ENOMEM;
3434+
3435+
/* Copy everything over because it might be __initdata */
3436+
for (i = 0, parent = parents; i < num_parents; i++, parent++) {
3437+
if (parent_names) {
3438+
/* throw a WARN if any entries are NULL */
3439+
WARN(!parent_names[i],
3440+
"%s: invalid NULL in %s's .parent_names\n",
3441+
__func__, core->name);
3442+
ret = clk_cpy_name(&parent->name, parent_names[i],
3443+
true);
3444+
} else if (parent_data) {
3445+
parent->hw = parent_data[i].hw;
3446+
ret = clk_cpy_name(&parent->fw_name,
3447+
parent_data[i].fw_name, false);
3448+
if (!ret)
3449+
ret = clk_cpy_name(&parent->name,
3450+
parent_data[i].name,
3451+
false);
3452+
} else if (parent_hws) {
3453+
parent->hw = parent_hws[i];
3454+
} else {
3455+
ret = -EINVAL;
3456+
WARN(1, "Must specify parents if num_parents > 0\n");
3457+
}
3458+
3459+
if (ret) {
3460+
do {
3461+
kfree_const(parents[i].name);
3462+
kfree_const(parents[i].fw_name);
3463+
} while (--i >= 0);
3464+
kfree(parents);
3465+
3466+
return ret;
3467+
}
3468+
}
3469+
3470+
return 0;
3471+
}
3472+
3473+
static void clk_core_free_parent_map(struct clk_core *core)
3474+
{
3475+
int i = core->num_parents;
3476+
3477+
if (!core->num_parents)
3478+
return;
3479+
3480+
while (--i >= 0) {
3481+
kfree_const(core->parents[i].name);
3482+
kfree_const(core->parents[i].fw_name);
3483+
}
3484+
3485+
kfree(core->parents);
3486+
}
3487+
33173488
static struct clk *
33183489
__clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
33193490
{
3320-
int i, ret;
3491+
int ret;
33213492
struct clk_core *core;
33223493

33233494
core = kzalloc(sizeof(*core), GFP_KERNEL);
@@ -3351,33 +3522,9 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
33513522
core->max_rate = ULONG_MAX;
33523523
hw->core = core;
33533524

3354-
/* allocate local copy in case parent_names is __initdata */
3355-
core->parent_names = kcalloc(core->num_parents, sizeof(char *),
3356-
GFP_KERNEL);
3357-
3358-
if (!core->parent_names) {
3359-
ret = -ENOMEM;
3360-
goto fail_parent_names;
3361-
}
3362-
3363-
3364-
/* copy each string name in case parent_names is __initdata */
3365-
for (i = 0; i < core->num_parents; i++) {
3366-
core->parent_names[i] = kstrdup_const(hw->init->parent_names[i],
3367-
GFP_KERNEL);
3368-
if (!core->parent_names[i]) {
3369-
ret = -ENOMEM;
3370-
goto fail_parent_names_copy;
3371-
}
3372-
}
3373-
3374-
/* avoid unnecessary string look-ups of clk_core's possible parents. */
3375-
core->parents = kcalloc(core->num_parents, sizeof(*core->parents),
3376-
GFP_KERNEL);
3377-
if (!core->parents) {
3378-
ret = -ENOMEM;
3525+
ret = clk_core_populate_parent_map(core);
3526+
if (ret)
33793527
goto fail_parents;
3380-
};
33813528

33823529
INIT_HLIST_HEAD(&core->clks);
33833530

@@ -3388,7 +3535,7 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
33883535
hw->clk = alloc_clk(core, NULL, NULL);
33893536
if (IS_ERR(hw->clk)) {
33903537
ret = PTR_ERR(hw->clk);
3391-
goto fail_parents;
3538+
goto fail_create_clk;
33923539
}
33933540

33943541
clk_core_link_consumer(hw->core, hw->clk);
@@ -3404,13 +3551,9 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
34043551
free_clk(hw->clk);
34053552
hw->clk = NULL;
34063553

3554+
fail_create_clk:
3555+
clk_core_free_parent_map(core);
34073556
fail_parents:
3408-
kfree(core->parents);
3409-
fail_parent_names_copy:
3410-
while (--i >= 0)
3411-
kfree_const(core->parent_names[i]);
3412-
kfree(core->parent_names);
3413-
fail_parent_names:
34143557
fail_ops:
34153558
kfree_const(core->name);
34163559
fail_name:
@@ -3473,15 +3616,10 @@ EXPORT_SYMBOL_GPL(of_clk_hw_register);
34733616
static void __clk_release(struct kref *ref)
34743617
{
34753618
struct clk_core *core = container_of(ref, struct clk_core, ref);
3476-
int i = core->num_parents;
34773619

34783620
lockdep_assert_held(&prepare_lock);
34793621

3480-
kfree(core->parents);
3481-
while (--i >= 0)
3482-
kfree_const(core->parent_names[i]);
3483-
3484-
kfree(core->parent_names);
3622+
clk_core_free_parent_map(core);
34853623
kfree_const(core->name);
34863624
kfree(core);
34873625
}

0 commit comments

Comments
 (0)