diff options
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/clk.c | 111 | ||||
-rw-r--r-- | drivers/clk/meson/g12a.c | 102 | ||||
-rw-r--r-- | drivers/clk/renesas/clk-sh73a0.c | 2 | ||||
-rw-r--r-- | drivers/clk/renesas/r8a774a1-cpg-mssr.c | 8 | ||||
-rw-r--r-- | drivers/clk/renesas/r8a774b1-cpg-mssr.c | 8 | ||||
-rw-r--r-- | drivers/clk/renesas/r8a774c0-cpg-mssr.c | 9 | ||||
-rw-r--r-- | drivers/clk/renesas/r8a779a0-cpg-mssr.c | 51 | ||||
-rw-r--r-- | drivers/clk/renesas/rcar-gen3-cpg.c | 79 | ||||
-rw-r--r-- | drivers/clk/renesas/rcar-gen3-cpg.h | 5 | ||||
-rw-r--r-- | drivers/clk/renesas/rcar-usb2-clock-sel.c | 2 | ||||
-rw-r--r-- | drivers/clk/renesas/renesas-cpg-mssr.c | 3 | ||||
-rw-r--r-- | drivers/clk/samsung/Kconfig | 67 | ||||
-rw-r--r-- | drivers/clk/samsung/Makefile | 22 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-pll.c | 147 |
14 files changed, 437 insertions, 179 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index f83dac54ed85..c77feb6f7115 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -420,7 +420,7 @@ static struct clk_core *clk_core_get(struct clk_core *core, u8 p_index) static void clk_core_fill_parent_index(struct clk_core *core, u8 index) { struct clk_parent_map *entry = &core->parents[index]; - struct clk_core *parent = ERR_PTR(-ENOENT); + struct clk_core *parent; if (entry->hw) { parent = entry->hw->core; @@ -3667,6 +3667,24 @@ struct clk *clk_hw_create_clk(struct device *dev, struct clk_hw *hw, return clk; } +/** + * clk_hw_get_clk - get clk consumer given an clk_hw + * @hw: clk_hw associated with the clk being consumed + * @con_id: connection ID string on device + * + * Returns: new clk consumer + * This is the function to be used by providers which need + * to get a consumer clk and act on the clock element + * Calls to this function must be balanced with calls clk_put() + */ +struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id) +{ + struct device *dev = hw->core->dev; + + return clk_hw_create_clk(dev, hw, dev_name(dev), con_id); +} +EXPORT_SYMBOL(clk_hw_get_clk); + static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist) { const char *dst; @@ -4068,12 +4086,12 @@ void clk_hw_unregister(struct clk_hw *hw) } EXPORT_SYMBOL_GPL(clk_hw_unregister); -static void devm_clk_release(struct device *dev, void *res) +static void devm_clk_unregister_cb(struct device *dev, void *res) { clk_unregister(*(struct clk **)res); } -static void devm_clk_hw_release(struct device *dev, void *res) +static void devm_clk_hw_unregister_cb(struct device *dev, void *res) { clk_hw_unregister(*(struct clk_hw **)res); } @@ -4093,7 +4111,7 @@ struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw) struct clk *clk; struct clk **clkp; - clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL); + clkp = devres_alloc(devm_clk_unregister_cb, sizeof(*clkp), GFP_KERNEL); if (!clkp) return ERR_PTR(-ENOMEM); @@ -4123,7 +4141,7 @@ int devm_clk_hw_register(struct device *dev, struct clk_hw *hw) struct clk_hw **hwp; int ret; - hwp = devres_alloc(devm_clk_hw_release, sizeof(*hwp), GFP_KERNEL); + hwp = devres_alloc(devm_clk_hw_unregister_cb, sizeof(*hwp), GFP_KERNEL); if (!hwp) return -ENOMEM; @@ -4167,7 +4185,7 @@ static int devm_clk_hw_match(struct device *dev, void *res, void *data) */ void devm_clk_unregister(struct device *dev, struct clk *clk) { - WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk)); + WARN_ON(devres_release(dev, devm_clk_unregister_cb, devm_clk_match, clk)); } EXPORT_SYMBOL_GPL(devm_clk_unregister); @@ -4182,11 +4200,54 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister); */ void devm_clk_hw_unregister(struct device *dev, struct clk_hw *hw) { - WARN_ON(devres_release(dev, devm_clk_hw_release, devm_clk_hw_match, + WARN_ON(devres_release(dev, devm_clk_hw_unregister_cb, devm_clk_hw_match, hw)); } EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); +static void devm_clk_release(struct device *dev, void *res) +{ + clk_put(*(struct clk **)res); +} + +/** + * devm_clk_hw_get_clk - resource managed clk_hw_get_clk() + * @dev: device that is registering this clock + * @hw: clk_hw associated with the clk being consumed + * @con_id: connection ID string on device + * + * Managed clk_hw_get_clk(). Clocks got with this function are + * automatically clk_put() on driver detach. See clk_put() + * for more information. + */ +struct clk *devm_clk_hw_get_clk(struct device *dev, struct clk_hw *hw, + const char *con_id) +{ + struct clk *clk; + struct clk **clkp; + + /* This should not happen because it would mean we have drivers + * passing around clk_hw pointers instead of having the caller use + * proper clk_get() style APIs + */ + WARN_ON_ONCE(dev != hw->core->dev); + + clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL); + if (!clkp) + return ERR_PTR(-ENOMEM); + + clk = clk_hw_get_clk(hw, con_id); + if (!IS_ERR(clk)) { + *clkp = clk; + devres_add(dev, clkp); + } else { + devres_free(clkp); + } + + return clk; +} +EXPORT_SYMBOL_GPL(devm_clk_hw_get_clk); + /* * clkdev helpers */ @@ -4334,6 +4395,42 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) } EXPORT_SYMBOL_GPL(clk_notifier_unregister); +struct clk_notifier_devres { + struct clk *clk; + struct notifier_block *nb; +}; + +static void devm_clk_notifier_release(struct device *dev, void *res) +{ + struct clk_notifier_devres *devres = res; + + clk_notifier_unregister(devres->clk, devres->nb); +} + +int devm_clk_notifier_register(struct device *dev, struct clk *clk, + struct notifier_block *nb) +{ + struct clk_notifier_devres *devres; + int ret; + + devres = devres_alloc(devm_clk_notifier_release, + sizeof(*devres), GFP_KERNEL); + + if (!devres) + return -ENOMEM; + + ret = clk_notifier_register(clk, nb); + if (!ret) { + devres->clk = clk; + devres->nb = nb; + } else { + devres_free(devres); + } + + return ret; +} +EXPORT_SYMBOL_GPL(devm_clk_notifier_register); + #ifdef CONFIG_OF static void clk_core_reparent_orphans(void) { diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index b814d44917a5..108e4491b1e2 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -5156,10 +5156,11 @@ static const struct reg_sequence g12a_init_regs[] = { { .reg = HHI_MPLL_CNTL0, .def = 0x00000543 }, }; -static int meson_g12a_dvfs_setup_common(struct platform_device *pdev, +#define DVFS_CON_ID "dvfs" + +static int meson_g12a_dvfs_setup_common(struct device *dev, struct clk_hw **hws) { - const char *notifier_clk_name; struct clk *notifier_clk; struct clk_hw *xtal; int ret; @@ -5168,21 +5169,22 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev, /* Setup clock notifier for cpu_clk_postmux0 */ g12a_cpu_clk_postmux0_nb_data.xtal = xtal; - notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_postmux0.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, - &g12a_cpu_clk_postmux0_nb_data.nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_postmux0.hw, + DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_postmux0_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk_postmux0 notifier\n"); + dev_err(dev, "failed to register the cpu_clk_postmux0 notifier\n"); return ret; } /* Setup clock notifier for cpu_clk_dyn mux */ - notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk_dyn.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk_dyn.hw, + DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk_dyn notifier\n"); + dev_err(dev, "failed to register the cpu_clk_dyn notifier\n"); return ret; } @@ -5192,33 +5194,34 @@ static int meson_g12a_dvfs_setup_common(struct platform_device *pdev, static int meson_g12b_dvfs_setup(struct platform_device *pdev) { struct clk_hw **hws = g12b_hw_onecell_data.hws; - const char *notifier_clk_name; + struct device *dev = &pdev->dev; struct clk *notifier_clk; struct clk_hw *xtal; int ret; - ret = meson_g12a_dvfs_setup_common(pdev, hws); + ret = meson_g12a_dvfs_setup_common(dev, hws); if (ret) return ret; xtal = clk_hw_get_parent_by_index(hws[CLKID_CPU_CLK_DYN1_SEL], 0); /* Setup clock notifier for cpu_clk mux */ - notifier_clk_name = clk_hw_get_name(&g12b_cpu_clk.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpu_clk.hw, + DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n"); + dev_err(dev, "failed to register the cpu_clk notifier\n"); return ret; } /* Setup clock notifier for sys1_pll */ - notifier_clk_name = clk_hw_get_name(&g12b_sys1_pll.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, - &g12b_cpu_clk_sys1_pll_nb_data.nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_sys1_pll.hw, + DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12b_cpu_clk_sys1_pll_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the sys1_pll notifier\n"); + dev_err(dev, "failed to register the sys1_pll notifier\n"); return ret; } @@ -5226,40 +5229,39 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) /* Setup clock notifier for cpub_clk_postmux0 */ g12b_cpub_clk_postmux0_nb_data.xtal = xtal; - notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_postmux0.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, - &g12b_cpub_clk_postmux0_nb_data.nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_postmux0.hw, + DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12b_cpub_clk_postmux0_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpub_clk_postmux0 notifier\n"); + dev_err(dev, "failed to register the cpub_clk_postmux0 notifier\n"); return ret; } /* Setup clock notifier for cpub_clk_dyn mux */ - notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk_dyn.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk_dyn.hw, "dvfs"); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpub_clk_dyn notifier\n"); + dev_err(dev, "failed to register the cpub_clk_dyn notifier\n"); return ret; } /* Setup clock notifier for cpub_clk mux */ - notifier_clk_name = clk_hw_get_name(&g12b_cpub_clk.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12b_cpub_clk.hw, DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpub_clk notifier\n"); + dev_err(dev, "failed to register the cpub_clk notifier\n"); return ret; } /* Setup clock notifier for sys_pll */ - notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, - &g12b_cpub_clk_sys_pll_nb_data.nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12b_cpub_clk_sys_pll_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the sys_pll notifier\n"); + dev_err(dev, "failed to register the sys_pll notifier\n"); return ret; } @@ -5269,29 +5271,29 @@ static int meson_g12b_dvfs_setup(struct platform_device *pdev) static int meson_g12a_dvfs_setup(struct platform_device *pdev) { struct clk_hw **hws = g12a_hw_onecell_data.hws; - const char *notifier_clk_name; + struct device *dev = &pdev->dev; struct clk *notifier_clk; int ret; - ret = meson_g12a_dvfs_setup_common(pdev, hws); + ret = meson_g12a_dvfs_setup_common(dev, hws); if (ret) return ret; /* Setup clock notifier for cpu_clk mux */ - notifier_clk_name = clk_hw_get_name(&g12a_cpu_clk.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, &g12a_cpu_clk_mux_nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_cpu_clk.hw, DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_cpu_clk_mux_nb); if (ret) { - dev_err(&pdev->dev, "failed to register the cpu_clk notifier\n"); + dev_err(dev, "failed to register the cpu_clk notifier\n"); return ret; } /* Setup clock notifier for sys_pll */ - notifier_clk_name = clk_hw_get_name(&g12a_sys_pll.hw); - notifier_clk = __clk_lookup(notifier_clk_name); - ret = clk_notifier_register(notifier_clk, &g12a_sys_pll_nb_data.nb); + notifier_clk = devm_clk_hw_get_clk(dev, &g12a_sys_pll.hw, DVFS_CON_ID); + ret = devm_clk_notifier_register(dev, notifier_clk, + &g12a_sys_pll_nb_data.nb); if (ret) { - dev_err(&pdev->dev, "failed to register the sys_pll notifier\n"); + dev_err(dev, "failed to register the sys_pll notifier\n"); return ret; } diff --git a/drivers/clk/renesas/clk-sh73a0.c b/drivers/clk/renesas/clk-sh73a0.c index 5f25a70bc61c..4146c1d717b9 100644 --- a/drivers/clk/renesas/clk-sh73a0.c +++ b/drivers/clk/renesas/clk-sh73a0.c @@ -121,7 +121,7 @@ sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg, (phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR); parent_name = phy_no ? "dsi1pck" : "dsi0pck"; - mult = __raw_readl(dsi_reg); + mult = readl(dsi_reg); if (!(mult & 0x8000)) mult = 1; else diff --git a/drivers/clk/renesas/r8a774a1-cpg-mssr.c b/drivers/clk/renesas/r8a774a1-cpg-mssr.c index fd54b9f625da..4a43ebec7d5e 100644 --- a/drivers/clk/renesas/r8a774a1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774a1-cpg-mssr.c @@ -41,6 +41,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, /* Module Clocks */ @@ -67,6 +68,12 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A774A1_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774A1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774A1_CLK_RPC), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -200,6 +207,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A774A1_CLK_S3D2), DEF_MOD("can-if1", 915, R8A774A1_CLK_S3D4), DEF_MOD("can-if0", 916, R8A774A1_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774A1_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A774A1_CLK_S0D6), DEF_MOD("i2c5", 919, R8A774A1_CLK_S0D6), DEF_MOD("i2c-dvfs", 926, R8A774A1_CLK_CP), diff --git a/drivers/clk/renesas/r8a774b1-cpg-mssr.c b/drivers/clk/renesas/r8a774b1-cpg-mssr.c index f436691271ec..6f04c40fe237 100644 --- a/drivers/clk/renesas/r8a774b1-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774b1-cpg-mssr.c @@ -40,6 +40,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, /* Module Clocks */ @@ -65,6 +66,12 @@ static const struct cpg_core_clk r8a774b1_core_clks[] __initconst = { DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1_DIV2, 2, 1), + DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1), + + DEF_BASE("rpc", R8A774B1_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774B1_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774B1_CLK_RPC), DEF_GEN3_OSC(".r", CLK_RINT, CLK_EXTAL, 32), @@ -196,6 +203,7 @@ static const struct mssr_mod_clk r8a774b1_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A774B1_CLK_S3D2), DEF_MOD("can-if1", 915, R8A774B1_CLK_S3D4), DEF_MOD("can-if0", 916, R8A774B1_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774B1_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A774B1_CLK_S0D6), DEF_MOD("i2c5", 919, R8A774B1_CLK_S0D6), DEF_MOD("i2c-dvfs", 926, R8A774B1_CLK_CP), diff --git a/drivers/clk/renesas/r8a774c0-cpg-mssr.c b/drivers/clk/renesas/r8a774c0-cpg-mssr.c index 9fc9fa9e531a..ed3a2cf0e0bb 100644 --- a/drivers/clk/renesas/r8a774c0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a774c0-cpg-mssr.c @@ -44,6 +44,7 @@ enum clk_ids { CLK_S2, CLK_S3, CLK_SDSRC, + CLK_RPCSRC, CLK_RINT, CLK_OCO, @@ -74,6 +75,13 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = { DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), + DEF_FIXED_RPCSRC_E3(".rpcsrc", CLK_RPCSRC, CLK_PLL0, CLK_PLL1), + + DEF_BASE("rpc", R8A774C0_CLK_RPC, CLK_TYPE_GEN3_RPC, + CLK_RPCSRC), + DEF_BASE("rpcd2", R8A774C0_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2, + R8A774C0_CLK_RPC), + DEF_DIV6_RO(".r", CLK_RINT, CLK_EXTAL, CPG_RCKCR, 32), DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), @@ -199,6 +207,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = { DEF_MOD("can-fd", 914, R8A774C0_CLK_S3D2), DEF_MOD("can-if1", 915, R8A774C0_CLK_S3D4), DEF_MOD("can-if0", 916, R8A774C0_CLK_S3D4), + DEF_MOD("rpc-if", 917, R8A774C0_CLK_RPCD2), DEF_MOD("i2c6", 918, R8A774C0_CLK_S3D2), DEF_MOD("i2c5", 919, R8A774C0_CLK_S3D2), DEF_MOD("i2c-dvfs", 926, R8A774C0_CLK_CP), diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index 17ebbac7ddfb..aa5389b04d74 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -26,7 +26,6 @@ #include <dt-bindings/clock/r8a779a0-cpg-mssr.h> #include "renesas-cpg-mssr.h" -#include "rcar-gen3-cpg.h" enum rcar_r8a779a0_clk_types { CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM, @@ -84,6 +83,14 @@ enum clk_ids { DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \ .offset = _offset) +#define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \ + DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL, \ + (_parent0) << 16 | (_parent1), \ + .div = (_div0) << 16 | (_div1), .offset = _md) + +#define DEF_OSC(_name, _id, _parent, _div) \ + DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_OSC, _parent, .div = _div) + static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { /* External Clock Inputs */ DEF_INPUT("extal", CLK_EXTAL), @@ -136,15 +143,51 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880), - DEF_GEN3_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8), - DEF_GEN3_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1), + DEF_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8), + DEF_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1), }; static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { + DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0), + DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), + DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), + DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0), DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8), + DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1), + DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1), + DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1), + DEF_MOD("vin03", 801, R8A779A0_CLK_S1D1), + DEF_MOD("vin04", 802, R8A779A0_CLK_S1D1), + DEF_MOD("vin05", 803, R8A779A0_CLK_S1D1), + DEF_MOD("vin06", 804, R8A779A0_CLK_S1D1), + DEF_MOD("vin07", 805, R8A779A0_CLK_S1D1), + DEF_MOD("vin10", 806, R8A779A0_CLK_S1D1), + DEF_MOD("vin11", 807, R8A779A0_CLK_S1D1), + DEF_MOD("vin12", 808, R8A779A0_CLK_S1D1), + DEF_MOD("vin13", 809, R8A779A0_CLK_S1D1), + DEF_MOD("vin14", 810, R8A779A0_CLK_S1D1), + DEF_MOD("vin15", 811, R8A779A0_CLK_S1D1), + DEF_MOD("vin16", 812, R8A779A0_CLK_S1D1), + DEF_MOD("vin17", 813, R8A779A0_CLK_S1D1), + DEF_MOD("vin20", 814, R8A779A0_CLK_S1D1), + DEF_MOD("vin21", 815, R8A779A0_CLK_S1D1), + DEF_MOD("vin22", 816, R8A779A0_CLK_S1D1), + DEF_MOD("vin23", 817, R8A779A0_CLK_S1D1), + DEF_MOD("vin24", 818, R8A779A0_CLK_S1D1), + DEF_MOD("vin25", 819, R8A779A0_CLK_S1D1), + DEF_MOD("vin26", 820, R8A779A0_CLK_S1D1), + DEF_MOD("vin27", 821, R8A779A0_CLK_S1D1), + DEF_MOD("vin30", 822, R8A779A0_CLK_S1D1), + DEF_MOD("vin31", 823, R8A779A0_CLK_S1D1), + DEF_MOD("vin32", 824, R8A779A0_CLK_S1D1), + DEF_MOD("vin33", 825, R8A779A0_CLK_S1D1), + DEF_MOD("vin34", 826, R8A779A0_CLK_S1D1), + DEF_MOD("vin35", 827, R8A779A0_CLK_S1D1), + DEF_MOD("vin36", 828, R8A779A0_CLK_S1D1), + DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1), }; static spinlock_t cpg_lock; @@ -153,7 +196,7 @@ static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; static u32 cpg_mode __initdata; -struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, +static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, const struct cpg_core_clk *core, const struct cpg_mssr_info *info, struct clk **clks, void __iomem *base, struct raw_notifier_head *notifiers) diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 488f8b3980c5..063b61151488 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -224,10 +224,9 @@ static struct clk * __init cpg_z_clk_register(const char *name, #define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) #define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) -#define CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) \ +#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \ { \ .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ - ((stp_ck) ? CPG_SD_STP_CK : 0) | \ ((sd_srcfc) << 2) | \ ((sd_fc) << 0), \ .div = (sd_div), \ @@ -247,36 +246,36 @@ struct sd_clock { }; /* SDn divider - * sd_srcfc sd_fc div - * stp_hck stp_ck (div) (div) = sd_srcfc x sd_fc - *------------------------------------------------------------------- - * 0 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) - * 0 0 1 (2) 1 (4) 8 : SDR50 - * 1 0 2 (4) 1 (4) 16 : HS / SDR25 - * 1 0 3 (8) 1 (4) 32 : NS / SDR12 - * 1 0 4 (16) 1 (4) 64 - * 0 0 0 (1) 0 (2) 2 - * 0 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) - * 1 0 2 (4) 0 (2) 8 - * 1 0 3 (8) 0 (2) 16 - * 1 0 4 (16) 0 (2) 32 + * sd_srcfc sd_fc div + * stp_hck (div) (div) = sd_srcfc x sd_fc + *--------------------------------------------------------- + * 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) + * 0 1 (2) 1 (4) 8 : SDR50 + * 1 2 (4) 1 (4) 16 : HS / SDR25 + * 1 3 (8) 1 (4) 32 : NS / SDR12 + * 1 4 (16) 1 (4) 64 + * 0 0 (1) 0 (2) 2 + * 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) + * 1 2 (4) 0 (2) 8 + * 1 3 (8) 0 (2) 16 + * 1 4 (16) 0 (2) 32 * * NOTE: There is a quirk option to ignore the first row of the dividers * table when searching for suitable settings. This is because HS400 on * early ES versions of H3 and M3-W requires a specific setting to work. */ static const struct sd_div_table cpg_sd_div_table[] = { -/* CPG_SD_DIV_TABLE_DATA(stp_hck, stp_ck, sd_srcfc, sd_fc, sd_div) */ - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 1, 4), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 1, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 1, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 1, 32), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 1, 64), - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 0, 2), - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 0, 4), - CPG_SD_DIV_TABLE_DATA(1, 0, 2, 0, 8), - CPG_SD_DIV_TABLE_DATA(1, 0, 3, 0, 16), - CPG_SD_DIV_TABLE_DATA(1, 0, 4, 0, 32), +/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */ + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4), + CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8), + CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16), + CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32), + CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64), + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2), + CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4), + CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8), + CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16), + CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32), }; #define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) @@ -696,6 +695,34 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, cpg_rpcsrc_div_table, &cpg_lock); + case CLK_TYPE_GEN3_E3_RPCSRC: + /* + * Register RPCSRC as fixed factor clock based on the + * MD[4:1] pins and CPG_RPCCKCR[4:3] register value for + * which has been set prior to booting the kernel. + */ + value = (readl(base + CPG_RPCCKCR) & GENMASK(4, 3)) >> 3; + + switch (value) { + case 0: + div = 5; + break; + case 1: + div = 3; + break; + case 2: + parent = clks[core->parent >> 16]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + div = core->div; + break; + case 3: + default: + div = 2; + break; + } + break; + case CLK_TYPE_GEN3_RPC: return cpg_rpc_clk_register(core->name, base, __clk_get_name(parent), notifiers); diff --git a/drivers/clk/renesas/rcar-gen3-cpg.h b/drivers/clk/renesas/rcar-gen3-cpg.h index c4ac80cac6a0..3d949c4a3244 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.h +++ b/drivers/clk/renesas/rcar-gen3-cpg.h @@ -24,6 +24,7 @@ enum rcar_gen3_clk_types { CLK_TYPE_GEN3_OSC, /* OSC EXTAL predivider and fixed divider */ CLK_TYPE_GEN3_RCKSEL, /* Select parent/divider using RCKCR.CKSEL */ CLK_TYPE_GEN3_RPCSRC, + CLK_TYPE_GEN3_E3_RPCSRC, CLK_TYPE_GEN3_RPC, CLK_TYPE_GEN3_RPCD2, @@ -54,6 +55,10 @@ enum rcar_gen3_clk_types { #define DEF_GEN3_Z(_name, _id, _type, _parent, _div, _offset) \ DEF_BASE(_name, _id, _type, _parent, .div = _div, .offset = _offset) +#define DEF_FIXED_RPCSRC_E3(_name, _id, _parent0, _parent1) \ + DEF_BASE(_name, _id, CLK_TYPE_GEN3_E3_RPCSRC, \ + (_parent0) << 16 | (_parent1), .div = 8) + struct rcar_gen3_cpg_pll_config { u8 extal_div; u8 pll1_mult; diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index d4c02986c34e..3abafd78f7c8 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -160,7 +160,7 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (ret < 0) return ret; - priv->rsts = devm_reset_control_array_get(dev, true, false); + priv->rsts = devm_reset_control_array_get_shared(dev); if (IS_ERR(priv->rsts)) return PTR_ERR(priv->rsts); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 94db88370337..1c3215dc4877 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -119,7 +119,8 @@ static const u16 srstclr_for_v3u[] = { }; /** - * Clock Pulse Generator / Module Standby and Software Reset Private Data + * struct cpg_mssr_priv - Clock Pulse Generator / Module Standby + * and Software Reset Private Data * * @rcdev: Optional reset controller entity * @dev: CPG/MSSR device diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig index 57d4b3f20417..9323fcfac6cc 100644 --- a/drivers/clk/samsung/Kconfig +++ b/drivers/clk/samsung/Kconfig @@ -2,10 +2,73 @@ # Recent Exynos platforms should just select COMMON_CLK_SAMSUNG: config COMMON_CLK_SAMSUNG bool "Samsung Exynos clock controller support" if COMPILE_TEST - # Clocks on ARM64 SoCs (e.g. Exynos5433, Exynos7) are chosen by - # EXYNOS_ARM64_COMMON_CLK to avoid building them on ARMv7: + select S3C64XX_COMMON_CLK if ARM && ARCH_S3C64XX + select S5PV210_COMMON_CLK if ARM && ARCH_S5PV210 + select EXYNOS_3250_COMMON_CLK if ARM && SOC_EXYNOS3250 + select EXYNOS_4_COMMON_CLK if ARM && ARCH_EXYNOS4 + select EXYNOS_5250_COMMON_CLK if ARM && SOC_EXYNOS5250 + select EXYNOS_5260_COMMON_CLK if ARM && SOC_EXYNOS5260 + select EXYNOS_5410_COMMON_CLK if ARM && SOC_EXYNOS5410 + select EXYNOS_5420_COMMON_CLK if ARM && SOC_EXYNOS5420 select EXYNOS_ARM64_COMMON_CLK if ARM64 && ARCH_EXYNOS +config S3C64XX_COMMON_CLK + bool "Samsung S3C64xx clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung S3C64xx SoCs. + Choose Y here only if you build for this SoC. + +config S5PV210_COMMON_CLK + bool "Samsung S5Pv210 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung S5Pv210 SoCs. + Choose Y here only if you build for this SoC. + +config EXYNOS_3250_COMMON_CLK + bool "Samsung Exynos3250 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos3250 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_4_COMMON_CLK + bool "Samsung Exynos4 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos4212 and Exynos4412 SoCs. Choose Y here only if you build for + this SoC. + +config EXYNOS_5250_COMMON_CLK + bool "Samsung Exynos5250 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5250 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_5260_COMMON_CLK + bool "Samsung Exynos5260 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5260 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_5410_COMMON_CLK + bool "Samsung Exynos5410 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5410 SoCs. Choose Y here only if you build for this SoC. + +config EXYNOS_5420_COMMON_CLK + bool "Samsung Exynos5420 clock controller support" if COMPILE_TEST + depends on COMMON_CLK_SAMSUNG + help + Support for the clock controller present on the Samsung + Exynos5420 SoCs. Choose Y here only if you build for this SoC. + config EXYNOS_ARM64_COMMON_CLK bool "Samsung Exynos ARMv8-family clock controller support" if COMPILE_TEST depends on COMMON_CLK_SAMSUNG diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 1a4e6b787978..bb1433f11c88 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -4,15 +4,15 @@ # obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o clk-cpu.o -obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o -obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o -obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4412-isp.o -obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o -obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5-subcmu.o -obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o -obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o -obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o -obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o +obj-$(CONFIG_EXYNOS_3250_COMMON_CLK) += clk-exynos3250.o +obj-$(CONFIG_EXYNOS_4_COMMON_CLK) += clk-exynos4.o +obj-$(CONFIG_EXYNOS_4_COMMON_CLK) += clk-exynos4412-isp.o +obj-$(CONFIG_EXYNOS_5250_COMMON_CLK) += clk-exynos5250.o +obj-$(CONFIG_EXYNOS_5250_COMMON_CLK) += clk-exynos5-subcmu.o +obj-$(CONFIG_EXYNOS_5260_COMMON_CLK) += clk-exynos5260.o +obj-$(CONFIG_EXYNOS_5410_COMMON_CLK) += clk-exynos5410.o +obj-$(CONFIG_EXYNOS_5420_COMMON_CLK) += clk-exynos5420.o +obj-$(CONFIG_EXYNOS_5420_COMMON_CLK) += clk-exynos5-subcmu.o obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o @@ -21,5 +21,5 @@ obj-$(CONFIG_S3C2410_COMMON_CLK)+= clk-s3c2410.o obj-$(CONFIG_S3C2410_COMMON_DCLK)+= clk-s3c2410-dclk.o obj-$(CONFIG_S3C2412_COMMON_CLK)+= clk-s3c2412.o obj-$(CONFIG_S3C2443_COMMON_CLK)+= clk-s3c2443.o -obj-$(CONFIG_ARCH_S3C64XX) += clk-s3c64xx.o -obj-$(CONFIG_ARCH_S5PV210) += clk-s5pv210.o clk-s5pv210-audss.o +obj-$(CONFIG_S3C64XX_COMMON_CLK) += clk-s3c64xx.o +obj-$(CONFIG_S5PV210_COMMON_CLK) += clk-s5pv210.o clk-s5pv210-audss.o diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index ac70ad785d8e..5873a9354b50 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -8,14 +8,17 @@ #include <linux/errno.h> #include <linux/hrtimer.h> +#include <linux/iopoll.h> #include <linux/delay.h> #include <linux/slab.h> +#include <linux/timekeeping.h> #include <linux/clk-provider.h> #include <linux/io.h> #include "clk.h" #include "clk-pll.h" -#define PLL_TIMEOUT_MS 10 +#define PLL_TIMEOUT_US 20000U +#define PLL_TIMEOUT_LOOPS 1000000U struct samsung_clk_pll { struct clk_hw hw; @@ -63,6 +66,53 @@ static long samsung_pll_round_rate(struct clk_hw *hw, return rate_table[i - 1].rate; } +static bool pll_early_timeout = true; + +static int __init samsung_pll_disable_early_timeout(void) +{ + pll_early_timeout = false; + return 0; +} +arch_initcall(samsung_pll_disable_early_timeout); + +/* Wait until the PLL is locked */ +static int samsung_pll_lock_wait(struct samsung_clk_pll *pll, + unsigned int reg_mask) +{ + int i, ret; + u32 val; + + /* + * This function might be called when the timekeeping API can't be used + * to detect timeouts. One situation is when the clocksource is not yet + * initialized, another when the timekeeping is suspended. udelay() also + * cannot be used when the clocksource is not running on arm64, since + * the current timer is used as cycle counter. So a simple busy loop + * is used here in that special cases. The limit of iterations has been + * derived from experimental measurements of various PLLs on multiple + * Exynos SoC variants. Single register read time was usually in range + * 0.4...1.5 us, never less than 0.4 us. + */ + if (pll_early_timeout || timekeeping_suspended) { + i = PLL_TIMEOUT_LOOPS; + while (i-- > 0) { + if (readl_relaxed(pll->con_reg) & reg_mask) + return 0; + + cpu_relax(); + } + ret = -ETIMEDOUT; + } else { + ret = readl_relaxed_poll_timeout_atomic(pll->con_reg, val, + val & reg_mask, 0, PLL_TIMEOUT_US); + } + + if (ret < 0) + pr_err("Could not lock PLL %s\n", clk_hw_get_name(&pll->hw)); + + return ret; +} + static int samsung_pll3xxx_enable(struct clk_hw *hw) { struct samsung_clk_pll *pll = to_clk_pll(hw); @@ -72,13 +122,7 @@ static int samsung_pll3xxx_enable(struct clk_hw *hw) tmp |= BIT(pll->enable_offs); writel_relaxed(tmp, pll->con_reg); - /* wait lock time */ - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & BIT(pll->lock_offs))); - - return 0; + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); } static void samsung_pll3xxx_disable(struct clk_hw *hw) @@ -240,13 +284,10 @@ static int samsung_pll35xx_set_rate(struct clk_hw *hw, unsigned long drate, (rate->sdiv << PLL35XX_SDIV_SHIFT); writel_relaxed(tmp, pll->con_reg); - /* Wait until the PLL is locked if it is enabled. */ - if (tmp & BIT(pll->enable_offs)) { - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & BIT(pll->lock_offs))); - } + /* Wait for PLL lock if the PLL is enabled */ + if (tmp & BIT(pll->enable_offs)) + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); + return 0; } @@ -318,7 +359,7 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long parent_rate) { struct samsung_clk_pll *pll = to_clk_pll(hw); - u32 tmp, pll_con0, pll_con1; + u32 pll_con0, pll_con1; const struct samsung_pll_rate_table *rate; rate = samsung_get_pll_settings(pll, drate); @@ -356,13 +397,8 @@ static int samsung_pll36xx_set_rate(struct clk_hw *hw, unsigned long drate, pll_con1 |= rate->kdiv << PLL36XX_KDIV_SHIFT; writel_relaxed(pll_con1, pll->con_reg + 4); - /* wait_lock_time */ - if (pll_con0 & BIT(pll->enable_offs)) { - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & BIT(pll->lock_offs))); - } + if (pll_con0 & BIT(pll->enable_offs)) + return samsung_pll_lock_wait(pll, BIT(pll->lock_offs)); return 0; } @@ -437,7 +473,6 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, struct samsung_clk_pll *pll = to_clk_pll(hw); const struct samsung_pll_rate_table *rate; u32 con0, con1; - ktime_t start; /* Get required rate settings from table */ rate = samsung_get_pll_settings(pll, drate); @@ -488,21 +523,8 @@ static int samsung_pll45xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(con1, pll->con_reg + 0x4); writel_relaxed(con0, pll->con_reg); - /* Wait for locking. */ - start = ktime_get(); - while (!(readl_relaxed(pll->con_reg) & PLL45XX_LOCKED)) { - ktime_t delta = ktime_sub(ktime_get(), start); - - if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { - pr_err("%s: could not lock PLL %s\n", - __func__, clk_hw_get_name(hw)); - return -EFAULT; - } - - cpu_relax(); - } - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, PLL45XX_LOCKED); } static const struct clk_ops samsung_pll45xx_clk_ops = { @@ -588,7 +610,6 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, struct samsung_clk_pll *pll = to_clk_pll(hw); const struct samsung_pll_rate_table *rate; u32 con0, con1, lock; - ktime_t start; /* Get required rate settings from table */ rate = samsung_get_pll_settings(pll, drate); @@ -647,21 +668,8 @@ static int samsung_pll46xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(con0, pll->con_reg); writel_relaxed(con1, pll->con_reg + 0x4); - /* Wait for locking. */ - start = ktime_get(); - while (!(readl_relaxed(pll->con_reg) & PLL46XX_LOCKED)) { - ktime_t delta = ktime_sub(ktime_get(), start); - - if (ktime_to_ms(delta) > PLL_TIMEOUT_MS) { - pr_err("%s: could not lock PLL %s\n", - __func__, clk_hw_get_name(hw)); - return -EFAULT; - } - - cpu_relax(); - } - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, PLL46XX_LOCKED); } static const struct clk_ops samsung_pll46xx_clk_ops = { @@ -1035,14 +1043,9 @@ static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate, (rate->sdiv << PLL2550XX_S_SHIFT); writel_relaxed(tmp, pll->con_reg); - /* wait_lock_time */ - do { - cpu_relax(); - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK - << PLL2550XX_LOCK_STAT_SHIFT))); - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, + PLL2550XX_LOCK_STAT_MASK << PLL2550XX_LOCK_STAT_SHIFT); } static const struct clk_ops samsung_pll2550xx_clk_ops = { @@ -1132,13 +1135,9 @@ static int samsung_pll2650x_set_rate(struct clk_hw *hw, unsigned long drate, con1 |= ((rate->kdiv & PLL2650X_K_MASK) << PLL2650X_K_SHIFT); writel_relaxed(con1, pll->con_reg + 4); - do { - cpu_relax(); - con0 = readl_relaxed(pll->con_reg); - } while (!(con0 & (PLL2650X_LOCK_STAT_MASK - << PLL2650X_LOCK_STAT_SHIFT))); - - return 0; + /* Wait for PLL lock */ + return samsung_pll_lock_wait(pll, + PLL2650X_LOCK_STAT_MASK << PLL2650X_LOCK_STAT_SHIFT); } static const struct clk_ops samsung_pll2650x_clk_ops = { @@ -1196,7 +1195,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, unsigned long parent_rate) { struct samsung_clk_pll *pll = to_clk_pll(hw); - u32 tmp, pll_con0, pll_con2; + u32 pll_con0, pll_con2; const struct samsung_pll_rate_table *rate; rate = samsung_get_pll_settings(pll, drate); @@ -1229,11 +1228,7 @@ static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, writel_relaxed(pll_con0, pll->con_reg); writel_relaxed(pll_con2, pll->con_reg + 8); - do { - tmp = readl_relaxed(pll->con_reg); - } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT))); - - return 0; + return samsung_pll_lock_wait(pll, 0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT); } static const struct clk_ops samsung_pll2650xx_clk_ops = { |