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 <digetx@gmail.com> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
This commit is contained in:
parent
efc351b1f4
commit
5d797111af
|
@ -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,
|
tegra_super_clk_gen4_init(clk_base, pmc_base, tegra114_clks,
|
||||||
&pll_x_params);
|
&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_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||||
|
|
||||||
tegra_clk_apply_init_table = tegra114_clock_apply_init_table;
|
tegra_clk_apply_init_table = tegra114_clock_apply_init_table;
|
||||||
|
|
|
@ -1479,7 +1479,7 @@ static void __init tegra124_132_clock_init_post(struct device_node *np)
|
||||||
&pll_x_params);
|
&pll_x_params);
|
||||||
tegra_init_special_resets(1, tegra124_reset_assert,
|
tegra_init_special_resets(1, tegra124_reset_assert,
|
||||||
tegra124_reset_deassert);
|
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,
|
clks[TEGRA124_CLK_EMC] = tegra_clk_register_emc(clk_base, np,
|
||||||
&emc_lock);
|
&emc_lock);
|
||||||
|
|
|
@ -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)
|
static void __init tegra20_clock_init(struct device_node *np)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
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_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_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||||
|
|
||||||
tegra_clk_apply_init_table = tegra20_clock_apply_init_table;
|
tegra_clk_apply_init_table = tegra20_clock_apply_init_table;
|
||||||
|
|
|
@ -3567,7 +3567,7 @@ static void __init tegra210_clock_init(struct device_node *np)
|
||||||
tegra_init_special_resets(2, tegra210_reset_assert,
|
tegra_init_special_resets(2, tegra210_reset_assert,
|
||||||
tegra210_reset_deassert);
|
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));
|
tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||||
|
|
||||||
tegra210_mbist_clk_init();
|
tegra210_mbist_clk_init();
|
||||||
|
|
|
@ -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_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_register_devclks(devclks, ARRAY_SIZE(devclks));
|
||||||
|
|
||||||
tegra_clk_apply_init_table = tegra30_clock_apply_init_table;
|
tegra_clk_apply_init_table = tegra30_clock_apply_init_table;
|
||||||
|
|
|
@ -298,7 +298,8 @@ static struct reset_controller_dev rst_ctlr = {
|
||||||
.of_reset_n_cells = 1,
|
.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;
|
int i;
|
||||||
|
|
||||||
|
@ -314,7 +315,7 @@ void __init tegra_add_of_provider(struct device_node *np)
|
||||||
|
|
||||||
clk_data.clks = clks;
|
clk_data.clks = clks;
|
||||||
clk_data.clk_num = clk_num;
|
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.of_node = np;
|
||||||
rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
|
rst_ctlr.nr_resets = periph_banks * 32 + num_special_reset;
|
||||||
|
|
|
@ -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);
|
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_register_devclks(struct tegra_devclk *dev_clks, int num);
|
||||||
|
|
||||||
void tegra_audio_clk_init(void __iomem *clk_base,
|
void tegra_audio_clk_init(void __iomem *clk_base,
|
||||||
|
|
Loading…
Reference in New Issue