summaryrefslogtreecommitdiff
path: root/drivers/clk/clk.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-08-16 07:41:21 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2018-08-16 07:41:21 +0300
commitdb06f826ec12bf0701ea7fc0a3c0aa00b84417c8 (patch)
tree0f5cd2bb7af57574ae8a20bfc0e916512c5f2255 /drivers/clk/clk.c
parent6de4c691eab8f421e34c5250f63bf3f477d30eec (diff)
parentac7da1b787d9ea43680c487613269742c48d8747 (diff)
downloadlinux-db06f826ec12bf0701ea7fc0a3c0aa00b84417c8.tar.xz
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk updates from Stephen Boyd: "The new and exciting feature this time around is in the clk core. We've added duty cycle support to the clk API so that clk signal duty cycle ratios can be adjusted while taking into account things like clk dividers and clk tree hierarchy. So far only one SoC has implemented support for this, but I expect there will be more to come in the future. Outside of the core, we have the usual pile of clk driver updates and additions. The Amlogic meson driver got the most lines in the diffstat this time around because it added support for a whole bunch of hardware and duty cycle configuration. After that the Rockchip PX30, Qualcomm SDM845, and Renesas SoC drivers fill in a majority of the diff. We're left with the collection of non-critical fixes after that. Overall it looks pretty quiet this time. Core: - Clk duty cycle support - Proper CLK_SET_RATE_GATE support throughout the tree New Drivers: - Actions Semi Owl series S700 SoC clk driver - Qualcomm SDM845 display clock controller - i.MX6SX ocram_s clk support - Uniphier NAND, USB3 PHY, and SPI clk support - Qualcomm RPMh clk driver - i.MX7D mailbox clk support - Maxim 9485 Programmable Clock Generator - expose 32 kHz PLL on PXA SoCs - imx6sll GPIO clk gate support - Atmel at91 I2S audio clk support - SI544/SI514 clk on/off support - i.MX6UL GPIO clock gates in CCM CCGR - Renesas Crypto Engine clocks on R-Car H3 - Renesas clk support for the new RZ/N1D SoC - Allwinner A64 display engine clock support - support for Rockchip's PX30 SoC - Amlogic Meson axg PCIe and audio clocks - Amlogic Meson GEN CLK on gxbb, gxl and axg Updates: - remove an unused variable from Exynos4412 ISP driver - fix a thinko bug in SCMI clk division logic - add missing of_node_put()s in some i.MX clk drivers - Tegra SDMMC clk jitter improvements with high speed signaling modes - SPDX tagging for qcom and cs2000-cp drivers - stop leaking con ids in __clk_put() - fix a corner case in fixed factor clk probing where node is in DT but parent clk is registered much later - Marvell Armada 3700 clk_pm_cpu_get_parent() had an invalid return value - i.MX clk init arrays removed in place of CLK_IS_CRITICAL - convert to CLK_IS_CRITICAL for i.MX51/53 driver - fix Tegra BPMP driver oops when xlating a NULL clk - proper default configuration for vic03 and vde clks on Tegra124 - mark Tegra memory controller clks as critical - fix array bounds clamp in Tegra's emc determine_rate() op - Ingenic i2s bit update and allow UDC clk to gate - fix name of aspeed SDC clk define to have only one 'CLK' - fix i.MX6QDL video clk parent - critical clk markings for qcom SDM845 - fix Stratix10 mpu_free_clk and sdmmc_free_clk parents - mark Rockchip's pclk_rkpwm_pmu as critical clock, due to it supplying the pwm used to drive the logic supply of the rk3399 core" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (85 commits) clk: rockchip: Add pclk_rkpwm_pmu to PMU critical clocks in rk3399 clk: cs2000-cp: convert to SPDX identifiers clk: scmi: Fix the rounding of clock rate clk: qcom: Add display clock controller driver for SDM845 clk: mvebu: armada-37xx-periph: Remove unused var num_parents clk: samsung: Remove unused mout_user_aclk400_mcuisp_p4x12 variable clk: actions: Add S700 SoC clock support dt-bindings: clock: Add S700 support for Actions Semi Soc's clk: actions: Add missing REGMAP_MMIO dependency clk: uniphier: add clock frequency support for SPI clk: uniphier: add more USB3 PHY clocks clk: uniphier: add NAND 200MHz clock clk: tegra: make sdmmc2 and sdmmc4 as sdmmc clocks clk: tegra: Add sdmmc mux divider clock clk: tegra: Refactor fractional divider calculation clk: tegra: Fix includes required by fence_udelay() clk: imx6sll: fix missing of_node_put() clk: imx6ul: fix missing of_node_put() clk: imx: add ocram_s clock for i.mx6sx clk: mvebu: armada-37xx-periph: Fix wrong return value in get_parent ...
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r--drivers/clk/clk.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 976f59e11f9a..d31055ae6ec6 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -691,6 +691,9 @@ static void clk_core_unprepare(struct clk_core *core)
"Unpreparing critical %s\n", core->name))
return;
+ if (core->flags & CLK_SET_RATE_GATE)
+ clk_core_rate_unprotect(core);
+
if (--core->prepare_count > 0)
return;
@@ -765,6 +768,16 @@ static int clk_core_prepare(struct clk_core *core)
core->prepare_count++;
+ /*
+ * CLK_SET_RATE_GATE is a special case of clock protection
+ * Instead of a consumer claiming exclusive rate control, it is
+ * actually the provider which prevents any consumer from making any
+ * operation which could result in a rate change or rate glitch while
+ * the clock is prepared.
+ */
+ if (core->flags & CLK_SET_RATE_GATE)
+ clk_core_rate_protect(core);
+
return 0;
unprepare:
clk_core_unprepare(core->parent);
@@ -1888,9 +1901,6 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
if (clk_core_rate_is_protected(core))
return -EBUSY;
- if ((core->flags & CLK_SET_RATE_GATE) && core->prepare_count)
- return -EBUSY;
-
/* calculate new rates and get the topmost changed clock */
top = clk_calc_new_rates(core, req_rate);
if (!top)
@@ -3122,6 +3132,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
return clk;
}
+/* keep in sync with __clk_put */
void __clk_free_clk(struct clk *clk)
{
clk_prepare_lock();
@@ -3501,6 +3512,7 @@ int __clk_get(struct clk *clk)
return 1;
}
+/* keep in sync with __clk_free_clk */
void __clk_put(struct clk *clk)
{
struct module *owner;
@@ -3534,6 +3546,7 @@ void __clk_put(struct clk *clk)
module_put(owner);
+ kfree_const(clk->con_id);
kfree(clk);
}