On Tue, May 08, 2018 at 07:26:06PM +0300, Dmitry Osipenko wrote: > 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 <dig...@gmail.com>
Acked-by: Peter De Schrijver <pdeschrij...@nvidia.com> > --- > drivers/clk/tegra/clk-tegra114.c | 2 +- > drivers/clk/tegra/clk-tegra124.c | 2 +- > drivers/clk/tegra/clk-tegra20.c | 32 +++++++++++++++++++++++++++++++- > drivers/clk/tegra/clk-tegra210.c | 2 +- > drivers/clk/tegra/clk-tegra30.c | 2 +- > drivers/clk/tegra/clk.c | 5 +++-- > drivers/clk/tegra/clk.h | 2 +- > 7 files changed, 39 insertions(+), 8 deletions(-) > > diff --git a/drivers/clk/tegra/clk-tegra114.c > b/drivers/clk/tegra/clk-tegra114.c > index 5d5a22d529f5..1824f014202b 100644 > --- a/drivers/clk/tegra/clk-tegra114.c > +++ b/drivers/clk/tegra/clk-tegra114.c > @@ -1367,7 +1367,7 @@ static void __init tegra114_clock_init(struct > device_node *np) > tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks, > &pll_x_params); > > - tegra_add_of_provider(np); > + tegra_add_of_provider(np, of_clk_src_onecell_get); > tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); > > tegra_clk_apply_init_table = tegra114_clock_apply_init_table; > diff --git a/drivers/clk/tegra/clk-tegra124.c > b/drivers/clk/tegra/clk-tegra124.c > index 50088e976611..0c69c7970950 100644 > --- a/drivers/clk/tegra/clk-tegra124.c > +++ b/drivers/clk/tegra/clk-tegra124.c > @@ -1479,7 +1479,7 @@ static void __init tegra124_132_clock_init_post(struct > device_node *np) > &pll_x_params); > tegra_init_special_resets(1, tegra124_reset_assert, > tegra124_reset_deassert); > - tegra_add_of_provider(np); > + tegra_add_of_provider(np, of_clk_src_onecell_get); > > clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np, > &emc_lock); > 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; > diff --git a/drivers/clk/tegra/clk-tegra210.c > b/drivers/clk/tegra/clk-tegra210.c > index 9fb5d51ccce4..5435d01c636a 100644 > --- a/drivers/clk/tegra/clk-tegra210.c > +++ b/drivers/clk/tegra/clk-tegra210.c > @@ -3567,7 +3567,7 @@ static void __init tegra210_clock_init(struct > device_node *np) > tegra_init_special_resets(2, tegra210_reset_assert, > tegra210_reset_deassert); > > - tegra_add_of_provider(np); > + tegra_add_of_provider(np, of_clk_src_onecell_get); > tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); > > tegra210_mbist_clk_init(); > diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c > index b316dfb6f6c7..acfe661b2ae7 100644 > --- a/drivers/clk/tegra/clk-tegra30.c > +++ b/drivers/clk/tegra/clk-tegra30.c > @@ -1349,7 +1349,7 @@ static void __init tegra30_clock_init(struct > device_node *np) > > tegra_init_dup_clks(tegra_clk_duplicates, clks, TEGRA30_CLK_CLK_MAX); > > - tegra_add_of_provider(np); > + tegra_add_of_provider(np, of_clk_src_onecell_get); > tegra_register_devclks(devclks, ARRAY_SIZE(devclks)); > > tegra_clk_apply_init_table = tegra30_clock_apply_init_table; > diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c > index ba923f0d5953..593d76a114f9 100644 > --- a/drivers/clk/tegra/clk.c > +++ b/drivers/clk/tegra/clk.c > @@ -298,7 +298,8 @@ static struct reset_controller_dev rst_ctlr = { > .of_reset_n_cells = 1, > }; > > -void __init tegra_add_of_provider(struct device_node *np) > +void __init tegra_add_of_provider(struct device_node *np, > + void *clk_src_onecell_get) > { > int i; > > @@ -314,7 +315,7 @@ void __init tegra_add_of_provider(struct device_node *np) > > clk_data.clks = clks; > clk_data.clk_num = clk_num; > - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); > + of_clk_add_provider(np, clk_src_onecell_get, &clk_data); > > rst_ctlr.of_node = np; > rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset; > diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h > index ba7e20e6a82b..e1f88463b600 100644 > --- a/drivers/clk/tegra/clk.h > +++ b/drivers/clk/tegra/clk.h > @@ -763,7 +763,7 @@ struct clk **tegra_clk_init(void __iomem *clk_base, int > num, int periph_banks); > > struct clk **tegra_lookup_dt_id(int clk_id, struct tegra_clk *tegra_clk); > > -void tegra_add_of_provider(struct device_node *np); > +void tegra_add_of_provider(struct device_node *np, void > *clk_src_onecell_get); > void tegra_register_devclks(struct tegra_devclk *dev_clks, int num); > > void tegra_audio_clk_init(void __iomem *clk_base, > -- > 2.17.0 >