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. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAl39mi8RHHNib3lkQGtl cm5lbC5vcmcACgkQrQKIl8bklSUqKBAAieZ+vd5y0G04xTsUHnM1p7zqvqSzHJoM zl1hd5t1ag6hOrkOiaei1W8n10xIw4oIsyJm5iirKzmtIiqLPxQhDjKIMGtcDj9s wqvOSSUEn6TKC9aajdjIHnZLmy6UWg5Zu+c8SaxE0ssuCKv/ZV3Mn0YViRSuZIIw isngZMsD4QlkdmtcKDuxdg27tz+FG72fMa7CN6xvlC5SXMqfrYl8UdShVQTNWoeE 4DQunD54zUDpBxwZIUuALTpFWnWbRRAnmSQxUBrXBqpJAbpofnfuiLM+T/RFwXiO qAawJtmv43AVAAjLVHtgA2UdgXhEJQhgjzmhVbjTz6y5tYV0oqBnOmHXIwOi1nG2 Rw1Zq4+5Vsn3ChlIdIaN1RyEyImIruOu3wP/ttAc5wFGV11jMEBn6SA/RC7ovuO6 3nUsoUHarnf4YYDAu7YFDcVaFyt+jLzySMg5dwwaIb+pfu6PyM10GKIEt04Js2Ul eZskXxLj133hV1Pj+Z6rMAmPdraLdZfi5o9IOaeJvfEnlqyzI4d1Q9J+1oXJl7Fc acB0zWO/NfHd3D7zUFcCi7Da49usuG3sxLeK6I9/GmBEPbeUfcufDrzTADpBqnhY J+Ra4KVNZI4lYzI5JMDHC491dyjIIoWe1eWuHaT3o4VFNgpNH6LBrOetqT6YnmKv 69/jiNEvCrg= =Ac9x -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
12ac9a08fc
|
@ -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 = {
|
||||
|
|
Loading…
Reference in New Issue