Commit 12ac9a08 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk fixes from Stephen Boyd:
 "One core framework fix to walk the orphan list and match up clks to
  parents when clk providers register the DT provider after registering
  all their clks (as they should).

  Then a handful of driver fixes for the qcom, imx, and at91 drivers.

  The driver fixes are relatively small fixes for incorrect register
  settings or missing locks causing race conditions"

* tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
  clk: qcom: Avoid SMMU/cx gdsc corner cases
  clk: qcom: gcc-sc7180: Fix setting flag for votable GDSCs
  clk: Move clk_core_reparent_orphans() under CONFIG_OF
  clk: at91: fix possible deadlock
  clk: walk orphan list on clock provider registration
  clk: imx: pll14xx: fix clk_pll14xx_wait_lock
  clk: imx: clk-imx7ulp: Add missing sentinel of ulp_div_table
  clk: imx: clk-composite-8m: add lock to gate/mux
parents f1fd1610 781d8cea
......@@ -348,7 +348,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
regmap = device_node_to_regmap(np);
if (IS_ERR(regmap))
return;
......
......@@ -83,7 +83,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
regmap = device_node_to_regmap(np);
if (IS_ERR(regmap))
return;
......
......@@ -146,7 +146,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
regmap = device_node_to_regmap(np);
if (IS_ERR(regmap))
return;
......
......@@ -275,7 +275,7 @@ static int __init pmc_register_ops(void)
np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
pmcreg = syscon_node_to_regmap(np);
pmcreg = device_node_to_regmap(np);
if (IS_ERR(pmcreg))
return PTR_ERR(pmcreg);
......
......@@ -162,7 +162,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
regmap = device_node_to_regmap(np);
if (IS_ERR(regmap))
return;
......
......@@ -136,7 +136,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
return;
mainxtal_name = of_clk_get_parent_name(np, i);
regmap = syscon_node_to_regmap(np);
regmap = device_node_to_regmap(np);
if (IS_ERR(regmap))
return;
......
......@@ -3249,6 +3249,34 @@ static inline void clk_debug_unregister(struct clk_core *core)
}
#endif
static void clk_core_reparent_orphans_nolock(void)
{
struct clk_core *orphan;
struct hlist_node *tmp2;
/*
* walk the list of orphan clocks and reparent any that newly finds a
* parent.
*/
hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
struct clk_core *parent = __clk_init_parent(orphan);
/*
* We need to use __clk_set_parent_before() and _after() to
* to properly migrate any prepare/enable count of the orphan
* clock. This is important for CLK_IS_CRITICAL clocks, which
* are enabled during init but might not have a parent yet.
*/
if (parent) {
/* update the clk tree topology */
__clk_set_parent_before(orphan, parent);
__clk_set_parent_after(orphan, parent, NULL);
__clk_recalc_accuracies(orphan);
__clk_recalc_rates(orphan, 0);
}
}
}
/**
* __clk_core_init - initialize the data structures in a struct clk_core
* @core: clk_core being initialized
......@@ -3259,8 +3287,6 @@ static inline void clk_debug_unregister(struct clk_core *core)
static int __clk_core_init(struct clk_core *core)
{
int ret;
struct clk_core *orphan;
struct hlist_node *tmp2;
unsigned long rate;
if (!core)
......@@ -3407,27 +3433,8 @@ static int __clk_core_init(struct clk_core *core)
clk_enable_unlock(flags);
}
/*
* walk the list of orphan clocks and reparent any that newly finds a
* parent.
*/
hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
struct clk_core *parent = __clk_init_parent(orphan);
clk_core_reparent_orphans_nolock();
/*
* We need to use __clk_set_parent_before() and _after() to
* to properly migrate any prepare/enable count of the orphan
* clock. This is important for CLK_IS_CRITICAL clocks, which
* are enabled during init but might not have a parent yet.
*/
if (parent) {
/* update the clk tree topology */
__clk_set_parent_before(orphan, parent);
__clk_set_parent_after(orphan, parent, NULL);
__clk_recalc_accuracies(orphan);
__clk_recalc_rates(orphan, 0);
}
}
kref_init(&core->ref);
out:
......@@ -4179,6 +4186,13 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
EXPORT_SYMBOL_GPL(clk_notifier_unregister);
#ifdef CONFIG_OF
static void clk_core_reparent_orphans(void)
{
clk_prepare_lock();
clk_core_reparent_orphans_nolock();
clk_prepare_unlock();
}
/**
* struct of_clk_provider - Clock provider registration structure
* @link: Entry in global list of clock providers
......@@ -4274,6 +4288,8 @@ int of_clk_add_provider(struct device_node *np,
mutex_unlock(&of_clk_mutex);
pr_debug("Added clock from %pOF\n", np);
clk_core_reparent_orphans();
ret = of_clk_set_defaults(np, true);
if (ret < 0)
of_clk_del_provider(np);
......@@ -4309,6 +4325,8 @@ int of_clk_add_hw_provider(struct device_node *np,
mutex_unlock(&of_clk_mutex);
pr_debug("Added clk_hw provider from %pOF\n", np);
clk_core_reparent_orphans();
ret = of_clk_set_defaults(np, true);
if (ret < 0)
of_clk_del_provider(np);
......
......@@ -142,6 +142,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
mux->reg = reg;
mux->shift = PCG_PCS_SHIFT;
mux->mask = PCG_PCS_MASK;
mux->lock = &imx_ccm_lock;
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
......@@ -161,6 +162,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
gate_hw = &gate->hw;
gate->reg = reg;
gate->bit_idx = PCG_CGC_SHIFT;
gate->lock = &imx_ccm_lock;
hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
mux_hw, &clk_mux_ops, div_hw,
......
......@@ -40,6 +40,7 @@ static const struct clk_div_table ulp_div_table[] = {
{ .val = 5, .div = 16, },
{ .val = 6, .div = 32, },
{ .val = 7, .div = 64, },
{ /* sentinel */ },
};
static const int pcc2_uart_clk_ids[] __initconst = {
......
......@@ -159,7 +159,7 @@ static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
{
u32 val;
return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US, 0,
return readl_poll_timeout(pll->base, val, val & LOCK_STATUS, 0,
LOCK_TIMEOUT_US);
}
......
......@@ -2186,7 +2186,8 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
.pd = {
.name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc",
},
.pwrsts = PWRSTS_OFF_ON | VOTABLE,
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
......@@ -2194,7 +2195,8 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
.pd = {
.name = "hlos1_vote_mmnoc_mmu_tbu_sf_gdsc",
},
.pwrsts = PWRSTS_OFF_ON | VOTABLE,
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
static struct gdsc *gcc_sc7180_gdscs[] = {
......
......@@ -242,10 +242,12 @@ static struct clk_branch gfx3d_isense_clk = {
static struct gdsc gpu_cx_gdsc = {
.gdscr = 0x1004,
.gds_hw_ctrl = 0x1008,
.pd = {
.name = "gpu_cx",
},
.pwrsts = PWRSTS_OFF_ON,
.flags = VOTABLE,
};
static struct gdsc gpu_gx_gdsc = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment