diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-03-21 01:44:27 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-03-21 01:44:27 +0100 |
commit | 3215b9d57a2c75c4305a3956ca303d7004485200 (patch) | |
tree | b388062ccd2c935d268d508f49939ecd9c5ef54a | |
parent | Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma (diff) | |
parent | clk: bcm2835: Protect sections updating shared registers (diff) | |
download | linux-3215b9d57a2c75c4305a3956ca303d7004485200.tar.xz linux-3215b9d57a2c75c4305a3956ca303d7004485200.zip |
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
-rw-r--r-- | drivers/clk/bcm/clk-bcm2835.c | 12 | ||||
-rw-r--r-- | drivers/clk/clk-aspeed.c | 28 | ||||
-rw-r--r-- | drivers/clk/clk.c | 46 | ||||
-rw-r--r-- | drivers/clk/hisilicon/clk-hi3660-stub.c | 2 | ||||
-rw-r--r-- | drivers/clk/imx/clk-imx51-imx53.c | 20 | ||||
-rw-r--r-- | drivers/clk/qcom/apcs-msm8916.c | 5 | ||||
-rw-r--r-- | drivers/clk/sunxi-ng/ccu-sun6i-a31.c | 6 | ||||
-rw-r--r-- | drivers/clk/ti/clk-33xx.c | 2 | ||||
-rw-r--r-- | drivers/clk/ti/clk-43xx.c | 2 | ||||
-rw-r--r-- | drivers/clk/ti/clkctrl.c | 2 |
10 files changed, 81 insertions, 44 deletions
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 44301a3d9963..a07f6451694a 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -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); diff --git a/drivers/clk/clk-aspeed.c b/drivers/clk/clk-aspeed.c index 9f7f931d6b2f..5eb50c31e455 100644 --- a/drivers/clk/clk-aspeed.c +++ b/drivers/clk/clk-aspeed.c @@ -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, diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0f686a9dac3e..076d4244d672 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -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); @@ -2968,22 +2973,37 @@ static int __clk_core_init(struct clk_core *core) 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); diff --git a/drivers/clk/hisilicon/clk-hi3660-stub.c b/drivers/clk/hisilicon/clk-hi3660-stub.c index 9b6c72bbddf9..e8b2c43b1bb8 100644 --- a/drivers/clk/hisilicon/clk-hi3660-stub.c +++ b/drivers/clk/hisilicon/clk-hi3660-stub.c @@ -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; diff --git a/drivers/clk/imx/clk-imx51-imx53.c b/drivers/clk/imx/clk-imx51-imx53.c index c864992e6983..caa8bd40692c 100644 --- a/drivers/clk/imx/clk-imx51-imx53.c +++ b/drivers/clk/imx/clk-imx51-imx53.c @@ -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); diff --git a/drivers/clk/qcom/apcs-msm8916.c b/drivers/clk/qcom/apcs-msm8916.c index 246957f1a413..b1cc8dbcd327 100644 --- a/drivers/clk/qcom/apcs-msm8916.c +++ b/drivers/clk/qcom/apcs-msm8916.c @@ -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; } diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c index 72b16ed1012b..3b97f60540ad 100644 --- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c +++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c @@ -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), }, }; diff --git a/drivers/clk/ti/clk-33xx.c b/drivers/clk/ti/clk-33xx.c index 612491a26070..12e0a2d19911 100644 --- a/drivers/clk/ti/clk-33xx.c +++ b/drivers/clk/ti/clk-33xx.c @@ -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" }, diff --git a/drivers/clk/ti/clk-43xx.c b/drivers/clk/ti/clk-43xx.c index 2b7c2e017665..63c5ddb50187 100644 --- a/drivers/clk/ti/clk-43xx.c +++ b/drivers/clk/ti/clk-43xx.c @@ -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 }, }; diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c index afa0d6bfc5c1..421b05392220 100644 --- a/drivers/clk/ti/clkctrl.c +++ b/drivers/clk/ti/clkctrl.c @@ -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); |