A late collection of fixes for regressions seen this release cycle.
Normally I send this earlier than now but real life got in the way. Things are back to normal now. There's the normal set of SoC driver fixes: i.MX boot warning, TI display clks, allwinner clk ops being wrong (fun), driver probe badness on error paths, correctness fix for the new aspeed driver, and even a fix for a race condition in the bcm2835 clk driver. At the core framework level we also got some fixes for the clk phase API caching at the wrong time, better handling of the enabled state of orphan clks, and a fix for a newly introduced bug in how we handle rate calculations for pass-through clks. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAlqxkWcRHHNib3lkQGtl cm5lbC5vcmcACgkQrQKIl8bklSVe/xAAwlUj9cVBVGfTpK7M58XZiH+Igm4fR0qp GxpcvU5AXc+YpUZJ8q7Wuu429JQllmgfwuEwm78Jte42ITtTo/jT4E5IY9yWxaaI H1WlwEde/FFQDkffaDa/wUPI5doO3cAdwqvJPW9XjyO6tCpADM1mmY35wAr0mdk3 HFN/pOEbpSasNAevYfg8MPEyZacYXALR+qQKDEhLJmliwa6xA2acEl2suBzu3w3D 3ncRNZMT82SA42aT5i4JfmD7b/NKAlvcqEmyc9MLkakyZz0nMYcRDkXtJHkVezMG Ij8QvLSWUP0YVHVmf69sMQdvAaJ91iOEg15AJ2Sbh6rie9DjLhQlVyqDhTaDtSTZ RSCxMESuI0Eq+mhRAPlVmgRnuklTP+afo83Hyg4CdJiK357LcjWz8rXcPnw7KlAh iiF3S/rtfOHTue2F0Ar9qiWlMhZPX0wh6Xv7TTYgyU6+W9GwTqBqgj7wJDLBwj8N D37p5q/5iAP73I1vwtpDqiQzZdA9B/sYebAjChPqqA1n6K6LQ6pl99shuavflKvH pHsp8TColZJSu6kqrM17rS5A0FFYy+hqBhlifOwQpXV5L0CwINafpOl3AfNU7Eom lvzM4rswFpHLUUmLaqOuyNzPO8tNkJ7w9nKEjvaOM3YxC3d+vK56pA2k5TGjvsdi 5+jzmtj4AbA= =Yjti -----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: "A late collection of fixes for regressions seen this release cycle. Normally I send this earlier than now but real life got in the way. Things are back to normal now. There's the normal set of SoC driver fixes: i.MX boot warning, TI display clks, allwinner clk ops being wrong (fun), driver probe badness on error paths, correctness fix for the new aspeed driver, and even a fix for a race condition in the bcm2835 clk driver. At the core framework level we also got some fixes for the clk phase API caching at the wrong time, better handling of the enabled state of orphan clks, and a fix for a newly introduced bug in how we handle rate calculations for pass-through clks" * tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: clk: bcm2835: Protect sections updating shared registers clk: bcm2835: Fix ana->maskX definitions clk: aspeed: Prevent reset if clock is enabled clk: aspeed: Fix is_enabled for certain clocks clk: qcom: msm8916: Fix return value check in qcom_apcs_msm8916_clk_probe() clk: hisilicon: hi3660:Fix potential NULL dereference in hi3660_stub_clk_probe() clk: fix determine rate error with pass-through clock clk: migrate the count of orphaned clocks at init clk: update cached phase to respect the fact when setting phase clk: ti: am43xx: add set-rate-parent support for display clkctrl clock clk: ti: am33xx: add set-rate-parent support for display clkctrl clock clk: ti: clkctrl: add support for CLK_SET_RATE_PARENT flag clk: imx51-imx53: Fix UART4/5 registration on i.MX50 and i.MX53 clk: sunxi-ng: a31: Fix CLK_OUT_* clock ops
This commit is contained in:
commit
3215b9d57a
@ -449,17 +449,17 @@ struct bcm2835_pll_ana_bits {
|
||||
static const struct bcm2835_pll_ana_bits bcm2835_ana_default = {
|
||||
.mask0 = 0,
|
||||
.set0 = 0,
|
||||
.mask1 = (u32)~(A2W_PLL_KI_MASK | A2W_PLL_KP_MASK),
|
||||
.mask1 = A2W_PLL_KI_MASK | A2W_PLL_KP_MASK,
|
||||
.set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT),
|
||||
.mask3 = (u32)~A2W_PLL_KA_MASK,
|
||||
.mask3 = A2W_PLL_KA_MASK,
|
||||
.set3 = (2 << A2W_PLL_KA_SHIFT),
|
||||
.fb_prediv_mask = BIT(14),
|
||||
};
|
||||
|
||||
static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = {
|
||||
.mask0 = (u32)~(A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK),
|
||||
.mask0 = A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK,
|
||||
.set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT),
|
||||
.mask1 = (u32)~(A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK),
|
||||
.mask1 = A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK,
|
||||
.set1 = (6 << A2W_PLLH_KP_SHIFT),
|
||||
.mask3 = 0,
|
||||
.set3 = 0,
|
||||
@ -623,8 +623,10 @@ static int bcm2835_pll_on(struct clk_hw *hw)
|
||||
~A2W_PLL_CTRL_PWRDN);
|
||||
|
||||
/* Take the PLL out of reset. */
|
||||
spin_lock(&cprman->regs_lock);
|
||||
cprman_write(cprman, data->cm_ctrl_reg,
|
||||
cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
|
||||
spin_unlock(&cprman->regs_lock);
|
||||
|
||||
/* Wait for the PLL to lock. */
|
||||
timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
|
||||
@ -701,9 +703,11 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
|
||||
}
|
||||
|
||||
/* Unmask the reference clock from the oscillator. */
|
||||
spin_lock(&cprman->regs_lock);
|
||||
cprman_write(cprman, A2W_XOSC_CTRL,
|
||||
cprman_read(cprman, A2W_XOSC_CTRL) |
|
||||
data->reference_enable_mask);
|
||||
spin_unlock(&cprman->regs_lock);
|
||||
|
||||
if (do_ana_setup_first)
|
||||
bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);
|
||||
|
@ -205,6 +205,18 @@ static const struct aspeed_clk_soc_data ast2400_data = {
|
||||
.calc_pll = aspeed_ast2400_calc_pll,
|
||||
};
|
||||
|
||||
static int aspeed_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
u32 clk = BIT(gate->clock_idx);
|
||||
u32 enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
|
||||
u32 reg;
|
||||
|
||||
regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, ®);
|
||||
|
||||
return ((reg & clk) == enval) ? 1 : 0;
|
||||
}
|
||||
|
||||
static int aspeed_clk_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
@ -215,6 +227,11 @@ static int aspeed_clk_enable(struct clk_hw *hw)
|
||||
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
if (aspeed_clk_is_enabled(hw)) {
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gate->reset_idx >= 0) {
|
||||
/* Put IP in reset */
|
||||
regmap_update_bits(gate->map, ASPEED_RESET_CTRL, rst, rst);
|
||||
@ -255,17 +272,6 @@ static void aspeed_clk_disable(struct clk_hw *hw)
|
||||
spin_unlock_irqrestore(gate->lock, flags);
|
||||
}
|
||||
|
||||
static int aspeed_clk_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
|
||||
u32 clk = BIT(gate->clock_idx);
|
||||
u32 reg;
|
||||
|
||||
regmap_read(gate->map, ASPEED_CLK_STOP_CTRL, ®);
|
||||
|
||||
return (reg & clk) ? 0 : 1;
|
||||
}
|
||||
|
||||
static const struct clk_ops aspeed_clk_gate_ops = {
|
||||
.enable = aspeed_clk_enable,
|
||||
.disable = aspeed_clk_disable,
|
||||
|
@ -1125,8 +1125,10 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
|
||||
{
|
||||
lockdep_assert_held(&prepare_lock);
|
||||
|
||||
if (!core)
|
||||
if (!core) {
|
||||
req->rate = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
clk_core_init_rate_req(core, req);
|
||||
|
||||
@ -2309,8 +2311,11 @@ static int clk_core_set_phase_nolock(struct clk_core *core, int degrees)
|
||||
|
||||
trace_clk_set_phase(core, degrees);
|
||||
|
||||
if (core->ops->set_phase)
|
||||
if (core->ops->set_phase) {
|
||||
ret = core->ops->set_phase(core->hw, degrees);
|
||||
if (!ret)
|
||||
core->phase = degrees;
|
||||
}
|
||||
|
||||
trace_clk_set_phase_complete(core, degrees);
|
||||
|
||||
@ -2967,23 +2972,38 @@ static int __clk_core_init(struct clk_core *core)
|
||||
rate = 0;
|
||||
core->rate = core->req_rate = rate;
|
||||
|
||||
/*
|
||||
* Enable CLK_IS_CRITICAL clocks so newly added critical clocks
|
||||
* don't get accidentally disabled when walking the orphan tree and
|
||||
* reparenting clocks
|
||||
*/
|
||||
if (core->flags & CLK_IS_CRITICAL) {
|
||||
unsigned long flags;
|
||||
|
||||
clk_core_prepare(core);
|
||||
|
||||
flags = clk_enable_lock();
|
||||
clk_core_enable(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);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* we could call __clk_set_parent, but that would result in a
|
||||
* redundant call to the .set_rate op, if it exists
|
||||
* 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 */
|
||||
flags = clk_enable_lock();
|
||||
clk_reparent(orphan, parent);
|
||||
clk_enable_unlock(flags);
|
||||
__clk_set_parent_before(orphan, parent);
|
||||
__clk_set_parent_after(orphan, parent, NULL);
|
||||
__clk_recalc_accuracies(orphan);
|
||||
__clk_recalc_rates(orphan, 0);
|
||||
}
|
||||
@ -3000,16 +3020,6 @@ static int __clk_core_init(struct clk_core *core)
|
||||
if (core->ops->init)
|
||||
core->ops->init(core->hw);
|
||||
|
||||
if (core->flags & CLK_IS_CRITICAL) {
|
||||
unsigned long flags;
|
||||
|
||||
clk_core_prepare(core);
|
||||
|
||||
flags = clk_enable_lock();
|
||||
clk_core_enable(core);
|
||||
clk_enable_unlock(flags);
|
||||
}
|
||||
|
||||
kref_init(&core->ref);
|
||||
out:
|
||||
clk_pm_runtime_put(core);
|
||||
|
@ -149,6 +149,8 @@ static int hi3660_stub_clk_probe(struct platform_device *pdev)
|
||||
return PTR_ERR(stub_clk_chan.mbox);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -EINVAL;
|
||||
freq_reg = devm_ioremap(dev, res->start, resource_size(res));
|
||||
if (!freq_reg)
|
||||
return -ENOMEM;
|
||||
|
@ -131,7 +131,17 @@ static const char *ieee1588_sels[] = { "pll3_sw", "pll4_sw", "dummy" /* usbphy2_
|
||||
static struct clk *clk[IMX5_CLK_END];
|
||||
static struct clk_onecell_data clk_data;
|
||||
|
||||
static struct clk ** const uart_clks[] __initconst = {
|
||||
static struct clk ** const uart_clks_mx51[] __initconst = {
|
||||
&clk[IMX5_CLK_UART1_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART1_PER_GATE],
|
||||
&clk[IMX5_CLK_UART2_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART2_PER_GATE],
|
||||
&clk[IMX5_CLK_UART3_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART3_PER_GATE],
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct clk ** const uart_clks_mx50_mx53[] __initconst = {
|
||||
&clk[IMX5_CLK_UART1_IPG_GATE],
|
||||
&clk[IMX5_CLK_UART1_PER_GATE],
|
||||
&clk[IMX5_CLK_UART2_IPG_GATE],
|
||||
@ -321,8 +331,6 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
|
||||
clk_prepare_enable(clk[IMX5_CLK_TMAX1]);
|
||||
clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
|
||||
clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
|
||||
|
||||
imx_register_uart_clocks(uart_clks);
|
||||
}
|
||||
|
||||
static void __init mx50_clocks_init(struct device_node *np)
|
||||
@ -388,6 +396,8 @@ static void __init mx50_clocks_init(struct device_node *np)
|
||||
|
||||
r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
|
||||
clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
|
||||
|
||||
imx_register_uart_clocks(uart_clks_mx50_mx53);
|
||||
}
|
||||
CLK_OF_DECLARE(imx50_ccm, "fsl,imx50-ccm", mx50_clocks_init);
|
||||
|
||||
@ -477,6 +487,8 @@ static void __init mx51_clocks_init(struct device_node *np)
|
||||
val = readl(MXC_CCM_CLPCR);
|
||||
val |= 1 << 23;
|
||||
writel(val, MXC_CCM_CLPCR);
|
||||
|
||||
imx_register_uart_clocks(uart_clks_mx51);
|
||||
}
|
||||
CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init);
|
||||
|
||||
@ -606,5 +618,7 @@ static void __init mx53_clocks_init(struct device_node *np)
|
||||
|
||||
r = clk_round_rate(clk[IMX5_CLK_USBOH3_PER_GATE], 54000000);
|
||||
clk_set_rate(clk[IMX5_CLK_USBOH3_PER_GATE], r);
|
||||
|
||||
imx_register_uart_clocks(uart_clks_mx50_mx53);
|
||||
}
|
||||
CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
|
||||
|
@ -49,11 +49,10 @@ static int qcom_apcs_msm8916_clk_probe(struct platform_device *pdev)
|
||||
struct clk_regmap_mux_div *a53cc;
|
||||
struct regmap *regmap;
|
||||
struct clk_init_data init = { };
|
||||
int ret;
|
||||
int ret = -ENODEV;
|
||||
|
||||
regmap = dev_get_regmap(parent, NULL);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
if (!regmap) {
|
||||
dev_err(dev, "failed to get regmap: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -762,7 +762,7 @@ static struct ccu_mp out_a_clk = {
|
||||
.features = CCU_FEATURE_FIXED_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("out-a",
|
||||
clk_out_parents,
|
||||
&ccu_div_ops,
|
||||
&ccu_mp_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
@ -783,7 +783,7 @@ static struct ccu_mp out_b_clk = {
|
||||
.features = CCU_FEATURE_FIXED_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("out-b",
|
||||
clk_out_parents,
|
||||
&ccu_div_ops,
|
||||
&ccu_mp_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
@ -804,7 +804,7 @@ static struct ccu_mp out_c_clk = {
|
||||
.features = CCU_FEATURE_FIXED_PREDIV,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("out-c",
|
||||
clk_out_parents,
|
||||
&ccu_div_ops,
|
||||
&ccu_mp_ops,
|
||||
0),
|
||||
},
|
||||
};
|
||||
|
@ -45,7 +45,7 @@ static const struct omap_clkctrl_bit_data am3_gpio4_bit_data[] __initconst = {
|
||||
|
||||
static const struct omap_clkctrl_reg_data am3_l4_per_clkctrl_regs[] __initconst = {
|
||||
{ AM3_CPGMAC0_CLKCTRL, NULL, CLKF_SW_SUP, "cpsw_125mhz_gclk", "cpsw_125mhz_clkdm" },
|
||||
{ AM3_LCDC_CLKCTRL, NULL, CLKF_SW_SUP, "lcd_gclk", "lcdc_clkdm" },
|
||||
{ AM3_LCDC_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_SET_RATE_PARENT, "lcd_gclk", "lcdc_clkdm" },
|
||||
{ AM3_USB_OTG_HS_CLKCTRL, NULL, CLKF_SW_SUP, "usbotg_fck", "l3s_clkdm" },
|
||||
{ AM3_TPTC0_CLKCTRL, NULL, CLKF_SW_SUP, "l3_gclk", "l3_clkdm" },
|
||||
{ AM3_EMIF_CLKCTRL, NULL, CLKF_SW_SUP, "dpll_ddr_m2_div2_ck", "l3_clkdm" },
|
||||
|
@ -187,7 +187,7 @@ static const struct omap_clkctrl_reg_data am4_l4_per_clkctrl_regs[] __initconst
|
||||
{ AM4_OCP2SCP0_CLKCTRL, NULL, CLKF_SW_SUP, "l4ls_gclk" },
|
||||
{ AM4_OCP2SCP1_CLKCTRL, NULL, CLKF_SW_SUP, "l4ls_gclk" },
|
||||
{ AM4_EMIF_CLKCTRL, NULL, CLKF_SW_SUP, "dpll_ddr_m2_ck", "emif_clkdm" },
|
||||
{ AM4_DSS_CORE_CLKCTRL, NULL, CLKF_SW_SUP, "disp_clk", "dss_clkdm" },
|
||||
{ AM4_DSS_CORE_CLKCTRL, NULL, CLKF_SW_SUP | CLKF_SET_RATE_PARENT, "disp_clk", "dss_clkdm" },
|
||||
{ AM4_CPGMAC0_CLKCTRL, NULL, CLKF_SW_SUP, "cpsw_125mhz_gclk", "cpsw_125mhz_clkdm" },
|
||||
{ 0 },
|
||||
};
|
||||
|
@ -537,6 +537,8 @@ static void __init _ti_omap4_clkctrl_setup(struct device_node *node)
|
||||
init.parent_names = ®_data->parent;
|
||||
init.num_parents = 1;
|
||||
init.flags = 0;
|
||||
if (reg_data->flags & CLKF_SET_RATE_PARENT)
|
||||
init.flags |= CLK_SET_RATE_PARENT;
|
||||
init.name = kasprintf(GFP_KERNEL, "%s:%s:%04x:%d",
|
||||
node->parent->name, node->name,
|
||||
reg_data->offset, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user