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;
&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);
{ },
};
+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;
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;
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();
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;
.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;
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;
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,