* [PATCH v13 0/9] Per-user clock constraints
@ 2014-09-23 18:40 Tomeu Vizoso
2014-09-23 18:40 ` [PATCH v13 1/9] clk: Add temporary mapping to the existing API Tomeu Vizoso
` (3 more replies)
0 siblings, 4 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:40 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
Hello,
this version of the patchset addresses some issues that Russell pointed out
yesterday:
* Refactor the changes to clkdev.c to reduce the amount of ifdefs.
* Properly release clocks when there isn't enough memory to create the per-user
wrapper.
* Add clk_provider_put(struct clk_core*) for clock implementations to call
instead of clk_put(struct clk*) (instead of exposing __clk_put).
As the previous versions, this is based on top of 3.17-rc4 and Mike's patch at
[0].
Follows the original cover letter blurb:
I'm retaking Rabin's patches [1] for splitting the clk API in two: one API for
clk consumers and another for providers. The consumer API uses a clk structure
that just keeps track of the consumer and has a reference to the actual
clk_core struct, which is used internally.
I have kept a patch from Rabin that aims to aid in debugging nested
enable/disable calls, though my personal aim is to allow more than one consumer
to influence the final, effective frequency rate. For now this is limited to
setting floor and ceiling constraints, with the short-term aim of allowing
devfreq and thermal drivers to set floor and ceiling frequencies on the memory
clock, respectively.
For those functions in the consumer clk API that were called from providers, I
have added variants to clk-provider.h that are the same only that accept a
clk_core instead. These functions are prefixed with clk_provider_.
Patch 1/9 just adds a bunch of defines with the goal of having all the renames
in their own commit while preserving git-bisectability, with patch 2/9
containing the rename itself as generated by the Coccinelle script in [2]. The
actual implementation of the API split comes in patch 3/9. I will be happy to
organize the refactoring differently if anybody has a better idea.
Patch 4/9 warns when there's an unbalanced usage of the enable and disable
APIs, and patch 5/9 adds the API for setting floor and ceiling frequencies, per
consumer. Patch 6/9 will warn when prepare/unprepare are used unbalanced,
printing the code location of the last call to unprepare.
Patches 7/9 and 8/9 add some locking when manipulating shared structures and
9/9 adds a bit to the API docs.
[0] http://permalink.gmane.org/gmane.linux.kernel/1782807
[1] http://thread.gmane.org/gmane.linux.kernel/1402006
[2] http://cgit.collabora.com/git/user/tomeu/linux.git/log/?h=clk-refactoring-13
Thanks,
Tomeu
Tomeu Vizoso (9):
clk: Add temporary mapping to the existing API
clk: Move all drivers to use internal API
clk: use struct clk only for external API
clk: per-user clock accounting for debug
clk: Add floor and ceiling constraints to clock rates
clk: Warn of unbalanced clk_prepare() calls
clk: Take the prepare lock when updating the list of per-user clks
clk: Take the prepare lock when updating the per-user constraints
clk: Add docs about calling clk_put after clk_get_parent
arch/arm/mach-dove/common.c | 10 +-
arch/arm/mach-imx/clk-busy.c | 9 +-
arch/arm/mach-imx/clk-fixup-div.c | 4 +-
arch/arm/mach-imx/clk-fixup-mux.c | 4 +-
arch/arm/mach-imx/clk-gate2.c | 4 +-
arch/arm/mach-imx/clk-imx1.c | 3 +-
arch/arm/mach-imx/clk-imx21.c | 3 +-
arch/arm/mach-imx/clk-imx25.c | 9 +-
arch/arm/mach-imx/clk-imx27.c | 5 +-
arch/arm/mach-imx/clk-imx31.c | 11 +-
arch/arm/mach-imx/clk-imx35.c | 23 +-
arch/arm/mach-imx/clk-imx51-imx53.c | 78 +--
arch/arm/mach-imx/clk-imx6q.c | 54 +-
arch/arm/mach-imx/clk-imx6sl.c | 14 +-
arch/arm/mach-imx/clk-imx6sx.c | 98 +--
arch/arm/mach-imx/clk-pfd.c | 5 +-
arch/arm/mach-imx/clk-pllv1.c | 5 +-
arch/arm/mach-imx/clk-pllv2.c | 5 +-
arch/arm/mach-imx/clk-pllv3.c | 5 +-
arch/arm/mach-imx/clk-vf610.c | 43 +-
arch/arm/mach-imx/clk.c | 11 +-
arch/arm/mach-imx/clk.h | 42 +-
arch/arm/mach-msm/clock-pcom.c | 2 +-
arch/arm/mach-msm/clock.c | 2 +-
arch/arm/mach-mv78xx0/common.c | 2 +-
arch/arm/mach-omap2/board-cm-t35.c | 2 +-
arch/arm/mach-omap2/cclock3xxx_data.c | 371 ++++++------
arch/arm/mach-omap2/clkt2xxx_dpll.c | 5 +-
arch/arm/mach-omap2/clkt2xxx_dpllcore.c | 5 +-
arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c | 11 +-
arch/arm/mach-omap2/clkt34xx_dpll3m2.c | 3 +-
arch/arm/mach-omap2/clkt_clksel.c | 46 +-
arch/arm/mach-omap2/clkt_dpll.c | 8 +-
arch/arm/mach-omap2/clock.c | 52 +-
arch/arm/mach-omap2/clock.h | 18 +-
arch/arm/mach-omap2/clock3xxx.c | 23 +-
arch/arm/mach-omap2/clock3xxx.h | 4 +-
arch/arm/mach-omap2/clock_common_data.c | 2 +-
arch/arm/mach-omap2/clockdomain.c | 9 +-
arch/arm/mach-omap2/clockdomain.h | 4 +-
arch/arm/mach-omap2/display.c | 6 +-
arch/arm/mach-omap2/dpll3xxx.c | 29 +-
arch/arm/mach-omap2/dpll44xx.c | 5 +-
arch/arm/mach-omap2/mcbsp.c | 5 +-
arch/arm/mach-omap2/omap_device.c | 10 +-
arch/arm/mach-omap2/omap_hwmod.c | 42 +-
arch/arm/mach-omap2/omap_hwmod.h | 12 +-
arch/arm/mach-omap2/pm24xx.c | 12 +-
arch/arm/mach-orion5x/common.c | 2 +-
arch/arm/mach-shmobile/clock.c | 10 +-
arch/arm/mach-vexpress/spc.c | 4 +-
arch/arm/plat-orion/common.c | 22 +-
arch/arm/plat-orion/include/plat/common.h | 12 +-
arch/mips/alchemy/common/clock.c | 42 +-
arch/powerpc/platforms/512x/clock-commonclk.c | 48 +-
drivers/acpi/acpi_lpss.c | 7 +-
drivers/clk/at91/clk-main.c | 24 +-
drivers/clk/at91/clk-master.c | 6 +-
drivers/clk/at91/clk-peripheral.c | 12 +-
drivers/clk/at91/clk-pll.c | 6 +-
drivers/clk/at91/clk-plldiv.c | 6 +-
drivers/clk/at91/clk-programmable.c | 10 +-
drivers/clk/at91/clk-slow.c | 24 +-
drivers/clk/at91/clk-smd.c | 6 +-
drivers/clk/at91/clk-system.c | 6 +-
drivers/clk/at91/clk-usb.c | 18 +-
drivers/clk/at91/clk-utmi.c | 6 +-
drivers/clk/bcm/clk-kona-setup.c | 6 +-
drivers/clk/bcm/clk-kona.c | 12 +-
drivers/clk/bcm/clk-kona.h | 2 +-
drivers/clk/berlin/berlin2-avpll.c | 4 +-
drivers/clk/berlin/berlin2-avpll.h | 4 +-
drivers/clk/berlin/berlin2-div.c | 2 +-
drivers/clk/berlin/berlin2-div.h | 2 +-
drivers/clk/berlin/berlin2-pll.c | 2 +-
drivers/clk/berlin/berlin2-pll.h | 2 +-
drivers/clk/berlin/bg2.c | 14 +-
drivers/clk/berlin/bg2q.c | 10 +-
drivers/clk/clk-axi-clkgen.c | 3 +-
drivers/clk/clk-axm5516.c | 4 +-
drivers/clk/clk-bcm2835.c | 2 +-
drivers/clk/clk-clps711x.c | 3 +-
drivers/clk/clk-composite.c | 11 +-
drivers/clk/clk-conf.c | 18 +-
drivers/clk/clk-devres.c | 31 +
drivers/clk/clk-divider.c | 8 +-
drivers/clk/clk-efm32gg.c | 3 +-
drivers/clk/clk-fixed-factor.c | 6 +-
drivers/clk/clk-fixed-rate.c | 8 +-
drivers/clk/clk-fractional-divider.c | 4 +-
drivers/clk/clk-gate.c | 4 +-
drivers/clk/clk-highbank.c | 8 +-
drivers/clk/clk-ls1x.c | 16 +-
drivers/clk/clk-max77686.c | 10 +-
drivers/clk/clk-moxart.c | 8 +-
drivers/clk/clk-mux.c | 7 +-
drivers/clk/clk-nomadik.c | 15 +-
drivers/clk/clk-nspire.c | 4 +-
drivers/clk/clk-palmas.c | 7 +-
drivers/clk/clk-ppc-corenet.c | 8 +-
drivers/clk/clk-s2mps11.c | 6 +-
drivers/clk/clk-si5351.c | 17 +-
drivers/clk/clk-si570.c | 4 +-
drivers/clk/clk-twl6040.c | 3 +-
drivers/clk/clk-u300.c | 13 +-
drivers/clk/clk-vt8500.c | 4 +-
drivers/clk/clk-wm831x.c | 7 +-
drivers/clk/clk-xgene.c | 12 +-
drivers/clk/clk.c | 830 +++++++++++++++++---------
drivers/clk/clk.h | 12 +-
drivers/clk/clkdev.c | 160 ++++-
drivers/clk/hisilicon/clk-hi3620.c | 9 +-
drivers/clk/hisilicon/clk-hip04.c | 1 -
drivers/clk/hisilicon/clk.c | 17 +-
drivers/clk/hisilicon/clk.h | 2 +-
drivers/clk/hisilicon/clkgate-separated.c | 5 +-
drivers/clk/keystone/gate.c | 7 +-
drivers/clk/keystone/pll.c | 11 +-
drivers/clk/mmp/clk-apbc.c | 5 +-
drivers/clk/mmp/clk-apmu.c | 5 +-
drivers/clk/mmp/clk-frac.c | 4 +-
drivers/clk/mmp/clk-mmp2.c | 14 +-
drivers/clk/mmp/clk-pxa168.c | 12 +-
drivers/clk/mmp/clk-pxa910.c | 12 +-
drivers/clk/mmp/clk.h | 8 +-
drivers/clk/mvebu/clk-corediv.c | 4 +-
drivers/clk/mvebu/clk-cpu.c | 8 +-
drivers/clk/mvebu/common.c | 15 +-
drivers/clk/mxs/clk-div.c | 5 +-
drivers/clk/mxs/clk-frac.c | 5 +-
drivers/clk/mxs/clk-imx23.c | 5 +-
drivers/clk/mxs/clk-imx28.c | 5 +-
drivers/clk/mxs/clk-pll.c | 5 +-
drivers/clk/mxs/clk-ref.c | 5 +-
drivers/clk/mxs/clk.h | 17 +-
drivers/clk/qcom/clk-rcg.c | 8 +-
drivers/clk/qcom/clk-rcg2.c | 14 +-
drivers/clk/qcom/clk-regmap.c | 2 +-
drivers/clk/qcom/clk-regmap.h | 2 +-
drivers/clk/qcom/common.c | 6 +-
drivers/clk/qcom/gcc-apq8084.c | 2 +-
drivers/clk/qcom/gcc-ipq806x.c | 2 +-
drivers/clk/qcom/gcc-msm8660.c | 2 +-
drivers/clk/qcom/gcc-msm8960.c | 2 +-
drivers/clk/qcom/gcc-msm8974.c | 2 +-
drivers/clk/qcom/mmcc-msm8960.c | 6 +-
drivers/clk/rockchip/clk-pll.c | 9 +-
drivers/clk/rockchip/clk-rk3188.c | 2 +-
drivers/clk/rockchip/clk-rk3288.c | 2 +-
drivers/clk/rockchip/clk-rockchip.c | 2 +-
drivers/clk/rockchip/clk.c | 15 +-
drivers/clk/rockchip/clk.h | 5 +-
drivers/clk/samsung/clk-exynos-audss.c | 16 +-
drivers/clk/samsung/clk-exynos-clkout.c | 9 +-
drivers/clk/samsung/clk-exynos3250.c | 1 -
drivers/clk/samsung/clk-exynos4.c | 7 +-
drivers/clk/samsung/clk-exynos5250.c | 1 -
drivers/clk/samsung/clk-exynos5260.c | 1 -
drivers/clk/samsung/clk-exynos5410.c | 1 -
drivers/clk/samsung/clk-exynos5420.c | 1 -
drivers/clk/samsung/clk-exynos5440.c | 1 -
drivers/clk/samsung/clk-pll.c | 6 +-
drivers/clk/samsung/clk-pll.h | 2 +-
drivers/clk/samsung/clk-s3c2410-dclk.c | 30 +-
drivers/clk/samsung/clk-s3c2410.c | 1 -
drivers/clk/samsung/clk-s3c2412.c | 1 -
drivers/clk/samsung/clk-s3c2443.c | 1 -
drivers/clk/samsung/clk-s3c64xx.c | 1 -
drivers/clk/samsung/clk-s5pv210-audss.c | 16 +-
drivers/clk/samsung/clk-s5pv210.c | 1 -
drivers/clk/samsung/clk.c | 22 +-
drivers/clk/samsung/clk.h | 3 +-
drivers/clk/shmobile/clk-div6.c | 2 +-
drivers/clk/shmobile/clk-emev2.c | 4 +-
drivers/clk/shmobile/clk-mstp.c | 6 +-
drivers/clk/shmobile/clk-r8a7740.c | 6 +-
drivers/clk/shmobile/clk-r8a7779.c | 6 +-
drivers/clk/shmobile/clk-rcar-gen2.c | 10 +-
drivers/clk/shmobile/clk-rz.c | 6 +-
drivers/clk/sirf/clk-atlas6.c | 3 +-
drivers/clk/sirf/clk-common.c | 30 +-
drivers/clk/sirf/clk-prima2.c | 3 +-
drivers/clk/socfpga/clk-gate.c | 3 +-
drivers/clk/socfpga/clk-periph.c | 3 +-
drivers/clk/socfpga/clk-pll.c | 5 +-
drivers/clk/spear/clk-aux-synth.c | 8 +-
drivers/clk/spear/clk-frac-synth.c | 4 +-
drivers/clk/spear/clk-gpt-synth.c | 4 +-
drivers/clk/spear/clk-vco-pll.c | 8 +-
drivers/clk/spear/clk.h | 14 +-
drivers/clk/spear/spear1310_clock.c | 3 +-
drivers/clk/spear/spear1340_clock.c | 3 +-
drivers/clk/spear/spear3xx_clock.c | 17 +-
drivers/clk/spear/spear6xx_clock.c | 3 +-
drivers/clk/st/clk-flexgen.c | 12 +-
drivers/clk/st/clkgen-fsyn.c | 22 +-
drivers/clk/st/clkgen-mux.c | 32 +-
drivers/clk/st/clkgen-pll.c | 34 +-
drivers/clk/sunxi/clk-a10-hosc.c | 2 +-
drivers/clk/sunxi/clk-a20-gmac.c | 2 +-
drivers/clk/sunxi/clk-factors.c | 4 +-
drivers/clk/sunxi/clk-sun6i-apb0-gates.c | 2 +-
drivers/clk/sunxi/clk-sun6i-apb0.c | 2 +-
drivers/clk/sunxi/clk-sun6i-ar100.c | 6 +-
drivers/clk/sunxi/clk-sun8i-apb0.c | 2 +-
drivers/clk/sunxi/clk-sunxi.c | 18 +-
drivers/clk/tegra/clk-audio-sync.c | 4 +-
drivers/clk/tegra/clk-divider.c | 5 +-
drivers/clk/tegra/clk-periph-gate.c | 5 +-
drivers/clk/tegra/clk-periph.c | 9 +-
drivers/clk/tegra/clk-pll-out.c | 5 +-
drivers/clk/tegra/clk-pll.c | 41 +-
drivers/clk/tegra/clk-super.c | 5 +-
drivers/clk/tegra/clk-tegra-audio.c | 5 +-
drivers/clk/tegra/clk-tegra-fixed.c | 9 +-
drivers/clk/tegra/clk-tegra-periph.c | 13 +-
drivers/clk/tegra/clk-tegra-pmc.c | 5 +-
drivers/clk/tegra/clk-tegra-super-gen4.c | 9 +-
drivers/clk/tegra/clk-tegra114.c | 11 +-
drivers/clk/tegra/clk-tegra124.c | 7 +-
drivers/clk/tegra/clk-tegra20.c | 13 +-
drivers/clk/tegra/clk-tegra30.c | 9 +-
drivers/clk/tegra/clk.c | 25 +-
drivers/clk/tegra/clk.h | 38 +-
drivers/clk/ti/apll.c | 8 +-
drivers/clk/ti/clk-2xxx.c | 8 +-
drivers/clk/ti/clk-33xx.c | 18 +-
drivers/clk/ti/clk-3xxx.c | 8 +-
drivers/clk/ti/clk-43xx.c | 8 +-
drivers/clk/ti/clk-44xx.c | 16 +-
drivers/clk/ti/clk-54xx.c | 25 +-
drivers/clk/ti/clk-7xx.c | 28 +-
drivers/clk/ti/clk-dra7-atl.c | 6 +-
drivers/clk/ti/clk.c | 2 +-
drivers/clk/ti/clockdomain.c | 4 +-
drivers/clk/ti/composite.c | 2 +-
drivers/clk/ti/divider.c | 6 +-
drivers/clk/ti/dpll.c | 8 +-
drivers/clk/ti/fixed-factor.c | 2 +-
drivers/clk/ti/gate.c | 2 +-
drivers/clk/ti/interface.c | 2 +-
drivers/clk/ti/mux.c | 6 +-
drivers/clk/ux500/abx500-clk.c | 3 +-
drivers/clk/ux500/clk-prcc.c | 8 +-
drivers/clk/ux500/clk-prcmu.c | 16 +-
drivers/clk/ux500/clk-sysctrl.c | 10 +-
drivers/clk/ux500/clk.h | 23 +-
drivers/clk/ux500/u8500_clk.c | 3 +-
drivers/clk/ux500/u8500_of_clk.c | 13 +-
drivers/clk/ux500/u8540_clk.c | 3 +-
drivers/clk/ux500/u9540_clk.c | 1 -
drivers/clk/versatile/clk-icst.c | 5 +-
drivers/clk/versatile/clk-icst.h | 2 +-
drivers/clk/versatile/clk-impd1.c | 19 +-
drivers/clk/versatile/clk-realview.c | 3 +-
drivers/clk/versatile/clk-sp810.c | 30 +-
drivers/clk/versatile/clk-versatile.c | 3 +-
drivers/clk/versatile/clk-vexpress-osc.c | 2 +-
drivers/clk/versatile/clk-vexpress.c | 6 +-
drivers/clk/x86/clk-lpt.c | 3 +-
drivers/clk/zynq/clkc.c | 22 +-
drivers/clk/zynq/pll.c | 4 +-
drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c | 3 +-
drivers/media/platform/exynos4-is/media-dev.c | 18 +-
drivers/media/platform/exynos4-is/media-dev.h | 7 +-
drivers/media/platform/omap3isp/isp.h | 2 +-
drivers/rtc/rtc-hym8563.c | 4 +-
drivers/staging/imx-drm/imx-tve.c | 27 +-
include/linux/clk-private.h | 51 +-
include/linux/clk-provider.h | 138 +++--
include/linux/clk.h | 53 +-
include/linux/clk/ti.h | 10 +-
include/linux/clk/zynq.h | 3 +-
include/linux/clkdev.h | 24 +-
include/linux/platform_data/clk-lpss.h | 2 +-
include/linux/platform_data/si5351.h | 4 +-
sound/soc/mxs/mxs-saif.c | 4 +-
277 files changed, 2383 insertions(+), 1925 deletions(-)
--
1.9.3
^ permalink raw reply [flat|nested] 24+ messages in thread
* [PATCH v13 1/9] clk: Add temporary mapping to the existing API
2014-09-23 18:40 [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
@ 2014-09-23 18:40 ` Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
` (2 subsequent siblings)
3 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:40 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
To preserve git-bisectability, add aliases from the future provider API to the
existing public API.
Also includes clk-provider.h and clk-dev.h in a few places so the right
functions are defined.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Acked-by: Simon Horman <horms+renesas@verge.net.au>
Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
v13: * Add mapping for clk_provider_put
v9: * Add mapping for clk_get_name
v7: * Add mappings for clk_notifier_[un]register
* Add more clk-provider.h includes to clk implementations
v4: * Add more clk-provider.h includes to clk implementations
* Add mapping for clk_provider_round_rate
---
arch/arm/mach-omap2/display.c | 1 +
arch/arm/mach-omap2/omap_device.c | 1 +
arch/arm/mach-shmobile/clock.c | 1 +
arch/arm/plat-orion/common.c | 1 +
drivers/clk/berlin/bg2.c | 1 +
drivers/clk/berlin/bg2q.c | 1 +
drivers/clk/clk-conf.c | 1 +
drivers/clk/clkdev.c | 1 +
drivers/media/platform/exynos4-is/media-dev.c | 1 +
include/linux/clk-provider.h | 28 +++++++++++++++++++++++++++
include/linux/clk/zynq.h | 1 +
11 files changed, 38 insertions(+)
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index bf852d7..0f9e479 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/of.h>
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index d22c30d..f138a62 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -32,6 +32,7 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/notifier.h>
diff --git a/arch/arm/mach-shmobile/clock.c b/arch/arm/mach-shmobile/clock.c
index 806f940..ed415dc 100644
--- a/arch/arm/mach-shmobile/clock.c
+++ b/arch/arm/mach-shmobile/clock.c
@@ -24,6 +24,7 @@
#ifdef CONFIG_COMMON_CLK
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include "clock.h"
diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c
index 3ec6e8e..961b593 100644
--- a/arch/arm/plat-orion/common.c
+++ b/arch/arm/plat-orion/common.c
@@ -15,6 +15,7 @@
#include <linux/serial_8250.h>
#include <linux/ata_platform.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/mv643xx_eth.h>
#include <linux/mv643xx_i2c.h>
diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c
index 515fb13..4c81e09 100644
--- a/drivers/clk/berlin/bg2.c
+++ b/drivers/clk/berlin/bg2.c
@@ -19,6 +19,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c
index 21784e4..748da9b 100644
--- a/drivers/clk/berlin/bg2q.c
+++ b/drivers/clk/berlin/bg2q.c
@@ -19,6 +19,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index aad4796..d36a7b3 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -8,6 +8,7 @@
*/
#include <linux/clk.h>
+#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/clk/clk-conf.h>
#include <linux/device.h>
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8..c751d0c 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/clk.h>
+#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/of.h>
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index 344718d..2620c48 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -13,6 +13,7 @@
#include <linux/bug.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/i2c.h>
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 411dd7e..03ad843 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -16,6 +16,34 @@
#ifdef CONFIG_COMMON_CLK
+/* Temporarily map the to-be-added API to the old API, just so stuff compiles */
+#define clk_core clk
+
+#define __clk_create_clk
+
+#define clk_provider_get clk_get
+#define clk_provider_put clk_put
+#define clk_provider_get_sys clk_get_sys
+#define devm_clk_provider_get devm_clk_get
+#define of_clk_provider_get of_clk_get
+#define of_clk_provider_get_by_name of_clk_get_by_name
+
+#define clk_provider_set_rate clk_set_rate
+#define clk_provider_get_rate clk_get_rate
+#define clk_provider_round_rate clk_round_rate
+#define clk_provider_set_parent clk_set_parent
+#define clk_provider_get_parent clk_get_parent
+#define clk_provider_prepare clk_prepare
+#define clk_provider_unprepare clk_unprepare
+#define clk_provider_enable clk_enable
+#define clk_provider_disable clk_disable
+#define clk_provider_prepare_enable clk_prepare_enable
+#define clk_provider_disable_unprepare clk_unprepare
+#define clk_provider_notifier_register clk_notifier_register
+#define clk_provider_notifier_unregister clk_notifier_unregister
+
+#define clk_get_name __clk_get_name
+
/*
* flags used across common struct clk. these flags should only affect the
* top-level framework. custom flags for dealing with hardware specifics
diff --git a/include/linux/clk/zynq.h b/include/linux/clk/zynq.h
index 7a5633b..a990a59 100644
--- a/include/linux/clk/zynq.h
+++ b/include/linux/clk/zynq.h
@@ -21,6 +21,7 @@
#define __LINUX_CLK_ZYNQ_H_
#include <linux/spinlock.h>
+#include <linux/clk-provider.h>
void zynq_clock_init(void);
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v13 3/9] clk: use struct clk only for external API
2014-09-23 18:40 [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
2014-09-23 18:40 ` [PATCH v13 1/9] clk: Add temporary mapping to the existing API Tomeu Vizoso
@ 2014-09-23 18:44 ` Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 4/9] clk: per-user clock accounting for debug Tomeu Vizoso
` (5 more replies)
2014-09-23 20:59 ` [PATCH v13 0/9] Per-user clock constraints Stephen Boyd
2014-09-24 9:14 ` [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
3 siblings, 6 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:44 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
In order to provide per-user accounting, this separates the struct clk
used in the common clock framework into two structures 'struct clk_core'
and 'struct clk'. struct clk_core will be used for internal
manipulation and struct clk will be used in the clock API
implementation.
In this patch, struct clk is simply renamed to struct clk_core and a new
struct clk is implemented which simply wraps it. In the next patch, the
new struct clk will be used to implement per-user clock enable
accounting.
Based on previous work by Rabin Vincent <rabin@rab.in>.
NOTE: with this patch, clk_get_parent() behaves like clk_get(), i.e. it
needs to be matched with a clk_put(). Otherwise, memory will leak.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
v13: * Rework changes to clkdev.c to reduce the amount of code that is ifdeffed
* Add clk_provider_put
* Improve cleanup before creating per-user clocks
v12: * Export of_clk_provider_get()
v9: * Removed superfluous variable
v7: * convert clk_is_enabled to clk_core
* add clk_provider_notifier_[un]register
v4: * export clk_to_clk_core so mach-msm can use it for clk_reset
* add clk_provider_round_rate, for mach-imx
* fix build with !CONFIG_COMMON_CLK
* keep handling NULL struct clk gracefully as before
v3: * Allocate and release the per-user struct clk
* Have clk_core_to_clk return any error it's passed, so calls to it can be chained
* Add provider API for enable and disable
* Remove clk_free_clk for now
* Have clk_to_clk_core be an inline function to benefit of type-checking
* Have devres wrap the clk struct instead of clk_core
* Rename clk_core_to_clk to __clk_create_clk to make more clear that it allocates
clk: improve error handling
---
arch/arm/mach-msm/clock.c | 2 +-
drivers/clk/clk-devres.c | 31 ++
drivers/clk/clk.c | 758 ++++++++++++++++++++++++++-----------------
drivers/clk/clk.h | 6 +
drivers/clk/clkdev.c | 158 +++++++--
include/linux/clk-private.h | 38 ++-
include/linux/clk-provider.h | 166 +++++-----
include/linux/clk.h | 32 +-
include/linux/clkdev.h | 24 +-
9 files changed, 779 insertions(+), 436 deletions(-)
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 35ea02b5..1de0b5a 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -21,7 +21,7 @@
int clk_reset(struct clk *clk, enum clk_reset_action action)
{
- struct clk_hw *hw = __clk_get_hw(clk);
+ struct clk_hw *hw = __clk_get_hw(clk_to_clk_core(clk));
struct msm_clk *m = to_msm_clk(hw);
return m->reset(hw, action);
}
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
index 8f57154..79cd4d3 100644
--- a/drivers/clk/clk-devres.c
+++ b/drivers/clk/clk-devres.c
@@ -5,10 +5,14 @@
*/
#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/export.h>
#include <linux/gfp.h>
+#include "clk.h"
+
static void devm_clk_release(struct device *dev, void *res)
{
clk_put(*(struct clk **)res);
@@ -34,6 +38,33 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
}
EXPORT_SYMBOL(devm_clk_get);
+#if defined(CONFIG_COMMON_CLK)
+static void devm_clk_core_release(struct device *dev, void *res)
+{
+ __clk_put(*(struct clk_core **)res);
+}
+
+struct clk_core *devm_clk_provider_get(struct device *dev, const char *id)
+{
+ struct clk_core **ptr, *clk;
+
+ ptr = devres_alloc(devm_clk_core_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ clk = clk_provider_get(dev, id);
+ if (!IS_ERR(clk)) {
+ *ptr = clk;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return clk;
+}
+EXPORT_SYMBOL(devm_clk_provider_get);
+#endif
+
static int devm_clk_match(struct device *dev, void *res, void *data)
{
struct clk **c = res;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b76fa69..ffe58ec 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,6 +37,8 @@ static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
+static long __clk_get_accuracy_internal(struct clk_core *clk);
+
/*** locking ***/
static void clk_prepare_lock(void)
{
@@ -112,7 +114,7 @@ static struct hlist_head *orphan_list[] = {
NULL,
};
-static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
@@ -120,14 +122,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
level * 3 + 1, "",
30 - level * 3, c->name,
- c->enable_count, c->prepare_count, clk_get_rate(c),
- clk_get_accuracy(c));
+ c->enable_count, c->prepare_count, clk_provider_get_rate(c),
+ __clk_get_accuracy_internal(c));
}
-static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -140,7 +142,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
static int clk_summary_show(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
struct hlist_head **lists = (struct hlist_head **)s->private;
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
@@ -170,7 +172,7 @@ static const struct file_operations clk_summary_fops = {
.release = single_release,
};
-static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
@@ -178,13 +180,13 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "\"%s\": { ", c->name);
seq_printf(s, "\"enable_count\": %d,", c->enable_count);
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
- seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
- seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
+ seq_printf(s, "\"rate\": %lu", clk_provider_get_rate(c));
+ seq_printf(s, "\"accuracy\": %lu", __clk_get_accuracy_internal(c));
}
-static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -201,7 +203,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
static int clk_dump(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
bool first_node = true;
struct hlist_head **lists = (struct hlist_head **)s->private;
@@ -238,7 +240,7 @@ static const struct file_operations clk_dump_fops = {
};
/* caller must hold prepare_lock */
-static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
{
struct dentry *d;
int ret = -ENOMEM;
@@ -301,9 +303,9 @@ out:
}
/* caller must hold prepare_lock */
-static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_subtree(struct clk_core *clk, struct dentry *pdentry)
{
- struct clk *child;
+ struct clk_core *child;
int ret = -EINVAL;;
if (!clk || !pdentry)
@@ -333,7 +335,7 @@ out:
* Caller must hold prepare_lock. Only clk_init calls this function (so
* far) so this is taken care.
*/
-static int clk_debug_register(struct clk *clk)
+static int clk_debug_register(struct clk_core *clk)
{
int ret = 0;
@@ -356,12 +358,12 @@ out:
*
* Caller must hold prepare_lock.
*/
-static void clk_debug_unregister(struct clk *clk)
+static void clk_debug_unregister(struct clk_core *clk)
{
debugfs_remove_recursive(clk->dentry);
}
-struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
+struct dentry *clk_debugfs_add_file(struct clk_core *clk, char *name, umode_t mode,
void *data, const struct file_operations *fops)
{
struct dentry *d = NULL;
@@ -387,7 +389,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
*/
static int __init clk_debug_init(void)
{
- struct clk *clk;
+ struct clk_core *clk;
struct dentry *d;
rootdir = debugfs_create_dir("clk", NULL);
@@ -431,19 +433,19 @@ static int __init clk_debug_init(void)
}
late_initcall(clk_debug_init);
#else
-static inline int clk_debug_register(struct clk *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+static inline int clk_debug_register(struct clk_core *clk) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *clk, struct clk_core *new_parent)
{
}
-static inline void clk_debug_unregister(struct clk *clk)
+static inline void clk_debug_unregister(struct clk_core *clk)
{
}
#endif
/* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
if (!clk)
return;
@@ -466,9 +468,9 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
}
/* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk *clk)
+static void clk_disable_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long flags;
if (!clk)
@@ -514,7 +516,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
static int clk_disable_unused(void)
{
- struct clk *clk;
+ struct clk_core *clk;
if (clk_ignore_unused) {
pr_warn("clk: Not disabling unused clocks\n");
@@ -541,33 +543,94 @@ static int clk_disable_unused(void)
}
late_initcall_sync(clk_disable_unused);
+struct clk *__clk_create_clk(struct clk_core *clk_core)
+{
+ struct clk *clk;
+
+ /* This is to allow this function to be chained to others */
+ if (!clk_core || IS_ERR(clk_core))
+ return (struct clk *) clk_core;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->core = clk_core;
+
+ return clk;
+}
+
+/*
+ * Free memory allocated for a clock.
+ * Caller must hold prepare_lock.
+ */
+static void __clk_release(struct kref *ref)
+{
+ struct clk_core *clk = container_of(ref, struct clk_core, ref);
+ int i = clk->num_parents;
+
+ kfree(clk->parents);
+ while (--i >= 0)
+ kfree(clk->parent_names[i]);
+
+ kfree(clk->parent_names);
+ kfree(clk->name);
+ kfree(clk);
+}
+
+/*
+ * clkdev helpers
+ */
+int __clk_get(struct clk_core *clk)
+{
+ if (clk) {
+ if (!try_module_get(clk->owner))
+ return 0;
+
+ kref_get(&clk->ref);
+ }
+ return 1;
+}
+
+void __clk_put(struct clk_core *clk)
+{
+ if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
+ return;
+
+ clk_prepare_lock();
+ kref_put(&clk->ref, __clk_release);
+ clk_prepare_unlock();
+
+ module_put(clk->owner);
+}
+
/*** helper functions ***/
-const char *__clk_get_name(struct clk *clk)
+const char *__clk_get_name(struct clk_core *clk)
{
return !clk ? NULL : clk->name;
}
EXPORT_SYMBOL_GPL(__clk_get_name);
-struct clk_hw *__clk_get_hw(struct clk *clk)
+struct clk_hw *__clk_get_hw(struct clk_core *clk)
{
return !clk ? NULL : clk->hw;
}
EXPORT_SYMBOL_GPL(__clk_get_hw);
-u8 __clk_get_num_parents(struct clk *clk)
+u8 __clk_get_num_parents(struct clk_core *clk)
{
return !clk ? 0 : clk->num_parents;
}
EXPORT_SYMBOL_GPL(__clk_get_num_parents);
-struct clk *__clk_get_parent(struct clk *clk)
+struct clk_core *__clk_get_parent(struct clk_core *clk)
{
return !clk ? NULL : clk->parent;
}
EXPORT_SYMBOL_GPL(__clk_get_parent);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+struct clk_core *clk_get_parent_by_index(struct clk_core *clk, u8 index)
{
if (!clk || index >= clk->num_parents)
return NULL;
@@ -581,17 +644,17 @@ struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
}
EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
-unsigned int __clk_get_enable_count(struct clk *clk)
+unsigned int __clk_get_enable_count(struct clk_core *clk)
{
return !clk ? 0 : clk->enable_count;
}
-unsigned int __clk_get_prepare_count(struct clk *clk)
+unsigned int __clk_get_prepare_count(struct clk_core *clk)
{
return !clk ? 0 : clk->prepare_count;
}
-unsigned long __clk_get_rate(struct clk *clk)
+unsigned long __clk_get_rate(struct clk_core *clk)
{
unsigned long ret;
@@ -613,7 +676,7 @@ out:
}
EXPORT_SYMBOL_GPL(__clk_get_rate);
-unsigned long __clk_get_accuracy(struct clk *clk)
+unsigned long __clk_get_accuracy(struct clk_core *clk)
{
if (!clk)
return 0;
@@ -621,13 +684,13 @@ unsigned long __clk_get_accuracy(struct clk *clk)
return clk->accuracy;
}
-unsigned long __clk_get_flags(struct clk *clk)
+unsigned long __clk_get_flags(struct clk_core *clk)
{
return !clk ? 0 : clk->flags;
}
EXPORT_SYMBOL_GPL(__clk_get_flags);
-bool __clk_is_prepared(struct clk *clk)
+bool __clk_is_prepared(struct clk_core *clk)
{
int ret;
@@ -648,7 +711,7 @@ out:
return !!ret;
}
-bool __clk_is_enabled(struct clk *clk)
+bool __clk_is_enabled(struct clk_core *clk)
{
int ret;
@@ -670,10 +733,10 @@ out:
}
EXPORT_SYMBOL_GPL(__clk_is_enabled);
-static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+static struct clk_core *__clk_lookup_subtree(const char *name, struct clk_core *clk)
{
- struct clk *child;
- struct clk *ret;
+ struct clk_core *child;
+ struct clk_core *ret;
if (!strcmp(clk->name, name))
return clk;
@@ -687,10 +750,10 @@ static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
return NULL;
}
-struct clk *__clk_lookup(const char *name)
+struct clk_core *__clk_lookup(const char *name)
{
- struct clk *root_clk;
- struct clk *ret;
+ struct clk_core *root_clk;
+ struct clk_core *ret;
if (!name)
return NULL;
@@ -719,9 +782,9 @@ struct clk *__clk_lookup(const char *name)
*/
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
- struct clk **best_parent_p)
+ struct clk_core **best_parent_p)
{
- struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+ struct clk_core *clk = hw->clk, *parent, *best_parent = NULL;
int i, num_parents;
unsigned long parent_rate, best = 0;
@@ -764,7 +827,7 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
/*** clk api ***/
-void __clk_unprepare(struct clk *clk)
+void __clk_unprepare(struct clk_core *clk)
{
if (!clk)
return;
@@ -783,9 +846,20 @@ void __clk_unprepare(struct clk *clk)
__clk_unprepare(clk->parent);
}
+void clk_provider_unprepare(struct clk_core *clk)
+{
+ if (IS_ERR_OR_NULL(clk))
+ return;
+
+ clk_prepare_lock();
+ __clk_unprepare(clk);
+ clk_prepare_unlock();
+}
+EXPORT_SYMBOL_GPL(clk_provider_unprepare);
+
/**
* clk_unprepare - undo preparation of a clock source
- * @clk: the clk being unprepared
+ * @clk_user: the clk being unprepared
*
* clk_unprepare may sleep, which differentiates it from clk_disable. In a
* simple case, clk_unprepare can be used instead of clk_disable to gate a clk
@@ -794,18 +868,16 @@ void __clk_unprepare(struct clk *clk)
* part. It is this reason that clk_unprepare and clk_disable are not mutually
* exclusive. In fact clk_disable must be called before clk_unprepare.
*/
-void clk_unprepare(struct clk *clk)
+void clk_unprepare(struct clk *clk_user)
{
- if (IS_ERR_OR_NULL(clk))
+ if (IS_ERR_OR_NULL(clk_user))
return;
- clk_prepare_lock();
- __clk_unprepare(clk);
- clk_prepare_unlock();
+ clk_provider_unprepare(clk_to_clk_core(clk_user));
}
EXPORT_SYMBOL_GPL(clk_unprepare);
-int __clk_prepare(struct clk *clk)
+int __clk_prepare(struct clk_core *clk)
{
int ret = 0;
@@ -831,9 +903,21 @@ int __clk_prepare(struct clk *clk)
return 0;
}
+int clk_provider_prepare(struct clk_core *clk)
+{
+ int ret;
+
+ clk_prepare_lock();
+ ret = __clk_prepare(clk);
+ clk_prepare_unlock();
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_provider_prepare);
+
/**
* clk_prepare - prepare a clock source
- * @clk: the clk being prepared
+ * @clk_user: the clk being prepared
*
* clk_prepare may sleep, which differentiates it from clk_enable. In a simple
* case, clk_prepare can be used instead of clk_enable to ungate a clk if the
@@ -843,19 +927,16 @@ int __clk_prepare(struct clk *clk)
* exclusive. In fact clk_prepare must be called before clk_enable.
* Returns 0 on success, -EERROR otherwise.
*/
-int clk_prepare(struct clk *clk)
+int clk_prepare(struct clk *clk_user)
{
- int ret;
-
- clk_prepare_lock();
- ret = __clk_prepare(clk);
- clk_prepare_unlock();
+ if (!clk_user)
+ return 0;
- return ret;
+ return clk_provider_prepare(clk_to_clk_core(clk_user));
}
EXPORT_SYMBOL_GPL(clk_prepare);
-static void __clk_disable(struct clk *clk)
+static void __clk_disable(struct clk_core *clk)
{
if (!clk)
return;
@@ -872,9 +953,22 @@ static void __clk_disable(struct clk *clk)
__clk_disable(clk->parent);
}
+void clk_provider_disable(struct clk_core *clk)
+{
+ unsigned long flags;
+
+ if (IS_ERR_OR_NULL(clk))
+ return;
+
+ flags = clk_enable_lock();
+ __clk_disable(clk);
+ clk_enable_unlock(flags);
+}
+EXPORT_SYMBOL_GPL(clk_provider_disable);
+
/**
* clk_disable - gate a clock
- * @clk: the clk being gated
+ * @clk_user: the clk being gated
*
* clk_disable must not sleep, which differentiates it from clk_unprepare. In
* a simple case, clk_disable can be used instead of clk_unprepare to gate a
@@ -884,20 +978,16 @@ static void __clk_disable(struct clk *clk)
* this reason that clk_unprepare and clk_disable are not mutually exclusive.
* In fact clk_disable must be called before clk_unprepare.
*/
-void clk_disable(struct clk *clk)
+void clk_disable(struct clk *clk_user)
{
- unsigned long flags;
-
- if (IS_ERR_OR_NULL(clk))
+ if (IS_ERR_OR_NULL(clk_user))
return;
- flags = clk_enable_lock();
- __clk_disable(clk);
- clk_enable_unlock(flags);
+ clk_provider_disable(clk_to_clk_core(clk_user));
}
EXPORT_SYMBOL_GPL(clk_disable);
-static int __clk_enable(struct clk *clk)
+static int __clk_enable(struct clk_core *clk)
{
int ret = 0;
@@ -926,9 +1016,22 @@ static int __clk_enable(struct clk *clk)
return 0;
}
+int clk_provider_enable(struct clk_core *clk)
+{
+ unsigned long flags;
+ int ret;
+
+ flags = clk_enable_lock();
+ ret = __clk_enable(clk);
+ clk_enable_unlock(flags);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_provider_enable);
+
/**
* clk_enable - ungate a clock
- * @clk: the clk being ungated
+ * @clk_user: the clk being ungated
*
* clk_enable must not sleep, which differentiates it from clk_prepare. In a
* simple case, clk_enable can be used instead of clk_prepare to ungate a clk
@@ -939,16 +1042,12 @@ static int __clk_enable(struct clk *clk)
* must be called before clk_enable. Returns 0 on success, -EERROR
* otherwise.
*/
-int clk_enable(struct clk *clk)
+int clk_enable(struct clk *clk_user)
{
- unsigned long flags;
- int ret;
-
- flags = clk_enable_lock();
- ret = __clk_enable(clk);
- clk_enable_unlock(flags);
+ if (!clk_user)
+ return 0;
- return ret;
+ return clk_provider_enable(clk_to_clk_core(clk_user));
}
EXPORT_SYMBOL_GPL(clk_enable);
@@ -959,10 +1058,10 @@ EXPORT_SYMBOL_GPL(clk_enable);
*
* Caller must hold prepare_lock. Useful for clk_ops such as .set_rate
*/
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+unsigned long __clk_round_rate(struct clk_core *clk, unsigned long rate)
{
unsigned long parent_rate = 0;
- struct clk *parent;
+ struct clk_core *parent;
if (!clk)
return 0;
@@ -983,42 +1082,51 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
}
EXPORT_SYMBOL_GPL(__clk_round_rate);
+long clk_provider_round_rate(struct clk_core *clk, unsigned long rate)
+{
+ unsigned long ret;
+
+ clk_prepare_lock();
+ ret = __clk_round_rate(clk, rate);
+ clk_prepare_unlock();
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(clk_provider_round_rate);
+
/**
* clk_round_rate - round the given rate for a clk
- * @clk: the clk for which we are rounding a rate
+ * @clk_user: the clk for which we are rounding a rate
* @rate: the rate which is to be rounded
*
* Takes in a rate as input and rounds it to a rate that the clk can actually
* use which is then returned. If clk doesn't support round_rate operation
* then the parent rate is returned.
*/
-long clk_round_rate(struct clk *clk, unsigned long rate)
+long clk_round_rate(struct clk *clk_user, unsigned long rate)
{
- unsigned long ret;
-
- clk_prepare_lock();
- ret = __clk_round_rate(clk, rate);
- clk_prepare_unlock();
+ if (!clk_user)
+ return 0;
- return ret;
+ return clk_provider_round_rate(clk_to_clk_core(clk_user), rate);
}
EXPORT_SYMBOL_GPL(clk_round_rate);
/**
* __clk_notify - call clk notifier chain
- * @clk: struct clk * that is changing rate
+ * @clk: struct clk_core * that is changing rate
* @msg: clk notifier type (see include/linux/clk.h)
* @old_rate: old clk rate
* @new_rate: new clk rate
*
* Triggers a notifier call chain on the clk rate-change notification
- * for 'clk'. Passes a pointer to the struct clk and the previous
+ * for 'clk'. Passes a pointer to the struct clk_core and the previous
* and current rates to the notifier callback. Intended to be called by
* internal clock code only. Returns NOTIFY_DONE from the last driver
* called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
* a driver returns that.
*/
-static int __clk_notify(struct clk *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *clk, unsigned long msg,
unsigned long old_rate, unsigned long new_rate)
{
struct clk_notifier *cn;
@@ -1051,10 +1159,10 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_accuracies(struct clk *clk)
+static void __clk_recalc_accuracies(struct clk_core *clk)
{
unsigned long parent_accuracy = 0;
- struct clk *child;
+ struct clk_core *child;
if (clk->parent)
parent_accuracy = clk->parent->accuracy;
@@ -1069,16 +1177,7 @@ static void __clk_recalc_accuracies(struct clk *clk)
__clk_recalc_accuracies(child);
}
-/**
- * clk_get_accuracy - return the accuracy of clk
- * @clk: the clk whose accuracy is being returned
- *
- * Simply returns the cached accuracy of the clk, unless
- * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
- * issued.
- * If clk is NULL then returns 0.
- */
-long clk_get_accuracy(struct clk *clk)
+static long __clk_get_accuracy_internal(struct clk_core *clk)
{
unsigned long accuracy;
@@ -1091,9 +1190,23 @@ long clk_get_accuracy(struct clk *clk)
return accuracy;
}
+
+/**
+ * clk_get_accuracy - return the accuracy of clk
+ * @clk_user: the clk whose accuracy is being returned
+ *
+ * Simply returns the cached accuracy of the clk, unless
+ * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
+ * issued.
+ * If clk is NULL then returns 0.
+ */
+long clk_get_accuracy(struct clk *clk_user)
+{
+ return __clk_get_accuracy_internal(clk_to_clk_core(clk_user));
+}
EXPORT_SYMBOL_GPL(clk_get_accuracy);
-static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
+static unsigned long clk_recalc(struct clk_core *clk, unsigned long parent_rate)
{
if (clk->ops->recalc_rate)
return clk->ops->recalc_rate(clk->hw, parent_rate);
@@ -1114,11 +1227,11 @@ static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
{
unsigned long old_rate;
unsigned long parent_rate = 0;
- struct clk *child;
+ struct clk_core *child;
old_rate = clk->rate;
@@ -1138,15 +1251,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
__clk_recalc_rates(child, msg);
}
-/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
- * is set, which means a recalc_rate will be issued.
- * If clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
+unsigned long clk_provider_get_rate(struct clk_core *clk)
{
unsigned long rate;
@@ -1160,15 +1265,32 @@ unsigned long clk_get_rate(struct clk *clk)
return rate;
}
+EXPORT_SYMBOL_GPL(clk_provider_get_rate);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk_user: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk_user)
+{
+ if (!clk_user)
+ return 0;
+
+ return clk_provider_get_rate(clk_to_clk_core(clk_user));
+}
EXPORT_SYMBOL_GPL(clk_get_rate);
-static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk_core *clk, struct clk_core *parent)
{
int i;
if (!clk->parents) {
clk->parents = kcalloc(clk->num_parents,
- sizeof(struct clk *), GFP_KERNEL);
+ sizeof(struct clk_core *), GFP_KERNEL);
if (!clk->parents)
return -ENOMEM;
}
@@ -1194,7 +1316,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
return -EINVAL;
}
-static void clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
{
hlist_del(&clk->child_node);
@@ -1211,10 +1333,10 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
clk->parent = new_parent;
}
-static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
+static struct clk_core *__clk_set_parent_before(struct clk_core *clk, struct clk_core *parent)
{
unsigned long flags;
- struct clk *old_parent = clk->parent;
+ struct clk_core *old_parent = clk->parent;
/*
* Migrate prepare state between parents and prevent race with
@@ -1235,8 +1357,8 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
*/
if (clk->prepare_count) {
__clk_prepare(parent);
- clk_enable(parent);
- clk_enable(clk);
+ clk_provider_enable(parent);
+ clk_provider_enable(clk);
}
/* update the clk tree topology */
@@ -1247,25 +1369,25 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
return old_parent;
}
-static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
- struct clk *old_parent)
+static void __clk_set_parent_after(struct clk_core *clk, struct clk_core *parent,
+ struct clk_core *old_parent)
{
/*
* Finish the migration of prepare state and undo the changes done
* for preventing a race with clk_enable().
*/
if (clk->prepare_count) {
- clk_disable(clk);
- clk_disable(old_parent);
+ clk_provider_disable(clk);
+ clk_provider_disable(old_parent);
__clk_unprepare(old_parent);
}
}
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent, u8 p_index)
{
unsigned long flags;
int ret = 0;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_parent = __clk_set_parent_before(clk, parent);
@@ -1279,8 +1401,8 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
clk_enable_unlock(flags);
if (clk->prepare_count) {
- clk_disable(clk);
- clk_disable(parent);
+ clk_provider_disable(clk);
+ clk_provider_disable(parent);
__clk_unprepare(parent);
}
return ret;
@@ -1307,9 +1429,9 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
*
* Caller must hold prepare_lock.
*/
-static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+static int __clk_speculate_rates(struct clk_core *clk, unsigned long parent_rate)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long new_rate;
int ret = NOTIFY_DONE;
@@ -1335,10 +1457,10 @@ out:
return ret;
}
-static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
- struct clk *new_parent, u8 p_index)
+static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+ struct clk_core *new_parent, u8 p_index)
{
- struct clk *child;
+ struct clk_core *child;
clk->new_rate = new_rate;
clk->new_parent = new_parent;
@@ -1358,10 +1480,10 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
* calculate the new rates returning the topmost clock that has to be
* changed.
*/
-static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+static struct clk_core *clk_calc_new_rates(struct clk_core *clk, unsigned long rate)
{
- struct clk *top = clk;
- struct clk *old_parent, *parent;
+ struct clk_core *top = clk;
+ struct clk_core *old_parent, *parent;
unsigned long best_parent_rate = 0;
unsigned long new_rate;
int p_index = 0;
@@ -1427,9 +1549,9 @@ out:
* so that in case of an error we can walk down the whole tree again and
* abort the change.
*/
-static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+static struct clk_core *clk_propagate_rate_change(struct clk_core *clk, unsigned long event)
{
- struct clk *child, *tmp_clk, *fail_clk = NULL;
+ struct clk_core *child, *tmp_clk, *fail_clk = NULL;
int ret = NOTIFY_DONE;
if (clk->rate == clk->new_rate)
@@ -1464,13 +1586,13 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
* walk down a subtree and set the new rates notifying the rate
* change on the way
*/
-static void clk_change_rate(struct clk *clk)
+static void clk_change_rate(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long old_rate;
unsigned long best_parent_rate = 0;
bool skip_set_rate = false;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_rate = clk->rate;
@@ -1514,30 +1636,9 @@ static void clk_change_rate(struct clk *clk)
clk_change_rate(clk->new_child);
}
-/**
- * clk_set_rate - specify a new rate for clk
- * @clk: the clk whose rate is being changed
- * @rate: the new rate for clk
- *
- * In the simplest case clk_set_rate will only adjust the rate of clk.
- *
- * Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to
- * propagate up to clk's parent; whether or not this happens depends on the
- * outcome of clk's .round_rate implementation. If *parent_rate is unchanged
- * after calling .round_rate then upstream parent propagation is ignored. If
- * *parent_rate comes back with a new rate for clk's parent then we propagate
- * up to clk's parent and set its rate. Upward propagation will continue
- * until either a clk does not support the CLK_SET_RATE_PARENT flag or
- * .round_rate stops requesting changes to clk's parent_rate.
- *
- * Rate changes are accomplished via tree traversal that also recalculates the
- * rates for the clocks and fires off POST_RATE_CHANGE notifiers.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_rate(struct clk *clk, unsigned long rate)
+int clk_provider_set_rate(struct clk_core *clk, unsigned long rate)
{
- struct clk *top, *fail_clk;
+ struct clk_core *top, *fail_clk;
int ret = 0;
if (!clk)
@@ -1547,7 +1648,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
clk_prepare_lock();
/* bail early if nothing to do */
- if (rate == clk_get_rate(clk))
+ if (rate == clk_provider_get_rate(clk))
goto out;
if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
@@ -1580,17 +1681,41 @@ out:
return ret;
}
-EXPORT_SYMBOL_GPL(clk_set_rate);
+EXPORT_SYMBOL_GPL(clk_provider_set_rate);
/**
- * clk_get_parent - return the parent of a clk
- * @clk: the clk whose parent gets returned
+ * clk_set_rate - specify a new rate for clk
+ * @clk_user: the clk whose rate is being changed
+ * @rate: the new rate for clk
*
- * Simply returns clk->parent. Returns NULL if clk is NULL.
+ * In the simplest case clk_set_rate will only adjust the rate of clk.
+ *
+ * Setting the CLK_SET_RATE_PARENT flag allows the rate change operation to
+ * propagate up to clk's parent; whether or not this happens depends on the
+ * outcome of clk's .round_rate implementation. If *parent_rate is unchanged
+ * after calling .round_rate then upstream parent propagation is ignored. If
+ * *parent_rate comes back with a new rate for clk's parent then we propagate
+ * up to clk's parent and set its rate. Upward propagation will continue
+ * until either a clk does not support the CLK_SET_RATE_PARENT flag or
+ * .round_rate stops requesting changes to clk's parent_rate.
+ *
+ * Rate changes are accomplished via tree traversal that also recalculates the
+ * rates for the clocks and fires off POST_RATE_CHANGE notifiers.
+ *
+ * Returns 0 on success, -EERROR otherwise.
*/
-struct clk *clk_get_parent(struct clk *clk)
+int clk_set_rate(struct clk *clk_user, unsigned long rate)
+{
+ if (!clk_user)
+ return 0;
+
+ return clk_provider_set_rate(clk_to_clk_core(clk_user), rate);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+struct clk_core *clk_provider_get_parent(struct clk_core *clk)
{
- struct clk *parent;
+ struct clk_core *parent;
clk_prepare_lock();
parent = __clk_get_parent(clk);
@@ -1598,8 +1723,42 @@ struct clk *clk_get_parent(struct clk *clk)
return parent;
}
+EXPORT_SYMBOL_GPL(clk_provider_get_parent);
+
+/**
+ * clk_get_parent - return the parent of a clk
+ * @clk_user: the clk whose parent gets returned
+ *
+ * Simply returns clk->parent. Returns NULL if clk is NULL.
+ */
+struct clk *clk_get_parent(struct clk *clk_user)
+{
+ struct clk_core *clk;
+ struct clk_core *parent;
+ struct clk *parent_user;
+
+ if (!clk_user)
+ return NULL;
+
+ clk = clk_to_clk_core(clk_user);
+ parent = clk_provider_get_parent(clk);
+ if (IS_ERR(parent))
+ return (void *)parent;
+
+ parent_user = __clk_create_clk(parent);
+ if (IS_ERR(parent_user))
+ __clk_put(parent);
+
+ return parent_user;
+}
EXPORT_SYMBOL_GPL(clk_get_parent);
+const char *clk_get_name(struct clk *clk_user)
+{
+ return __clk_get_name(clk_to_clk_core(clk_user));
+}
+EXPORT_SYMBOL_GPL(clk_get_name);
+
/*
* .get_parent is mandatory for clocks with multiple possible parents. It is
* optional for single-parent clocks. Always call .get_parent if it is
@@ -1609,9 +1768,9 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
* .parents array exists, and if so use it to avoid an expensive tree
* traversal. If .parents does not exist then walk the tree with __clk_lookup.
*/
-static struct clk *__clk_init_parent(struct clk *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *clk)
{
- struct clk *ret = NULL;
+ struct clk_core *ret = NULL;
u8 index;
/* handle the trivial cases */
@@ -1643,7 +1802,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
if (!clk->parents)
clk->parents =
- kcalloc(clk->num_parents, sizeof(struct clk *),
+ kcalloc(clk->num_parents, sizeof(struct clk_core *),
GFP_KERNEL);
ret = clk_get_parent_by_index(clk, index);
@@ -1652,31 +1811,14 @@ out:
return ret;
}
-void __clk_reparent(struct clk *clk, struct clk *new_parent)
+void __clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
{
clk_reparent(clk, new_parent);
__clk_recalc_accuracies(clk);
__clk_recalc_rates(clk, POST_RATE_CHANGE);
}
-/**
- * clk_set_parent - switch the parent of a mux clk
- * @clk: the mux clk whose input we are switching
- * @parent: the new input to clk
- *
- * Re-parent clk to use parent as its new input source. If clk is in
- * prepared state, the clk will get enabled for the duration of this call. If
- * that's not acceptable for a specific clk (Eg: the consumer can't handle
- * that, the reparenting is glitchy in hardware, etc), use the
- * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
- *
- * After successfully changing clk's parent clk_set_parent will update the
- * clk topology, sysfs topology and propagate rate recalculation via
- * __clk_recalc_rates.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_parent(struct clk *clk, struct clk *parent)
+int clk_provider_set_parent(struct clk_core *clk, struct clk_core *parent)
{
int ret = 0;
int p_index = 0;
@@ -1736,6 +1878,38 @@ out:
return ret;
}
+EXPORT_SYMBOL_GPL(clk_provider_set_parent);
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk_user: the mux clk whose input we are switching
+ * @parent_user: the new input to clk
+ *
+ * Re-parent clk to use parent as its new input source. If clk is in
+ * prepared state, the clk will get enabled for the duration of this call. If
+ * that's not acceptable for a specific clk (Eg: the consumer can't handle
+ * that, the reparenting is glitchy in hardware, etc), use the
+ * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
+ *
+ * After successfully changing clk's parent clk_set_parent will update the
+ * clk topology, sysfs topology and propagate rate recalculation via
+ * __clk_recalc_rates.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk_user, struct clk *parent_user)
+{
+ struct clk_core *clk;
+ struct clk_core *parent;
+
+ if (!clk_user)
+ return 0;
+
+ clk = clk_to_clk_core(clk_user);
+ parent = clk_to_clk_core(parent_user);
+
+ return clk_provider_set_parent(clk, parent);
+}
EXPORT_SYMBOL_GPL(clk_set_parent);
/**
@@ -1746,10 +1920,10 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
* Initializes the lists in struct clk, queries the hardware for the
* parent and rate and sets them both.
*/
-int __clk_init(struct device *dev, struct clk *clk)
+int __clk_init(struct device *dev, struct clk_core *clk)
{
int i, ret = 0;
- struct clk *orphan;
+ struct clk_core *orphan;
struct hlist_node *tmp2;
if (!clk)
@@ -1797,7 +1971,7 @@ int __clk_init(struct device *dev, struct clk *clk)
__func__, clk->name);
/*
- * Allocate an array of struct clk *'s to avoid unnecessary string
+ * Allocate an array of struct clk_core *'s to avoid unnecessary string
* look-ups of clk's possible parents. This can fail for clocks passed
* in to clk_init during early boot; thus any access to clk->parents[]
* must always check for a NULL pointer and try to populate it if
@@ -1807,7 +1981,7 @@ int __clk_init(struct device *dev, struct clk *clk)
* for clock drivers to statically initialize clk->parents.
*/
if (clk->num_parents > 1 && !clk->parents) {
- clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
+ clk->parents = kcalloc(clk->num_parents, sizeof(struct clk_core *),
GFP_KERNEL);
/*
* __clk_lookup returns NULL for parents that have not been
@@ -1913,7 +2087,7 @@ out:
*
* Same as clk_register, except that the .clk field inside hw shall point to a
* preallocated (generally statically allocated) struct clk. None of the fields
- * of the struct clk need to be initialized.
+ * of the struct clk_core need to be initialized.
*
* The data pointed to by .init and .clk field shall NOT be marked as init
* data.
@@ -1925,10 +2099,10 @@ out:
* separate C file from the logic that implements its operations. Returns 0
* on success, otherwise an error code.
*/
-struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
+struct clk_core *__clk_register(struct device *dev, struct clk_hw *hw)
{
int ret;
- struct clk *clk;
+ struct clk_core *clk;
clk = hw->clk;
clk->name = hw->init->name;
@@ -1956,15 +2130,15 @@ EXPORT_SYMBOL_GPL(__clk_register);
* @hw: link to hardware-specific clock data
*
* clk_register is the primary interface for populating the clock tree with new
- * clock nodes. It returns a pointer to the newly allocated struct clk which
+ * clock nodes. It returns a pointer to the newly allocated struct clk_core which
* cannot be dereferenced by driver code but may be used in conjuction with the
* rest of the clock API. In the event of an error clk_register will return an
* error code; drivers must test for an error code after calling clk_register.
*/
-struct clk *clk_register(struct device *dev, struct clk_hw *hw)
+struct clk_core *clk_register(struct device *dev, struct clk_hw *hw)
{
int i, ret;
- struct clk *clk;
+ struct clk_core *clk;
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
if (!clk) {
@@ -2027,24 +2201,6 @@ fail_out:
EXPORT_SYMBOL_GPL(clk_register);
/*
- * Free memory allocated for a clock.
- * Caller must hold prepare_lock.
- */
-static void __clk_release(struct kref *ref)
-{
- struct clk *clk = container_of(ref, struct clk, ref);
- int i = clk->num_parents;
-
- kfree(clk->parents);
- while (--i >= 0)
- kfree(clk->parent_names[i]);
-
- kfree(clk->parent_names);
- kfree(clk->name);
- kfree(clk);
-}
-
-/*
* Empty clk_ops for unregistered clocks. These are used temporarily
* after clk_unregister() was called on a clock and until last clock
* consumer calls clk_put() and the struct clk object is freed.
@@ -2083,7 +2239,7 @@ static const struct clk_ops clk_nodrv_ops = {
* clk_unregister - unregister a currently registered clock
* @clk: clock to unregister
*/
-void clk_unregister(struct clk *clk)
+void clk_unregister(struct clk_core *clk)
{
unsigned long flags;
@@ -2105,12 +2261,12 @@ void clk_unregister(struct clk *clk)
clk_enable_unlock(flags);
if (!hlist_empty(&clk->children)) {
- struct clk *child;
+ struct clk_core *child;
struct hlist_node *t;
/* Reparent all children to the orphan list. */
hlist_for_each_entry_safe(child, t, &clk->children, child_node)
- clk_set_parent(child, NULL);
+ clk_provider_set_parent(child, NULL);
}
clk_debug_unregister(clk);
@@ -2129,8 +2285,14 @@ EXPORT_SYMBOL_GPL(clk_unregister);
static void devm_clk_release(struct device *dev, void *res)
{
- clk_unregister(*(struct clk **)res);
+ clk_unregister(*(struct clk_core **)res);
+}
+
+struct clk_core *clk_to_clk_core(struct clk *clk)
+{
+ return clk->core;
}
+EXPORT_SYMBOL_GPL(clk_to_clk_core);
/**
* devm_clk_register - resource managed clk_register()
@@ -2141,10 +2303,10 @@ static void devm_clk_release(struct device *dev, void *res)
* automatically clk_unregister()ed on driver detach. See clk_register() for
* more information.
*/
-struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
+struct clk_core *devm_clk_register(struct device *dev, struct clk_hw *hw)
{
- struct clk *clk;
- struct clk **clkp;
+ struct clk_core *clk;
+ struct clk_core **clkp;
clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
if (!clkp)
@@ -2164,7 +2326,7 @@ EXPORT_SYMBOL_GPL(devm_clk_register);
static int devm_clk_match(struct device *dev, void *res, void *data)
{
- struct clk *c = res;
+ struct clk_core *c = res;
if (WARN_ON(!c))
return 0;
return c == data;
@@ -2178,62 +2340,15 @@ static int devm_clk_match(struct device *dev, void *res, void *data)
* this function will not need to be called and the resource management
* code will ensure that the resource is freed.
*/
-void devm_clk_unregister(struct device *dev, struct clk *clk)
+void devm_clk_unregister(struct device *dev, struct clk_core *clk)
{
WARN_ON(devres_release(dev, devm_clk_release, devm_clk_match, clk));
}
EXPORT_SYMBOL_GPL(devm_clk_unregister);
-/*
- * clkdev helpers
- */
-int __clk_get(struct clk *clk)
-{
- if (clk) {
- if (!try_module_get(clk->owner))
- return 0;
-
- kref_get(&clk->ref);
- }
- return 1;
-}
-
-void __clk_put(struct clk *clk)
-{
- if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
- return;
-
- clk_prepare_lock();
- kref_put(&clk->ref, __clk_release);
- clk_prepare_unlock();
-
- module_put(clk->owner);
-}
-
/*** clk rate change notifiers ***/
-/**
- * clk_notifier_register - add a clk rate change notifier
- * @clk: struct clk * to watch
- * @nb: struct notifier_block * with callback info
- *
- * Request notification when clk's rate changes. This uses an SRCU
- * notifier because we want it to block and notifier unregistrations are
- * uncommon. The callbacks associated with the notifier must not
- * re-enter into the clk framework by calling any top-level clk APIs;
- * this will cause a nested prepare_lock mutex.
- *
- * In all notification cases cases (pre, post and abort rate change) the
- * original clock rate is passed to the callback via struct
- * clk_notifier_data.old_rate and the new frequency is passed via struct
- * clk_notifier_data.new_rate.
- *
- * clk_notifier_register() must be called from non-atomic context.
- * Returns -EINVAL if called with null arguments, -ENOMEM upon
- * allocation failure; otherwise, passes along the return value of
- * srcu_notifier_chain_register().
- */
-int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
+int clk_provider_notifier_register(struct clk_core *clk, struct notifier_block *nb)
{
struct clk_notifier *cn;
int ret = -ENOMEM;
@@ -2269,20 +2384,38 @@ out:
return ret;
}
-EXPORT_SYMBOL_GPL(clk_notifier_register);
+EXPORT_SYMBOL_GPL(clk_provider_notifier_register);
/**
- * clk_notifier_unregister - remove a clk rate change notifier
- * @clk: struct clk *
+ * clk_notifier_register - add a clk rate change notifier
+ * @clk_user: struct clk * to watch
* @nb: struct notifier_block * with callback info
*
- * Request no further notification for changes to 'clk' and frees memory
- * allocated in clk_notifier_register.
+ * Request notification when clk's rate changes. This uses an SRCU
+ * notifier because we want it to block and notifier unregistrations are
+ * uncommon. The callbacks associated with the notifier must not
+ * re-enter into the clk framework by calling any top-level clk APIs;
+ * this will cause a nested prepare_lock mutex.
*
- * Returns -EINVAL if called with null arguments; otherwise, passes
- * along the return value of srcu_notifier_chain_unregister().
+ * In all notification cases cases (pre, post and abort rate change) the
+ * original clock rate is passed to the callback via struct
+ * clk_notifier_data.old_rate and the new frequency is passed via struct
+ * clk_notifier_data.new_rate.
+ *
+ * clk_notifier_register() must be called from non-atomic context.
+ * Returns -EINVAL if called with null arguments, -ENOMEM upon
+ * allocation failure; otherwise, passes along the return value of
+ * srcu_notifier_chain_register().
*/
-int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
+int clk_notifier_register(struct clk *clk_user, struct notifier_block *nb)
+{
+ struct clk_core *clk = clk_to_clk_core(clk_user);
+
+ return clk_provider_notifier_register(clk, nb);
+}
+EXPORT_SYMBOL_GPL(clk_notifier_register);
+
+int clk_provider_notifier_unregister(struct clk_core *clk, struct notifier_block *nb)
{
struct clk_notifier *cn = NULL;
int ret = -EINVAL;
@@ -2316,6 +2449,25 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
return ret;
}
+EXPORT_SYMBOL_GPL(clk_provider_notifier_unregister);
+
+/**
+ * clk_notifier_unregister - remove a clk rate change notifier
+ * @clk_user: struct clk_core *
+ * @nb: struct notifier_block * with callback info
+ *
+ * Request no further notification for changes to 'clk' and frees memory
+ * allocated in clk_notifier_register.
+ *
+ * Returns -EINVAL if called with null arguments; otherwise, passes
+ * along the return value of srcu_notifier_chain_unregister().
+ */
+int clk_notifier_unregister(struct clk *clk_user, struct notifier_block *nb)
+{
+ struct clk_core *clk = clk_to_clk_core(clk_user);
+
+ return clk_provider_notifier_unregister(clk, nb);
+}
EXPORT_SYMBOL_GPL(clk_notifier_unregister);
#ifdef CONFIG_OF
@@ -2323,7 +2475,7 @@ EXPORT_SYMBOL_GPL(clk_notifier_unregister);
* struct of_clk_provider - Clock provider registration structure
* @link: Entry in global list of clock providers
* @node: Pointer to device tree node of clock provider
- * @get: Get clock callback. Returns NULL or a struct clk for the
+ * @get: Get clock callback. Returns NULL or a struct clk_core for the
* given clock specifier
* @data: context pointer to be passed into @get callback
*/
@@ -2331,7 +2483,7 @@ struct of_clk_provider {
struct list_head link;
struct device_node *node;
- struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
+ struct clk_core *(*get)(struct of_phandle_args *clkspec, void *data);
void *data;
};
@@ -2352,14 +2504,14 @@ void of_clk_unlock(void)
mutex_unlock(&of_clk_mutex);
}
-struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
+struct clk_core *of_clk_src_simple_get(struct of_phandle_args *clkspec,
void *data)
{
return data;
}
EXPORT_SYMBOL_GPL(of_clk_src_simple_get);
-struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
+struct clk_core *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
{
struct clk_onecell_data *clk_data = data;
unsigned int idx = clkspec->args[0];
@@ -2380,7 +2532,7 @@ EXPORT_SYMBOL_GPL(of_clk_src_onecell_get);
* @data: context pointer for @clk_src_get callback.
*/
int of_clk_add_provider(struct device_node *np,
- struct clk *(*clk_src_get)(struct of_phandle_args *clkspec,
+ struct clk_core *(*clk_src_get)(struct of_phandle_args *clkspec,
void *data),
void *data)
{
@@ -2429,10 +2581,10 @@ void of_clk_del_provider(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_clk_del_provider);
-struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
+struct clk_core *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
{
struct of_clk_provider *provider;
- struct clk *clk = ERR_PTR(-EPROBE_DEFER);
+ struct clk_core *clk = ERR_PTR(-EPROBE_DEFER);
/* Check if we have such a provider in our array */
list_for_each_entry(provider, &of_clk_providers, link) {
@@ -2445,9 +2597,9 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec)
return clk;
}
-struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec)
+struct clk_core *of_clk_get_from_provider(struct of_phandle_args *clkspec)
{
- struct clk *clk;
+ struct clk_core *clk;
mutex_lock(&of_clk_mutex);
clk = __of_clk_get_from_provider(clkspec);
@@ -2522,11 +2674,11 @@ static int parent_ready(struct device_node *np)
int i = 0;
while (true) {
- struct clk *clk = of_clk_get(np, i);
+ struct clk_core *clk = of_clk_provider_get(np, i);
/* this parent is ready we can check the next one */
if (!IS_ERR(clk)) {
- clk_put(clk);
+ __clk_put(clk);
i++;
continue;
}
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index d278572..3b3068b 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -9,9 +9,15 @@
* published by the Free Software Foundation.
*/
+#include <linux/clk-private.h>
+
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
struct clk_core *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
struct clk_core *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
void of_clk_lock(void);
void of_clk_unlock(void);
#endif
+
+#if defined(CONFIG_COMMON_CLK)
+struct clk *__clk_create_clk(struct clk_core *clk_core);
+#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index c751d0c..f99c1e4 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -18,6 +18,7 @@
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/clk.h>
+#include <linux/clk-private.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/of.h>
@@ -27,19 +28,31 @@
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
+/*
+ * Use clkdev_ret_t as an alias to either clk or clk_core to avoid scattering
+ * ifdefs within the rest of the file.
+ */
+#if defined(CONFIG_COMMON_CLK)
+typedef struct clk_core clkdev_ret_t;
+#else
+typedef struct clk clkdev_ret_t;
+#define __clk_create_clk(clk) clk
+#define clk_to_clk_core(clk) clk
+#endif
+
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
/**
* of_clk_get_by_clkspec() - Lookup a clock form a clock provider
* @clkspec: pointer to a clock specifier data structure
*
- * This function looks up a struct clk from the registered list of clock
+ * This function looks up a struct clk_core from the registered list of clock
* providers, an input is a clock specifier data structure as returned
* from the of_parse_phandle_with_args() function call.
*/
-struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
+struct clk_core *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
{
- struct clk *clk;
+ struct clk_core *clk;
if (!clkspec)
return ERR_PTR(-EINVAL);
@@ -54,10 +67,10 @@ struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec)
return clk;
}
-struct clk *of_clk_get(struct device_node *np, int index)
+struct clk_core *of_clk_provider_get(struct device_node *np, int index)
{
struct of_phandle_args clkspec;
- struct clk *clk;
+ struct clk_core *clk;
int rc;
if (index < 0)
@@ -72,20 +85,28 @@ struct clk *of_clk_get(struct device_node *np, int index)
of_node_put(clkspec.np);
return clk;
}
+EXPORT_SYMBOL(of_clk_provider_get);
+
+struct clk *of_clk_get(struct device_node *np, int index)
+{
+ struct clk_core *clk;
+ struct clk *clk_user;
+
+ clk = of_clk_provider_get(np, index);
+ if (IS_ERR(clk))
+ return (void *)clk;
+
+ clk_user = __clk_create_clk(clk);
+ if (IS_ERR(clk_user))
+ __clk_put(clk);
+
+ return clk_user;
+}
EXPORT_SYMBOL(of_clk_get);
-/**
- * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
- * @np: pointer to clock consumer node
- * @name: name of consumer's clock input, or NULL for the first clock reference
- *
- * This function parses the clocks and clock-names properties,
- * and uses them to look up the struct clk from the registered list of clock
- * providers.
- */
-struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+struct clk_core *of_clk_provider_get_by_name(struct device_node *np, const char *name)
{
- struct clk *clk = ERR_PTR(-ENOENT);
+ struct clk_core *clk = ERR_PTR(-ENOENT);
/* Walk up the tree of devices looking for a clock that matches */
while (np) {
@@ -98,7 +119,7 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
*/
if (name)
index = of_property_match_string(np, "clock-names", name);
- clk = of_clk_get(np, index);
+ clk = of_clk_provider_get(np, index);
if (!IS_ERR(clk))
break;
else if (name && index >= 0) {
@@ -120,11 +141,36 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
return clk;
}
+
+/**
+ * of_clk_get_by_name() - Parse and lookup a clock referenced by a device node
+ * @np: pointer to clock consumer node
+ * @name: name of consumer's clock input, or NULL for the first clock reference
+ *
+ * This function parses the clocks and clock-names properties,
+ * and uses them to look up the clock from the registered list of clock
+ * providers.
+ */
+struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
+{
+ struct clk_core *clk;
+ struct clk *clk_user;
+
+ clk = of_clk_provider_get_by_name(np, name);
+ if (IS_ERR(clk))
+ return (void *)clk;
+
+ clk_user = __clk_create_clk(clk);
+ if (IS_ERR(clk_user))
+ __clk_put(clk);
+
+ return clk_user;
+}
EXPORT_SYMBOL(of_clk_get_by_name);
#endif
/*
- * Find the correct struct clk for the device and connection ID.
+ * Find the correct clock for the device and connection ID.
* We do slightly fuzzy matching here:
* An entry with a NULL ID is assumed to be a wildcard.
* If an entry has a device ID, it must match
@@ -166,7 +212,7 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
return cl;
}
-struct clk *clk_get_sys(const char *dev_id, const char *con_id)
+clkdev_ret_t *clk_provider_get_sys(const char *dev_id, const char *con_id)
{
struct clk_lookup *cl;
@@ -176,30 +222,80 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
cl = NULL;
mutex_unlock(&clocks_mutex);
- return cl ? cl->clk : ERR_PTR(-ENOENT);
+ if (!cl)
+ return ERR_PTR(-ENOENT);
+
+ return cl->clk;
+}
+EXPORT_SYMBOL_GPL(clk_provider_get_sys);
+
+struct clk *clk_get_sys(const char *dev_id, const char *con_id)
+{
+ clkdev_ret_t *clk;
+ struct clk *clk_user;
+
+ clk = clk_provider_get_sys(dev_id, con_id);
+ if (IS_ERR(clk))
+ return (void *)clk;
+
+ clk_user = __clk_create_clk(clk);
+ if (IS_ERR(clk_user))
+ __clk_put(clk);
+
+ return clk_user;
}
EXPORT_SYMBOL(clk_get_sys);
-struct clk *clk_get(struct device *dev, const char *con_id)
+clkdev_ret_t *clk_provider_get(struct device *dev, const char *con_id)
{
const char *dev_id = dev ? dev_name(dev) : NULL;
- struct clk *clk;
+ clkdev_ret_t *clk;
if (dev) {
- clk = of_clk_get_by_name(dev->of_node, con_id);
+ clk = of_clk_provider_get_by_name(dev->of_node, con_id);
if (!IS_ERR(clk))
return clk;
if (PTR_ERR(clk) == -EPROBE_DEFER)
return clk;
}
- return clk_get_sys(dev_id, con_id);
+ return clk_provider_get_sys(dev_id, con_id);
+}
+EXPORT_SYMBOL(clk_provider_get);
+
+struct clk *clk_get(struct device *dev, const char *con_id)
+{
+ clkdev_ret_t *clk;
+ struct clk *clk_user;
+
+ clk = clk_provider_get(dev, con_id);
+ if (IS_ERR(clk))
+ return (void *)clk;
+
+ clk_user = __clk_create_clk(clk);
+ if (IS_ERR(clk_user))
+ __clk_put(clk);
+
+ return clk_user;
}
EXPORT_SYMBOL(clk_get);
+void clk_provider_put(clkdev_ret_t *clk)
+{
+ __clk_put(clk);
+}
+EXPORT_SYMBOL(clk_provider_put);
+
void clk_put(struct clk *clk)
{
+#if defined(CONFIG_COMMON_CLK)
+ struct clk_core *core = clk_to_clk_core(clk);
+
+ kfree(clk);
+ clk_provider_put(core);
+#else
__clk_put(clk);
+#endif
}
EXPORT_SYMBOL(clk_put);
@@ -231,7 +327,7 @@ struct clk_lookup_alloc {
};
static struct clk_lookup * __init_refok
-vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
+vclkdev_alloc(clkdev_ret_t *clk, const char *con_id, const char *dev_fmt,
va_list ap)
{
struct clk_lookup_alloc *cla;
@@ -255,7 +351,7 @@ vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
}
struct clk_lookup * __init_refok
-clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
+clkdev_alloc(clkdev_ret_t *clk, const char *con_id, const char *dev_fmt, ...)
{
struct clk_lookup *cl;
va_list ap;
@@ -277,7 +373,7 @@ int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
if (IS_ERR(r))
return PTR_ERR(r);
- l = clkdev_alloc(r, alias, alias_dev_name);
+ l = clkdev_alloc(clk_to_clk_core(r), alias, alias_dev_name);
clk_put(r);
if (!l)
return -ENODEV;
@@ -300,7 +396,7 @@ EXPORT_SYMBOL(clkdev_drop);
/**
* clk_register_clkdev - register one clock lookup for a struct clk
- * @clk: struct clk to associate with all clk_lookups
+ * @clk: clock to associate with all clk_lookups
* @con_id: connection ID string on device
* @dev_id: format string describing device name
*
@@ -312,7 +408,7 @@ EXPORT_SYMBOL(clkdev_drop);
* those. This is to permit this function to be called immediately
* after clk_register().
*/
-int clk_register_clkdev(struct clk *clk, const char *con_id,
+int clk_register_clkdev(clkdev_ret_t *clk, const char *con_id,
const char *dev_fmt, ...)
{
struct clk_lookup *cl;
@@ -335,7 +431,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
/**
* clk_register_clkdevs - register a set of clk_lookup for a struct clk
- * @clk: struct clk to associate with all clk_lookups
+ * @clk: clock to associate with all clk_lookups
* @cl: array of clk_lookup structures with con_id and dev_id pre-initialized
* @num: number of clk_lookup structures to register
*
@@ -344,7 +440,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
* those. This is to permit this function to be called immediately
* after clk_register().
*/
-int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
+int clk_register_clkdevs(clkdev_ret_t *clk, struct clk_lookup *cl, size_t num)
{
unsigned i;
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index efbf70b..2c1ece9 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -28,20 +28,20 @@
struct module;
-struct clk {
+struct clk_core {
const char *name;
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
- struct clk *parent;
+ struct clk_core *parent;
const char **parent_names;
- struct clk **parents;
+ struct clk_core **parents;
u8 num_parents;
u8 new_parent_index;
unsigned long rate;
unsigned long new_rate;
- struct clk *new_parent;
- struct clk *new_child;
+ struct clk_core *new_parent;
+ struct clk_core *new_child;
unsigned long flags;
unsigned int enable_count;
unsigned int prepare_count;
@@ -55,6 +55,10 @@ struct clk {
struct kref ref;
};
+struct clk {
+ struct clk_core *core;
+};
+
/*
* DOC: Basic clock implementations common to many platforms
*
@@ -66,7 +70,7 @@ struct clk {
#define DEFINE_CLK(_name, _ops, _flags, _parent_names, \
_parents) \
- static struct clk _name = { \
+ static struct clk_core _name = { \
.name = #_name, \
.ops = &_ops, \
.hw = &_name##_hw.hw, \
@@ -78,7 +82,7 @@ struct clk {
#define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate, \
_fixed_rate_flags) \
- static struct clk _name; \
+ static struct clk_core _name; \
static const char *_name##_parent_names[] = {}; \
static struct clk_fixed_rate _name##_hw = { \
.hw = { \
@@ -93,11 +97,11 @@ struct clk {
#define DEFINE_CLK_GATE(_name, _parent_name, _parent_ptr, \
_flags, _reg, _bit_idx, \
_gate_flags, _lock) \
- static struct clk _name; \
+ static struct clk_core _name; \
static const char *_name##_parent_names[] = { \
_parent_name, \
}; \
- static struct clk *_name##_parents[] = { \
+ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \
}; \
static struct clk_gate _name##_hw = { \
@@ -115,11 +119,11 @@ struct clk {
#define _DEFINE_CLK_DIVIDER(_name, _parent_name, _parent_ptr, \
_flags, _reg, _shift, _width, \
_divider_flags, _table, _lock) \
- static struct clk _name; \
+ static struct clk_core _name; \
static const char *_name##_parent_names[] = { \
_parent_name, \
}; \
- static struct clk *_name##_parents[] = { \
+ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \
}; \
static struct clk_divider _name##_hw = { \
@@ -154,7 +158,7 @@ struct clk {
#define DEFINE_CLK_MUX(_name, _parent_names, _parents, _flags, \
_reg, _shift, _width, \
_mux_flags, _lock) \
- static struct clk _name; \
+ static struct clk_core _name; \
static struct clk_mux _name##_hw = { \
.hw = { \
.clk = &_name, \
@@ -171,11 +175,11 @@ struct clk {
#define DEFINE_CLK_FIXED_FACTOR(_name, _parent_name, \
_parent_ptr, _flags, \
_mult, _div) \
- static struct clk _name; \
+ static struct clk_core _name; \
static const char *_name##_parent_names[] = { \
_parent_name, \
}; \
- static struct clk *_name##_parents[] = { \
+ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \
}; \
static struct clk_fixed_factor _name##_hw = { \
@@ -196,7 +200,7 @@ struct clk {
* Initializes the lists in struct clk, queries the hardware for the
* parent and rate and sets them both.
*
- * Any struct clk passed into __clk_init must have the following members
+ * Any struct clk_core passed into __clk_init must have the following members
* populated:
* .name
* .ops
@@ -210,9 +214,9 @@ struct clk {
*
* Returns 0 on success, otherwise an error code.
*/
-int __clk_init(struct device *dev, struct clk *clk);
+int __clk_init(struct device *dev, struct clk_core *clk);
-struct clk *__clk_register(struct device *dev, struct clk_hw *hw);
+struct clk_core *__clk_register(struct device *dev, struct clk_hw *hw);
#endif /* CONFIG_COMMON_CLK */
#endif /* CLK_PRIVATE_H */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 03ad843..c65d721 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -16,36 +16,8 @@
#ifdef CONFIG_COMMON_CLK
-/* Temporarily map the to-be-added API to the old API, just so stuff compiles */
-#define clk_core clk
-
-#define __clk_create_clk
-
-#define clk_provider_get clk_get
-#define clk_provider_put clk_put
-#define clk_provider_get_sys clk_get_sys
-#define devm_clk_provider_get devm_clk_get
-#define of_clk_provider_get of_clk_get
-#define of_clk_provider_get_by_name of_clk_get_by_name
-
-#define clk_provider_set_rate clk_set_rate
-#define clk_provider_get_rate clk_get_rate
-#define clk_provider_round_rate clk_round_rate
-#define clk_provider_set_parent clk_set_parent
-#define clk_provider_get_parent clk_get_parent
-#define clk_provider_prepare clk_prepare
-#define clk_provider_unprepare clk_unprepare
-#define clk_provider_enable clk_enable
-#define clk_provider_disable clk_disable
-#define clk_provider_prepare_enable clk_prepare_enable
-#define clk_provider_disable_unprepare clk_unprepare
-#define clk_provider_notifier_register clk_notifier_register
-#define clk_provider_notifier_unregister clk_notifier_unregister
-
-#define clk_get_name __clk_get_name
-
/*
- * flags used across common struct clk. these flags should only affect the
+ * flags used across common struct clk_core. these flags should only affect the
* top-level framework. custom flags for dealing with hardware specifics
* belong in struct clk_foo
*/
@@ -195,7 +167,7 @@ struct clk_ops {
unsigned long *parent_rate);
long (*determine_rate)(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
- struct clk **best_parent_clk);
+ struct clk_core **best_parent_clk);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -228,19 +200,19 @@ struct clk_init_data {
};
/**
- * struct clk_hw - handle for traversing from a struct clk to its corresponding
+ * struct clk_hw - handle for traversing from a struct clk_core to its corresponding
* hardware-specific structure. struct clk_hw should be declared within struct
- * clk_foo and then referenced by the struct clk instance that uses struct
+ * clk_foo and then referenced by the struct clk_core instance that uses struct
* clk_foo's clk_ops
*
- * @clk: pointer to the struct clk instance that points back to this struct
+ * @clk: pointer to the struct clk_core instance that points back to this struct
* clk_hw instance
*
* @init: pointer to struct clk_init_data that contains the init data shared
* with the common clock framework.
*/
struct clk_hw {
- struct clk *clk;
+ struct clk_core *clk;
const struct clk_init_data *init;
};
@@ -266,10 +238,10 @@ struct clk_fixed_rate {
};
extern const struct clk_ops clk_fixed_rate_ops;
-struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
+struct clk_core *clk_register_fixed_rate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
unsigned long fixed_rate);
-struct clk *clk_register_fixed_rate_with_accuracy(struct device *dev,
+struct clk_core *clk_register_fixed_rate_with_accuracy(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
unsigned long fixed_rate, unsigned long fixed_accuracy);
@@ -307,7 +279,7 @@ struct clk_gate {
#define CLK_GATE_HIWORD_MASK BIT(1)
extern const struct clk_ops clk_gate_ops;
-struct clk *clk_register_gate(struct device *dev, const char *name,
+struct clk_core *clk_register_gate(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 bit_idx,
u8 clk_gate_flags, spinlock_t *lock);
@@ -370,11 +342,11 @@ struct clk_divider {
extern const struct clk_ops clk_divider_ops;
extern const struct clk_ops clk_divider_ro_ops;
-struct clk *clk_register_divider(struct device *dev, const char *name,
+struct clk_core *clk_register_divider(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, spinlock_t *lock);
-struct clk *clk_register_divider_table(struct device *dev, const char *name,
+struct clk_core *clk_register_divider_table(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_divider_flags, const struct clk_div_table *table,
@@ -419,12 +391,12 @@ struct clk_mux {
extern const struct clk_ops clk_mux_ops;
extern const struct clk_ops clk_mux_ro_ops;
-struct clk *clk_register_mux(struct device *dev, const char *name,
+struct clk_core *clk_register_mux(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags, spinlock_t *lock);
-struct clk *clk_register_mux_table(struct device *dev, const char *name,
+struct clk_core *clk_register_mux_table(struct device *dev, const char *name,
const char **parent_names, u8 num_parents, unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock);
@@ -450,7 +422,7 @@ struct clk_fixed_factor {
};
extern struct clk_ops clk_fixed_factor_ops;
-struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
+struct clk_core *clk_register_fixed_factor(struct device *dev, const char *name,
const char *parent_name, unsigned long flags,
unsigned int mult, unsigned int div);
@@ -480,7 +452,7 @@ struct clk_fractional_divider {
};
extern const struct clk_ops clk_fractional_divider_ops;
-struct clk *clk_register_fractional_divider(struct device *dev,
+struct clk_core *clk_register_fractional_divider(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
u8 clk_divider_flags, spinlock_t *lock);
@@ -509,7 +481,7 @@ struct clk_composite {
const struct clk_ops *gate_ops;
};
-struct clk *clk_register_composite(struct device *dev, const char *name,
+struct clk_core *clk_register_composite(struct device *dev, const char *name,
const char **parent_names, int num_parents,
struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
struct clk_hw *rate_hw, const struct clk_ops *rate_ops,
@@ -522,49 +494,88 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
* @hw: link to hardware-specific clock data
*
* clk_register is the primary interface for populating the clock tree with new
- * clock nodes. It returns a pointer to the newly allocated struct clk which
+ * clock nodes. It returns a pointer to the newly allocated struct clk_core which
* cannot be dereferenced by driver code but may be used in conjuction with the
* rest of the clock API. In the event of an error clk_register will return an
* error code; drivers must test for an error code after calling clk_register.
*/
-struct clk *clk_register(struct device *dev, struct clk_hw *hw);
-struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw);
+struct clk_core *clk_register(struct device *dev, struct clk_hw *hw);
+struct clk_core *devm_clk_register(struct device *dev, struct clk_hw *hw);
-void clk_unregister(struct clk *clk);
-void devm_clk_unregister(struct device *dev, struct clk *clk);
+void clk_unregister(struct clk_core *clk);
+void devm_clk_unregister(struct device *dev, struct clk_core *clk);
/* helper functions */
-const char *__clk_get_name(struct clk *clk);
-struct clk_hw *__clk_get_hw(struct clk *clk);
-u8 __clk_get_num_parents(struct clk *clk);
-struct clk *__clk_get_parent(struct clk *clk);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index);
-unsigned int __clk_get_enable_count(struct clk *clk);
-unsigned int __clk_get_prepare_count(struct clk *clk);
-unsigned long __clk_get_rate(struct clk *clk);
-unsigned long __clk_get_accuracy(struct clk *clk);
-unsigned long __clk_get_flags(struct clk *clk);
-bool __clk_is_prepared(struct clk *clk);
-bool __clk_is_enabled(struct clk *clk);
-struct clk *__clk_lookup(const char *name);
+const char *__clk_get_name(struct clk_core *clk);
+struct clk_hw *__clk_get_hw(struct clk_core *clk);
+u8 __clk_get_num_parents(struct clk_core *clk);
+struct clk_core *__clk_get_parent(struct clk_core *clk);
+struct clk_core *clk_get_parent_by_index(struct clk_core *clk, u8 index);
+unsigned int __clk_get_enable_count(struct clk_core *clk);
+unsigned int __clk_get_prepare_count(struct clk_core *clk);
+unsigned long __clk_get_rate(struct clk_core *clk);
+unsigned long __clk_get_accuracy(struct clk_core *clk);
+unsigned long __clk_get_flags(struct clk_core *clk);
+bool __clk_is_prepared(struct clk_core *clk);
+bool __clk_is_enabled(struct clk_core *clk);
+struct clk_core *__clk_lookup(const char *name);
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
- struct clk **best_parent_p);
+ struct clk_core **best_parent_p);
+
+int clk_provider_prepare(struct clk_core *clk);
+void clk_provider_unprepare(struct clk_core *clk);
+int clk_provider_enable(struct clk_core *clk);
+void clk_provider_disable(struct clk_core *clk);
+int clk_provider_set_parent(struct clk_core *clk, struct clk_core *parent);
+int clk_provider_set_rate(struct clk_core *clk, unsigned long rate);
+struct clk_core *clk_provider_get_parent(struct clk_core *clk);
+unsigned long clk_provider_get_rate(struct clk_core *clk);
+long clk_provider_round_rate(struct clk_core *clk, unsigned long rate);
+struct clk_core *clk_provider_get_sys(const char *dev_id, const char *con_id);
+struct clk_core *clk_provider_get(struct device *dev, const char *con_id);
+void clk_provider_put(struct clk_core *clk);
+struct clk_core *devm_clk_provider_get(struct device *dev, const char *id);
+int clk_provider_notifier_register(struct clk_core *clk, struct notifier_block *nb);
+int clk_provider_notifier_unregister(struct clk_core *clk, struct notifier_block *nb);
+struct clk_core *clk_to_clk_core(struct clk *clk);
+
+/* clk_provider_prepare_enable helps cases using clk_enable in non-atomic context. */
+static inline int clk_provider_prepare_enable(struct clk_core *clk)
+{
+ int ret;
+
+ ret = clk_provider_prepare(clk);
+ if (ret)
+ return ret;
+ ret = clk_provider_enable(clk);
+ if (ret)
+ clk_provider_unprepare(clk);
+
+ return ret;
+}
+
+/* clk_provider_disable_unprepare helps cases using clk_disable in non-atomic context. */
+static inline void clk_provider_disable_unprepare(struct clk_core *clk)
+{
+ clk_provider_disable(clk);
+ clk_provider_unprepare(clk);
+}
/*
* FIXME clock api without lock protection
*/
-int __clk_prepare(struct clk *clk);
-void __clk_unprepare(struct clk *clk);
-void __clk_reparent(struct clk *clk, struct clk *new_parent);
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate);
+int __clk_prepare(struct clk_core *clk);
+void __clk_unprepare(struct clk_core *clk);
+void __clk_reparent(struct clk_core *clk, struct clk_core *new_parent);
+unsigned long __clk_round_rate(struct clk_core *clk, unsigned long rate);
struct of_device_id;
typedef void (*of_clk_init_cb_t)(struct device_node *);
struct clk_onecell_data {
- struct clk **clks;
+ struct clk_core **clks;
unsigned int clk_num;
};
@@ -574,22 +585,23 @@ extern struct of_device_id __clk_of_table;
#ifdef CONFIG_OF
int of_clk_add_provider(struct device_node *np,
- struct clk *(*clk_src_get)(struct of_phandle_args *args,
+ struct clk_core *(*clk_src_get)(struct of_phandle_args *args,
void *data),
void *data);
void of_clk_del_provider(struct device_node *np);
-struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
+struct clk_core *of_clk_src_simple_get(struct of_phandle_args *clkspec,
void *data);
-struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
+struct clk_core *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
int of_clk_get_parent_count(struct device_node *np);
const char *of_clk_get_parent_name(struct device_node *np, int index);
+struct clk_core *of_clk_provider_get(struct device_node *np, int index);
void of_clk_init(const struct of_device_id *matches);
#else /* !CONFIG_OF */
static inline int of_clk_add_provider(struct device_node *np,
- struct clk *(*clk_src_get)(struct of_phandle_args *args,
+ struct clk_core *(*clk_src_get)(struct of_phandle_args *args,
void *data),
void *data)
{
@@ -597,12 +609,12 @@ static inline int of_clk_add_provider(struct device_node *np,
}
#define of_clk_del_provider(np) \
{ while (0); }
-static inline struct clk *of_clk_src_simple_get(
+static inline struct clk_core *of_clk_src_simple_get(
struct of_phandle_args *clkspec, void *data)
{
return ERR_PTR(-ENOENT);
}
-static inline struct clk *of_clk_src_onecell_get(
+static inline struct clk_core *of_clk_src_onecell_get(
struct of_phandle_args *clkspec, void *data)
{
return ERR_PTR(-ENOENT);
@@ -612,6 +624,10 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
{
return NULL;
}
+static inline struct clk_core *of_clk_provider_get(struct device_node *np, int index)
+{
+ return NULL;
+}
#define of_clk_init(matches) \
{ while (0); }
#endif /* CONFIG_OF */
@@ -648,7 +664,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
#endif /* platform dependent I/O accessors */
#ifdef CONFIG_DEBUG_FS
-struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
+struct dentry *clk_debugfs_add_file(struct clk_core *clk, char *name, umode_t mode,
void *data, const struct file_operations *fops);
#endif
diff --git a/include/linux/clk.h b/include/linux/clk.h
index fb5e097..f46a2eb 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -22,6 +22,8 @@ struct clk;
#ifdef CONFIG_COMMON_CLK
+struct clk_core;
+
/**
* DOC: clk notifier callback types
*
@@ -56,7 +58,7 @@ struct clk;
* @notifier_head.
*/
struct clk_notifier {
- struct clk *clk;
+ struct clk_core *clk;
struct srcu_notifier_head notifier_head;
struct list_head node;
};
@@ -73,7 +75,7 @@ struct clk_notifier {
* current rate (this was done to optimize the implementation).
*/
struct clk_notifier_data {
- struct clk *clk;
+ struct clk_core *clk;
unsigned long old_rate;
unsigned long new_rate;
};
@@ -307,6 +309,14 @@ struct clk *clk_get_parent(struct clk *clk);
*/
struct clk *clk_get_sys(const char *dev_id, const char *con_id);
+/**
+ * clk_get_name - get a clock's name
+ * @clk: clock source
+ *
+ * Returns the name of the provided clock.
+ */
+const char *clk_get_name(struct clk *clk);
+
#else /* !CONFIG_HAVE_CLK */
static inline struct clk *clk_get(struct device *dev, const char *id)
@@ -398,7 +408,8 @@ struct of_phandle_args;
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
struct clk *of_clk_get(struct device_node *np, int index);
struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
-struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec);
+struct clk_core *of_clk_provider_get_by_name(struct device_node *np, const char *name);
+struct clk_core *of_clk_get_from_provider(struct of_phandle_args *clkspec);
#else
static inline struct clk *of_clk_get(struct device_node *np, int index)
{
@@ -409,6 +420,21 @@ static inline struct clk *of_clk_get_by_name(struct device_node *np,
{
return ERR_PTR(-ENOENT);
}
+
+#if defined(CONFIG_COMMON_CLK)
+static inline struct clk_core *of_clk_provider_get_by_name(struct device_node *np,
+ const char *name)
+{
+ return ERR_PTR(-ENOENT);
+}
+#else
+static inline struct clk *of_clk_provider_get_by_name(struct device_node *np,
+ const char *name)
+{
+ return ERR_PTR(-ENOENT);
+}
+#endif /* CONFIG_COMMON_CLK */
+
#endif
#endif
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index 94bad77..a6c5d67 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -17,11 +17,23 @@
struct clk;
struct device;
+/*
+ * To avoid a mass-rename of all non-common clock implementations (spread out
+ * in arch-specific code), we let them use struct clk for both the internal and
+ * external view.
+ */
+#ifdef CONFIG_COMMON_CLK
+struct clk_core;
+#define clk_core_t struct clk_core
+#else
+#define clk_core_t struct clk
+#endif
+
struct clk_lookup {
struct list_head node;
const char *dev_id;
const char *con_id;
- struct clk *clk;
+ clk_core_t *clk;
};
#define CLKDEV_INIT(d, n, c) \
@@ -31,7 +43,7 @@ struct clk_lookup {
.clk = c, \
}
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
+struct clk_lookup *clkdev_alloc(clk_core_t *clk, const char *con_id,
const char *dev_fmt, ...);
void clkdev_add(struct clk_lookup *cl);
@@ -40,12 +52,12 @@ void clkdev_drop(struct clk_lookup *cl);
void clkdev_add_table(struct clk_lookup *, size_t);
int clk_add_alias(const char *, const char *, char *, struct device *);
-int clk_register_clkdev(struct clk *, const char *, const char *, ...);
-int clk_register_clkdevs(struct clk *, struct clk_lookup *, size_t);
+int clk_register_clkdev(clk_core_t *, const char *, const char *, ...);
+int clk_register_clkdevs(clk_core_t *, struct clk_lookup *, size_t);
#ifdef CONFIG_COMMON_CLK
-int __clk_get(struct clk *clk);
-void __clk_put(struct clk *clk);
+int __clk_get(struct clk_core *clk);
+void __clk_put(struct clk_core *clk);
#endif
#endif
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v13 4/9] clk: per-user clock accounting for debug
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
@ 2014-09-23 18:44 ` Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 5/9] clk: Add floor and ceiling constraints to clock rates Tomeu Vizoso
` (4 subsequent siblings)
5 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:44 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
When a clock has multiple users, the WARNING on imbalance of
enable/disable may not show the guilty party since although they may
have commited the error earlier, the warning is emitted later when some
other user, presumably innocent, disables the clock.
Provide per-user clock enable/disable accounting and disabler tracking
in order to help debug these problems.
Based on previous work by Rabin Vincent <rabin@rab.in>.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
drivers/clk/clk.c | 38 ++++++++++++++++++++++++++++++++++----
drivers/clk/clk.h | 3 ++-
drivers/clk/clkdev.c | 11 ++++++-----
include/linux/clk-private.h | 5 +++++
4 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index ffe58ec..b34922e 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -543,7 +543,8 @@ static int clk_disable_unused(void)
}
late_initcall_sync(clk_disable_unused);
-struct clk *__clk_create_clk(struct clk_core *clk_core)
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
+ const char *con)
{
struct clk *clk;
@@ -556,6 +557,8 @@ struct clk *__clk_create_clk(struct clk_core *clk_core)
return ERR_PTR(-ENOMEM);
clk->core = clk_core;
+ clk->dev_id = dev;
+ clk->con_id = con;
return clk;
}
@@ -980,10 +983,25 @@ EXPORT_SYMBOL_GPL(clk_provider_disable);
*/
void clk_disable(struct clk *clk_user)
{
+ struct clk_core *clk;
+ unsigned long flags;
+
if (IS_ERR_OR_NULL(clk_user))
return;
- clk_provider_disable(clk_to_clk_core(clk_user));
+ clk = clk_to_clk_core(clk_user);
+
+ flags = clk_enable_lock();
+ if (!WARN(clk_user->enable_count == 0,
+ "incorrect disable clk dev %s con %s last disabler %pF\n",
+ clk_user->dev_id, clk_user->con_id, clk_user->last_disable)) {
+
+ clk_user->last_disable = __builtin_return_address(0);
+ clk_user->enable_count--;
+
+ __clk_disable(clk);
+ }
+ clk_enable_unlock(flags);
}
EXPORT_SYMBOL_GPL(clk_disable);
@@ -1044,10 +1062,22 @@ EXPORT_SYMBOL_GPL(clk_provider_enable);
*/
int clk_enable(struct clk *clk_user)
{
+ struct clk_core *clk;
+ unsigned long flags;
+ int ret;
+
if (!clk_user)
return 0;
- return clk_provider_enable(clk_to_clk_core(clk_user));
+ clk = clk_to_clk_core(clk_user);
+
+ flags = clk_enable_lock();
+ ret = __clk_enable(clk);
+ if (!ret)
+ clk_user->enable_count++;
+ clk_enable_unlock(flags);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(clk_enable);
@@ -1745,7 +1775,7 @@ struct clk *clk_get_parent(struct clk *clk_user)
if (IS_ERR(parent))
return (void *)parent;
- parent_user = __clk_create_clk(parent);
+ parent_user = __clk_create_clk(parent, clk_user->dev_id, clk_user->con_id);
if (IS_ERR(parent_user))
__clk_put(parent);
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index 3b3068b..49eff38 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -19,5 +19,6 @@ void of_clk_unlock(void);
#endif
#if defined(CONFIG_COMMON_CLK)
-struct clk *__clk_create_clk(struct clk_core *clk_core);
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
+ const char *con);
#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index f99c1e4..8699a9b 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -36,7 +36,7 @@ static DEFINE_MUTEX(clocks_mutex);
typedef struct clk_core clkdev_ret_t;
#else
typedef struct clk clkdev_ret_t;
-#define __clk_create_clk(clk) clk
+#define __clk_create_clk(clk, dev_id, con_id) clk
#define clk_to_clk_core(clk) clk
#endif
@@ -96,7 +96,7 @@ struct clk *of_clk_get(struct device_node *np, int index)
if (IS_ERR(clk))
return (void *)clk;
- clk_user = __clk_create_clk(clk);
+ clk_user = __clk_create_clk(clk, np->full_name, NULL);
if (IS_ERR(clk_user))
__clk_put(clk);
@@ -160,7 +160,7 @@ struct clk *of_clk_get_by_name(struct device_node *np, const char *name)
if (IS_ERR(clk))
return (void *)clk;
- clk_user = __clk_create_clk(clk);
+ clk_user = __clk_create_clk(clk, np->full_name, NULL);
if (IS_ERR(clk_user))
__clk_put(clk);
@@ -238,7 +238,7 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id)
if (IS_ERR(clk))
return (void *)clk;
- clk_user = __clk_create_clk(clk);
+ clk_user = __clk_create_clk(clk, dev_id, con_id);
if (IS_ERR(clk_user))
__clk_put(clk);
@@ -265,6 +265,7 @@ EXPORT_SYMBOL(clk_provider_get);
struct clk *clk_get(struct device *dev, const char *con_id)
{
+ const char *dev_id = dev ? dev_name(dev) : NULL;
clkdev_ret_t *clk;
struct clk *clk_user;
@@ -272,7 +273,7 @@ struct clk *clk_get(struct device *dev, const char *con_id)
if (IS_ERR(clk))
return (void *)clk;
- clk_user = __clk_create_clk(clk);
+ clk_user = __clk_create_clk(clk, dev_id, con_id);
if (IS_ERR(clk_user))
__clk_put(clk);
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 2c1ece9..ce6a528 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -57,6 +57,11 @@ struct clk_core {
struct clk {
struct clk_core *core;
+ const char *dev_id;
+ const char *con_id;
+
+ unsigned int enable_count;
+ void *last_disable;
};
/*
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v13 5/9] clk: Add floor and ceiling constraints to clock rates
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 4/9] clk: per-user clock accounting for debug Tomeu Vizoso
@ 2014-09-23 18:44 ` Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 6/9] clk: Warn of unbalanced clk_prepare() calls Tomeu Vizoso
` (3 subsequent siblings)
5 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:44 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
Adds a way for clock consumers to set maximum and minimum rates. This can be
used for thermal drivers to set ceiling rates, or by misc. drivers to set
floor rates to assure a minimum performance level.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Tested-by: Heiko Stuebner <heiko@sntech.de>
---
v9: * Apply first all the floor constraints, then the ceiling constraints.
* WARN on ceiling constraints below the current floor, for a given user clk
v5: * Move the storage of constraints to the per-user clk struct, as suggested
by Stephen Warren.
---
drivers/clk/clk.c | 43 +++++++++++++++++++++++++++++++++++++++++++
drivers/clk/clk.h | 1 +
drivers/clk/clkdev.c | 2 +-
include/linux/clk-private.h | 5 +++++
include/linux/clk.h | 18 ++++++++++++++++++
5 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index b34922e..11ab923 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -560,6 +560,8 @@ struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
clk->dev_id = dev;
clk->con_id = con;
+ hlist_add_head(&clk->child_node, &clk_core->per_user_clks);
+
return clk;
}
@@ -1669,6 +1671,7 @@ static void clk_change_rate(struct clk_core *clk)
int clk_provider_set_rate(struct clk_core *clk, unsigned long rate)
{
struct clk_core *top, *fail_clk;
+ struct clk *clk_user;
int ret = 0;
if (!clk)
@@ -1677,6 +1680,15 @@ int clk_provider_set_rate(struct clk_core *clk, unsigned long rate)
/* prevent racing with updates to the clock topology */
clk_prepare_lock();
+ hlist_for_each_entry(clk_user, &clk->per_user_clks, child_node) {
+ rate = max(rate, clk_user->floor_constraint);
+ }
+
+ hlist_for_each_entry(clk_user, &clk->per_user_clks, child_node) {
+ if (clk_user->ceiling_constraint > 0)
+ rate = min(rate, clk_user->ceiling_constraint);
+ }
+
/* bail early if nothing to do */
if (rate == clk_provider_get_rate(clk))
goto out;
@@ -1743,6 +1755,29 @@ int clk_set_rate(struct clk *clk_user, unsigned long rate)
}
EXPORT_SYMBOL_GPL(clk_set_rate);
+int clk_set_floor_rate(struct clk *clk_user, unsigned long rate)
+{
+ struct clk_core *clk = clk_to_clk_core(clk_user);
+
+ clk_user->floor_constraint = rate;
+ return clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+}
+EXPORT_SYMBOL_GPL(clk_set_floor_rate);
+
+int clk_set_ceiling_rate(struct clk *clk_user, unsigned long rate)
+{
+ struct clk_core *clk = clk_to_clk_core(clk_user);
+
+ WARN(rate > 0 && rate < clk_user->floor_constraint,
+ "clk %s dev %s con %s: new ceiling %lu lower than existing floor %lu\n",
+ __clk_get_name(clk), clk_user->dev_id, clk_user->con_id, rate,
+ clk_user->floor_constraint);
+
+ clk_user->ceiling_constraint = rate;
+ return clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+}
+EXPORT_SYMBOL_GPL(clk_set_ceiling_rate);
+
struct clk_core *clk_provider_get_parent(struct clk_core *clk)
{
struct clk_core *parent;
@@ -2094,6 +2129,8 @@ int __clk_init(struct device *dev, struct clk_core *clk)
}
}
+ INIT_HLIST_HEAD(&clk->per_user_clks);
+
/*
* optional platform-specific magic
*
@@ -2500,6 +2537,12 @@ int clk_notifier_unregister(struct clk *clk_user, struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(clk_notifier_unregister);
+void __clk_free_clk(struct clk *clk_user)
+{
+ hlist_del(&clk_user->child_node);
+ kfree(clk_user);
+}
+
#ifdef CONFIG_OF
/**
* struct of_clk_provider - Clock provider registration structure
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index 49eff38..005deb3 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -21,4 +21,5 @@ void of_clk_unlock(void);
#if defined(CONFIG_COMMON_CLK)
struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
const char *con);
+void __clk_free_clk(struct clk *clk_user);
#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 8699a9b..a555e58 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -292,7 +292,7 @@ void clk_put(struct clk *clk)
#if defined(CONFIG_COMMON_CLK)
struct clk_core *core = clk_to_clk_core(clk);
- kfree(clk);
+ __clk_free_clk(clk);
clk_provider_put(core);
#else
__clk_put(clk);
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index ce6a528..8126046 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -48,6 +48,7 @@ struct clk_core {
unsigned long accuracy;
struct hlist_head children;
struct hlist_node child_node;
+ struct hlist_head per_user_clks;
unsigned int notifier_count;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
@@ -62,6 +63,10 @@ struct clk {
unsigned int enable_count;
void *last_disable;
+
+ unsigned long floor_constraint;
+ unsigned long ceiling_constraint;
+ struct hlist_node child_node;
};
/*
diff --git a/include/linux/clk.h b/include/linux/clk.h
index f46a2eb..066b100 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -275,6 +275,24 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
int clk_set_rate(struct clk *clk, unsigned long rate);
/**
+ * clk_set_floor_rate - set a minimum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired minimum clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_floor_rate(struct clk *clk, unsigned long rate);
+
+/**
+ * clk_set_ceiling_rate - set a maximum clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired maximum clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_ceiling_rate(struct clk *clk, unsigned long rate);
+
+/**
* clk_set_parent - set the parent clock source for this clock
* @clk: clock source
* @parent: parent clock source
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v13 6/9] clk: Warn of unbalanced clk_prepare() calls
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 4/9] clk: per-user clock accounting for debug Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 5/9] clk: Add floor and ceiling constraints to clock rates Tomeu Vizoso
@ 2014-09-23 18:44 ` Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 7/9] clk: Take the prepare lock when updating the list of per-user clks Tomeu Vizoso
` (2 subsequent siblings)
5 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:44 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
The warning will display the clock user that is trying to unprepare the clock,
and the location of the last unprepare call.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
v8: * Patch added
---
drivers/clk/clk.c | 22 ++++++++++++++++++++--
include/linux/clk-private.h | 3 +++
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 11ab923..bfb4672 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -878,7 +878,17 @@ void clk_unprepare(struct clk *clk_user)
if (IS_ERR_OR_NULL(clk_user))
return;
- clk_provider_unprepare(clk_to_clk_core(clk_user));
+ clk_prepare_lock();
+ if (!WARN(clk_user->prepare_count == 0,
+ "incorrect unprepare clk dev %s con %s last caller of unprepare %pF\n",
+ clk_user->dev_id, clk_user->con_id, clk_user->last_unprepare)) {
+
+ clk_user->last_unprepare = __builtin_return_address(0);
+ clk_user->prepare_count--;
+
+ __clk_unprepare(clk_to_clk_core(clk_user));
+ }
+ clk_prepare_unlock();
}
EXPORT_SYMBOL_GPL(clk_unprepare);
@@ -934,10 +944,18 @@ EXPORT_SYMBOL_GPL(clk_provider_prepare);
*/
int clk_prepare(struct clk *clk_user)
{
+ int ret;
+
if (!clk_user)
return 0;
- return clk_provider_prepare(clk_to_clk_core(clk_user));
+ clk_prepare_lock();
+ ret = __clk_prepare(clk_to_clk_core(clk_user));
+ if (!ret)
+ clk_user->prepare_count++;
+ clk_prepare_unlock();
+
+ return ret;
}
EXPORT_SYMBOL_GPL(clk_prepare);
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index 8126046..cf93bde 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -64,6 +64,9 @@ struct clk {
unsigned int enable_count;
void *last_disable;
+ unsigned int prepare_count;
+ void *last_unprepare;
+
unsigned long floor_constraint;
unsigned long ceiling_constraint;
struct hlist_node child_node;
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v13 7/9] clk: Take the prepare lock when updating the list of per-user clks
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
` (2 preceding siblings ...)
2014-09-23 18:44 ` [PATCH v13 6/9] clk: Warn of unbalanced clk_prepare() calls Tomeu Vizoso
@ 2014-09-23 18:44 ` Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 8/9] clk: Take the prepare lock when updating the per-user constraints Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 9/9] clk: Add docs about calling clk_put after clk_get_parent Tomeu Vizoso
5 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:44 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
drivers/clk/clk.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bfb4672..3eb133c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -560,7 +560,9 @@ struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev,
clk->dev_id = dev;
clk->con_id = con;
+ clk_prepare_lock();
hlist_add_head(&clk->child_node, &clk_core->per_user_clks);
+ clk_prepare_unlock();
return clk;
}
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v13 8/9] clk: Take the prepare lock when updating the per-user constraints
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
` (3 preceding siblings ...)
2014-09-23 18:44 ` [PATCH v13 7/9] clk: Take the prepare lock when updating the list of per-user clks Tomeu Vizoso
@ 2014-09-23 18:44 ` Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 9/9] clk: Add docs about calling clk_put after clk_get_parent Tomeu Vizoso
5 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:44 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
drivers/clk/clk.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 3eb133c..c507548 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1778,15 +1778,25 @@ EXPORT_SYMBOL_GPL(clk_set_rate);
int clk_set_floor_rate(struct clk *clk_user, unsigned long rate)
{
struct clk_core *clk = clk_to_clk_core(clk_user);
+ int ret;
+
+ clk_prepare_lock();
clk_user->floor_constraint = rate;
- return clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+ ret = clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+
+ clk_prepare_unlock();
+
+ return ret;
}
EXPORT_SYMBOL_GPL(clk_set_floor_rate);
int clk_set_ceiling_rate(struct clk *clk_user, unsigned long rate)
{
struct clk_core *clk = clk_to_clk_core(clk_user);
+ int ret;
+
+ clk_prepare_lock();
WARN(rate > 0 && rate < clk_user->floor_constraint,
"clk %s dev %s con %s: new ceiling %lu lower than existing floor %lu\n",
@@ -1794,7 +1804,11 @@ int clk_set_ceiling_rate(struct clk *clk_user, unsigned long rate)
clk_user->floor_constraint);
clk_user->ceiling_constraint = rate;
- return clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+ ret = clk_provider_set_rate(clk, clk_provider_get_rate(clk));
+
+ clk_prepare_unlock();
+
+ return ret;
}
EXPORT_SYMBOL_GPL(clk_set_ceiling_rate);
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [PATCH v13 9/9] clk: Add docs about calling clk_put after clk_get_parent
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
` (4 preceding siblings ...)
2014-09-23 18:44 ` [PATCH v13 8/9] clk: Take the prepare lock when updating the per-user constraints Tomeu Vizoso
@ 2014-09-23 18:44 ` Tomeu Vizoso
5 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-23 18:44 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, tomasz.figa, Peter De Schrijver,
rabin, linux-kernel, linux-arm-kernel, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
As otherwise the per-user clk will be leaked.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
drivers/clk/clk.c | 3 ++-
include/linux/clk.h | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index c507548..2c7baea 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1828,7 +1828,8 @@ EXPORT_SYMBOL_GPL(clk_provider_get_parent);
* clk_get_parent - return the parent of a clk
* @clk_user: the clk whose parent gets returned
*
- * Simply returns clk->parent. Returns NULL if clk is NULL.
+ * Simply returns clk->parent. Returns NULL if clk is NULL. Caller must call
+ * clk_put() to release the returned struct clk.
*/
struct clk *clk_get_parent(struct clk *clk_user)
{
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 066b100..4f54952 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -306,7 +306,8 @@ int clk_set_parent(struct clk *clk, struct clk *parent);
* @clk: clock source
*
* Returns struct clk corresponding to parent clock source, or
- * valid IS_ERR() condition containing errno.
+ * valid IS_ERR() condition containing errno. Caller must call
+ * clk_put() to release the returned struct clk.
*/
struct clk *clk_get_parent(struct clk *clk);
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [PATCH v13 0/9] Per-user clock constraints
2014-09-23 18:40 [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
2014-09-23 18:40 ` [PATCH v13 1/9] clk: Add temporary mapping to the existing API Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
@ 2014-09-23 20:59 ` Stephen Boyd
2014-09-24 8:27 ` Tomeu Vizoso
2014-09-24 9:14 ` [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
3 siblings, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2014-09-23 20:59 UTC (permalink / raw)
To: Tomeu Vizoso, Mike Turquette
Cc: Russell King, Stephen Warren, Peter De Schrijver, linux-kernel,
tomasz.figa, rabin, Thierry Reding, Javier Martinez Canillas,
linux-arm-kernel
On 09/23/14 11:40, Tomeu Vizoso wrote:
> Hello,
>
> this version of the patchset addresses some issues that Russell pointed out
> yesterday:
>
> * Refactor the changes to clkdev.c to reduce the amount of ifdefs.
>
> * Properly release clocks when there isn't enough memory to create the per-user
> wrapper.
>
> * Add clk_provider_put(struct clk_core*) for clock implementations to call
> instead of clk_put(struct clk*) (instead of exposing __clk_put).
>
> As the previous versions, this is based on top of 3.17-rc4 and Mike's patch at
> [0].
Any thoughts on my comments on patch set #10[1]? It seems like we can
avoid having a flag day to support this.
[1] https://lkml.org/lkml/2014/9/9/960
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v13 0/9] Per-user clock constraints
2014-09-23 20:59 ` [PATCH v13 0/9] Per-user clock constraints Stephen Boyd
@ 2014-09-24 8:27 ` Tomeu Vizoso
2014-09-26 1:29 ` Stephen Boyd
0 siblings, 1 reply; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-24 8:27 UTC (permalink / raw)
To: Stephen Boyd, Mike Turquette
Cc: Russell King, Stephen Warren, Peter De Schrijver, linux-kernel,
tomasz.figa, rabin, Thierry Reding, Javier Martinez Canillas,
linux-arm-kernel
On 09/23/2014 10:59 PM, Stephen Boyd wrote:
> On 09/23/14 11:40, Tomeu Vizoso wrote:
>> Hello,
>>
>> this version of the patchset addresses some issues that Russell pointed out
>> yesterday:
>>
>> * Refactor the changes to clkdev.c to reduce the amount of ifdefs.
>>
>> * Properly release clocks when there isn't enough memory to create the per-user
>> wrapper.
>>
>> * Add clk_provider_put(struct clk_core*) for clock implementations to call
>> instead of clk_put(struct clk*) (instead of exposing __clk_put).
>>
>> As the previous versions, this is based on top of 3.17-rc4 and Mike's patch at
>> [0].
>
> Any thoughts on my comments on patch set #10[1]? It seems like we can
> avoid having a flag day to support this.
I cannot say that I fully understand your proposal, but IMO the most
valuable thing in this patchset is precisely the API split (and thus,
the flag day is inherent to it).
I see a lot of value in clk consumers to use a defined set of functions
that all take and/or return struct clk, and for providers to use the
functions that take and/or return struct clk_core. Makes the API clearer
and allows it to have a more scalable growth in the future.
A less important feature of the patchset are per-user clocks, which (if
I understand correctly) your proposal would address without requiring a
flag day.
And then we have clock constraints, which is probably the least
important feature in the grand scheme of things, but it's actually what
I personally care about.
If we wanted to add a way for clk users to specify clock constraints
without any refactoring, we could easily do so by reusing the request
pattern that pm_qos uses:
void clk_add_constraint(struct clk_request *req,
int constraint_type,
unsigned long value);
void clk_update_constraint(struct clk_request *req,
unsigned long new_value);
void clk_remove_constraint(struct clk_request *req);
It wouldn't be that bad IMO, but the API refactoring was something that
was long desired and this was seen as a good opportunity to tackle it
before it gets worst.
Cheers,
Tomeu
> [1] https://lkml.org/lkml/2014/9/9/960
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v13 0/9] Per-user clock constraints
2014-09-23 18:40 [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
` (2 preceding siblings ...)
2014-09-23 20:59 ` [PATCH v13 0/9] Per-user clock constraints Stephen Boyd
@ 2014-09-24 9:14 ` Tomeu Vizoso
3 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-24 9:14 UTC (permalink / raw)
To: Mike Turquette
Cc: Stephen Warren, Thierry Reding, Tomasz Figa, Peter De Schrijver,
rabin, linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Javier Martinez Canillas,
Russell King, Tomeu Vizoso
On 23 September 2014 20:40, Tomeu Vizoso <tomeu.vizoso@collabora.com> wrote:
> Hello,
>
> this version of the patchset addresses some issues that Russell pointed out
> yesterday:
Just an update with the test build results from kbuild. I'm not sure
about the timeouts, but it can be seen that allmodconfig succeeds for
all arches except sh and sparc64, which timed out. Other configs
succeed for those arches, though.
Regards,
Tomeu
-------- Forwarded Message --------
Subject: [tomeu:clk-refactoring-13]
26c9a94cb870d0c5a10b73ac454b19df7664ed01 BUILD INCOMPLETE
Date: Wed, 24 Sep 2014 07:29:29 +0800
From: kbuild test robot <fengguang.wu@intel.com>
To: Tomeu Vizoso <tomeu.vizoso@collabora.com>
git://git.collabora.co.uk/git/user/tomeu/linux.git clk-refactoring-13
26c9a94cb870d0c5a10b73ac454b19df7664ed01 clk: Add docs about calling
clk_put after clk_get_parent
TIMEOUT after 300m
Sorry we cannot finish the testset for your branch within a reasonable time.
It may either be some build server is down or some build worker is busy doing
bisects. The branch will get more complete coverage and possible error reports
when our build infrastructure is restored or catches up. There will be no more
build success notification for this branch head, but you can expect reasonably
good test coverage after waiting for 1 day.
configs timed out: 105
alpha allyesconfig
avr32 allyesconfig
avr32 atngw100_defconfig
avr32 atstk1006_defconfig
blackfin allyesconfig
blackfin defconfig
cris allyesconfig
frv defconfig
i386 randconfig-ha0
i386 randconfig-ha1
i386 randconfig-ha2
i386 randconfig-ha3
i386 randconfig-hsxa0
i386 randconfig-hsxa1
i386 randconfig-hsxa2
i386 randconfig-hsxa3
i386 randconfig-hsxa4
i386 randconfig-hsxa5
i386 randconfig-hsxa6
i386 randconfig-hsxa7
i386 randconfig-hsxa8
i386 randconfig-hsxa9
i386 randconfig-hxb0
i386 randconfig-hxb1
i386 randconfig-hxb2
i386 randconfig-hxb3
i386 randconfig-r0
i386 randconfig-r1
i386 randconfig-r2
i386 randconfig-r3
i386 randconfig-x000
i386 randconfig-x001
i386 randconfig-x002
i386 randconfig-x003
i386 randconfig-x004
i386 randconfig-x005
i386 randconfig-x006
i386 randconfig-x007
i386 randconfig-x008
i386 randconfig-x009
ia64 allyesconfig
m68k allyesconfig
mips allyesconfig
mips defconfig
mn10300 asb2364_defconfig
openrisc or1ksim_defconfig
parisc allyesconfig
powerpc allyesconfig
powerpc chroma_defconfig
powerpc corenet64_smp_defconfig
powerpc gamecube_defconfig
powerpc linkstation_defconfig
powerpc mpc512x
powerpc powerpc
powerpc ppc44x
powerpc wii_defconfig
s390 allyesconfig
sh allmodconfig
sh allyesconfig
sh defconfig
sparc64 allmodconfig
sparc64 allyesconfig
sparc allyesconfig
tile allyesconfig
tile tilegx_defconfig
um i386_defconfig
um x86_64_defconfig
x86_64 allyesconfig
x86_64 lkp
x86_64 randconfig-c0
x86_64 randconfig-c1
x86_64 randconfig-c2
x86_64 randconfig-c3
x86_64 randconfig-ha0
x86_64 randconfig-ha1
x86_64 randconfig-ha2
x86_64 randconfig-ha3
x86_64 randconfig-hsxa0
x86_64 randconfig-hsxa1
x86_64 randconfig-hsxa2
x86_64 randconfig-hsxa3
x86_64 randconfig-hsxa4
x86_64 randconfig-hsxa5
x86_64 randconfig-hsxa6
x86_64 randconfig-hsxa7
x86_64 randconfig-hsxa8
x86_64 randconfig-hsxa9
x86_64 randconfig-hxb0
x86_64 randconfig-hxb1
x86_64 randconfig-hxb2
x86_64 randconfig-hxb3
x86_64 randconfig-j0
x86_64 randconfig-j1
x86_64 randconfig-x000
x86_64 randconfig-x001
x86_64 randconfig-x002
x86_64 randconfig-x003
x86_64 randconfig-x004
x86_64 randconfig-x005
x86_64 randconfig-x006
x86_64 randconfig-x007
x86_64 randconfig-x008
x86_64 randconfig-x009
x86_64 rhel
xtensa allyesconfig
configs tested: 99
parisc c3000_defconfig
parisc b180_defconfig
parisc defconfig
alpha defconfig
parisc allnoconfig
x86_64 allnoconfig
x86_64 randconfig-c3-0924
x86_64 randconfig-c1-0924
x86_64 randconfig-c2-0924
x86_64 randconfig-c0-0924
ia64 allmodconfig
ia64 allnoconfig
ia64 defconfig
ia64 alldefconfig
i386 randconfig-ha0-0924
i386 randconfig-ha2-0924
i386 randconfig-ha1-0924
i386 randconfig-ha3-0924
s390 allmodconfig
s390 allnoconfig
s390 defconfig
x86_64 randconfig-ha1-0924
x86_64 randconfig-ha3-0924
x86_64 randconfig-ha0-0924
x86_64 randconfig-ha2-0924
arm omap2plus_defconfig
arm sa1100
arm allmodconfig
arm prima2_defconfig
arm at91_dt_defconfig
arm allnoconfig
arm samsung
arm spear13xx_defconfig
arm s3c2410_defconfig
arm iop-adma
arm imx_v6_v7_defconfig
arm mmp
arm tegra_defconfig
arm arm5
arm marzen_defconfig
arm at_hdmac
arm ep93xx
arm sh
arm arm67
cris etrax-100lx_v2_defconfig
blackfin TCM-BF537_defconfig
blackfin BF561-EZKIT-SMP_defconfig
blackfin BF533-EZKIT_defconfig
blackfin BF526-EZBRD_defconfig
i386 randconfig-hxb3-0924
i386 randconfig-hxb1-0924
i386 randconfig-hxb2-0924
i386 randconfig-hxb0-0924
m68k multi_defconfig
m68k m5475evb_defconfig
m68k allmodconfig
m68k amiga_defconfig
mips allmodconfig
mips jz4740
mips allnoconfig
mips fuloong2e_defconfig
mips txx9
powerpc defconfig
powerpc ppc64_defconfig
powerpc allnoconfig
powerpc allmodconfig
sh titan_defconfig
sh rsk7269_defconfig
sh sh7785lcr_32bit_defconfig
sh allnoconfig
x86_64 randconfig-hxb2-0924
x86_64 randconfig-hxb0-0924
x86_64 randconfig-hxb3-0924
x86_64 randconfig-hxb1-0924
sparc defconfig
sparc64 allnoconfig
sparc64 defconfig
xtensa common_defconfig
m32r m32104ut_defconfig
xtensa iss_defconfig
m32r opsput_defconfig
m32r usrv_defconfig
m32r mappi3.smp_defconfig
microblaze mmu_defconfig
microblaze nommu_defconfig
microblaze allyesconfig
i386 allyesconfig
i386 randconfig-r0-0924
i386 randconfig-r2-0924
i386 randconfig-r3-0924
i386 randconfig-r1-0924
x86_64 allmodconfig
i386 allnoconfig
i386 defconfig
i386 allmodconfig
i386 alldefconfig
x86_64 acpi-redef
x86_64 allyesdebian
x86_64 nfsroot
Thanks,
Fengguang
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v13 0/9] Per-user clock constraints
2014-09-24 8:27 ` Tomeu Vizoso
@ 2014-09-26 1:29 ` Stephen Boyd
2014-09-26 8:09 ` Tomeu Vizoso
0 siblings, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2014-09-26 1:29 UTC (permalink / raw)
To: Tomeu Vizoso, Mike Turquette
Cc: Russell King, Stephen Warren, Peter De Schrijver, linux-kernel,
tomasz.figa, rabin, Thierry Reding, Javier Martinez Canillas,
linux-arm-kernel
On 09/24/14 01:27, Tomeu Vizoso wrote:
> On 09/23/2014 10:59 PM, Stephen Boyd wrote:
>>
>> Any thoughts on my comments on patch set #10[1]? It seems like we can
>> avoid having a flag day to support this.
> I cannot say that I fully understand your proposal, but IMO the most
> valuable thing in this patchset is precisely the API split (and thus,
> the flag day is inherent to it).
>
> I see a lot of value in clk consumers to use a defined set of functions
> that all take and/or return struct clk, and for providers to use the
> functions that take and/or return struct clk_core. Makes the API clearer
> and allows it to have a more scalable growth in the future.
I see a lot of non-value. It's hugely invasive needing every driver to
change. Invariably we're going to break something. Back porting things
across this is a real pain (good luck stable trees!). Reviewing the
patches aren't feasible given their size. There's a reason why we don't
do flag days. They suck.
We already have the consumer/provider split in the struct clk_hw and
struct clk separation. Why don't we just use struct clk_hw throughout
the provider APIs? The only op that isn't doing this is determine_rate()
which might be able to accept a flag day. Otherwise we rename it to
something else and migrate everyone over to a different named function
that doesn't take a struct clk **. Then we introduce new APIs for the
providers to use that are struct clk_hw focused instead of struct clk
focused and migrate them too. The benefit being that we get proper
review of this stuff because the patches are small. We can let
coccinelle do it too.
>
> A less important feature of the patchset are per-user clocks, which (if
> I understand correctly) your proposal would address without requiring a
> flag day.
The subject of this thread seems to imply that it's the most important
part. I'm confused.
>
> And then we have clock constraints, which is probably the least
> important feature in the grand scheme of things, but it's actually what
> I personally care about.
>
> If we wanted to add a way for clk users to specify clock constraints
> without any refactoring, we could easily do so by reusing the request
> pattern that pm_qos uses:
>
> void clk_add_constraint(struct clk_request *req,
> int constraint_type,
> unsigned long value);
>
> void clk_update_constraint(struct clk_request *req,
> unsigned long new_value);
>
> void clk_remove_constraint(struct clk_request *req);
>
> It wouldn't be that bad IMO, but the API refactoring was something that
> was long desired and this was seen as a good opportunity to tackle it
> before it gets worst.
>
Sure. Maybe we should just do that so we don't break things.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v13 0/9] Per-user clock constraints
2014-09-26 1:29 ` Stephen Boyd
@ 2014-09-26 8:09 ` Tomeu Vizoso
2014-09-26 23:20 ` Mike Turquette
0 siblings, 1 reply; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-26 8:09 UTC (permalink / raw)
To: Stephen Boyd, Mike Turquette
Cc: Russell King, Stephen Warren, Peter De Schrijver, linux-kernel,
tomasz.figa, rabin, Thierry Reding, Javier Martinez Canillas,
linux-arm-kernel
On 09/26/2014 03:29 AM, Stephen Boyd wrote:
> On 09/24/14 01:27, Tomeu Vizoso wrote:
>> On 09/23/2014 10:59 PM, Stephen Boyd wrote:
>>>
>>> Any thoughts on my comments on patch set #10[1]? It seems like we can
>>> avoid having a flag day to support this.
>> I cannot say that I fully understand your proposal, but IMO the most
>> valuable thing in this patchset is precisely the API split (and thus,
>> the flag day is inherent to it).
>>
>> I see a lot of value in clk consumers to use a defined set of functions
>> that all take and/or return struct clk, and for providers to use the
>> functions that take and/or return struct clk_core. Makes the API clearer
>> and allows it to have a more scalable growth in the future.
>
> I see a lot of non-value. It's hugely invasive needing every driver to
> change.
There's obviously a trade-off to be made by the maintainer, and I don't
think that Mike has taken this lightly. He has already stated what his
opinion is and I have acted accordingly.
> Invariably we're going to break something.
Given all the build tests that these series have passed and the nature
of the changes (you can also check the script that does the
refactoring), I don't expect that much breakage.
> Back porting things
> across this is a real pain (good luck stable trees!). Reviewing the
> patches aren't feasible given their size. There's a reason why we don't
> do flag days. They suck.
Flag days are sometimes needed and is up to each maintainer to decide
what is better for the subsystem since they are the ones dealing with
the issues that may arise anyway.
> We already have the consumer/provider split in the struct clk_hw and
> struct clk separation. Why don't we just use struct clk_hw throughout
> the provider APIs? The only op that isn't doing this is determine_rate()
> which might be able to accept a flag day. Otherwise we rename it to
> something else and migrate everyone over to a different named function
> that doesn't take a struct clk **. Then we introduce new APIs for the
> providers to use that are struct clk_hw focused instead of struct clk
> focused and migrate them too. The benefit being that we get proper
> review of this stuff because the patches are small. We can let
> coccinelle do it too.
Really, the bulk of it is just a plain function rename that is in its
own commit. And we have a simple script that can be reviewed. And it has
passed the kbuild tests. Given that, and if we don't focus on just the
line count of that patch, I don't see your proposal as being
significantly better.
>> A less important feature of the patchset are per-user clocks, which (if
>> I understand correctly) your proposal would address without requiring a
>> flag day.
>
> The subject of this thread seems to imply that it's the most important
> part. I'm confused.
Sorry about that, I agree that it could be improved.
>> And then we have clock constraints, which is probably the least
>> important feature in the grand scheme of things, but it's actually what
>> I personally care about.
>>
>> If we wanted to add a way for clk users to specify clock constraints
>> without any refactoring, we could easily do so by reusing the request
>> pattern that pm_qos uses:
>>
>> void clk_add_constraint(struct clk_request *req,
>> int constraint_type,
>> unsigned long value);
>>
>> void clk_update_constraint(struct clk_request *req,
>> unsigned long new_value);
>>
>> void clk_remove_constraint(struct clk_request *req);
>>
>> It wouldn't be that bad IMO, but the API refactoring was something that
>> was long desired and this was seen as a good opportunity to tackle it
>> before it gets worst.
>>
>
> Sure. Maybe we should just do that so we don't break things.
That hasn't been what Mike has stated in the past, but I actually have
such a patch somewhere that I can dust off and send for review.
Cheers,
Tomeu
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v13 0/9] Per-user clock constraints
2014-09-26 8:09 ` Tomeu Vizoso
@ 2014-09-26 23:20 ` Mike Turquette
2014-09-27 0:15 ` Stephen Boyd
` (2 more replies)
0 siblings, 3 replies; 24+ messages in thread
From: Mike Turquette @ 2014-09-26 23:20 UTC (permalink / raw)
To: Tomeu Vizoso, Stephen Boyd
Cc: Russell King, Stephen Warren, Peter De Schrijver, linux-kernel,
tomasz.figa, rabin, Thierry Reding, Javier Martinez Canillas,
linux-arm-kernel
Quoting Tomeu Vizoso (2014-09-26 01:09:20)
> On 09/26/2014 03:29 AM, Stephen Boyd wrote:
> > On 09/24/14 01:27, Tomeu Vizoso wrote:
> >> On 09/23/2014 10:59 PM, Stephen Boyd wrote:
> >>>
> >>> Any thoughts on my comments on patch set #10[1]? It seems like we can
> >>> avoid having a flag day to support this.
> >> I cannot say that I fully understand your proposal, but IMO the most
> >> valuable thing in this patchset is precisely the API split (and thus,
> >> the flag day is inherent to it).
> >>
> >> I see a lot of value in clk consumers to use a defined set of functions
> >> that all take and/or return struct clk, and for providers to use the
> >> functions that take and/or return struct clk_core. Makes the API clearer
> >> and allows it to have a more scalable growth in the future.
> >
> > I see a lot of non-value. It's hugely invasive needing every driver to
> > change.
>
> There's obviously a trade-off to be made by the maintainer, and I don't
> think that Mike has taken this lightly. He has already stated what his
> opinion is and I have acted accordingly.
I respect Stephen's opinion on this. You both have the goal of getting
clock-based constraints merged in, which is good.
>
> > Invariably we're going to break something.
>
> Given all the build tests that these series have passed and the nature
> of the changes (you can also check the script that does the
> refactoring), I don't expect that much breakage.
>
> > Back porting things
> > across this is a real pain (good luck stable trees!). Reviewing the
> > patches aren't feasible given their size. There's a reason why we don't
> > do flag days. They suck.
>
> Flag days are sometimes needed and is up to each maintainer to decide
> what is better for the subsystem since they are the ones dealing with
> the issues that may arise anyway.
>
> > We already have the consumer/provider split in the struct clk_hw and
> > struct clk separation. Why don't we just use struct clk_hw throughout
> > the provider APIs? The only op that isn't doing this is determine_rate()
> > which might be able to accept a flag day. Otherwise we rename it to
> > something else and migrate everyone over to a different named function
> > that doesn't take a struct clk **. Then we introduce new APIs for the
> > providers to use that are struct clk_hw focused instead of struct clk
> > focused and migrate them too. The benefit being that we get proper
> > review of this stuff because the patches are small. We can let
> > coccinelle do it too.
I have been opposed to mucking with clk_hw before, but that was because
the goal was never clear. Now that we know that we're trying to split
the API then it might be reasonable to use it.
Stephen, does your above proposal still allow for unique struct clk
cookies for each user of a clock?
Regards,
Mike
>
> Really, the bulk of it is just a plain function rename that is in its
> own commit. And we have a simple script that can be reviewed. And it has
> passed the kbuild tests. Given that, and if we don't focus on just the
> line count of that patch, I don't see your proposal as being
> significantly better.
>
> >> A less important feature of the patchset are per-user clocks, which (if
> >> I understand correctly) your proposal would address without requiring a
> >> flag day.
> >
> > The subject of this thread seems to imply that it's the most important
> > part. I'm confused.
>
> Sorry about that, I agree that it could be improved.
>
> >> And then we have clock constraints, which is probably the least
> >> important feature in the grand scheme of things, but it's actually what
> >> I personally care about.
> >>
> >> If we wanted to add a way for clk users to specify clock constraints
> >> without any refactoring, we could easily do so by reusing the request
> >> pattern that pm_qos uses:
> >>
> >> void clk_add_constraint(struct clk_request *req,
> >> int constraint_type,
> >> unsigned long value);
> >>
> >> void clk_update_constraint(struct clk_request *req,
> >> unsigned long new_value);
> >>
> >> void clk_remove_constraint(struct clk_request *req);
> >>
> >> It wouldn't be that bad IMO, but the API refactoring was something that
> >> was long desired and this was seen as a good opportunity to tackle it
> >> before it gets worst.
> >>
> >
> > Sure. Maybe we should just do that so we don't break things.
>
> That hasn't been what Mike has stated in the past, but I actually have
> such a patch somewhere that I can dust off and send for review.
>
> Cheers,
>
> Tomeu
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [PATCH v13 0/9] Per-user clock constraints
2014-09-26 23:20 ` Mike Turquette
@ 2014-09-27 0:15 ` Stephen Boyd
2014-09-29 18:17 ` [RFC] clk: Make clk API return per-user struct clk instances Tomeu Vizoso
2014-09-30 14:28 ` [RFC v2] " Tomeu Vizoso
2 siblings, 0 replies; 24+ messages in thread
From: Stephen Boyd @ 2014-09-27 0:15 UTC (permalink / raw)
To: Mike Turquette, Tomeu Vizoso
Cc: Russell King, Stephen Warren, Peter De Schrijver, linux-kernel,
tomasz.figa, rabin, Thierry Reding, Javier Martinez Canillas,
linux-arm-kernel
On 09/26/14 16:20, Mike Turquette wrote:
> Quoting Tomeu Vizoso (2014-09-26 01:09:20)
>> On 09/26/2014 03:29 AM, Stephen Boyd wrote:
>>
>>> We already have the consumer/provider split in the struct clk_hw and
>>> struct clk separation. Why don't we just use struct clk_hw throughout
>>> the provider APIs? The only op that isn't doing this is determine_rate()
>>> which might be able to accept a flag day. Otherwise we rename it to
>>> something else and migrate everyone over to a different named function
>>> that doesn't take a struct clk **. Then we introduce new APIs for the
>>> providers to use that are struct clk_hw focused instead of struct clk
>>> focused and migrate them too. The benefit being that we get proper
>>> review of this stuff because the patches are small. We can let
>>> coccinelle do it too.
> I have been opposed to mucking with clk_hw before, but that was because
> the goal was never clear. Now that we know that we're trying to split
> the API then it might be reasonable to use it.
>
> Stephen, does your above proposal still allow for unique struct clk
> cookies for each user of a clock?
>
>
Yes. The clkdev code would know that it's getting clk_hw pointers back
from the provider instead of struct clk pointers because it uses a
different callback:
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bacc06ff939b..76c356b779d1 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2337,6 +2337,7 @@ struct of_clk_provider {
struct device_node *node;
struct clk *(*get)(struct of_phandle_args *clkspec, void *data);
+ struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
void *data;
};
It would test for the presence of the get_hw callback and then fall back
to the get callback. Similarly we would have a clk_hw pointer in the
clkdev lookup structure. Once clkdev has the hw pointer it can ask the
ccf to generate a struct clk cookie. This would happen either in
__of_clk_get_from_provider() or clk_get_sys() depending on if we're
using DT or not.
The clk_hw structure will need to be updated to have a pointer to
clk_core. During the transition we would have struct clk and struct
clk_core next to each other in struct clk_hw. Eventually once we convert
all drivers we can remove struct clk from clk_hw. This would require
getting rid of the DEFINE_CLK macro in clk-private.h though.
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply related [flat|nested] 24+ messages in thread
* [RFC] clk: Make clk API return per-user struct clk instances
2014-09-26 23:20 ` Mike Turquette
2014-09-27 0:15 ` Stephen Boyd
@ 2014-09-29 18:17 ` Tomeu Vizoso
2014-09-30 1:40 ` Stephen Boyd
2014-09-30 9:14 ` Russell King - ARM Linux
2014-09-30 14:28 ` [RFC v2] " Tomeu Vizoso
2 siblings, 2 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-29 18:17 UTC (permalink / raw)
To: Mike Turquette, Russell King
Cc: linux-kernel, Stephen Boyd, Javier Martinez Canillas,
Tomeu Vizoso
Also moves clock state to struct clk_core, but takes care to change as little
API as possible.
struct clk_hw still has a pointer to a struct clk, which is the
implementation's per-user clk instance, for backwards compatibility.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
Hello,
I'm sending this alternate implementation of the switch to per-user clocks,
with the added goal of not requiring any substantial changes to existing users
of the API.
This is pretty much RFC-quality right now, having only tested that it builds on
tegra_defconfig.
My main question right now is what do we want to do with those drivers that
statically declare clocks. State is now in struct clk_core, so updating the
drivers accordingly will amount to a substantial amount of lines changed, which
we are now trying to avoid.
Thanks,
Tomeu
---
drivers/clk/clk-composite.c | 12 +-
drivers/clk/clk.c | 573 +++++++++++++++++++++++++++----------------
drivers/clk/clk.h | 5 +
drivers/clk/clkdev.c | 20 +-
drivers/clk/tegra/clk.c | 2 +-
include/linux/clk-private.h | 20 +-
include/linux/clk-provider.h | 22 +-
include/linux/clkdev.h | 2 +-
8 files changed, 410 insertions(+), 246 deletions(-)
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index b9355da..cb4a09d 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -57,14 +57,14 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
- struct clk **best_parent_p)
+ struct clk_core **best_parent_p)
{
struct clk_composite *composite = to_clk_composite(hw);
const struct clk_ops *rate_ops = composite->rate_ops;
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *rate_hw = composite->rate_hw;
struct clk_hw *mux_hw = composite->mux_hw;
- struct clk *parent;
+ struct clk_core *parent;
unsigned long parent_rate;
long tmp_rate, best_rate = 0;
unsigned long rate_diff;
@@ -80,19 +80,19 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
*best_parent_p = NULL;
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
- *best_parent_p = clk_get_parent(mux_hw->clk);
- *best_parent_rate = __clk_get_rate(*best_parent_p);
+ *best_parent_p = clk_provider_get_parent(mux_hw->core);
+ *best_parent_rate = clk_provider_get_rate(*best_parent_p);
return rate_ops->round_rate(rate_hw, rate,
best_parent_rate);
}
for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
- parent = clk_get_parent_by_index(mux_hw->clk, i);
+ parent = clk_provider_get_parent_by_index(mux_hw->core, i);
if (!parent)
continue;
- parent_rate = __clk_get_rate(parent);
+ parent_rate = clk_provider_get_rate(parent);
tmp_rate = rate_ops->round_rate(rate_hw, rate,
&parent_rate);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bacc06f..27ef77c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,6 +37,12 @@ static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
+static long clk_provider_get_accuracy(struct clk_core *clk);
+static bool clk_provider_is_prepared(struct clk_core *clk);
+static bool clk_provider_is_enabled(struct clk_core *clk);
+static long clk_provider_round_rate(struct clk_core *clk, unsigned long rate);
+static struct clk_core *clk_provider_lookup(const char *name);
+
/*** locking ***/
static void clk_prepare_lock(void)
{
@@ -112,7 +118,7 @@ static struct hlist_head *orphan_list[] = {
NULL,
};
-static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
@@ -120,14 +126,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
level * 3 + 1, "",
30 - level * 3, c->name,
- c->enable_count, c->prepare_count, clk_get_rate(c),
- clk_get_accuracy(c));
+ c->enable_count, c->prepare_count, clk_provider_get_rate(c),
+ clk_provider_get_accuracy(c));
}
-static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -140,7 +146,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
static int clk_summary_show(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
struct hlist_head **lists = (struct hlist_head **)s->private;
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
@@ -170,7 +176,7 @@ static const struct file_operations clk_summary_fops = {
.release = single_release,
};
-static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
@@ -178,13 +184,13 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "\"%s\": { ", c->name);
seq_printf(s, "\"enable_count\": %d,", c->enable_count);
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
- seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
- seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
+ seq_printf(s, "\"rate\": %lu", clk_provider_get_rate(c));
+ seq_printf(s, "\"accuracy\": %lu", clk_provider_get_accuracy(c));
}
-static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -201,7 +207,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
static int clk_dump(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
bool first_node = true;
struct hlist_head **lists = (struct hlist_head **)s->private;
@@ -238,7 +244,7 @@ static const struct file_operations clk_dump_fops = {
};
/* caller must hold prepare_lock */
-static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
{
struct dentry *d;
int ret = -ENOMEM;
@@ -301,9 +307,9 @@ out:
}
/* caller must hold prepare_lock */
-static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_subtree(struct clk_core *clk, struct dentry *pdentry)
{
- struct clk *child;
+ struct clk_core *child;
int ret = -EINVAL;;
if (!clk || !pdentry)
@@ -333,7 +339,7 @@ out:
* Caller must hold prepare_lock. Only clk_init calls this function (so
* far) so this is taken care.
*/
-static int clk_debug_register(struct clk *clk)
+static int clk_debug_register(struct clk_core *clk)
{
int ret = 0;
@@ -356,7 +362,7 @@ out:
*
* Caller must hold prepare_lock.
*/
-static void clk_debug_unregister(struct clk *clk)
+static void clk_debug_unregister(struct clk_core *clk)
{
debugfs_remove_recursive(clk->dentry);
}
@@ -366,8 +372,8 @@ struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
{
struct dentry *d = NULL;
- if (clk->dentry)
- d = debugfs_create_file(name, mode, clk->dentry, data, fops);
+ if (clk->core->dentry)
+ d = debugfs_create_file(name, mode, clk->core->dentry, data, fops);
return d;
}
@@ -387,7 +393,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
*/
static int __init clk_debug_init(void)
{
- struct clk *clk;
+ struct clk_core *clk;
struct dentry *d;
rootdir = debugfs_create_dir("clk", NULL);
@@ -431,19 +437,20 @@ static int __init clk_debug_init(void)
}
late_initcall(clk_debug_init);
#else
-static inline int clk_debug_register(struct clk *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+static inline int clk_debug_register(struct clk_core *clk) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *clk,
+ struct clk_core *new_parent)
{
}
-static inline void clk_debug_unregister(struct clk *clk)
+static inline void clk_debug_unregister(struct clk_core *clk)
{
}
#endif
/* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
if (!clk)
return;
@@ -457,7 +464,7 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
if (clk->flags & CLK_IGNORE_UNUSED)
return;
- if (__clk_is_prepared(clk)) {
+ if (clk_provider_is_prepared(clk)) {
if (clk->ops->unprepare_unused)
clk->ops->unprepare_unused(clk->hw);
else if (clk->ops->unprepare)
@@ -466,9 +473,9 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
}
/* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk *clk)
+static void clk_disable_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long flags;
if (!clk)
@@ -490,7 +497,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
* sequence. call .disable_unused if available, otherwise fall
* back to .disable
*/
- if (__clk_is_enabled(clk)) {
+ if (clk_provider_is_enabled(clk)) {
if (clk->ops->disable_unused)
clk->ops->disable_unused(clk->hw);
else if (clk->ops->disable)
@@ -514,7 +521,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
static int clk_disable_unused(void)
{
- struct clk *clk;
+ struct clk_core *clk;
if (clk_ignore_unused) {
pr_warn("clk: Not disabling unused clocks\n");
@@ -545,53 +552,61 @@ late_initcall_sync(clk_disable_unused);
const char *__clk_get_name(struct clk *clk)
{
- return !clk ? NULL : clk->name;
+ return !clk ? NULL : clk->core->name;
}
EXPORT_SYMBOL_GPL(__clk_get_name);
struct clk_hw *__clk_get_hw(struct clk *clk)
{
- return !clk ? NULL : clk->hw;
+ return !clk ? NULL : clk->core->hw;
}
EXPORT_SYMBOL_GPL(__clk_get_hw);
u8 __clk_get_num_parents(struct clk *clk)
{
- return !clk ? 0 : clk->num_parents;
+ return !clk ? 0 : clk->core->num_parents;
}
EXPORT_SYMBOL_GPL(__clk_get_num_parents);
struct clk *__clk_get_parent(struct clk *clk)
{
- return !clk ? NULL : clk->parent;
+ return !clk ? NULL : __clk_create_clk(clk->core->parent);
}
EXPORT_SYMBOL_GPL(__clk_get_parent);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+struct clk_core *clk_provider_get_parent_by_index(struct clk_core *clk,
+ u8 index)
{
if (!clk || index >= clk->num_parents)
return NULL;
else if (!clk->parents)
- return __clk_lookup(clk->parent_names[index]);
+ return clk_provider_lookup(clk->parent_names[index]);
else if (!clk->parents[index])
return clk->parents[index] =
- __clk_lookup(clk->parent_names[index]);
+ clk_provider_lookup(clk->parent_names[index]);
else
return clk->parents[index];
}
+EXPORT_SYMBOL_GPL(clk_provider_get_parent_by_index);
+
+struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+{
+ return __clk_create_clk(clk_provider_get_parent_by_index(clk->core,
+ index));
+}
EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
unsigned int __clk_get_enable_count(struct clk *clk)
{
- return !clk ? 0 : clk->enable_count;
+ return !clk ? 0 : clk->core->enable_count;
}
unsigned int __clk_get_prepare_count(struct clk *clk)
{
- return !clk ? 0 : clk->prepare_count;
+ return !clk ? 0 : clk->core->prepare_count;
}
-unsigned long __clk_get_rate(struct clk *clk)
+static unsigned long clk_provider_get_rate_nolock(struct clk_core *clk)
{
unsigned long ret;
@@ -611,9 +626,14 @@ unsigned long __clk_get_rate(struct clk *clk)
out:
return ret;
}
+
+unsigned long __clk_get_rate(struct clk *clk)
+{
+ return clk_provider_get_rate_nolock(clk->core);
+}
EXPORT_SYMBOL_GPL(__clk_get_rate);
-unsigned long __clk_get_accuracy(struct clk *clk)
+unsigned long __clk_get_accuracy(struct clk_core *clk)
{
if (!clk)
return 0;
@@ -623,11 +643,11 @@ unsigned long __clk_get_accuracy(struct clk *clk)
unsigned long __clk_get_flags(struct clk *clk)
{
- return !clk ? 0 : clk->flags;
+ return !clk ? 0 : clk->core->flags;
}
EXPORT_SYMBOL_GPL(__clk_get_flags);
-bool __clk_is_prepared(struct clk *clk)
+static bool clk_provider_is_prepared(struct clk_core *clk)
{
int ret;
@@ -648,7 +668,12 @@ out:
return !!ret;
}
-bool __clk_is_enabled(struct clk *clk)
+bool __clk_is_prepared(struct clk *clk)
+{
+ return clk_provider_is_prepared(clk->core);
+}
+
+bool clk_provider_is_enabled(struct clk_core *clk)
{
int ret;
@@ -668,12 +693,17 @@ bool __clk_is_enabled(struct clk *clk)
out:
return !!ret;
}
+
+bool __clk_is_enabled(struct clk *clk)
+{
+ return clk_provider_is_enabled(clk->core);
+}
EXPORT_SYMBOL_GPL(__clk_is_enabled);
-static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+static struct clk_core *__clk_lookup_subtree(const char *name, struct clk_core *clk)
{
- struct clk *child;
- struct clk *ret;
+ struct clk_core *child;
+ struct clk_core *ret;
if (!strcmp(clk->name, name))
return clk;
@@ -687,10 +717,10 @@ static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
return NULL;
}
-struct clk *__clk_lookup(const char *name)
+static struct clk_core *clk_provider_lookup(const char *name)
{
- struct clk *root_clk;
- struct clk *ret;
+ struct clk_core *root_clk;
+ struct clk_core *ret;
if (!name)
return NULL;
@@ -712,6 +742,13 @@ struct clk *__clk_lookup(const char *name)
return NULL;
}
+struct clk *__clk_lookup(const char *name)
+{
+ struct clk_core *clk = clk_provider_lookup(name);
+
+ return clk ? NULL : clk->hw->clk;
+}
+
/*
* Helper for finding best parent to provide a given frequency. This can be used
* directly as a determine_rate callback (e.g. for a mux), or from a more
@@ -719,9 +756,9 @@ struct clk *__clk_lookup(const char *name)
*/
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
- struct clk **best_parent_p)
+ struct clk_core **best_parent_p)
{
- struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+ struct clk_core *clk = hw->clk->core, *parent, *best_parent = NULL;
int i, num_parents;
unsigned long parent_rate, best = 0;
@@ -729,24 +766,24 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
parent = clk->parent;
if (clk->flags & CLK_SET_RATE_PARENT)
- best = __clk_round_rate(parent, rate);
+ best = clk_provider_round_rate(parent, rate);
else if (parent)
- best = __clk_get_rate(parent);
+ best = clk_provider_get_rate(parent);
else
- best = __clk_get_rate(clk);
+ best = clk_provider_get_rate(clk);
goto out;
}
/* find the parent that can provide the fastest rate <= rate */
num_parents = clk->num_parents;
for (i = 0; i < num_parents; i++) {
- parent = clk_get_parent_by_index(clk, i);
+ parent = clk_provider_get_parent_by_index(clk, i);
if (!parent)
continue;
if (clk->flags & CLK_SET_RATE_PARENT)
- parent_rate = __clk_round_rate(parent, rate);
+ parent_rate = clk_provider_round_rate(parent, rate);
else
- parent_rate = __clk_get_rate(parent);
+ parent_rate = clk_provider_get_rate(parent);
if (parent_rate <= rate && parent_rate > best) {
best_parent = parent;
best = parent_rate;
@@ -764,7 +801,7 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
/*** clk api ***/
-void __clk_unprepare(struct clk *clk)
+static void clk_provider_unprepare(struct clk_core *clk)
{
if (!clk)
return;
@@ -780,7 +817,12 @@ void __clk_unprepare(struct clk *clk)
if (clk->ops->unprepare)
clk->ops->unprepare(clk->hw);
- __clk_unprepare(clk->parent);
+ clk_provider_unprepare(clk->parent);
+}
+
+void __clk_unprepare(struct clk *clk)
+{
+ clk_provider_unprepare(clk->core);
}
/**
@@ -805,7 +847,7 @@ void clk_unprepare(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_unprepare);
-int __clk_prepare(struct clk *clk)
+static int clk_provider_prepare(struct clk_core *clk)
{
int ret = 0;
@@ -813,14 +855,14 @@ int __clk_prepare(struct clk *clk)
return 0;
if (clk->prepare_count == 0) {
- ret = __clk_prepare(clk->parent);
+ ret = clk_provider_prepare(clk->parent);
if (ret)
return ret;
if (clk->ops->prepare) {
ret = clk->ops->prepare(clk->hw);
if (ret) {
- __clk_unprepare(clk->parent);
+ clk_provider_unprepare(clk->parent);
return ret;
}
}
@@ -831,6 +873,11 @@ int __clk_prepare(struct clk *clk)
return 0;
}
+int __clk_prepare(struct clk *clk)
+{
+ return clk_provider_prepare(clk->core);
+}
+
/**
* clk_prepare - prepare a clock source
* @clk: the clk being prepared
@@ -855,7 +902,7 @@ int clk_prepare(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_prepare);
-static void __clk_disable(struct clk *clk)
+static void clk_provider_disable(struct clk_core *clk)
{
if (!clk)
return;
@@ -869,7 +916,12 @@ static void __clk_disable(struct clk *clk)
if (clk->ops->disable)
clk->ops->disable(clk->hw);
- __clk_disable(clk->parent);
+ clk_provider_disable(clk->parent);
+}
+
+static void __clk_disable(struct clk *clk)
+{
+ clk_provider_disable(clk->core);
}
/**
@@ -897,7 +949,7 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_disable);
-static int __clk_enable(struct clk *clk)
+static int clk_provider_enable(struct clk_core *clk)
{
int ret = 0;
@@ -908,7 +960,7 @@ static int __clk_enable(struct clk *clk)
return -ESHUTDOWN;
if (clk->enable_count == 0) {
- ret = __clk_enable(clk->parent);
+ ret = clk_provider_enable(clk->parent);
if (ret)
return ret;
@@ -916,7 +968,7 @@ static int __clk_enable(struct clk *clk)
if (clk->ops->enable) {
ret = clk->ops->enable(clk->hw);
if (ret) {
- __clk_disable(clk->parent);
+ clk_provider_disable(clk->parent);
return ret;
}
}
@@ -926,6 +978,11 @@ static int __clk_enable(struct clk *clk)
return 0;
}
+static int __clk_enable(struct clk *clk)
+{
+ return clk_provider_enable(clk->core);
+}
+
/**
* clk_enable - ungate a clock
* @clk: the clk being ungated
@@ -952,17 +1009,11 @@ int clk_enable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_enable);
-/**
- * __clk_round_rate - round the given rate for a clk
- * @clk: round the rate of this clock
- * @rate: the rate which is to be rounded
- *
- * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate
- */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long clk_provider_round_rate_nolock(struct clk_core *clk,
+ unsigned long rate)
{
unsigned long parent_rate = 0;
- struct clk *parent;
+ struct clk_core *parent;
if (!clk)
return 0;
@@ -977,12 +1028,35 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
else if (clk->ops->round_rate)
return clk->ops->round_rate(clk->hw, rate, &parent_rate);
else if (clk->flags & CLK_SET_RATE_PARENT)
- return __clk_round_rate(clk->parent, rate);
+ return clk_provider_round_rate_nolock(clk->parent, rate);
else
return clk->rate;
}
+
+/**
+ * __clk_round_rate - round the given rate for a clk
+ * @clk: round the rate of this clock
+ * @rate: the rate which is to be rounded
+ *
+ * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate
+ */
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ return clk_provider_round_rate_nolock(clk->core, rate);
+}
EXPORT_SYMBOL_GPL(__clk_round_rate);
+static long clk_provider_round_rate(struct clk_core *clk, unsigned long rate)
+{
+ unsigned long ret;
+
+ clk_prepare_lock();
+ ret = clk_provider_round_rate_nolock(clk, rate);
+ clk_prepare_unlock();
+
+ return ret;
+}
+
/**
* clk_round_rate - round the given rate for a clk
* @clk: the clk for which we are rounding a rate
@@ -994,13 +1068,7 @@ EXPORT_SYMBOL_GPL(__clk_round_rate);
*/
long clk_round_rate(struct clk *clk, unsigned long rate)
{
- unsigned long ret;
-
- clk_prepare_lock();
- ret = __clk_round_rate(clk, rate);
- clk_prepare_unlock();
-
- return ret;
+ return clk_provider_round_rate(clk->core, rate);
}
EXPORT_SYMBOL_GPL(clk_round_rate);
@@ -1018,22 +1086,21 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
* called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
* a driver returns that.
*/
-static int __clk_notify(struct clk *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *clk, unsigned long msg,
unsigned long old_rate, unsigned long new_rate)
{
struct clk_notifier *cn;
struct clk_notifier_data cnd;
int ret = NOTIFY_DONE;
- cnd.clk = clk;
cnd.old_rate = old_rate;
cnd.new_rate = new_rate;
list_for_each_entry(cn, &clk_notifier_list, node) {
- if (cn->clk == clk) {
+ if (cn->clk->core == clk) {
+ cnd.clk = cn->clk;
ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
&cnd);
- break;
}
}
@@ -1051,10 +1118,10 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_accuracies(struct clk *clk)
+static void __clk_recalc_accuracies(struct clk_core *clk)
{
unsigned long parent_accuracy = 0;
- struct clk *child;
+ struct clk_core *child;
if (clk->parent)
parent_accuracy = clk->parent->accuracy;
@@ -1069,16 +1136,7 @@ static void __clk_recalc_accuracies(struct clk *clk)
__clk_recalc_accuracies(child);
}
-/**
- * clk_get_accuracy - return the accuracy of clk
- * @clk: the clk whose accuracy is being returned
- *
- * Simply returns the cached accuracy of the clk, unless
- * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
- * issued.
- * If clk is NULL then returns 0.
- */
-long clk_get_accuracy(struct clk *clk)
+static long clk_provider_get_accuracy(struct clk_core *clk)
{
unsigned long accuracy;
@@ -1091,9 +1149,24 @@ long clk_get_accuracy(struct clk *clk)
return accuracy;
}
+
+/**
+ * clk_get_accuracy - return the accuracy of clk
+ * @clk: the clk whose accuracy is being returned
+ *
+ * Simply returns the cached accuracy of the clk, unless
+ * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
+ * issued.
+ * If clk is NULL then returns 0.
+ */
+long clk_get_accuracy(struct clk *clk)
+{
+ return clk_provider_get_accuracy(clk->core);
+}
EXPORT_SYMBOL_GPL(clk_get_accuracy);
-static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
+static unsigned long clk_recalc(struct clk_core *clk,
+ unsigned long parent_rate)
{
if (clk->ops->recalc_rate)
return clk->ops->recalc_rate(clk->hw, parent_rate);
@@ -1114,11 +1187,11 @@ static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
{
unsigned long old_rate;
unsigned long parent_rate = 0;
- struct clk *child;
+ struct clk_core *child;
old_rate = clk->rate;
@@ -1138,15 +1211,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
__clk_recalc_rates(child, msg);
}
-/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
- * is set, which means a recalc_rate will be issued.
- * If clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
+unsigned long clk_provider_get_rate(struct clk_core *clk)
{
unsigned long rate;
@@ -1155,14 +1220,29 @@ unsigned long clk_get_rate(struct clk *clk)
if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
__clk_recalc_rates(clk, 0);
- rate = __clk_get_rate(clk);
+ rate = clk_provider_get_rate_nolock(clk);
clk_prepare_unlock();
return rate;
}
+EXPORT_SYMBOL_GPL(clk_provider_get_rate);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk_provider_get_rate(clk->core);
+}
EXPORT_SYMBOL_GPL(clk_get_rate);
-static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk_core *clk,
+ struct clk_core *parent)
{
int i;
@@ -1176,7 +1256,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
/*
* find index of new parent clock using cached parent ptrs,
* or if not yet cached, use string name comparison and cache
- * them now to avoid future calls to __clk_lookup.
+ * them now to avoid future calls to clk_provider_lookup.
*/
for (i = 0; i < clk->num_parents; i++) {
if (clk->parents[i] == parent)
@@ -1186,7 +1266,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
continue;
if (!strcmp(clk->parent_names[i], parent->name)) {
- clk->parents[i] = __clk_lookup(parent->name);
+ clk->parents[i] = clk_provider_lookup(parent->name);
return i;
}
}
@@ -1194,7 +1274,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
return -EINVAL;
}
-static void clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
{
hlist_del(&clk->child_node);
@@ -1211,10 +1291,11 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
clk->parent = new_parent;
}
-static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
+static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+ struct clk_core *parent)
{
unsigned long flags;
- struct clk *old_parent = clk->parent;
+ struct clk_core *old_parent = clk->parent;
/*
* Migrate prepare state between parents and prevent race with
@@ -1234,9 +1315,9 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
* See also: Comment for clk_set_parent() below.
*/
if (clk->prepare_count) {
- __clk_prepare(parent);
- clk_enable(parent);
- clk_enable(clk);
+ clk_provider_prepare(parent);
+ clk_provider_enable(parent);
+ clk_provider_enable(clk);
}
/* update the clk tree topology */
@@ -1247,25 +1328,27 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
return old_parent;
}
-static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
- struct clk *old_parent)
+static void __clk_set_parent_after(struct clk_core *clk,
+ struct clk_core *parent,
+ struct clk_core *old_parent)
{
/*
* Finish the migration of prepare state and undo the changes done
* for preventing a race with clk_enable().
*/
if (clk->prepare_count) {
- clk_disable(clk);
- clk_disable(old_parent);
- __clk_unprepare(old_parent);
+ clk_provider_disable(clk);
+ clk_provider_disable(old_parent);
+ clk_provider_unprepare(old_parent);
}
}
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+ u8 p_index)
{
unsigned long flags;
int ret = 0;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_parent = __clk_set_parent_before(clk, parent);
@@ -1279,9 +1362,9 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
clk_enable_unlock(flags);
if (clk->prepare_count) {
- clk_disable(clk);
- clk_disable(parent);
- __clk_unprepare(parent);
+ clk_provider_disable(clk);
+ clk_provider_disable(parent);
+ clk_provider_unprepare(parent);
}
return ret;
}
@@ -1307,9 +1390,10 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
*
* Caller must hold prepare_lock.
*/
-static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+static int __clk_speculate_rates(struct clk_core *clk,
+ unsigned long parent_rate)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long new_rate;
int ret = NOTIFY_DONE;
@@ -1335,10 +1419,10 @@ out:
return ret;
}
-static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
- struct clk *new_parent, u8 p_index)
+static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+ struct clk_core *new_parent, u8 p_index)
{
- struct clk *child;
+ struct clk_core *child;
clk->new_rate = new_rate;
clk->new_parent = new_parent;
@@ -1358,10 +1442,11 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
* calculate the new rates returning the topmost clock that has to be
* changed.
*/
-static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+ unsigned long rate)
{
- struct clk *top = clk;
- struct clk *old_parent, *parent;
+ struct clk_core *top = clk;
+ struct clk_core *old_parent, *parent;
unsigned long best_parent_rate = 0;
unsigned long new_rate;
int p_index = 0;
@@ -1427,9 +1512,10 @@ out:
* so that in case of an error we can walk down the whole tree again and
* abort the change.
*/
-static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+ unsigned long event)
{
- struct clk *child, *tmp_clk, *fail_clk = NULL;
+ struct clk_core *child, *tmp_clk, *fail_clk = NULL;
int ret = NOTIFY_DONE;
if (clk->rate == clk->new_rate)
@@ -1464,14 +1550,14 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
* walk down a subtree and set the new rates notifying the rate
* change on the way
*/
-static void clk_change_rate(struct clk *clk)
+static void clk_change_rate(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
struct hlist_node *tmp;
unsigned long old_rate;
unsigned long best_parent_rate = 0;
bool skip_set_rate = false;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_rate = clk->rate;
@@ -1542,7 +1628,7 @@ static void clk_change_rate(struct clk *clk)
*/
int clk_set_rate(struct clk *clk, unsigned long rate)
{
- struct clk *top, *fail_clk;
+ struct clk_core *top, *fail_clk;
int ret = 0;
if (!clk)
@@ -1555,13 +1641,14 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (rate == clk_get_rate(clk))
goto out;
- if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
+ if ((clk->core->flags & CLK_SET_RATE_GATE) &&
+ clk->core->prepare_count) {
ret = -EBUSY;
goto out;
}
/* calculate new rates and get the topmost changed clock */
- top = clk_calc_new_rates(clk, rate);
+ top = clk_calc_new_rates(clk->core, rate);
if (!top) {
ret = -EINVAL;
goto out;
@@ -1587,6 +1674,18 @@ out:
}
EXPORT_SYMBOL_GPL(clk_set_rate);
+struct clk_core *clk_provider_get_parent(struct clk_core *clk)
+{
+ struct clk_core *parent;
+
+ clk_prepare_lock();
+ parent = !clk ? NULL : clk->parent;
+ clk_prepare_unlock();
+
+ return parent;
+}
+EXPORT_SYMBOL_GPL(clk_provider_get_parent);
+
/**
* clk_get_parent - return the parent of a clk
* @clk: the clk whose parent gets returned
@@ -1595,13 +1694,7 @@ EXPORT_SYMBOL_GPL(clk_set_rate);
*/
struct clk *clk_get_parent(struct clk *clk)
{
- struct clk *parent;
-
- clk_prepare_lock();
- parent = __clk_get_parent(clk);
- clk_prepare_unlock();
-
- return parent;
+ return __clk_create_clk(clk_provider_get_parent(clk->core));
}
EXPORT_SYMBOL_GPL(clk_get_parent);
@@ -1612,11 +1705,11 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
*
* For single-parent clocks without .get_parent, first check to see if the
* .parents array exists, and if so use it to avoid an expensive tree
- * traversal. If .parents does not exist then walk the tree with __clk_lookup.
+ * traversal. If .parents does not exist then walk the tree with clk_provider_lookup.
*/
-static struct clk *__clk_init_parent(struct clk *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *clk)
{
- struct clk *ret = NULL;
+ struct clk_core *ret = NULL;
u8 index;
/* handle the trivial cases */
@@ -1626,7 +1719,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
if (clk->num_parents == 1) {
if (IS_ERR_OR_NULL(clk->parent))
- ret = clk->parent = __clk_lookup(clk->parent_names[0]);
+ ret = clk->parent = clk_provider_lookup(clk->parent_names[0]);
ret = clk->parent;
goto out;
}
@@ -1640,7 +1733,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
/*
* Do our best to cache parent clocks in clk->parents. This prevents
- * unnecessary and expensive calls to __clk_lookup. We don't set
+ * unnecessary and expensive calls to clk_provider_lookup. We don't set
* clk->parent here; that is done by the calling function
*/
@@ -1651,37 +1744,26 @@ static struct clk *__clk_init_parent(struct clk *clk)
kcalloc(clk->num_parents, sizeof(struct clk *),
GFP_KERNEL);
- ret = clk_get_parent_by_index(clk, index);
+ ret = clk_provider_get_parent_by_index(clk, index);
out:
return ret;
}
-void __clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_provider_reparent(struct clk_core *clk,
+ struct clk_core *new_parent)
{
clk_reparent(clk, new_parent);
__clk_recalc_accuracies(clk);
__clk_recalc_rates(clk, POST_RATE_CHANGE);
}
-/**
- * clk_set_parent - switch the parent of a mux clk
- * @clk: the mux clk whose input we are switching
- * @parent: the new input to clk
- *
- * Re-parent clk to use parent as its new input source. If clk is in
- * prepared state, the clk will get enabled for the duration of this call. If
- * that's not acceptable for a specific clk (Eg: the consumer can't handle
- * that, the reparenting is glitchy in hardware, etc), use the
- * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
- *
- * After successfully changing clk's parent clk_set_parent will update the
- * clk topology, sysfs topology and propagate rate recalculation via
- * __clk_recalc_rates.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_parent(struct clk *clk, struct clk *parent)
+void __clk_reparent(struct clk *clk, struct clk *new_parent)
+{
+ clk_provider_reparent(clk->core, new_parent->core);
+}
+
+static int clk_provider_set_parent(struct clk_core *clk, struct clk_core *parent)
{
int ret = 0;
int p_index = 0;
@@ -1741,6 +1823,28 @@ out:
return ret;
}
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk: the mux clk whose input we are switching
+ * @parent: the new input to clk
+ *
+ * Re-parent clk to use parent as its new input source. If clk is in
+ * prepared state, the clk will get enabled for the duration of this call. If
+ * that's not acceptable for a specific clk (Eg: the consumer can't handle
+ * that, the reparenting is glitchy in hardware, etc), use the
+ * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
+ *
+ * After successfully changing clk's parent clk_set_parent will update the
+ * clk topology, sysfs topology and propagate rate recalculation via
+ * __clk_recalc_rates.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ return clk_provider_set_parent(clk->core, parent->core);
+}
EXPORT_SYMBOL_GPL(clk_set_parent);
/**
@@ -1748,13 +1852,13 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
* @dev: device initializing this clk, placeholder for now
* @clk: clk being initialized
*
- * Initializes the lists in struct clk, queries the hardware for the
+ * Initializes the lists in struct clk_core, queries the hardware for the
* parent and rate and sets them both.
*/
-int __clk_init(struct device *dev, struct clk *clk)
+int __clk_init(struct device *dev, struct clk_core *clk)
{
int i, ret = 0;
- struct clk *orphan;
+ struct clk_core *orphan;
struct hlist_node *tmp2;
if (!clk)
@@ -1763,7 +1867,7 @@ int __clk_init(struct device *dev, struct clk *clk)
clk_prepare_lock();
/* check to see if a clock with this name is already registered */
- if (__clk_lookup(clk->name)) {
+ if (clk_provider_lookup(clk->name)) {
pr_debug("%s: clk %s already initialized\n",
__func__, clk->name);
ret = -EEXIST;
@@ -1815,7 +1919,7 @@ int __clk_init(struct device *dev, struct clk *clk)
clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
GFP_KERNEL);
/*
- * __clk_lookup returns NULL for parents that have not been
+ * clk_provider_lookup returns NULL for parents that have not been
* clk_init'd; thus any access to clk->parents[] must check
* for a NULL pointer. We can always perform lazy lookups for
* missing parents later on.
@@ -1823,7 +1927,7 @@ int __clk_init(struct device *dev, struct clk *clk)
if (clk->parents)
for (i = 0; i < clk->num_parents; i++)
clk->parents[i] =
- __clk_lookup(clk->parent_names[i]);
+ clk_provider_lookup(clk->parent_names[i]);
}
clk->parent = __clk_init_parent(clk);
@@ -1869,7 +1973,7 @@ int __clk_init(struct device *dev, struct clk *clk)
*/
if (clk->ops->recalc_rate)
clk->rate = clk->ops->recalc_rate(clk->hw,
- __clk_get_rate(clk->parent));
+ clk_provider_get_rate_nolock(clk->parent));
else if (clk->parent)
clk->rate = clk->parent->rate;
else
@@ -1884,13 +1988,13 @@ int __clk_init(struct device *dev, struct clk *clk)
if (orphan->num_parents && orphan->ops->get_parent) {
i = orphan->ops->get_parent(orphan->hw);
if (!strcmp(clk->name, orphan->parent_names[i]))
- __clk_reparent(orphan, clk);
+ clk_provider_reparent(orphan, clk);
continue;
}
for (i = 0; i < orphan->num_parents; i++)
if (!strcmp(clk->name, orphan->parent_names[i])) {
- __clk_reparent(orphan, clk);
+ clk_provider_reparent(orphan, clk);
break;
}
}
@@ -1916,9 +2020,9 @@ out:
/**
* __clk_register - register a clock and return a cookie.
*
- * Same as clk_register, except that the .clk field inside hw shall point to a
- * preallocated (generally statically allocated) struct clk. None of the fields
- * of the struct clk need to be initialized.
+ * Same as clk_register, except that the .core field inside hw shall point to a
+ * preallocated (generally statically allocated) struct clk_core. None of the
+ * fields of the struct clk_core need to be initialized.
*
* The data pointed to by .init and .clk field shall NOT be marked as init
* data.
@@ -1933,9 +2037,9 @@ out:
struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
{
int ret;
- struct clk *clk;
+ struct clk_core *clk;
- clk = hw->clk;
+ clk = hw->core;
clk->name = hw->init->name;
clk->ops = hw->init->ops;
clk->hw = hw;
@@ -1951,7 +2055,9 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
if (ret)
return ERR_PTR(ret);
- return clk;
+ hw->clk = __clk_create_clk(clk);
+
+ return hw->clk;
}
EXPORT_SYMBOL_GPL(__clk_register);
@@ -1969,7 +2075,7 @@ EXPORT_SYMBOL_GPL(__clk_register);
struct clk *clk_register(struct device *dev, struct clk_hw *hw)
{
int i, ret;
- struct clk *clk;
+ struct clk_core *clk;
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
if (!clk) {
@@ -1990,7 +2096,8 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
clk->hw = hw;
clk->flags = hw->init->flags;
clk->num_parents = hw->init->num_parents;
- hw->clk = clk;
+ hw->core = clk;
+ hw->clk = __clk_create_clk(clk);
/* allocate local copy in case parent_names is __initdata */
clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
@@ -2016,7 +2123,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
ret = __clk_init(dev, clk);
if (!ret)
- return clk;
+ return hw->clk;
fail_parent_names_copy:
while (--i >= 0)
@@ -2024,6 +2131,7 @@ fail_parent_names_copy:
kfree(clk->parent_names);
fail_parent_names:
kfree(clk->name);
+ kfree(hw->clk);
fail_name:
kfree(clk);
fail_out:
@@ -2037,7 +2145,7 @@ EXPORT_SYMBOL_GPL(clk_register);
*/
static void __clk_release(struct kref *ref)
{
- struct clk *clk = container_of(ref, struct clk, ref);
+ struct clk_core *clk = container_of(ref, struct clk_core, ref);
int i = clk->num_parents;
kfree(clk->parents);
@@ -2097,8 +2205,9 @@ void clk_unregister(struct clk *clk)
clk_prepare_lock();
- if (clk->ops == &clk_nodrv_ops) {
- pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
+ if (clk->core->ops == &clk_nodrv_ops) {
+ pr_err("%s: unregistered clock: %s\n", __func__,
+ clk->core->name);
goto out;
}
/*
@@ -2106,27 +2215,27 @@ void clk_unregister(struct clk *clk)
* a reference to this clock.
*/
flags = clk_enable_lock();
- clk->ops = &clk_nodrv_ops;
+ clk->core->ops = &clk_nodrv_ops;
clk_enable_unlock(flags);
- if (!hlist_empty(&clk->children)) {
- struct clk *child;
+ if (!hlist_empty(&clk->core->children)) {
+ struct clk_core *child;
struct hlist_node *t;
/* Reparent all children to the orphan list. */
- hlist_for_each_entry_safe(child, t, &clk->children, child_node)
- clk_set_parent(child, NULL);
+ hlist_for_each_entry_safe(child, t, &clk->core->children, child_node)
+ clk_provider_set_parent(child, NULL);
}
- clk_debug_unregister(clk);
+ clk_debug_unregister(clk->core);
- hlist_del_init(&clk->child_node);
+ hlist_del_init(&clk->core->child_node);
- if (clk->prepare_count)
+ if (clk->core->prepare_count)
pr_warn("%s: unregistering prepared clock: %s\n",
- __func__, clk->name);
+ __func__, clk->core->name);
- kref_put(&clk->ref, __clk_release);
+ kref_put(&clk->core->ref, __clk_release);
out:
clk_prepare_unlock();
}
@@ -2195,10 +2304,10 @@ EXPORT_SYMBOL_GPL(devm_clk_unregister);
int __clk_get(struct clk *clk)
{
if (clk) {
- if (!try_module_get(clk->owner))
+ if (!try_module_get(clk->core->owner))
return 0;
- kref_get(&clk->ref);
+ kref_get(&clk->core->ref);
}
return 1;
}
@@ -2209,10 +2318,10 @@ void __clk_put(struct clk *clk)
return;
clk_prepare_lock();
- kref_put(&clk->ref, __clk_release);
+ kref_put(&clk->core->ref, __clk_release);
clk_prepare_unlock();
- module_put(clk->owner);
+ module_put(clk->core->owner);
}
/*** clk rate change notifiers ***/
@@ -2267,7 +2376,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
- clk->notifier_count++;
+ clk->core->notifier_count++;
out:
clk_prepare_unlock();
@@ -2304,7 +2413,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
if (cn->clk == clk) {
ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
- clk->notifier_count--;
+ clk->core->notifier_count--;
/* XXX the notifier code should handle this better */
if (!cn->notifier_head.head) {
@@ -2323,6 +2432,34 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(clk_notifier_unregister);
+struct clk *__clk_create_clk(struct clk_core *clk_core)
+{
+ struct clk *clk;
+
+ /* This is to allow this function to be chained to others */
+ if (!clk_core || IS_ERR(clk_core))
+ return (struct clk *) clk_core;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->core = clk_core;
+
+ return clk;
+}
+
+void __clk_free_clk(struct clk *clk)
+{
+ kfree(clk);
+}
+
+struct clk_core *__clk_to_clk_core(struct clk *clk)
+{
+ return clk->core;
+}
+EXPORT_SYMBOL_GPL(__clk_to_clk_core);
+
#ifdef CONFIG_OF
/**
* struct of_clk_provider - Clock provider registration structure
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index c798138..f480784 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -9,9 +9,14 @@
* published by the Free Software Foundation.
*/
+#include <linux/clk-private.h>
+
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
void of_clk_lock(void);
void of_clk_unlock(void);
#endif
+
+struct clk *__clk_create_clk(struct clk_core *clk_core);
+void __clk_free_clk(struct clk *clk);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8..ab22460 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -168,14 +168,20 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
struct clk *clk_get_sys(const char *dev_id, const char *con_id)
{
struct clk_lookup *cl;
+ struct clk *clk = NULL;
mutex_lock(&clocks_mutex);
cl = clk_find(dev_id, con_id);
- if (cl && !__clk_get(cl->clk))
- cl = NULL;
+ if (cl) {
+ clk = __clk_create_clk(cl->clk);
+ if (clk && !__clk_get(clk)) {
+ __clk_free_clk(clk);
+ clk = NULL;
+ }
+ }
mutex_unlock(&clocks_mutex);
- return cl ? cl->clk : ERR_PTR(-ENOENT);
+ return clk ? clk : ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL(clk_get_sys);
@@ -230,7 +236,7 @@ struct clk_lookup_alloc {
};
static struct clk_lookup * __init_refok
-vclkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt,
+vclkdev_alloc(struct clk_core *clk, const char *con_id, const char *dev_fmt,
va_list ap)
{
struct clk_lookup_alloc *cla;
@@ -260,7 +266,7 @@ clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
va_list ap;
va_start(ap, dev_fmt);
- cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
+ cl = vclkdev_alloc(clk->core, con_id, dev_fmt, ap);
va_end(ap);
return cl;
@@ -321,7 +327,7 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
return PTR_ERR(clk);
va_start(ap, dev_fmt);
- cl = vclkdev_alloc(clk, con_id, dev_fmt, ap);
+ cl = vclkdev_alloc(clk->core, con_id, dev_fmt, ap);
va_end(ap);
if (!cl)
@@ -351,7 +357,7 @@ int clk_register_clkdevs(struct clk *clk, struct clk_lookup *cl, size_t num)
return PTR_ERR(clk);
for (i = 0; i < num; i++, cl++) {
- cl->clk = clk;
+ cl->clk = clk->core;
clkdev_add(cl);
}
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index f87c609..4fa2f3e 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -195,7 +195,7 @@ void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
for (; dup_list->clk_id < clk_max; dup_list++) {
clk = clks[dup_list->clk_id];
- dup_list->lookup.clk = clk;
+ dup_list->lookup.clk = __clk_to_clk_core(clk);
clkdev_add(&dup_list->lookup);
}
}
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index efbf70b..b0a548f 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -28,20 +28,20 @@
struct module;
-struct clk {
+struct clk_core {
const char *name;
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
- struct clk *parent;
+ struct clk_core *parent;
const char **parent_names;
- struct clk **parents;
+ struct clk_core **parents;
u8 num_parents;
u8 new_parent_index;
unsigned long rate;
unsigned long new_rate;
- struct clk *new_parent;
- struct clk *new_child;
+ struct clk_core *new_parent;
+ struct clk_core *new_child;
unsigned long flags;
unsigned int enable_count;
unsigned int prepare_count;
@@ -55,6 +55,10 @@ struct clk {
struct kref ref;
};
+struct clk {
+ struct clk_core *core;
+};
+
/*
* DOC: Basic clock implementations common to many platforms
*
@@ -193,10 +197,10 @@ struct clk {
* @dev: device initializing this clk, placeholder for now
* @clk: clk being initialized
*
- * Initializes the lists in struct clk, queries the hardware for the
+ * Initializes the lists in struct clk_core, queries the hardware for the
* parent and rate and sets them both.
*
- * Any struct clk passed into __clk_init must have the following members
+ * Any struct clk_core passed into __clk_init must have the following members
* populated:
* .name
* .ops
@@ -210,7 +214,7 @@ struct clk {
*
* Returns 0 on success, otherwise an error code.
*/
-int __clk_init(struct device *dev, struct clk *clk);
+int __clk_init(struct device *dev, struct clk_core *clk);
struct clk *__clk_register(struct device *dev, struct clk_hw *hw);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 411dd7e..3da6e6e 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -32,6 +32,7 @@
#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
struct clk_hw;
+struct clk_core;
struct dentry;
/**
@@ -167,7 +168,7 @@ struct clk_ops {
unsigned long *parent_rate);
long (*determine_rate)(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
- struct clk **best_parent_clk);
+ struct clk_core **best_parent_clk);
int (*set_parent)(struct clk_hw *hw, u8 index);
u8 (*get_parent)(struct clk_hw *hw);
int (*set_rate)(struct clk_hw *hw, unsigned long rate,
@@ -205,13 +206,17 @@ struct clk_init_data {
* clk_foo and then referenced by the struct clk instance that uses struct
* clk_foo's clk_ops
*
- * @clk: pointer to the struct clk instance that points back to this struct
- * clk_hw instance
+ * @core: pointer to the struct clk_core instance that points back to this
+ * struct clk_hw instance
+ *
+ * @clk: pointer to the per-user struct clk instance that can be used to call
+ * into the clk API
*
* @init: pointer to struct clk_init_data that contains the init data shared
* with the common clock framework.
*/
struct clk_hw {
+ struct clk_core *core;
struct clk *clk;
const struct clk_init_data *init;
};
@@ -514,14 +519,21 @@ struct clk *clk_get_parent_by_index(struct clk *clk, u8 index);
unsigned int __clk_get_enable_count(struct clk *clk);
unsigned int __clk_get_prepare_count(struct clk *clk);
unsigned long __clk_get_rate(struct clk *clk);
-unsigned long __clk_get_accuracy(struct clk *clk);
+unsigned long __clk_get_accuracy(struct clk_core *clk);
unsigned long __clk_get_flags(struct clk *clk);
bool __clk_is_prepared(struct clk *clk);
bool __clk_is_enabled(struct clk *clk);
struct clk *__clk_lookup(const char *name);
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
- struct clk **best_parent_p);
+ struct clk_core **best_parent_p);
+
+unsigned long clk_provider_get_rate(struct clk_core *clk);
+struct clk_core *clk_provider_get_parent(struct clk_core *clk);
+struct clk_core *clk_provider_get_parent_by_index(struct clk_core *clk,
+ u8 index);
+
+struct clk_core *__clk_to_clk_core(struct clk *clk);
/*
* FIXME clock api without lock protection
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
index 94bad77..63612f0 100644
--- a/include/linux/clkdev.h
+++ b/include/linux/clkdev.h
@@ -21,7 +21,7 @@ struct clk_lookup {
struct list_head node;
const char *dev_id;
const char *con_id;
- struct clk *clk;
+ struct clk_core *clk;
};
#define CLKDEV_INIT(d, n, c) \
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [RFC] clk: Make clk API return per-user struct clk instances
2014-09-29 18:17 ` [RFC] clk: Make clk API return per-user struct clk instances Tomeu Vizoso
@ 2014-09-30 1:40 ` Stephen Boyd
2014-09-30 6:54 ` Mike Turquette
2014-09-30 9:14 ` Russell King - ARM Linux
1 sibling, 1 reply; 24+ messages in thread
From: Stephen Boyd @ 2014-09-30 1:40 UTC (permalink / raw)
To: Tomeu Vizoso, Mike Turquette, Russell King
Cc: linux-kernel, Javier Martinez Canillas
On 09/29/14 11:17, Tomeu Vizoso wrote:
> Also moves clock state to struct clk_core, but takes care to change as little
> API as possible.
>
> struct clk_hw still has a pointer to a struct clk, which is the
> implementation's per-user clk instance, for backwards compatibility.
>
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>
> ---
>
> Hello,
>
> I'm sending this alternate implementation of the switch to per-user clocks,
> with the added goal of not requiring any substantial changes to existing users
> of the API.
>
> This is pretty much RFC-quality right now, having only tested that it builds on
> tegra_defconfig.
>
> My main question right now is what do we want to do with those drivers that
> statically declare clocks. State is now in struct clk_core, so updating the
> drivers accordingly will amount to a substantial amount of lines changed, which
> we are now trying to avoid.
Who's actually using the static clocks? Isn't it just omap2? It looks
like all of those are behind the DEFINE_CLK define so changing it in
clk-private.h should "just work". I'm lost as to why static clocks are
being used there though. If it was a problem with allocating memory too
early it doesn't seem to be the case given that sometimes the .parents
field isn't set for a mux and __clk_init() will go and allocate an array
of pointers. Maybe I missed something though.
>
> Thanks,
>
> Tomeu
> ---
> drivers/clk/clk-composite.c | 12 +-
> drivers/clk/clk.c | 573 +++++++++++++++++++++++++++----------------
> drivers/clk/clk.h | 5 +
> drivers/clk/clkdev.c | 20 +-
> drivers/clk/tegra/clk.c | 2 +-
> include/linux/clk-private.h | 20 +-
> include/linux/clk-provider.h | 22 +-
> include/linux/clkdev.h | 2 +-
> 8 files changed, 410 insertions(+), 246 deletions(-)
>
> diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> index b9355da..cb4a09d 100644
> --- a/drivers/clk/clk-composite.c
> +++ b/drivers/clk/clk-composite.c
> @@ -57,14 +57,14 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
>
> static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long *best_parent_rate,
> - struct clk **best_parent_p)
> + struct clk_core **best_parent_p)
We should avoid exposing clk_core to anything besides clk.c or users of
clk-private.h (the latter which should go away once we remove all static
clocks).
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [RFC] clk: Make clk API return per-user struct clk instances
2014-09-30 1:40 ` Stephen Boyd
@ 2014-09-30 6:54 ` Mike Turquette
2014-09-30 7:41 ` Tero Kristo
0 siblings, 1 reply; 24+ messages in thread
From: Mike Turquette @ 2014-09-30 6:54 UTC (permalink / raw)
To: Stephen Boyd, Tomeu Vizoso, Russell King
Cc: linux-kernel, Javier Martinez Canillas, t-kristo, tony
Quoting Stephen Boyd (2014-09-29 18:40:23)
> On 09/29/14 11:17, Tomeu Vizoso wrote:
> > Also moves clock state to struct clk_core, but takes care to change as little
> > API as possible.
> >
> > struct clk_hw still has a pointer to a struct clk, which is the
> > implementation's per-user clk instance, for backwards compatibility.
> >
> > Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >
> > ---
> >
> > Hello,
> >
> > I'm sending this alternate implementation of the switch to per-user clocks,
> > with the added goal of not requiring any substantial changes to existing users
> > of the API.
> >
> > This is pretty much RFC-quality right now, having only tested that it builds on
> > tegra_defconfig.
> >
> > My main question right now is what do we want to do with those drivers that
> > statically declare clocks. State is now in struct clk_core, so updating the
> > drivers accordingly will amount to a substantial amount of lines changed, which
> > we are now trying to avoid.
>
> Who's actually using the static clocks? Isn't it just omap2? It looks
> like all of those are behind the DEFINE_CLK define so changing it in
> clk-private.h should "just work". I'm lost as to why static clocks are
> being used there though. If it was a problem with allocating memory too
> early it doesn't seem to be the case given that sometimes the .parents
> field isn't set for a mux and __clk_init() will go and allocate an array
> of pointers. Maybe I missed something though.
Yeah, the old omap2+ static clocks were due to very very early init of
things which required clocks
If memory serves, that isn't a problem any more. I've talked to Tony and
Tero about my desire to remove clk-private.h and the need to get rid of
its use in the omap clock code.
Tero, what is the status of DT conversion for OMAP2/OMAP3? Can we get
get away with only defining clock data in DT for those platforms? Can we
finally kill off clk-private.h?
Regards,
Mike
>
> >
> > Thanks,
> >
> > Tomeu
> > ---
> > drivers/clk/clk-composite.c | 12 +-
> > drivers/clk/clk.c | 573 +++++++++++++++++++++++++++----------------
> > drivers/clk/clk.h | 5 +
> > drivers/clk/clkdev.c | 20 +-
> > drivers/clk/tegra/clk.c | 2 +-
> > include/linux/clk-private.h | 20 +-
> > include/linux/clk-provider.h | 22 +-
> > include/linux/clkdev.h | 2 +-
> > 8 files changed, 410 insertions(+), 246 deletions(-)
> >
> > diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
> > index b9355da..cb4a09d 100644
> > --- a/drivers/clk/clk-composite.c
> > +++ b/drivers/clk/clk-composite.c
> > @@ -57,14 +57,14 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
> >
> > static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
> > unsigned long *best_parent_rate,
> > - struct clk **best_parent_p)
> > + struct clk_core **best_parent_p)
>
>
> We should avoid exposing clk_core to anything besides clk.c or users of
> clk-private.h (the latter which should go away once we remove all static
> clocks).
>
> --
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> hosted by The Linux Foundation
>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [RFC] clk: Make clk API return per-user struct clk instances
2014-09-30 6:54 ` Mike Turquette
@ 2014-09-30 7:41 ` Tero Kristo
2014-09-30 18:16 ` Tony Lindgren
0 siblings, 1 reply; 24+ messages in thread
From: Tero Kristo @ 2014-09-30 7:41 UTC (permalink / raw)
To: Mike Turquette, Stephen Boyd, Tomeu Vizoso, Russell King
Cc: linux-kernel, Javier Martinez Canillas, tony
On 09/30/2014 09:54 AM, Mike Turquette wrote:
> Quoting Stephen Boyd (2014-09-29 18:40:23)
>> On 09/29/14 11:17, Tomeu Vizoso wrote:
>>> Also moves clock state to struct clk_core, but takes care to change as little
>>> API as possible.
>>>
>>> struct clk_hw still has a pointer to a struct clk, which is the
>>> implementation's per-user clk instance, for backwards compatibility.
>>>
>>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>>>
>>> ---
>>>
>>> Hello,
>>>
>>> I'm sending this alternate implementation of the switch to per-user clocks,
>>> with the added goal of not requiring any substantial changes to existing users
>>> of the API.
>>>
>>> This is pretty much RFC-quality right now, having only tested that it builds on
>>> tegra_defconfig.
>>>
>>> My main question right now is what do we want to do with those drivers that
>>> statically declare clocks. State is now in struct clk_core, so updating the
>>> drivers accordingly will amount to a substantial amount of lines changed, which
>>> we are now trying to avoid.
>>
>> Who's actually using the static clocks? Isn't it just omap2? It looks
>> like all of those are behind the DEFINE_CLK define so changing it in
>> clk-private.h should "just work". I'm lost as to why static clocks are
>> being used there though. If it was a problem with allocating memory too
>> early it doesn't seem to be the case given that sometimes the .parents
>> field isn't set for a mux and __clk_init() will go and allocate an array
>> of pointers. Maybe I missed something though.
>
> Yeah, the old omap2+ static clocks were due to very very early init of
> things which required clocks
>
> If memory serves, that isn't a problem any more. I've talked to Tony and
> Tero about my desire to remove clk-private.h and the need to get rid of
> its use in the omap clock code.
>
> Tero, what is the status of DT conversion for OMAP2/OMAP3? Can we get
> get away with only defining clock data in DT for those platforms? Can we
> finally kill off clk-private.h?
Clock data has been converted for all SoCs. The problem is currently
that we are missing some OMAP3 based DT board definitions and still
require legacy boot => thus requiring legacy clock data also => omap3
legacy clock data can't be removed yet.
Tony, whats the latest status with these missing omap3 boards? How many
board->dt conversions are still needed? Is there anything someone can do
on this front?
-Tero
>
> Regards,
> Mike
>
>>
>>>
>>> Thanks,
>>>
>>> Tomeu
>>> ---
>>> drivers/clk/clk-composite.c | 12 +-
>>> drivers/clk/clk.c | 573 +++++++++++++++++++++++++++----------------
>>> drivers/clk/clk.h | 5 +
>>> drivers/clk/clkdev.c | 20 +-
>>> drivers/clk/tegra/clk.c | 2 +-
>>> include/linux/clk-private.h | 20 +-
>>> include/linux/clk-provider.h | 22 +-
>>> include/linux/clkdev.h | 2 +-
>>> 8 files changed, 410 insertions(+), 246 deletions(-)
>>>
>>> diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
>>> index b9355da..cb4a09d 100644
>>> --- a/drivers/clk/clk-composite.c
>>> +++ b/drivers/clk/clk-composite.c
>>> @@ -57,14 +57,14 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
>>>
>>> static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
>>> unsigned long *best_parent_rate,
>>> - struct clk **best_parent_p)
>>> + struct clk_core **best_parent_p)
>>
>>
>> We should avoid exposing clk_core to anything besides clk.c or users of
>> clk-private.h (the latter which should go away once we remove all static
>> clocks).
>>
>> --
>> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
>> hosted by The Linux Foundation
>>
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [RFC] clk: Make clk API return per-user struct clk instances
2014-09-29 18:17 ` [RFC] clk: Make clk API return per-user struct clk instances Tomeu Vizoso
2014-09-30 1:40 ` Stephen Boyd
@ 2014-09-30 9:14 ` Russell King - ARM Linux
1 sibling, 0 replies; 24+ messages in thread
From: Russell King - ARM Linux @ 2014-09-30 9:14 UTC (permalink / raw)
To: Tomeu Vizoso
Cc: Mike Turquette, linux-kernel, Stephen Boyd,
Javier Martinez Canillas
On Mon, Sep 29, 2014 at 08:17:23PM +0200, Tomeu Vizoso wrote:
> diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
> index da4bda8..ab22460 100644
> --- a/drivers/clk/clkdev.c
> +++ b/drivers/clk/clkdev.c
> @@ -168,14 +168,20 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
> struct clk *clk_get_sys(const char *dev_id, const char *con_id)
> {
> struct clk_lookup *cl;
> + struct clk *clk = NULL;
>
> mutex_lock(&clocks_mutex);
> cl = clk_find(dev_id, con_id);
> - if (cl && !__clk_get(cl->clk))
> - cl = NULL;
> + if (cl) {
> + clk = __clk_create_clk(cl->clk);
> + if (clk && !__clk_get(clk)) {
> + __clk_free_clk(clk);
> + clk = NULL;
> + }
> + }
> mutex_unlock(&clocks_mutex);
>
> - return cl ? cl->clk : ERR_PTR(-ENOENT);
> + return clk ? clk : ERR_PTR(-ENOENT);
NAK. We have places where we explicitly expect clk_get* to return NULL.
--
FTTC broadband for 0.8mile line: currently at 9.5Mbps down 400kbps up
according to speedtest.net.
^ permalink raw reply [flat|nested] 24+ messages in thread
* [RFC v2] clk: Make clk API return per-user struct clk instances
2014-09-26 23:20 ` Mike Turquette
2014-09-27 0:15 ` Stephen Boyd
2014-09-29 18:17 ` [RFC] clk: Make clk API return per-user struct clk instances Tomeu Vizoso
@ 2014-09-30 14:28 ` Tomeu Vizoso
2 siblings, 0 replies; 24+ messages in thread
From: Tomeu Vizoso @ 2014-09-30 14:28 UTC (permalink / raw)
To: Mike Turquette, Russell King
Cc: linux-kernel, Stephen Boyd, Javier Martinez Canillas,
Tomeu Vizoso
Also moves clock state to struct clk_core, but takes care to change as little
API as possible.
struct clk_hw still has a pointer to a struct clk, which is the
implementation's per-user clk instance, for backwards compatibility.
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
Hi,
have gotten static clock registration working while trying to minimize the changes to the clock implementations. Will be happy to hear any suggestions to make it better.
Have also made determine_rate() work without changing the signature by returning the per-user clks that belong to the clock implementation.
This builds on a bunch of ARM defconfigs and have tested it on a Jetson TK1. Next I plan to do some more tests and rebase the patches from the old series on top.
Regards,
Tomeu
---
arch/arm/mach-omap2/cclock3xxx_data.c | 108 ++++--
arch/arm/mach-omap2/clock.h | 11 +-
arch/arm/mach-omap2/clock_common_data.c | 5 +-
drivers/clk/clk-composite.c | 11 +-
drivers/clk/clk.c | 622 ++++++++++++++++++++------------
drivers/clk/clk.h | 7 +
drivers/clk/clkdev.c | 19 +-
include/linux/clk-private.h | 35 +-
include/linux/clk-provider.h | 29 +-
9 files changed, 559 insertions(+), 288 deletions(-)
diff --git a/arch/arm/mach-omap2/cclock3xxx_data.c b/arch/arm/mach-omap2/cclock3xxx_data.c
index eb8c75e..9b210df 100644
--- a/arch/arm/mach-omap2/cclock3xxx_data.c
+++ b/arch/arm/mach-omap2/cclock3xxx_data.c
@@ -82,7 +82,7 @@ DEFINE_CLK_MUX(osc_sys_ck, osc_sys_ck_parent_names, NULL, 0x0,
OMAP3430_PRM_CLKSEL, OMAP3430_SYS_CLKIN_SEL_SHIFT,
OMAP3430_SYS_CLKIN_SEL_WIDTH, 0x0, NULL);
-DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck, 0x0,
+DEFINE_CLK_DIVIDER(sys_ck, "osc_sys_ck", &osc_sys_ck_core, 0x0,
OMAP3430_PRM_CLKSRC_CTRL, OMAP_SYSCLKDIV_SHIFT,
OMAP_SYSCLKDIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
@@ -131,7 +131,7 @@ static struct clk_hw_omap dpll3_ck_hw = {
DEFINE_STRUCT_CLK(dpll3_ck, dpll3_ck_parent_names, dpll3_ck_ops);
-DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll3_m2_ck, "dpll3_ck", &dpll3_ck_core, 0x0,
OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
OMAP3430_CORE_DPLL_CLKOUT_DIV_SHIFT,
OMAP3430_CORE_DPLL_CLKOUT_DIV_WIDTH,
@@ -148,12 +148,12 @@ static const struct clk_ops core_ck_ops = {};
DEFINE_STRUCT_CLK_HW_OMAP(core_ck, NULL);
DEFINE_STRUCT_CLK(core_ck, core_ck_parent_names, core_ck_ops);
-DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(l3_ick, "core_ck", &core_ck_core, 0x0,
OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
OMAP3430_CLKSEL_L3_SHIFT, OMAP3430_CLKSEL_L3_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
-DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick, 0x0,
+DEFINE_CLK_DIVIDER(l4_ick, "l3_ick", &l3_ick_core, 0x0,
OMAP_CM_REGADDR(CORE_MOD, CM_CLKSEL),
OMAP3430_CLKSEL_L4_SHIFT, OMAP3430_CLKSEL_L4_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -271,9 +271,9 @@ static struct clk_hw_omap dpll1_ck_hw = {
DEFINE_STRUCT_CLK(dpll1_ck, dpll3_ck_parent_names, dpll1_ck_ops);
-DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck, 0x0, 2, 1);
+DEFINE_CLK_FIXED_FACTOR(dpll1_x2_ck, "dpll1_ck", &dpll1_ck_core, 0x0, 2, 1);
-DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll1_x2m2_ck, "dpll1_x2_ck", &dpll1_x2_ck_core, 0x0,
OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL2_PLL),
OMAP3430_MPU_DPLL_CLKOUT_DIV_SHIFT,
OMAP3430_MPU_DPLL_CLKOUT_DIV_WIDTH,
@@ -288,7 +288,7 @@ static const char *mpu_ck_parent_names[] = {
DEFINE_STRUCT_CLK_HW_OMAP(mpu_ck, "mpu_clkdm");
DEFINE_STRUCT_CLK(mpu_ck, mpu_ck_parent_names, core_l4_ick_ops);
-DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck, 0x0,
+DEFINE_CLK_DIVIDER(arm_fck, "mpu_ck", &mpu_ck_core, 0x0,
OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
OMAP3430_ST_MPU_CLK_SHIFT, OMAP3430_ST_MPU_CLK_WIDTH,
0x0, NULL);
@@ -417,7 +417,7 @@ static const struct clk_div_table dpll4_mx_ck_div_table[] = {
{ .div = 0 },
};
-DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll4_m5_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_CLKSEL),
OMAP3430_CLKSEL_CAM_SHIFT, OMAP3630_CLKSEL_CAM_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -459,7 +459,7 @@ static struct clk_hw_omap dpll4_m5x2_ck_hw = {
DEFINE_STRUCT_CLK_FLAGS(dpll4_m5x2_ck, dpll4_m5x2_ck_parent_names,
dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
-static struct clk dpll4_m5x2_ck_3630 = {
+static struct clk_core dpll4_m5x2_ck_3630_core = {
.name = "dpll4_m5x2_ck",
.hw = &dpll4_m5x2_ck_hw.hw,
.parent_names = dpll4_m5x2_ck_parent_names,
@@ -468,6 +468,10 @@ static struct clk dpll4_m5x2_ck_3630 = {
.flags = CLK_SET_RATE_PARENT,
};
+static struct clk dpll4_m5x2_ck_3630 = {
+ .core = &dpll4_m5x2_ck_3630_core,
+};
+
static struct clk cam_mclk;
static const char *cam_mclk_parent_names[] = {
@@ -483,7 +487,7 @@ static struct clk_hw_omap cam_mclk_hw = {
.clkdm_name = "cam_clkdm",
};
-static struct clk cam_mclk = {
+static struct clk_core cam_mclk_core = {
.name = "cam_mclk",
.hw = &cam_mclk_hw.hw,
.parent_names = cam_mclk_parent_names,
@@ -492,6 +496,10 @@ static struct clk cam_mclk = {
.flags = CLK_SET_RATE_PARENT,
};
+static struct clk cam_mclk = {
+ .core = &cam_mclk_core,
+};
+
static const struct clksel_rate clkout2_src_core_rates[] = {
{ .div = 1, .val = 0, .flags = RATE_IN_3XXX },
{ .div = 0 }
@@ -507,7 +515,7 @@ static const struct clksel_rate clkout2_src_96m_rates[] = {
{ .div = 0 }
};
-DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll4_m2_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
OMAP_CM_REGADDR(PLL_MOD, OMAP3430_CM_CLKSEL3),
OMAP3430_DIV_96M_SHIFT, OMAP3630_DIV_96M_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -531,7 +539,7 @@ static struct clk_hw_omap dpll4_m2x2_ck_hw = {
DEFINE_STRUCT_CLK(dpll4_m2x2_ck, dpll4_m2x2_ck_parent_names, dpll4_m5x2_ck_ops);
-static struct clk dpll4_m2x2_ck_3630 = {
+static struct clk_core dpll4_m2x2_ck_3630_core = {
.name = "dpll4_m2x2_ck",
.hw = &dpll4_m2x2_ck_hw.hw,
.parent_names = dpll4_m2x2_ck_parent_names,
@@ -539,6 +547,10 @@ static struct clk dpll4_m2x2_ck_3630 = {
.ops = &dpll4_m5x2_ck_3630_ops,
};
+static struct clk dpll4_m2x2_ck_3630 = {
+ .core = &dpll4_m2x2_ck_3630_core,
+};
+
static struct clk omap_96m_alwon_fck;
static const char *omap_96m_alwon_fck_parent_names[] = {
@@ -563,7 +575,7 @@ static const struct clksel_rate clkout2_src_54m_rates[] = {
{ .div = 0 }
};
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER_TABLE(dpll4_m3_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
OMAP3430_CLKSEL_TV_SHIFT, OMAP3630_CLKSEL_TV_WIDTH,
0, dpll4_mx_ck_div_table, NULL);
@@ -587,7 +599,7 @@ static struct clk_hw_omap dpll4_m3x2_ck_hw = {
DEFINE_STRUCT_CLK(dpll4_m3x2_ck, dpll4_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
-static struct clk dpll4_m3x2_ck_3630 = {
+static struct clk_core dpll4_m3x2_ck_3630_core = {
.name = "dpll4_m3x2_ck",
.hw = &dpll4_m3x2_ck_hw.hw,
.parent_names = dpll4_m3x2_ck_parent_names,
@@ -595,6 +607,10 @@ static struct clk dpll4_m3x2_ck_3630 = {
.ops = &dpll4_m5x2_ck_3630_ops,
};
+static struct clk dpll4_m3x2_ck_3630 = {
+ .core = &dpll4_m3x2_ck_3630_core,
+};
+
static const char *omap_54m_fck_parent_names[] = {
"dpll4_m3x2_ck", "sys_altclk",
};
@@ -670,7 +686,7 @@ static struct clk_hw_omap omap_48m_fck_hw = {
DEFINE_STRUCT_CLK(omap_48m_fck, omap_48m_fck_parent_names, omap_48m_fck_ops);
-DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck, 0x0, 1, 4);
+DEFINE_CLK_FIXED_FACTOR(omap_12m_fck, "omap_48m_fck", &omap_48m_fck_core, 0x0, 1, 4);
static struct clk core_12m_fck;
@@ -716,7 +732,7 @@ static const char *core_l3_ick_parent_names[] = {
DEFINE_STRUCT_CLK_HW_OMAP(core_l3_ick, "core_l3_clkdm");
DEFINE_STRUCT_CLK(core_l3_ick, core_l3_ick_parent_names, core_l4_ick_ops);
-DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck, 0x0, 2, 1);
+DEFINE_CLK_FIXED_FACTOR(dpll3_m2x2_ck, "dpll3_m2_ck", &dpll3_m2_ck_core, 0x0, 2, 1);
static struct clk corex2_fck;
@@ -798,7 +814,7 @@ static struct clk_hw_omap des2_ick_hw = {
DEFINE_STRUCT_CLK(des2_ick, aes2_ick_parent_names, aes2_ick_ops);
-DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll1_fck, "core_ck", &core_ck_core, 0x0,
OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
OMAP3430_MPU_CLK_SRC_SHIFT, OMAP3430_MPU_CLK_SRC_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -841,18 +857,18 @@ static struct clk_hw_omap dpll2_ck_hw = {
DEFINE_STRUCT_CLK(dpll2_ck, dpll3_ck_parent_names, dpll1_ck_ops);
-DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll2_fck, "core_ck", &core_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
OMAP3430_IVA2_CLK_SRC_SHIFT, OMAP3430_IVA2_CLK_SRC_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
-DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll2_m2_ck, "dpll2_ck", &dpll2_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL2_PLL),
OMAP3430_IVA2_DPLL_CLKOUT_DIV_SHIFT,
OMAP3430_IVA2_DPLL_CLKOUT_DIV_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
-DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll3_m3_ck, "dpll3_ck", &dpll3_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
OMAP3430_DIV_DPLL3_SHIFT, OMAP3430_DIV_DPLL3_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -876,7 +892,7 @@ static struct clk_hw_omap dpll3_m3x2_ck_hw = {
DEFINE_STRUCT_CLK(dpll3_m3x2_ck, dpll3_m3x2_ck_parent_names, dpll4_m5x2_ck_ops);
-static struct clk dpll3_m3x2_ck_3630 = {
+static struct clk_core dpll3_m3x2_ck_3630_core = {
.name = "dpll3_m3x2_ck",
.hw = &dpll3_m3x2_ck_hw.hw,
.parent_names = dpll3_m3x2_ck_parent_names,
@@ -884,9 +900,13 @@ static struct clk dpll3_m3x2_ck_3630 = {
.ops = &dpll4_m5x2_ck_3630_ops,
};
-DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck, 0x0, 2, 1);
+static struct clk dpll3_m3x2_ck_3630 = {
+ .core = &dpll3_m3x2_ck_3630_core,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll3_x2_ck, "dpll3_ck", &dpll3_ck_core, 0x0, 2, 1);
-DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck, 0x0,
+DEFINE_CLK_DIVIDER_TABLE(dpll4_m4_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_CLKSEL),
OMAP3430_CLKSEL_DSS1_SHIFT, OMAP3630_CLKSEL_DSS1_WIDTH,
0, dpll4_mx_ck_div_table, NULL);
@@ -911,7 +931,7 @@ static struct clk_hw_omap dpll4_m4x2_ck_hw = {
DEFINE_STRUCT_CLK_FLAGS(dpll4_m4x2_ck, dpll4_m4x2_ck_parent_names,
dpll4_m5x2_ck_ops, CLK_SET_RATE_PARENT);
-static struct clk dpll4_m4x2_ck_3630 = {
+static struct clk_core dpll4_m4x2_ck_3630_core = {
.name = "dpll4_m4x2_ck",
.hw = &dpll4_m4x2_ck_hw.hw,
.parent_names = dpll4_m4x2_ck_parent_names,
@@ -920,7 +940,11 @@ static struct clk dpll4_m4x2_ck_3630 = {
.flags = CLK_SET_RATE_PARENT,
};
-DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck, 0x0,
+static struct clk dpll4_m4x2_ck_3630 = {
+ .core = &dpll4_m4x2_ck_3630_core,
+};
+
+DEFINE_CLK_DIVIDER(dpll4_m6_ck, "dpll4_ck", &dpll4_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
OMAP3430_DIV_DPLL4_SHIFT, OMAP3630_DIV_DPLL4_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -944,7 +968,7 @@ static struct clk_hw_omap dpll4_m6x2_ck_hw = {
DEFINE_STRUCT_CLK(dpll4_m6x2_ck, dpll4_m6x2_ck_parent_names, dpll4_m5x2_ck_ops);
-static struct clk dpll4_m6x2_ck_3630 = {
+static struct clk_core dpll4_m6x2_ck_3630_core = {
.name = "dpll4_m6x2_ck",
.hw = &dpll4_m6x2_ck_hw.hw,
.parent_names = dpll4_m6x2_ck_parent_names,
@@ -952,7 +976,11 @@ static struct clk dpll4_m6x2_ck_3630 = {
.ops = &dpll4_m5x2_ck_3630_ops,
};
-DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck, 0x0, 2, 1);
+static struct clk dpll4_m6x2_ck_3630 = {
+ .core = &dpll4_m6x2_ck_3630_core,
+};
+
+DEFINE_CLK_FIXED_FACTOR(dpll4_x2_ck, "dpll4_ck", &dpll4_ck_core, 0x0, 2, 1);
static struct dpll_data dpll5_dd = {
.mult_div1_reg = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
@@ -989,7 +1017,7 @@ static struct clk_hw_omap dpll5_ck_hw = {
DEFINE_STRUCT_CLK(dpll5_ck, dpll3_ck_parent_names, dpll1_ck_ops);
-DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck, 0x0,
+DEFINE_CLK_DIVIDER(dpll5_m2_ck, "dpll5_ck", &dpll5_ck_core, 0x0,
OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL5),
OMAP3430ES2_DIV_120M_SHIFT, OMAP3430ES2_DIV_120M_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -1236,7 +1264,7 @@ static struct clk_hw_omap emu_src_ck_hw = {
DEFINE_STRUCT_CLK(emu_src_ck, emu_src_ck_parent_names, emu_src_ck_ops);
-DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(atclk_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
OMAP3430_CLKSEL_ATCLK_SHIFT, OMAP3430_CLKSEL_ATCLK_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -1287,7 +1315,7 @@ static struct clk_hw_omap gfx_l3_ck_hw = {
DEFINE_STRUCT_CLK(gfx_l3_ck, core_l3_ick_parent_names, aes1_ick_ops);
-DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick, 0x0,
+DEFINE_CLK_DIVIDER(gfx_l3_fck, "l3_ick", &l3_ick_core, 0x0,
OMAP_CM_REGADDR(GFX_MOD, CM_CLKSEL),
OMAP_CLKSEL_GFX_SHIFT, OMAP_CLKSEL_GFX_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -2487,7 +2515,7 @@ static struct clk_hw_omap omap_96m_alwon_fck_3630_hw = {
.clksel_mask = OMAP3630_CLKSEL_96M_MASK,
};
-static struct clk omap_96m_alwon_fck_3630 = {
+static struct clk_core omap_96m_alwon_fck_3630_core = {
.name = "omap_96m_alwon_fck",
.hw = &omap_96m_alwon_fck_3630_hw.hw,
.parent_names = omap_96m_alwon_fck_3630_parent_names,
@@ -2495,6 +2523,10 @@ static struct clk omap_96m_alwon_fck_3630 = {
.ops = &omap_96m_alwon_fck_3630_ops,
};
+static struct clk omap_96m_alwon_fck_3630 = {
+ .core = &omap_96m_alwon_fck_3630_core,
+};
+
static struct clk omapctrl_ick;
static struct clk_hw_omap omapctrl_ick_hw = {
@@ -2510,12 +2542,12 @@ static struct clk_hw_omap omapctrl_ick_hw = {
DEFINE_STRUCT_CLK(omapctrl_ick, aes2_ick_parent_names, aes2_ick_ops);
-DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(pclk_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
OMAP3430_CLKSEL_PCLK_SHIFT, OMAP3430_CLKSEL_PCLK_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
-DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(pclkx2_fck, "emu_src_ck", &emu_src_ck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
OMAP3430_CLKSEL_PCLKX2_SHIFT, OMAP3430_CLKSEL_PCLKX2_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -2547,7 +2579,7 @@ static struct clk_hw_omap pka_ick_hw = {
DEFINE_STRUCT_CLK(pka_ick, pka_ick_parent_names, aes1_ick_ops);
-DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick, 0x0,
+DEFINE_CLK_DIVIDER(rm_ick, "l4_ick", &l4_ick_core, 0x0,
OMAP_CM_REGADDR(WKUP_MOD, CM_CLKSEL),
OMAP3430_CLKSEL_RM_SHIFT, OMAP3430_CLKSEL_RM_WIDTH,
CLK_DIVIDER_ONE_BASED, NULL);
@@ -2808,10 +2840,10 @@ DEFINE_CLK_OMAP_MUX_GATE(ssi_ssr_fck_3430es2, "core_l4_clkdm",
ssi_ssr_fck_3430es1_ops);
DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es1, "ssi_ssr_fck_3430es1",
- &ssi_ssr_fck_3430es1, 0x0, 1, 2);
+ &ssi_ssr_fck_3430es1_core, 0x0, 1, 2);
DEFINE_CLK_FIXED_FACTOR(ssi_sst_fck_3430es2, "ssi_ssr_fck_3430es2",
- &ssi_ssr_fck_3430es2, 0x0, 1, 2);
+ &ssi_ssr_fck_3430es2_core, 0x0, 1, 2);
static struct clk sys_clkout1;
@@ -2829,7 +2861,7 @@ static struct clk_hw_omap sys_clkout1_hw = {
DEFINE_STRUCT_CLK(sys_clkout1, sys_clkout1_parent_names, aes1_ick_ops);
-DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck, 0x0,
+DEFINE_CLK_DIVIDER(sys_clkout2, "clkout2_src_ck", &clkout2_src_ck_core, 0x0,
OMAP3430_CM_CLKOUT_CTRL, OMAP3430_CLKOUT2_DIV_SHIFT,
OMAP3430_CLKOUT2_DIV_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
@@ -2838,7 +2870,7 @@ DEFINE_CLK_MUX(traceclk_src_fck, emu_src_ck_parent_names, NULL, 0x0,
OMAP3430_TRACE_MUX_CTRL_SHIFT, OMAP3430_TRACE_MUX_CTRL_WIDTH,
0x0, NULL);
-DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck, 0x0,
+DEFINE_CLK_DIVIDER(traceclk_fck, "traceclk_src_fck", &traceclk_src_fck_core, 0x0,
OMAP_CM_REGADDR(OMAP3430_EMU_MOD, CM_CLKSEL1),
OMAP3430_CLKSEL_TRACECLK_SHIFT,
OMAP3430_CLKSEL_TRACECLK_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
index 4592a27..1e42f26 100644
--- a/arch/arm/mach-omap2/clock.h
+++ b/arch/arm/mach-omap2/clock.h
@@ -40,23 +40,29 @@ struct omap_clk {
struct clockdomain;
#define DEFINE_STRUCT_CLK(_name, _parent_array_name, _clkops_name) \
- static struct clk _name = { \
+ static struct clk_core _name##_core = { \
.name = #_name, \
.hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \
+ }; \
+ static struct clk _name = { \
+ .core = &_name##_core, \
};
#define DEFINE_STRUCT_CLK_FLAGS(_name, _parent_array_name, \
_clkops_name, _flags) \
- static struct clk _name = { \
+ static struct clk_core _name##_core = { \
.name = #_name, \
.hw = &_name##_hw.hw, \
.parent_names = _parent_array_name, \
.num_parents = ARRAY_SIZE(_parent_array_name), \
.ops = &_clkops_name, \
.flags = _flags, \
+ }; \
+ static struct clk _name = { \
+ .core = &_name##_core, \
};
#define DEFINE_STRUCT_CLK_HW_OMAP(_name, _clkdm_name) \
@@ -247,6 +253,7 @@ extern const struct clksel_rate gpt_32k_rates[];
extern const struct clksel_rate gpt_sys_rates[];
extern const struct clksel_rate gfx_l3_rates[];
extern const struct clksel_rate dsp_ick_rates[];
+extern struct clk_core dummy_ck_core;
extern struct clk dummy_ck;
extern const struct clk_hw_omap_ops clkhwops_iclk_wait;
diff --git a/arch/arm/mach-omap2/clock_common_data.c b/arch/arm/mach-omap2/clock_common_data.c
index ef4d21b..febd0a2 100644
--- a/arch/arm/mach-omap2/clock_common_data.c
+++ b/arch/arm/mach-omap2/clock_common_data.c
@@ -119,8 +119,11 @@ const struct clksel_rate div31_1to31_rates[] = {
static struct clk_ops dummy_ck_ops = {};
-struct clk dummy_ck = {
+struct clk_core dummy_ck_core = {
.name = "dummy_clk",
.ops = &dummy_ck_ops,
.flags = CLK_IS_BASIC,
};
+struct clk dummy_ck = {
+ .core = &dummy_ck_core,
+};
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
index b9355da..48cc13c 100644
--- a/drivers/clk/clk-composite.c
+++ b/drivers/clk/clk-composite.c
@@ -64,7 +64,7 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *rate_hw = composite->rate_hw;
struct clk_hw *mux_hw = composite->mux_hw;
- struct clk *parent;
+ struct clk_core *parent;
unsigned long parent_rate;
long tmp_rate, best_rate = 0;
unsigned long rate_diff;
@@ -80,7 +80,8 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
*best_parent_p = NULL;
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
- *best_parent_p = clk_get_parent(mux_hw->clk);
+ parent = clk_provider_get_parent(mux_hw->core);
+ *best_parent_p = __clk_core_to_clk(parent);
*best_parent_rate = __clk_get_rate(*best_parent_p);
return rate_ops->round_rate(rate_hw, rate,
@@ -88,11 +89,11 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
}
for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
- parent = clk_get_parent_by_index(mux_hw->clk, i);
+ parent = clk_provider_get_parent_by_index(mux_hw->core, i);
if (!parent)
continue;
- parent_rate = __clk_get_rate(parent);
+ parent_rate = clk_provider_get_rate(parent);
tmp_rate = rate_ops->round_rate(rate_hw, rate,
&parent_rate);
@@ -103,7 +104,7 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
if (!rate_diff || !*best_parent_p
|| best_rate_diff > rate_diff) {
- *best_parent_p = parent;
+ *best_parent_p = __clk_core_to_clk(parent);
*best_parent_rate = parent_rate;
best_rate_diff = rate_diff;
best_rate = tmp_rate;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bacc06f..5199e47 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -37,6 +37,13 @@ static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
+static void clk_provider_put(struct clk_core *clk);
+static long clk_provider_get_accuracy(struct clk_core *clk);
+static bool clk_provider_is_prepared(struct clk_core *clk);
+static bool clk_provider_is_enabled(struct clk_core *clk);
+static long clk_provider_round_rate(struct clk_core *clk, unsigned long rate);
+static struct clk_core *clk_provider_lookup(const char *name);
+
/*** locking ***/
static void clk_prepare_lock(void)
{
@@ -112,7 +119,7 @@ static struct hlist_head *orphan_list[] = {
NULL,
};
-static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
+static void clk_summary_show_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
@@ -120,14 +127,14 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "%*s%-*s %11d %12d %11lu %10lu\n",
level * 3 + 1, "",
30 - level * 3, c->name,
- c->enable_count, c->prepare_count, clk_get_rate(c),
- clk_get_accuracy(c));
+ c->enable_count, c->prepare_count, clk_provider_get_rate(c),
+ clk_provider_get_accuracy(c));
}
-static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
+static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -140,7 +147,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk *c,
static int clk_summary_show(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
struct hlist_head **lists = (struct hlist_head **)s->private;
seq_puts(s, " clock enable_cnt prepare_cnt rate accuracy\n");
@@ -170,7 +177,7 @@ static const struct file_operations clk_summary_fops = {
.release = single_release,
};
-static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
@@ -178,13 +185,13 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
seq_printf(s, "\"%s\": { ", c->name);
seq_printf(s, "\"enable_count\": %d,", c->enable_count);
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
- seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
- seq_printf(s, "\"accuracy\": %lu", clk_get_accuracy(c));
+ seq_printf(s, "\"rate\": %lu", clk_provider_get_rate(c));
+ seq_printf(s, "\"accuracy\": %lu", clk_provider_get_accuracy(c));
}
-static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
+static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
{
- struct clk *child;
+ struct clk_core *child;
if (!c)
return;
@@ -201,7 +208,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
static int clk_dump(struct seq_file *s, void *data)
{
- struct clk *c;
+ struct clk_core *c;
bool first_node = true;
struct hlist_head **lists = (struct hlist_head **)s->private;
@@ -238,7 +245,7 @@ static const struct file_operations clk_dump_fops = {
};
/* caller must hold prepare_lock */
-static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_one(struct clk_core *clk, struct dentry *pdentry)
{
struct dentry *d;
int ret = -ENOMEM;
@@ -301,9 +308,9 @@ out:
}
/* caller must hold prepare_lock */
-static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry)
+static int clk_debug_create_subtree(struct clk_core *clk, struct dentry *pdentry)
{
- struct clk *child;
+ struct clk_core *child;
int ret = -EINVAL;;
if (!clk || !pdentry)
@@ -333,7 +340,7 @@ out:
* Caller must hold prepare_lock. Only clk_init calls this function (so
* far) so this is taken care.
*/
-static int clk_debug_register(struct clk *clk)
+static int clk_debug_register(struct clk_core *clk)
{
int ret = 0;
@@ -356,7 +363,7 @@ out:
*
* Caller must hold prepare_lock.
*/
-static void clk_debug_unregister(struct clk *clk)
+static void clk_debug_unregister(struct clk_core *clk)
{
debugfs_remove_recursive(clk->dentry);
}
@@ -366,8 +373,8 @@ struct dentry *clk_debugfs_add_file(struct clk *clk, char *name, umode_t mode,
{
struct dentry *d = NULL;
- if (clk->dentry)
- d = debugfs_create_file(name, mode, clk->dentry, data, fops);
+ if (clk->core->dentry)
+ d = debugfs_create_file(name, mode, clk->core->dentry, data, fops);
return d;
}
@@ -387,7 +394,7 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
*/
static int __init clk_debug_init(void)
{
- struct clk *clk;
+ struct clk_core *clk;
struct dentry *d;
rootdir = debugfs_create_dir("clk", NULL);
@@ -431,19 +438,20 @@ static int __init clk_debug_init(void)
}
late_initcall(clk_debug_init);
#else
-static inline int clk_debug_register(struct clk *clk) { return 0; }
-static inline void clk_debug_reparent(struct clk *clk, struct clk *new_parent)
+static inline int clk_debug_register(struct clk_core *clk) { return 0; }
+static inline void clk_debug_reparent(struct clk_core *clk,
+ struct clk_core *new_parent)
{
}
-static inline void clk_debug_unregister(struct clk *clk)
+static inline void clk_debug_unregister(struct clk_core *clk)
{
}
#endif
/* caller must hold prepare_lock */
-static void clk_unprepare_unused_subtree(struct clk *clk)
+static void clk_unprepare_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
if (!clk)
return;
@@ -457,7 +465,7 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
if (clk->flags & CLK_IGNORE_UNUSED)
return;
- if (__clk_is_prepared(clk)) {
+ if (clk_provider_is_prepared(clk)) {
if (clk->ops->unprepare_unused)
clk->ops->unprepare_unused(clk->hw);
else if (clk->ops->unprepare)
@@ -466,9 +474,9 @@ static void clk_unprepare_unused_subtree(struct clk *clk)
}
/* caller must hold prepare_lock */
-static void clk_disable_unused_subtree(struct clk *clk)
+static void clk_disable_unused_subtree(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long flags;
if (!clk)
@@ -490,7 +498,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
* sequence. call .disable_unused if available, otherwise fall
* back to .disable
*/
- if (__clk_is_enabled(clk)) {
+ if (clk_provider_is_enabled(clk)) {
if (clk->ops->disable_unused)
clk->ops->disable_unused(clk->hw);
else if (clk->ops->disable)
@@ -514,7 +522,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup);
static int clk_disable_unused(void)
{
- struct clk *clk;
+ struct clk_core *clk;
if (clk_ignore_unused) {
pr_warn("clk: Not disabling unused clocks\n");
@@ -545,53 +553,72 @@ late_initcall_sync(clk_disable_unused);
const char *__clk_get_name(struct clk *clk)
{
- return !clk ? NULL : clk->name;
+ return !clk ? NULL : clk->core->name;
}
EXPORT_SYMBOL_GPL(__clk_get_name);
struct clk_hw *__clk_get_hw(struct clk *clk)
{
- return !clk ? NULL : clk->hw;
+ return !clk ? NULL : clk->core->hw;
}
EXPORT_SYMBOL_GPL(__clk_get_hw);
u8 __clk_get_num_parents(struct clk *clk)
{
- return !clk ? 0 : clk->num_parents;
+ return !clk ? 0 : clk->core->num_parents;
}
EXPORT_SYMBOL_GPL(__clk_get_num_parents);
struct clk *__clk_get_parent(struct clk *clk)
{
- return !clk ? NULL : clk->parent;
+ return !clk ? NULL : __clk_create_clk(clk->core->parent,
+ clk->dev_id, clk->con_id);
}
EXPORT_SYMBOL_GPL(__clk_get_parent);
-struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+struct clk_core *clk_provider_get_parent_by_index(struct clk_core *clk,
+ u8 index)
{
if (!clk || index >= clk->num_parents)
return NULL;
else if (!clk->parents)
- return __clk_lookup(clk->parent_names[index]);
+ return clk_provider_lookup(clk->parent_names[index]);
else if (!clk->parents[index])
return clk->parents[index] =
- __clk_lookup(clk->parent_names[index]);
+ clk_provider_lookup(clk->parent_names[index]);
else
return clk->parents[index];
}
+EXPORT_SYMBOL_GPL(clk_provider_get_parent_by_index);
+
+struct clk *clk_get_parent_by_index(struct clk *clk, u8 index)
+{
+ struct clk_core *parent;
+ struct clk *parent_user;
+
+ parent = clk_provider_get_parent_by_index(clk->core, index);
+ if (IS_ERR(parent))
+ return (void *)parent;
+
+ parent_user = __clk_create_clk(parent, clk->dev_id, clk->con_id);
+ if (IS_ERR(parent_user))
+ clk_provider_put(parent);
+
+ return parent_user;
+}
EXPORT_SYMBOL_GPL(clk_get_parent_by_index);
unsigned int __clk_get_enable_count(struct clk *clk)
{
- return !clk ? 0 : clk->enable_count;
+ return !clk ? 0 : clk->core->enable_count;
}
unsigned int __clk_get_prepare_count(struct clk *clk)
{
- return !clk ? 0 : clk->prepare_count;
+ return !clk ? 0 : clk->core->prepare_count;
}
-unsigned long __clk_get_rate(struct clk *clk)
+static unsigned long clk_provider_get_rate_nolock(struct clk_core *clk)
{
unsigned long ret;
@@ -611,9 +638,14 @@ unsigned long __clk_get_rate(struct clk *clk)
out:
return ret;
}
+
+unsigned long __clk_get_rate(struct clk *clk)
+{
+ return clk_provider_get_rate_nolock(clk->core);
+}
EXPORT_SYMBOL_GPL(__clk_get_rate);
-unsigned long __clk_get_accuracy(struct clk *clk)
+unsigned long __clk_get_accuracy(struct clk_core *clk)
{
if (!clk)
return 0;
@@ -623,11 +655,11 @@ unsigned long __clk_get_accuracy(struct clk *clk)
unsigned long __clk_get_flags(struct clk *clk)
{
- return !clk ? 0 : clk->flags;
+ return !clk ? 0 : clk->core->flags;
}
EXPORT_SYMBOL_GPL(__clk_get_flags);
-bool __clk_is_prepared(struct clk *clk)
+static bool clk_provider_is_prepared(struct clk_core *clk)
{
int ret;
@@ -648,7 +680,12 @@ out:
return !!ret;
}
-bool __clk_is_enabled(struct clk *clk)
+bool __clk_is_prepared(struct clk *clk)
+{
+ return clk_provider_is_prepared(clk->core);
+}
+
+bool clk_provider_is_enabled(struct clk_core *clk)
{
int ret;
@@ -668,12 +705,17 @@ bool __clk_is_enabled(struct clk *clk)
out:
return !!ret;
}
+
+bool __clk_is_enabled(struct clk *clk)
+{
+ return clk_provider_is_enabled(clk->core);
+}
EXPORT_SYMBOL_GPL(__clk_is_enabled);
-static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
+static struct clk_core *__clk_lookup_subtree(const char *name, struct clk_core *clk)
{
- struct clk *child;
- struct clk *ret;
+ struct clk_core *child;
+ struct clk_core *ret;
if (!strcmp(clk->name, name))
return clk;
@@ -687,10 +729,10 @@ static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk)
return NULL;
}
-struct clk *__clk_lookup(const char *name)
+static struct clk_core *clk_provider_lookup(const char *name)
{
- struct clk *root_clk;
- struct clk *ret;
+ struct clk_core *root_clk;
+ struct clk_core *ret;
if (!name)
return NULL;
@@ -712,6 +754,13 @@ struct clk *__clk_lookup(const char *name)
return NULL;
}
+struct clk *__clk_lookup(const char *name)
+{
+ struct clk_core *clk = clk_provider_lookup(name);
+
+ return !clk ? NULL : clk->hw->clk;
+}
+
/*
* Helper for finding best parent to provide a given frequency. This can be used
* directly as a determine_rate callback (e.g. for a mux), or from a more
@@ -721,7 +770,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_p)
{
- struct clk *clk = hw->clk, *parent, *best_parent = NULL;
+ struct clk_core *clk = hw->clk->core, *parent, *best_parent = NULL;
int i, num_parents;
unsigned long parent_rate, best = 0;
@@ -729,24 +778,24 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
if (clk->flags & CLK_SET_RATE_NO_REPARENT) {
parent = clk->parent;
if (clk->flags & CLK_SET_RATE_PARENT)
- best = __clk_round_rate(parent, rate);
+ best = clk_provider_round_rate(parent, rate);
else if (parent)
- best = __clk_get_rate(parent);
+ best = clk_provider_get_rate(parent);
else
- best = __clk_get_rate(clk);
+ best = clk_provider_get_rate(clk);
goto out;
}
/* find the parent that can provide the fastest rate <= rate */
num_parents = clk->num_parents;
for (i = 0; i < num_parents; i++) {
- parent = clk_get_parent_by_index(clk, i);
+ parent = clk_provider_get_parent_by_index(clk, i);
if (!parent)
continue;
if (clk->flags & CLK_SET_RATE_PARENT)
- parent_rate = __clk_round_rate(parent, rate);
+ parent_rate = clk_provider_round_rate(parent, rate);
else
- parent_rate = __clk_get_rate(parent);
+ parent_rate = clk_provider_get_rate(parent);
if (parent_rate <= rate && parent_rate > best) {
best_parent = parent;
best = parent_rate;
@@ -755,7 +804,7 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
out:
if (best_parent)
- *best_parent_p = best_parent;
+ *best_parent_p = best_parent->hw->clk;
*best_parent_rate = best;
return best;
@@ -764,7 +813,7 @@ EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
/*** clk api ***/
-void __clk_unprepare(struct clk *clk)
+static void clk_provider_unprepare(struct clk_core *clk)
{
if (!clk)
return;
@@ -780,7 +829,12 @@ void __clk_unprepare(struct clk *clk)
if (clk->ops->unprepare)
clk->ops->unprepare(clk->hw);
- __clk_unprepare(clk->parent);
+ clk_provider_unprepare(clk->parent);
+}
+
+void __clk_unprepare(struct clk *clk)
+{
+ clk_provider_unprepare(clk->core);
}
/**
@@ -805,7 +859,7 @@ void clk_unprepare(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_unprepare);
-int __clk_prepare(struct clk *clk)
+static int clk_provider_prepare(struct clk_core *clk)
{
int ret = 0;
@@ -813,14 +867,14 @@ int __clk_prepare(struct clk *clk)
return 0;
if (clk->prepare_count == 0) {
- ret = __clk_prepare(clk->parent);
+ ret = clk_provider_prepare(clk->parent);
if (ret)
return ret;
if (clk->ops->prepare) {
ret = clk->ops->prepare(clk->hw);
if (ret) {
- __clk_unprepare(clk->parent);
+ clk_provider_unprepare(clk->parent);
return ret;
}
}
@@ -831,6 +885,11 @@ int __clk_prepare(struct clk *clk)
return 0;
}
+int __clk_prepare(struct clk *clk)
+{
+ return clk_provider_prepare(clk->core);
+}
+
/**
* clk_prepare - prepare a clock source
* @clk: the clk being prepared
@@ -855,7 +914,7 @@ int clk_prepare(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_prepare);
-static void __clk_disable(struct clk *clk)
+static void clk_provider_disable(struct clk_core *clk)
{
if (!clk)
return;
@@ -869,7 +928,12 @@ static void __clk_disable(struct clk *clk)
if (clk->ops->disable)
clk->ops->disable(clk->hw);
- __clk_disable(clk->parent);
+ clk_provider_disable(clk->parent);
+}
+
+static void __clk_disable(struct clk *clk)
+{
+ clk_provider_disable(clk->core);
}
/**
@@ -897,7 +961,7 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_disable);
-static int __clk_enable(struct clk *clk)
+static int clk_provider_enable(struct clk_core *clk)
{
int ret = 0;
@@ -908,7 +972,7 @@ static int __clk_enable(struct clk *clk)
return -ESHUTDOWN;
if (clk->enable_count == 0) {
- ret = __clk_enable(clk->parent);
+ ret = clk_provider_enable(clk->parent);
if (ret)
return ret;
@@ -916,7 +980,7 @@ static int __clk_enable(struct clk *clk)
if (clk->ops->enable) {
ret = clk->ops->enable(clk->hw);
if (ret) {
- __clk_disable(clk->parent);
+ clk_provider_disable(clk->parent);
return ret;
}
}
@@ -926,6 +990,11 @@ static int __clk_enable(struct clk *clk)
return 0;
}
+static int __clk_enable(struct clk *clk)
+{
+ return clk_provider_enable(clk->core);
+}
+
/**
* clk_enable - ungate a clock
* @clk: the clk being ungated
@@ -952,17 +1021,12 @@ int clk_enable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_enable);
-/**
- * __clk_round_rate - round the given rate for a clk
- * @clk: round the rate of this clock
- * @rate: the rate which is to be rounded
- *
- * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate
- */
-unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+static unsigned long clk_provider_round_rate_nolock(struct clk_core *clk,
+ unsigned long rate)
{
unsigned long parent_rate = 0;
- struct clk *parent;
+ struct clk_core *parent;
+ struct clk *parent_user;
if (!clk)
return 0;
@@ -973,16 +1037,39 @@ unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
if (clk->ops->determine_rate)
return clk->ops->determine_rate(clk->hw, rate, &parent_rate,
- &parent);
+ &parent_user);
else if (clk->ops->round_rate)
return clk->ops->round_rate(clk->hw, rate, &parent_rate);
else if (clk->flags & CLK_SET_RATE_PARENT)
- return __clk_round_rate(clk->parent, rate);
+ return clk_provider_round_rate_nolock(clk->parent, rate);
else
return clk->rate;
}
+
+/**
+ * __clk_round_rate - round the given rate for a clk
+ * @clk: round the rate of this clock
+ * @rate: the rate which is to be rounded
+ *
+ * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate
+ */
+unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ return clk_provider_round_rate_nolock(clk->core, rate);
+}
EXPORT_SYMBOL_GPL(__clk_round_rate);
+static long clk_provider_round_rate(struct clk_core *clk, unsigned long rate)
+{
+ unsigned long ret;
+
+ clk_prepare_lock();
+ ret = clk_provider_round_rate_nolock(clk, rate);
+ clk_prepare_unlock();
+
+ return ret;
+}
+
/**
* clk_round_rate - round the given rate for a clk
* @clk: the clk for which we are rounding a rate
@@ -994,13 +1081,7 @@ EXPORT_SYMBOL_GPL(__clk_round_rate);
*/
long clk_round_rate(struct clk *clk, unsigned long rate)
{
- unsigned long ret;
-
- clk_prepare_lock();
- ret = __clk_round_rate(clk, rate);
- clk_prepare_unlock();
-
- return ret;
+ return clk_provider_round_rate(clk->core, rate);
}
EXPORT_SYMBOL_GPL(clk_round_rate);
@@ -1018,22 +1099,21 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
* called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
* a driver returns that.
*/
-static int __clk_notify(struct clk *clk, unsigned long msg,
+static int __clk_notify(struct clk_core *clk, unsigned long msg,
unsigned long old_rate, unsigned long new_rate)
{
struct clk_notifier *cn;
struct clk_notifier_data cnd;
int ret = NOTIFY_DONE;
- cnd.clk = clk;
cnd.old_rate = old_rate;
cnd.new_rate = new_rate;
list_for_each_entry(cn, &clk_notifier_list, node) {
- if (cn->clk == clk) {
+ if (cn->clk->core == clk) {
+ cnd.clk = cn->clk;
ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
&cnd);
- break;
}
}
@@ -1051,10 +1131,10 @@ static int __clk_notify(struct clk *clk, unsigned long msg,
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_accuracies(struct clk *clk)
+static void __clk_recalc_accuracies(struct clk_core *clk)
{
unsigned long parent_accuracy = 0;
- struct clk *child;
+ struct clk_core *child;
if (clk->parent)
parent_accuracy = clk->parent->accuracy;
@@ -1069,16 +1149,7 @@ static void __clk_recalc_accuracies(struct clk *clk)
__clk_recalc_accuracies(child);
}
-/**
- * clk_get_accuracy - return the accuracy of clk
- * @clk: the clk whose accuracy is being returned
- *
- * Simply returns the cached accuracy of the clk, unless
- * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
- * issued.
- * If clk is NULL then returns 0.
- */
-long clk_get_accuracy(struct clk *clk)
+static long clk_provider_get_accuracy(struct clk_core *clk)
{
unsigned long accuracy;
@@ -1091,9 +1162,24 @@ long clk_get_accuracy(struct clk *clk)
return accuracy;
}
+
+/**
+ * clk_get_accuracy - return the accuracy of clk
+ * @clk: the clk whose accuracy is being returned
+ *
+ * Simply returns the cached accuracy of the clk, unless
+ * CLK_GET_ACCURACY_NOCACHE flag is set, which means a recalc_rate will be
+ * issued.
+ * If clk is NULL then returns 0.
+ */
+long clk_get_accuracy(struct clk *clk)
+{
+ return clk_provider_get_accuracy(clk->core);
+}
EXPORT_SYMBOL_GPL(clk_get_accuracy);
-static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
+static unsigned long clk_recalc(struct clk_core *clk,
+ unsigned long parent_rate)
{
if (clk->ops->recalc_rate)
return clk->ops->recalc_rate(clk->hw, parent_rate);
@@ -1114,11 +1200,11 @@ static unsigned long clk_recalc(struct clk *clk, unsigned long parent_rate)
*
* Caller must hold prepare_lock.
*/
-static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
+static void __clk_recalc_rates(struct clk_core *clk, unsigned long msg)
{
unsigned long old_rate;
unsigned long parent_rate = 0;
- struct clk *child;
+ struct clk_core *child;
old_rate = clk->rate;
@@ -1138,15 +1224,7 @@ static void __clk_recalc_rates(struct clk *clk, unsigned long msg)
__clk_recalc_rates(child, msg);
}
-/**
- * clk_get_rate - return the rate of clk
- * @clk: the clk whose rate is being returned
- *
- * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
- * is set, which means a recalc_rate will be issued.
- * If clk is NULL then returns 0.
- */
-unsigned long clk_get_rate(struct clk *clk)
+unsigned long clk_provider_get_rate(struct clk_core *clk)
{
unsigned long rate;
@@ -1155,14 +1233,29 @@ unsigned long clk_get_rate(struct clk *clk)
if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
__clk_recalc_rates(clk, 0);
- rate = __clk_get_rate(clk);
+ rate = clk_provider_get_rate_nolock(clk);
clk_prepare_unlock();
return rate;
}
+EXPORT_SYMBOL_GPL(clk_provider_get_rate);
+
+/**
+ * clk_get_rate - return the rate of clk
+ * @clk: the clk whose rate is being returned
+ *
+ * Simply returns the cached rate of the clk, unless CLK_GET_RATE_NOCACHE flag
+ * is set, which means a recalc_rate will be issued.
+ * If clk is NULL then returns 0.
+ */
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk_provider_get_rate(clk->core);
+}
EXPORT_SYMBOL_GPL(clk_get_rate);
-static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
+static int clk_fetch_parent_index(struct clk_core *clk,
+ struct clk_core *parent)
{
int i;
@@ -1176,7 +1269,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
/*
* find index of new parent clock using cached parent ptrs,
* or if not yet cached, use string name comparison and cache
- * them now to avoid future calls to __clk_lookup.
+ * them now to avoid future calls to clk_provider_lookup.
*/
for (i = 0; i < clk->num_parents; i++) {
if (clk->parents[i] == parent)
@@ -1186,7 +1279,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
continue;
if (!strcmp(clk->parent_names[i], parent->name)) {
- clk->parents[i] = __clk_lookup(parent->name);
+ clk->parents[i] = clk_provider_lookup(parent->name);
return i;
}
}
@@ -1194,7 +1287,7 @@ static int clk_fetch_parent_index(struct clk *clk, struct clk *parent)
return -EINVAL;
}
-static void clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_reparent(struct clk_core *clk, struct clk_core *new_parent)
{
hlist_del(&clk->child_node);
@@ -1211,10 +1304,11 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
clk->parent = new_parent;
}
-static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
+static struct clk_core *__clk_set_parent_before(struct clk_core *clk,
+ struct clk_core *parent)
{
unsigned long flags;
- struct clk *old_parent = clk->parent;
+ struct clk_core *old_parent = clk->parent;
/*
* Migrate prepare state between parents and prevent race with
@@ -1234,9 +1328,9 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
* See also: Comment for clk_set_parent() below.
*/
if (clk->prepare_count) {
- __clk_prepare(parent);
- clk_enable(parent);
- clk_enable(clk);
+ clk_provider_prepare(parent);
+ clk_provider_enable(parent);
+ clk_provider_enable(clk);
}
/* update the clk tree topology */
@@ -1247,25 +1341,27 @@ static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
return old_parent;
}
-static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
- struct clk *old_parent)
+static void __clk_set_parent_after(struct clk_core *clk,
+ struct clk_core *parent,
+ struct clk_core *old_parent)
{
/*
* Finish the migration of prepare state and undo the changes done
* for preventing a race with clk_enable().
*/
if (clk->prepare_count) {
- clk_disable(clk);
- clk_disable(old_parent);
- __clk_unprepare(old_parent);
+ clk_provider_disable(clk);
+ clk_provider_disable(old_parent);
+ clk_provider_unprepare(old_parent);
}
}
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static int __clk_set_parent(struct clk_core *clk, struct clk_core *parent,
+ u8 p_index)
{
unsigned long flags;
int ret = 0;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_parent = __clk_set_parent_before(clk, parent);
@@ -1279,9 +1375,9 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
clk_enable_unlock(flags);
if (clk->prepare_count) {
- clk_disable(clk);
- clk_disable(parent);
- __clk_unprepare(parent);
+ clk_provider_disable(clk);
+ clk_provider_disable(parent);
+ clk_provider_unprepare(parent);
}
return ret;
}
@@ -1307,9 +1403,10 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
*
* Caller must hold prepare_lock.
*/
-static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate)
+static int __clk_speculate_rates(struct clk_core *clk,
+ unsigned long parent_rate)
{
- struct clk *child;
+ struct clk_core *child;
unsigned long new_rate;
int ret = NOTIFY_DONE;
@@ -1335,10 +1432,10 @@ out:
return ret;
}
-static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
- struct clk *new_parent, u8 p_index)
+static void clk_calc_subtree(struct clk_core *clk, unsigned long new_rate,
+ struct clk_core *new_parent, u8 p_index)
{
- struct clk *child;
+ struct clk_core *child;
clk->new_rate = new_rate;
clk->new_parent = new_parent;
@@ -1358,10 +1455,12 @@ static void clk_calc_subtree(struct clk *clk, unsigned long new_rate,
* calculate the new rates returning the topmost clock that has to be
* changed.
*/
-static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
+static struct clk_core *clk_calc_new_rates(struct clk_core *clk,
+ unsigned long rate)
{
- struct clk *top = clk;
- struct clk *old_parent, *parent;
+ struct clk_core *top = clk;
+ struct clk_core *old_parent, *parent;
+ struct clk *parent_user;
unsigned long best_parent_rate = 0;
unsigned long new_rate;
int p_index = 0;
@@ -1379,7 +1478,8 @@ static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate)
if (clk->ops->determine_rate) {
new_rate = clk->ops->determine_rate(clk->hw, rate,
&best_parent_rate,
- &parent);
+ &parent_user);
+ parent = parent_user->core;
} else if (clk->ops->round_rate) {
new_rate = clk->ops->round_rate(clk->hw, rate,
&best_parent_rate);
@@ -1427,9 +1527,10 @@ out:
* so that in case of an error we can walk down the whole tree again and
* abort the change.
*/
-static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event)
+static struct clk_core *clk_propagate_rate_change(struct clk_core *clk,
+ unsigned long event)
{
- struct clk *child, *tmp_clk, *fail_clk = NULL;
+ struct clk_core *child, *tmp_clk, *fail_clk = NULL;
int ret = NOTIFY_DONE;
if (clk->rate == clk->new_rate)
@@ -1464,14 +1565,14 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
* walk down a subtree and set the new rates notifying the rate
* change on the way
*/
-static void clk_change_rate(struct clk *clk)
+static void clk_change_rate(struct clk_core *clk)
{
- struct clk *child;
+ struct clk_core *child;
struct hlist_node *tmp;
unsigned long old_rate;
unsigned long best_parent_rate = 0;
bool skip_set_rate = false;
- struct clk *old_parent;
+ struct clk_core *old_parent;
old_rate = clk->rate;
@@ -1542,7 +1643,7 @@ static void clk_change_rate(struct clk *clk)
*/
int clk_set_rate(struct clk *clk, unsigned long rate)
{
- struct clk *top, *fail_clk;
+ struct clk_core *top, *fail_clk;
int ret = 0;
if (!clk)
@@ -1555,13 +1656,14 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
if (rate == clk_get_rate(clk))
goto out;
- if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
+ if ((clk->core->flags & CLK_SET_RATE_GATE) &&
+ clk->core->prepare_count) {
ret = -EBUSY;
goto out;
}
/* calculate new rates and get the topmost changed clock */
- top = clk_calc_new_rates(clk, rate);
+ top = clk_calc_new_rates(clk->core, rate);
if (!top) {
ret = -EINVAL;
goto out;
@@ -1587,6 +1689,18 @@ out:
}
EXPORT_SYMBOL_GPL(clk_set_rate);
+struct clk_core *clk_provider_get_parent(struct clk_core *clk)
+{
+ struct clk_core *parent;
+
+ clk_prepare_lock();
+ parent = !clk ? NULL : clk->parent;
+ clk_prepare_unlock();
+
+ return parent;
+}
+EXPORT_SYMBOL_GPL(clk_provider_get_parent);
+
/**
* clk_get_parent - return the parent of a clk
* @clk: the clk whose parent gets returned
@@ -1595,13 +1709,18 @@ EXPORT_SYMBOL_GPL(clk_set_rate);
*/
struct clk *clk_get_parent(struct clk *clk)
{
- struct clk *parent;
+ struct clk_core *parent;
+ struct clk *parent_user;
- clk_prepare_lock();
- parent = __clk_get_parent(clk);
- clk_prepare_unlock();
+ parent = clk_provider_get_parent(clk->core);
+ if (IS_ERR(parent))
+ return (void *)parent;
- return parent;
+ parent_user = __clk_create_clk(parent, clk->dev_id, clk->con_id);
+ if (IS_ERR(parent_user))
+ clk_provider_put(parent);
+
+ return parent_user;
}
EXPORT_SYMBOL_GPL(clk_get_parent);
@@ -1612,11 +1731,11 @@ EXPORT_SYMBOL_GPL(clk_get_parent);
*
* For single-parent clocks without .get_parent, first check to see if the
* .parents array exists, and if so use it to avoid an expensive tree
- * traversal. If .parents does not exist then walk the tree with __clk_lookup.
+ * traversal. If .parents does not exist then walk the tree with clk_provider_lookup.
*/
-static struct clk *__clk_init_parent(struct clk *clk)
+static struct clk_core *__clk_init_parent(struct clk_core *clk)
{
- struct clk *ret = NULL;
+ struct clk_core *ret = NULL;
u8 index;
/* handle the trivial cases */
@@ -1626,7 +1745,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
if (clk->num_parents == 1) {
if (IS_ERR_OR_NULL(clk->parent))
- ret = clk->parent = __clk_lookup(clk->parent_names[0]);
+ ret = clk->parent = clk_provider_lookup(clk->parent_names[0]);
ret = clk->parent;
goto out;
}
@@ -1640,7 +1759,7 @@ static struct clk *__clk_init_parent(struct clk *clk)
/*
* Do our best to cache parent clocks in clk->parents. This prevents
- * unnecessary and expensive calls to __clk_lookup. We don't set
+ * unnecessary and expensive calls to clk_provider_lookup. We don't set
* clk->parent here; that is done by the calling function
*/
@@ -1651,37 +1770,26 @@ static struct clk *__clk_init_parent(struct clk *clk)
kcalloc(clk->num_parents, sizeof(struct clk *),
GFP_KERNEL);
- ret = clk_get_parent_by_index(clk, index);
+ ret = clk_provider_get_parent_by_index(clk, index);
out:
return ret;
}
-void __clk_reparent(struct clk *clk, struct clk *new_parent)
+static void clk_provider_reparent(struct clk_core *clk,
+ struct clk_core *new_parent)
{
clk_reparent(clk, new_parent);
__clk_recalc_accuracies(clk);
__clk_recalc_rates(clk, POST_RATE_CHANGE);
}
-/**
- * clk_set_parent - switch the parent of a mux clk
- * @clk: the mux clk whose input we are switching
- * @parent: the new input to clk
- *
- * Re-parent clk to use parent as its new input source. If clk is in
- * prepared state, the clk will get enabled for the duration of this call. If
- * that's not acceptable for a specific clk (Eg: the consumer can't handle
- * that, the reparenting is glitchy in hardware, etc), use the
- * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
- *
- * After successfully changing clk's parent clk_set_parent will update the
- * clk topology, sysfs topology and propagate rate recalculation via
- * __clk_recalc_rates.
- *
- * Returns 0 on success, -EERROR otherwise.
- */
-int clk_set_parent(struct clk *clk, struct clk *parent)
+void __clk_reparent(struct clk *clk, struct clk *new_parent)
+{
+ clk_provider_reparent(clk->core, new_parent->core);
+}
+
+static int clk_provider_set_parent(struct clk_core *clk, struct clk_core *parent)
{
int ret = 0;
int p_index = 0;
@@ -1741,6 +1849,28 @@ out:
return ret;
}
+
+/**
+ * clk_set_parent - switch the parent of a mux clk
+ * @clk: the mux clk whose input we are switching
+ * @parent: the new input to clk
+ *
+ * Re-parent clk to use parent as its new input source. If clk is in
+ * prepared state, the clk will get enabled for the duration of this call. If
+ * that's not acceptable for a specific clk (Eg: the consumer can't handle
+ * that, the reparenting is glitchy in hardware, etc), use the
+ * CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
+ *
+ * After successfully changing clk's parent clk_set_parent will update the
+ * clk topology, sysfs topology and propagate rate recalculation via
+ * __clk_recalc_rates.
+ *
+ * Returns 0 on success, -EERROR otherwise.
+ */
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ return clk_provider_set_parent(clk->core, parent->core);
+}
EXPORT_SYMBOL_GPL(clk_set_parent);
/**
@@ -1748,14 +1878,15 @@ EXPORT_SYMBOL_GPL(clk_set_parent);
* @dev: device initializing this clk, placeholder for now
* @clk: clk being initialized
*
- * Initializes the lists in struct clk, queries the hardware for the
+ * Initializes the lists in struct clk_core, queries the hardware for the
* parent and rate and sets them both.
*/
-int __clk_init(struct device *dev, struct clk *clk)
+int __clk_init(struct device *dev, struct clk *clk_user)
{
int i, ret = 0;
- struct clk *orphan;
+ struct clk_core *orphan;
struct hlist_node *tmp2;
+ struct clk_core *clk = clk_user->core;
if (!clk)
return -EINVAL;
@@ -1763,7 +1894,7 @@ int __clk_init(struct device *dev, struct clk *clk)
clk_prepare_lock();
/* check to see if a clock with this name is already registered */
- if (__clk_lookup(clk->name)) {
+ if (clk_provider_lookup(clk->name)) {
pr_debug("%s: clk %s already initialized\n",
__func__, clk->name);
ret = -EEXIST;
@@ -1815,7 +1946,7 @@ int __clk_init(struct device *dev, struct clk *clk)
clk->parents = kcalloc(clk->num_parents, sizeof(struct clk *),
GFP_KERNEL);
/*
- * __clk_lookup returns NULL for parents that have not been
+ * clk_provider_lookup returns NULL for parents that have not been
* clk_init'd; thus any access to clk->parents[] must check
* for a NULL pointer. We can always perform lazy lookups for
* missing parents later on.
@@ -1823,7 +1954,7 @@ int __clk_init(struct device *dev, struct clk *clk)
if (clk->parents)
for (i = 0; i < clk->num_parents; i++)
clk->parents[i] =
- __clk_lookup(clk->parent_names[i]);
+ clk_provider_lookup(clk->parent_names[i]);
}
clk->parent = __clk_init_parent(clk);
@@ -1869,7 +2000,7 @@ int __clk_init(struct device *dev, struct clk *clk)
*/
if (clk->ops->recalc_rate)
clk->rate = clk->ops->recalc_rate(clk->hw,
- __clk_get_rate(clk->parent));
+ clk_provider_get_rate_nolock(clk->parent));
else if (clk->parent)
clk->rate = clk->parent->rate;
else
@@ -1884,13 +2015,13 @@ int __clk_init(struct device *dev, struct clk *clk)
if (orphan->num_parents && orphan->ops->get_parent) {
i = orphan->ops->get_parent(orphan->hw);
if (!strcmp(clk->name, orphan->parent_names[i]))
- __clk_reparent(orphan, clk);
+ clk_provider_reparent(orphan, clk);
continue;
}
for (i = 0; i < orphan->num_parents; i++)
if (!strcmp(clk->name, orphan->parent_names[i])) {
- __clk_reparent(orphan, clk);
+ clk_provider_reparent(orphan, clk);
break;
}
}
@@ -1916,12 +2047,13 @@ out:
/**
* __clk_register - register a clock and return a cookie.
*
- * Same as clk_register, except that the .clk field inside hw shall point to a
- * preallocated (generally statically allocated) struct clk. None of the fields
- * of the struct clk need to be initialized.
+ * Same as clk_register, except that the .core and .clk fields inside hw shall
+ * point to preallocated (generally statically allocated) struct clk_core, and
+ * struct clk (respectively). None of the fields of the struct clk_core need
+ * to be initialized.
*
- * The data pointed to by .init and .clk field shall NOT be marked as init
- * data.
+ * The data pointed to by .init, .core and .clk field shall NOT be marked as
+ * init data.
*
* __clk_register is only exposed via clk-private.h and is intended for use with
* very large numbers of clocks that need to be statically initialized. It is
@@ -1933,9 +2065,9 @@ out:
struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
{
int ret;
- struct clk *clk;
+ struct clk_core *clk;
- clk = hw->clk;
+ clk = hw->core;
clk->name = hw->init->name;
clk->ops = hw->init->ops;
clk->hw = hw;
@@ -1947,11 +2079,11 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
else
clk->owner = NULL;
- ret = __clk_init(dev, clk);
+ ret = __clk_init(dev, hw->clk);
if (ret)
return ERR_PTR(ret);
- return clk;
+ return hw->clk;
}
EXPORT_SYMBOL_GPL(__clk_register);
@@ -1969,7 +2101,7 @@ EXPORT_SYMBOL_GPL(__clk_register);
struct clk *clk_register(struct device *dev, struct clk_hw *hw)
{
int i, ret;
- struct clk *clk;
+ struct clk_core *clk;
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
if (!clk) {
@@ -1990,7 +2122,7 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
clk->hw = hw;
clk->flags = hw->init->flags;
clk->num_parents = hw->init->num_parents;
- hw->clk = clk;
+ hw->core = clk;
/* allocate local copy in case parent_names is __initdata */
clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
@@ -2014,9 +2146,10 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw)
}
}
- ret = __clk_init(dev, clk);
+ hw->clk = __clk_create_clk(clk, NULL, NULL);
+ ret = __clk_init(dev, hw->clk);
if (!ret)
- return clk;
+ return hw->clk;
fail_parent_names_copy:
while (--i >= 0)
@@ -2024,6 +2157,7 @@ fail_parent_names_copy:
kfree(clk->parent_names);
fail_parent_names:
kfree(clk->name);
+ kfree(hw->clk);
fail_name:
kfree(clk);
fail_out:
@@ -2037,7 +2171,7 @@ EXPORT_SYMBOL_GPL(clk_register);
*/
static void __clk_release(struct kref *ref)
{
- struct clk *clk = container_of(ref, struct clk, ref);
+ struct clk_core *clk = container_of(ref, struct clk_core, ref);
int i = clk->num_parents;
kfree(clk->parents);
@@ -2097,8 +2231,9 @@ void clk_unregister(struct clk *clk)
clk_prepare_lock();
- if (clk->ops == &clk_nodrv_ops) {
- pr_err("%s: unregistered clock: %s\n", __func__, clk->name);
+ if (clk->core->ops == &clk_nodrv_ops) {
+ pr_err("%s: unregistered clock: %s\n", __func__,
+ clk->core->name);
goto out;
}
/*
@@ -2106,27 +2241,27 @@ void clk_unregister(struct clk *clk)
* a reference to this clock.
*/
flags = clk_enable_lock();
- clk->ops = &clk_nodrv_ops;
+ clk->core->ops = &clk_nodrv_ops;
clk_enable_unlock(flags);
- if (!hlist_empty(&clk->children)) {
- struct clk *child;
+ if (!hlist_empty(&clk->core->children)) {
+ struct clk_core *child;
struct hlist_node *t;
/* Reparent all children to the orphan list. */
- hlist_for_each_entry_safe(child, t, &clk->children, child_node)
- clk_set_parent(child, NULL);
+ hlist_for_each_entry_safe(child, t, &clk->core->children, child_node)
+ clk_provider_set_parent(child, NULL);
}
- clk_debug_unregister(clk);
+ clk_debug_unregister(clk->core);
- hlist_del_init(&clk->child_node);
+ hlist_del_init(&clk->core->child_node);
- if (clk->prepare_count)
+ if (clk->core->prepare_count)
pr_warn("%s: unregistering prepared clock: %s\n",
- __func__, clk->name);
+ __func__, clk->core->name);
- kref_put(&clk->ref, __clk_release);
+ kref_put(&clk->core->ref, __clk_release);
out:
clk_prepare_unlock();
}
@@ -2189,30 +2324,36 @@ void devm_clk_unregister(struct device *dev, struct clk *clk)
}
EXPORT_SYMBOL_GPL(devm_clk_unregister);
+static void clk_provider_put(struct clk_core *clk)
+{
+ if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
+ return;
+
+ clk_prepare_lock();
+ kref_put(&clk->ref, __clk_release);
+ clk_prepare_unlock();
+
+ module_put(clk->owner);
+}
+
/*
* clkdev helpers
*/
int __clk_get(struct clk *clk)
{
if (clk) {
- if (!try_module_get(clk->owner))
+ if (!try_module_get(clk->core->owner))
return 0;
- kref_get(&clk->ref);
+ kref_get(&clk->core->ref);
}
return 1;
}
void __clk_put(struct clk *clk)
{
- if (!clk || WARN_ON_ONCE(IS_ERR(clk)))
- return;
-
- clk_prepare_lock();
- kref_put(&clk->ref, __clk_release);
- clk_prepare_unlock();
-
- module_put(clk->owner);
+ clk_provider_put(clk->core);
+ kfree(clk);
}
/*** clk rate change notifiers ***/
@@ -2267,7 +2408,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
ret = srcu_notifier_chain_register(&cn->notifier_head, nb);
- clk->notifier_count++;
+ clk->core->notifier_count++;
out:
clk_prepare_unlock();
@@ -2304,7 +2445,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
if (cn->clk == clk) {
ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb);
- clk->notifier_count--;
+ clk->core->notifier_count--;
/* XXX the notifier code should handle this better */
if (!cn->notifier_head.head) {
@@ -2323,6 +2464,31 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
}
EXPORT_SYMBOL_GPL(clk_notifier_unregister);
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev_id,
+ const char *con_id)
+{
+ struct clk *clk;
+
+ /* This is to allow this function to be chained to others */
+ if (!clk_core || IS_ERR(clk_core))
+ return (struct clk *) clk_core;
+
+ clk = kzalloc(sizeof(*clk), GFP_KERNEL);
+ if (!clk)
+ return ERR_PTR(-ENOMEM);
+
+ clk->core = clk_core;
+ clk->dev_id = dev_id;
+ clk->con_id = con_id;
+
+ return clk;
+}
+
+struct clk *__clk_core_to_clk(struct clk_core *clk)
+{
+ return !clk ? NULL : clk->hw->clk;
+}
+
#ifdef CONFIG_OF
/**
* struct of_clk_provider - Clock provider registration structure
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index c798138..4a17902 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -9,9 +9,16 @@
* published by the Free Software Foundation.
*/
+#include <linux/clk-private.h>
+
#if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
struct clk *of_clk_get_by_clkspec(struct of_phandle_args *clkspec);
struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec);
void of_clk_lock(void);
void of_clk_unlock(void);
#endif
+
+#if defined(CONFIG_COMMON_CLK)
+struct clk *__clk_create_clk(struct clk_core *clk_core, const char *dev_id,
+ const char *con_id);
+#endif
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index da4bda8..53bcaf8 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -168,14 +168,27 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
struct clk *clk_get_sys(const char *dev_id, const char *con_id)
{
struct clk_lookup *cl;
+ struct clk *clk = NULL;
mutex_lock(&clocks_mutex);
cl = clk_find(dev_id, con_id);
- if (cl && !__clk_get(cl->clk))
- cl = NULL;
+ if (cl) {
+#if defined(CONFIG_COMMON_CLK)
+ clk = __clk_create_clk(cl->clk->core, dev_id, con_id);
+ if (clk && !__clk_get(clk)) {
+ kfree(clk);
+ clk = NULL;
+ }
+#else
+ if (!__clk_get(cl->clk))
+ cl = NULL;
+ else
+ clk = cl->clk;
+#endif
+ }
mutex_unlock(&clocks_mutex);
- return cl ? cl->clk : ERR_PTR(-ENOENT);
+ return cl ? clk : ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL(clk_get_sys);
diff --git a/include/linux/clk-private.h b/include/linux/clk-private.h
index efbf70b..b45620f 100644
--- a/include/linux/clk-private.h
+++ b/include/linux/clk-private.h
@@ -28,20 +28,20 @@
struct module;
-struct clk {
+struct clk_core {
const char *name;
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
- struct clk *parent;
+ struct clk_core *parent;
const char **parent_names;
- struct clk **parents;
+ struct clk_core **parents;
u8 num_parents;
u8 new_parent_index;
unsigned long rate;
unsigned long new_rate;
- struct clk *new_parent;
- struct clk *new_child;
+ struct clk_core *new_parent;
+ struct clk_core *new_child;
unsigned long flags;
unsigned int enable_count;
unsigned int prepare_count;
@@ -55,6 +55,12 @@ struct clk {
struct kref ref;
};
+struct clk {
+ struct clk_core *core;
+ const char *dev_id;
+ const char *con_id;
+};
+
/*
* DOC: Basic clock implementations common to many platforms
*
@@ -67,6 +73,9 @@ struct clk {
#define DEFINE_CLK(_name, _ops, _flags, _parent_names, \
_parents) \
static struct clk _name = { \
+ .core = &_name##_core \
+ }; \
+ static struct clk_core _name##_core = { \
.name = #_name, \
.ops = &_ops, \
.hw = &_name##_hw.hw, \
@@ -79,9 +88,11 @@ struct clk {
#define DEFINE_CLK_FIXED_RATE(_name, _flags, _rate, \
_fixed_rate_flags) \
static struct clk _name; \
+ static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = {}; \
static struct clk_fixed_rate _name##_hw = { \
.hw = { \
+ .core = &_name##_core, \
.clk = &_name, \
}, \
.fixed_rate = _rate, \
@@ -94,14 +105,16 @@ struct clk {
_flags, _reg, _bit_idx, \
_gate_flags, _lock) \
static struct clk _name; \
+ static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = { \
_parent_name, \
}; \
- static struct clk *_name##_parents[] = { \
+ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \
}; \
static struct clk_gate _name##_hw = { \
.hw = { \
+ .core = &_name##_core, \
.clk = &_name, \
}, \
.reg = _reg, \
@@ -116,14 +129,16 @@ struct clk {
_flags, _reg, _shift, _width, \
_divider_flags, _table, _lock) \
static struct clk _name; \
+ static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = { \
_parent_name, \
}; \
- static struct clk *_name##_parents[] = { \
+ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \
}; \
static struct clk_divider _name##_hw = { \
.hw = { \
+ .core = &_name##_core, \
.clk = &_name, \
}, \
.reg = _reg, \
@@ -155,8 +170,10 @@ struct clk {
_reg, _shift, _width, \
_mux_flags, _lock) \
static struct clk _name; \
+ static struct clk_core _name##_core; \
static struct clk_mux _name##_hw = { \
.hw = { \
+ .core = &_name##_core, \
.clk = &_name, \
}, \
.reg = _reg, \
@@ -172,14 +189,16 @@ struct clk {
_parent_ptr, _flags, \
_mult, _div) \
static struct clk _name; \
+ static struct clk_core _name##_core; \
static const char *_name##_parent_names[] = { \
_parent_name, \
}; \
- static struct clk *_name##_parents[] = { \
+ static struct clk_core *_name##_parents[] = { \
_parent_ptr, \
}; \
static struct clk_fixed_factor _name##_hw = { \
.hw = { \
+ .core = &_name##_core, \
.clk = &_name, \
}, \
.mult = _mult, \
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 411dd7e..64d6f9d 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -32,6 +32,7 @@
#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */
struct clk_hw;
+struct clk_core;
struct dentry;
/**
@@ -205,13 +206,17 @@ struct clk_init_data {
* clk_foo and then referenced by the struct clk instance that uses struct
* clk_foo's clk_ops
*
- * @clk: pointer to the struct clk instance that points back to this struct
- * clk_hw instance
+ * @core: pointer to the struct clk_core instance that points back to this
+ * struct clk_hw instance
+ *
+ * @clk: pointer to the per-user struct clk instance that can be used to call
+ * into the clk API
*
* @init: pointer to struct clk_init_data that contains the init data shared
* with the common clock framework.
*/
struct clk_hw {
+ struct clk_core *core;
struct clk *clk;
const struct clk_init_data *init;
};
@@ -514,7 +519,7 @@ struct clk *clk_get_parent_by_index(struct clk *clk, u8 index);
unsigned int __clk_get_enable_count(struct clk *clk);
unsigned int __clk_get_prepare_count(struct clk *clk);
unsigned long __clk_get_rate(struct clk *clk);
-unsigned long __clk_get_accuracy(struct clk *clk);
+unsigned long __clk_get_accuracy(struct clk_core *clk);
unsigned long __clk_get_flags(struct clk *clk);
bool __clk_is_prepared(struct clk *clk);
bool __clk_is_enabled(struct clk *clk);
@@ -523,6 +528,24 @@ long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_p);
+unsigned long clk_provider_get_rate(struct clk_core *clk);
+struct clk_core *clk_provider_get_parent(struct clk_core *clk);
+struct clk_core *clk_provider_get_parent_by_index(struct clk_core *clk,
+ u8 index);
+
+/**
+ * __clk_core_to_clk - return per-user clk
+ * @clk: struct clk_core for which we want a per-user clk
+ *
+ * Returns a per-user clock that is owned by its provider. The caller shall not
+ * call clk_get() on it.
+ *
+ * This function should be only needed by implementors of
+ * clk_ops.determine_rate() and should be dropped once all have moved to a
+ * variant that returns **clk_core instead.
+ */
+struct clk *__clk_core_to_clk(struct clk_core *clk);
+
/*
* FIXME clock api without lock protection
*/
--
1.9.3
^ permalink raw reply related [flat|nested] 24+ messages in thread
* Re: [RFC] clk: Make clk API return per-user struct clk instances
2014-09-30 7:41 ` Tero Kristo
@ 2014-09-30 18:16 ` Tony Lindgren
2014-10-03 14:13 ` Tero Kristo
0 siblings, 1 reply; 24+ messages in thread
From: Tony Lindgren @ 2014-09-30 18:16 UTC (permalink / raw)
To: Tero Kristo
Cc: Mike Turquette, Stephen Boyd, Tomeu Vizoso, Russell King,
linux-kernel, Javier Martinez Canillas
* Tero Kristo <t-kristo@ti.com> [140930 00:41]:
> On 09/30/2014 09:54 AM, Mike Turquette wrote:
> >Quoting Stephen Boyd (2014-09-29 18:40:23)
> >>On 09/29/14 11:17, Tomeu Vizoso wrote:
> >>>Also moves clock state to struct clk_core, but takes care to change as little
> >>>API as possible.
> >>>
> >>>struct clk_hw still has a pointer to a struct clk, which is the
> >>>implementation's per-user clk instance, for backwards compatibility.
> >>>
> >>>Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> >>>
> >>>---
> >>>
> >>>Hello,
> >>>
> >>>I'm sending this alternate implementation of the switch to per-user clocks,
> >>>with the added goal of not requiring any substantial changes to existing users
> >>>of the API.
> >>>
> >>>This is pretty much RFC-quality right now, having only tested that it builds on
> >>>tegra_defconfig.
> >>>
> >>>My main question right now is what do we want to do with those drivers that
> >>>statically declare clocks. State is now in struct clk_core, so updating the
> >>>drivers accordingly will amount to a substantial amount of lines changed, which
> >>>we are now trying to avoid.
> >>
> >>Who's actually using the static clocks? Isn't it just omap2? It looks
> >>like all of those are behind the DEFINE_CLK define so changing it in
> >>clk-private.h should "just work". I'm lost as to why static clocks are
> >>being used there though. If it was a problem with allocating memory too
> >>early it doesn't seem to be the case given that sometimes the .parents
> >>field isn't set for a mux and __clk_init() will go and allocate an array
> >>of pointers. Maybe I missed something though.
> >
> >Yeah, the old omap2+ static clocks were due to very very early init of
> >things which required clocks
> >
> >If memory serves, that isn't a problem any more. I've talked to Tony and
> >Tero about my desire to remove clk-private.h and the need to get rid of
> >its use in the omap clock code.
> >
> >Tero, what is the status of DT conversion for OMAP2/OMAP3? Can we get
> >get away with only defining clock data in DT for those platforms? Can we
> >finally kill off clk-private.h?
>
> Clock data has been converted for all SoCs. The problem is currently that we
> are missing some OMAP3 based DT board definitions and still require legacy
> boot => thus requiring legacy clock data also => omap3 legacy clock data
> can't be removed yet.
>
> Tony, whats the latest status with these missing omap3 boards? How many
> board->dt conversions are still needed? Is there anything someone can do on
> this front?
Well things are looking good for device tree based booting for omap3
in general. We just need to wait so people have enough time to update
their boards and do the missing .dts files. I guess all we can say is
we drop omap3 legacy booting when we can.
Can we remove the depenency to the omap3 DT conversion for the clocks
to remove the DT conversion dependency here?
Regards,
Tony
^ permalink raw reply [flat|nested] 24+ messages in thread
* Re: [RFC] clk: Make clk API return per-user struct clk instances
2014-09-30 18:16 ` Tony Lindgren
@ 2014-10-03 14:13 ` Tero Kristo
0 siblings, 0 replies; 24+ messages in thread
From: Tero Kristo @ 2014-10-03 14:13 UTC (permalink / raw)
To: Tony Lindgren
Cc: Mike Turquette, Stephen Boyd, Tomeu Vizoso, Russell King,
linux-kernel, Javier Martinez Canillas
On 09/30/2014 09:16 PM, Tony Lindgren wrote:
> * Tero Kristo <t-kristo@ti.com> [140930 00:41]:
>> On 09/30/2014 09:54 AM, Mike Turquette wrote:
>>> Quoting Stephen Boyd (2014-09-29 18:40:23)
>>>> On 09/29/14 11:17, Tomeu Vizoso wrote:
>>>>> Also moves clock state to struct clk_core, but takes care to change as little
>>>>> API as possible.
>>>>>
>>>>> struct clk_hw still has a pointer to a struct clk, which is the
>>>>> implementation's per-user clk instance, for backwards compatibility.
>>>>>
>>>>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>>>>>
>>>>> ---
>>>>>
>>>>> Hello,
>>>>>
>>>>> I'm sending this alternate implementation of the switch to per-user clocks,
>>>>> with the added goal of not requiring any substantial changes to existing users
>>>>> of the API.
>>>>>
>>>>> This is pretty much RFC-quality right now, having only tested that it builds on
>>>>> tegra_defconfig.
>>>>>
>>>>> My main question right now is what do we want to do with those drivers that
>>>>> statically declare clocks. State is now in struct clk_core, so updating the
>>>>> drivers accordingly will amount to a substantial amount of lines changed, which
>>>>> we are now trying to avoid.
>>>>
>>>> Who's actually using the static clocks? Isn't it just omap2? It looks
>>>> like all of those are behind the DEFINE_CLK define so changing it in
>>>> clk-private.h should "just work". I'm lost as to why static clocks are
>>>> being used there though. If it was a problem with allocating memory too
>>>> early it doesn't seem to be the case given that sometimes the .parents
>>>> field isn't set for a mux and __clk_init() will go and allocate an array
>>>> of pointers. Maybe I missed something though.
>>>
>>> Yeah, the old omap2+ static clocks were due to very very early init of
>>> things which required clocks
>>>
>>> If memory serves, that isn't a problem any more. I've talked to Tony and
>>> Tero about my desire to remove clk-private.h and the need to get rid of
>>> its use in the omap clock code.
>>>
>>> Tero, what is the status of DT conversion for OMAP2/OMAP3? Can we get
>>> get away with only defining clock data in DT for those platforms? Can we
>>> finally kill off clk-private.h?
>>
>> Clock data has been converted for all SoCs. The problem is currently that we
>> are missing some OMAP3 based DT board definitions and still require legacy
>> boot => thus requiring legacy clock data also => omap3 legacy clock data
>> can't be removed yet.
>>
>> Tony, whats the latest status with these missing omap3 boards? How many
>> board->dt conversions are still needed? Is there anything someone can do on
>> this front?
>
> Well things are looking good for device tree based booting for omap3
> in general. We just need to wait so people have enough time to update
> their boards and do the missing .dts files. I guess all we can say is
> we drop omap3 legacy booting when we can.
>
> Can we remove the depenency to the omap3 DT conversion for the clocks
> to remove the DT conversion dependency here?
Well, we can. But this basically requires converting the legacy clock
data to some intermediate format, parsing this init time and registering
the individual clocks.. something similar to what is done with DT clocks
now. Kind of pointless exercise with data that is going to be removed
eventually, no? I think converting the boards to DT files is easier and
more fruitful also.
-Tero
^ permalink raw reply [flat|nested] 24+ messages in thread
end of thread, other threads:[~2014-10-03 14:14 UTC | newest]
Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-23 18:40 [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
2014-09-23 18:40 ` [PATCH v13 1/9] clk: Add temporary mapping to the existing API Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 3/9] clk: use struct clk only for external API Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 4/9] clk: per-user clock accounting for debug Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 5/9] clk: Add floor and ceiling constraints to clock rates Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 6/9] clk: Warn of unbalanced clk_prepare() calls Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 7/9] clk: Take the prepare lock when updating the list of per-user clks Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 8/9] clk: Take the prepare lock when updating the per-user constraints Tomeu Vizoso
2014-09-23 18:44 ` [PATCH v13 9/9] clk: Add docs about calling clk_put after clk_get_parent Tomeu Vizoso
2014-09-23 20:59 ` [PATCH v13 0/9] Per-user clock constraints Stephen Boyd
2014-09-24 8:27 ` Tomeu Vizoso
2014-09-26 1:29 ` Stephen Boyd
2014-09-26 8:09 ` Tomeu Vizoso
2014-09-26 23:20 ` Mike Turquette
2014-09-27 0:15 ` Stephen Boyd
2014-09-29 18:17 ` [RFC] clk: Make clk API return per-user struct clk instances Tomeu Vizoso
2014-09-30 1:40 ` Stephen Boyd
2014-09-30 6:54 ` Mike Turquette
2014-09-30 7:41 ` Tero Kristo
2014-09-30 18:16 ` Tony Lindgren
2014-10-03 14:13 ` Tero Kristo
2014-09-30 9:14 ` Russell King - ARM Linux
2014-09-30 14:28 ` [RFC v2] " Tomeu Vizoso
2014-09-24 9:14 ` [PATCH v13 0/9] Per-user clock constraints Tomeu Vizoso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).