aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@kernel.org>2019-04-30 13:22:30 -0400
committerStephen Boyd <sboyd@kernel.org>2019-05-03 13:38:01 -0400
commit1a079560b1450b72ff4e944bb9185e77633d74c4 (patch)
tree813133407b3a887e7525350ab5bed50848a10e59
parente4818d615b58f145ace70fefa43aeae8611b55a1 (diff)
clk: Cache core in clk_fetch_parent_index() without names
If a clk has specified parents via clk_hw pointers it won't specify the globally unique names for the parents. Without the unique names, we can't fallback to comparing them against the name of the 'parent' pointer here. Therefore, do a pointer comparison against the clk_hw pointers too and cache the clk_core structure if they match. This fixes parent lookup code for clks that only specify clk_hw pointers and nothing else, like muxes that are purely inside a clk controller. Similarly, if the parent pointer isn't cached after trying to match clk_core or clk_hw pointers, lookup the pointer from DT or via clkdev lookups instead of relying purely on the globally unique clk name match. This should allow us to move away from having to specify global names for clk parents entirely. While we're in the area, add some comments so it's clearer what's going on. The if statements don't lend themselves to much clarity in their raw form. Fixes: fc0c209c147f ("clk: Allow parents to be specified without string names") Reported-by: Charles Keepax <ckeepax@opensource.cirrus.com> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
-rw-r--r--drivers/clk/clk.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index dc05cb339761..dcb7e1cddd2d 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -327,8 +327,7 @@ static struct clk_core *clk_core_lookup(const char *name)
327/** 327/**
328 * clk_core_get - Find the clk_core parent of a clk 328 * clk_core_get - Find the clk_core parent of a clk
329 * @core: clk to find parent of 329 * @core: clk to find parent of
330 * @name: name to search for (if string based) 330 * @p_index: parent index to search for
331 * @index: index to use for search (if DT index based)
332 * 331 *
333 * This is the preferred method for clk providers to find the parent of a 332 * This is the preferred method for clk providers to find the parent of a
334 * clk when that parent is external to the clk controller. The parent_names 333 * clk when that parent is external to the clk controller. The parent_names
@@ -360,9 +359,10 @@ static struct clk_core *clk_core_lookup(const char *name)
360 * provider knows about the clk but it isn't provided on this system. 359 * provider knows about the clk but it isn't provided on this system.
361 * A valid clk_core pointer when the clk can be found in the provider. 360 * A valid clk_core pointer when the clk can be found in the provider.
362 */ 361 */
363static struct clk_core *clk_core_get(struct clk_core *core, const char *name, 362static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index)
364 int index)
365{ 363{
364 const char *name = core->parents[p_index].fw_name;
365 int index = core->parents[p_index].index;
366 struct clk_hw *hw = ERR_PTR(-ENOENT); 366 struct clk_hw *hw = ERR_PTR(-ENOENT);
367 struct device *dev = core->dev; 367 struct device *dev = core->dev;
368 const char *dev_id = dev ? dev_name(dev) : NULL; 368 const char *dev_id = dev ? dev_name(dev) : NULL;
@@ -400,7 +400,7 @@ static void clk_core_fill_parent_index(struct clk_core *core, u8 index)
400 if (!parent) 400 if (!parent)
401 parent = ERR_PTR(-EPROBE_DEFER); 401 parent = ERR_PTR(-EPROBE_DEFER);
402 } else { 402 } else {
403 parent = clk_core_get(core, entry->fw_name, entry->index); 403 parent = clk_core_get(core, index);
404 if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT) 404 if (IS_ERR(parent) && PTR_ERR(parent) == -ENOENT)
405 parent = clk_core_lookup(entry->name); 405 parent = clk_core_lookup(entry->name);
406 } 406 }
@@ -1612,20 +1612,37 @@ static int clk_fetch_parent_index(struct clk_core *core,
1612 return -EINVAL; 1612 return -EINVAL;
1613 1613
1614 for (i = 0; i < core->num_parents; i++) { 1614 for (i = 0; i < core->num_parents; i++) {
1615 /* Found it first try! */
1615 if (core->parents[i].core == parent) 1616 if (core->parents[i].core == parent)
1616 return i; 1617 return i;
1617 1618
1619 /* Something else is here, so keep looking */
1618 if (core->parents[i].core) 1620 if (core->parents[i].core)
1619 continue; 1621 continue;
1620 1622
1621 /* Fallback to comparing globally unique names */ 1623 /* Maybe core hasn't been cached but the hw is all we know? */
1622 if (!strcmp(parent->name, core->parents[i].name)) { 1624 if (core->parents[i].hw) {
1623 core->parents[i].core = parent; 1625 if (core->parents[i].hw == parent->hw)
1624 return i; 1626 break;
1627
1628 /* Didn't match, but we're expecting a clk_hw */
1629 continue;
1625 } 1630 }
1631
1632 /* Maybe it hasn't been cached (clk_set_parent() path) */
1633 if (parent == clk_core_get(core, i))
1634 break;
1635
1636 /* Fallback to comparing globally unique names */
1637 if (!strcmp(parent->name, core->parents[i].name))
1638 break;
1626 } 1639 }
1627 1640
1628 return -EINVAL; 1641 if (i == core->num_parents)
1642 return -EINVAL;
1643
1644 core->parents[i].core = parent;
1645 return i;
1629} 1646}
1630 1647
1631/* 1648/*