From 5d797111afe12e488e08432fd9b372fae2cc7e93 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 8 May 2018 19:26:06 +0300 Subject: clk: tegra: Add quirk for getting CDEV1/2 clocks on Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent clock is created by the pinctrl driver. It should be possible for clk user to request these clocks before pinctrl driver got probed and hence user will get an orphaned clock. That might be undesirable because user may expect parent clock to be enabled by the child, so let's return -EPROBE_DEFER till parent clock appears. Signed-off-by: Dmitry Osipenko Acked-by: Peter De Schrijver Signed-off-by: Thierry Reding --- drivers/clk/tegra/clk-tegra20.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/clk/tegra/clk-tegra20.c') diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 636500a98561..cc857d4d4a86 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1089,6 +1089,36 @@ static const struct of_device_id pmc_match[] __initconst = { { }, }; +static struct clk *tegra20_clk_src_onecell_get(struct of_phandle_args *clkspec, + void *data) +{ + struct clk_hw *parent_hw; + struct clk_hw *hw; + struct clk *clk; + + clk = of_clk_src_onecell_get(clkspec, data); + if (IS_ERR(clk)) + return clk; + + /* + * Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent + * clock is created by the pinctrl driver. It is possible for clk user + * to request these clocks before pinctrl driver got probed and hence + * user will get an orphaned clock. That might be undesirable because + * user may expect parent clock to be enabled by the child. + */ + if (clkspec->args[0] == TEGRA20_CLK_CDEV1 || + clkspec->args[0] == TEGRA20_CLK_CDEV2) { + hw = __clk_get_hw(clk); + + parent_hw = clk_hw_get_parent(hw); + if (!parent_hw) + return ERR_PTR(-EPROBE_DEFER); + } + + return clk; +} + static void __init tegra20_clock_init(struct device_node *np) { struct device_node *node; @@ -1127,7 +1157,7 @@ static void __init tegra20_clock_init(struct device_node *np) tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA20_CLK_CLK_MAX); - tegra_add_of_provider(np); + tegra_add_of_provider(np, tegra20_clk_src_onecell_get); tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); tegra_clk_apply_init_table = tegra20_clock_apply_init_table; -- cgit v1.2.3