diff options
author | Thierry Reding <treding@nvidia.com> | 2015-03-26 12:43:56 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2015-04-10 10:04:20 -0400 |
commit | 63cc5a4da1fafedee24d8f5af67c1dd9d08f95c7 (patch) | |
tree | cd2e48fa02b4982784ad5cf7c09bd0eb90fc06c8 /drivers/clk | |
parent | 699b477a0d3a5bc68034a1520a4337ea0a20f63b (diff) |
clk: tegra: Model oscillator as clock
Currently the Tegra clock driver simplifies the clock tree somewhat by
taking advantage of the fact that clk_m runs at the same frequency as
the oscillator. While that's true on all currently supported SoCs, it
does not apply to Tegra210 anymore. On Tegra210 clk_m is typically
divided down from the oscillator frequency. To support that setup, add
a separate clock for the oscillator that both clk_m and pll_ref derive
from.
Modify the tegra_osc_clk_init() function to take an additional divider
parameter for clk_m. Existing SoCs always pass in 1, whereas Tegra210
will read the divider from a register in the clock & reset controller.
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/clk')
-rw-r--r-- | drivers/clk/tegra/clk-tegra-fixed.c | 24 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra124.c | 3 | ||||
-rw-r--r-- | drivers/clk/tegra/clk-tegra30.c | 3 | ||||
-rw-r--r-- | drivers/clk/tegra/clk.h | 8 |
4 files changed, 21 insertions, 17 deletions
diff --git a/drivers/clk/tegra/clk-tegra-fixed.c b/drivers/clk/tegra/clk-tegra-fixed.c index f3b773833429..605676d368eb 100644 --- a/drivers/clk/tegra/clk-tegra-fixed.c +++ b/drivers/clk/tegra/clk-tegra-fixed.c | |||
@@ -30,13 +30,12 @@ | |||
30 | #define OSC_CTRL_OSC_FREQ_SHIFT 28 | 30 | #define OSC_CTRL_OSC_FREQ_SHIFT 28 |
31 | #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 | 31 | #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 |
32 | 32 | ||
33 | int __init tegra_osc_clk_init(void __iomem *clk_base, | 33 | int __init tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks, |
34 | struct tegra_clk *tegra_clks, | 34 | unsigned long *input_freqs, unsigned int num, |
35 | unsigned long *input_freqs, int num, | 35 | unsigned int clk_m_div, unsigned long *osc_freq, |
36 | unsigned long *osc_freq, | 36 | unsigned long *pll_ref_freq) |
37 | unsigned long *pll_ref_freq) | ||
38 | { | 37 | { |
39 | struct clk *clk; | 38 | struct clk *clk, *osc; |
40 | struct clk **dt_clk; | 39 | struct clk **dt_clk; |
41 | u32 val, pll_ref_div; | 40 | u32 val, pll_ref_div; |
42 | unsigned osc_idx; | 41 | unsigned osc_idx; |
@@ -54,22 +53,25 @@ int __init tegra_osc_clk_init(void __iomem *clk_base, | |||
54 | return -EINVAL; | 53 | return -EINVAL; |
55 | } | 54 | } |
56 | 55 | ||
57 | dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, tegra_clks); | 56 | osc = clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT, |
57 | *osc_freq); | ||
58 | |||
59 | dt_clk = tegra_lookup_dt_id(tegra_clk_clk_m, clks); | ||
58 | if (!dt_clk) | 60 | if (!dt_clk) |
59 | return 0; | 61 | return 0; |
60 | 62 | ||
61 | clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, | 63 | clk = clk_register_fixed_factor(NULL, "clk_m", "osc", |
62 | *osc_freq); | 64 | 0, 1, clk_m_div); |
63 | *dt_clk = clk; | 65 | *dt_clk = clk; |
64 | 66 | ||
65 | /* pll_ref */ | 67 | /* pll_ref */ |
66 | val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3; | 68 | val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3; |
67 | pll_ref_div = 1 << val; | 69 | pll_ref_div = 1 << val; |
68 | dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, tegra_clks); | 70 | dt_clk = tegra_lookup_dt_id(tegra_clk_pll_ref, clks); |
69 | if (!dt_clk) | 71 | if (!dt_clk) |
70 | return 0; | 72 | return 0; |
71 | 73 | ||
72 | clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", | 74 | clk = clk_register_fixed_factor(NULL, "pll_ref", "osc", |
73 | 0, 1, pll_ref_div); | 75 | 0, 1, pll_ref_div); |
74 | *dt_clk = clk; | 76 | *dt_clk = clk; |
75 | 77 | ||
diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 29b39c8c3151..f1fa29ec7951 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c | |||
@@ -1480,7 +1480,8 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np) | |||
1480 | return; | 1480 | return; |
1481 | 1481 | ||
1482 | if (tegra_osc_clk_init(clk_base, tegra124_clks, tegra124_input_freq, | 1482 | if (tegra_osc_clk_init(clk_base, tegra124_clks, tegra124_input_freq, |
1483 | ARRAY_SIZE(tegra124_input_freq), &osc_freq, &pll_ref_freq) < 0) | 1483 | ARRAY_SIZE(tegra124_input_freq), 1, &osc_freq, |
1484 | &pll_ref_freq) < 0) | ||
1484 | return; | 1485 | return; |
1485 | 1486 | ||
1486 | tegra_fixed_clk_init(tegra124_clks); | 1487 | tegra_fixed_clk_init(tegra124_clks); |
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 0659db79d1c5..4b26509fc218 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c | |||
@@ -1434,7 +1434,8 @@ static void __init tegra30_clock_init(struct device_node *np) | |||
1434 | return; | 1434 | return; |
1435 | 1435 | ||
1436 | if (tegra_osc_clk_init(clk_base, tegra30_clks, tegra30_input_freq, | 1436 | if (tegra_osc_clk_init(clk_base, tegra30_clks, tegra30_input_freq, |
1437 | ARRAY_SIZE(tegra30_input_freq), &input_freq, NULL) < 0) | 1437 | ARRAY_SIZE(tegra30_input_freq), 1, &input_freq, |
1438 | NULL) < 0) | ||
1438 | return; | 1439 | return; |
1439 | 1440 | ||
1440 | 1441 | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 48cb1c13ede5..d6ac00647faf 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -615,10 +615,10 @@ void tegra_periph_clk_init(void __iomem *clk_base, void __iomem *pmc_base, | |||
615 | 615 | ||
616 | void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks); | 616 | void tegra_pmc_clk_init(void __iomem *pmc_base, struct tegra_clk *tegra_clks); |
617 | void tegra_fixed_clk_init(struct tegra_clk *tegra_clks); | 617 | void tegra_fixed_clk_init(struct tegra_clk *tegra_clks); |
618 | int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *tegra_clks, | 618 | int tegra_osc_clk_init(void __iomem *clk_base, struct tegra_clk *clks, |
619 | unsigned long *input_freqs, int num, | 619 | unsigned long *input_freqs, unsigned int num, |
620 | unsigned long *osc_freq, | 620 | unsigned int clk_m_div, unsigned long *osc_freq, |
621 | unsigned long *pll_ref_freq); | 621 | unsigned long *pll_ref_freq); |
622 | void tegra_super_clk_gen4_init(void __iomem *clk_base, | 622 | void tegra_super_clk_gen4_init(void __iomem *clk_base, |
623 | void __iomem *pmc_base, struct tegra_clk *tegra_clks, | 623 | void __iomem *pmc_base, struct tegra_clk *tegra_clks, |
624 | struct tegra_clk_pll_params *pll_params); | 624 | struct tegra_clk_pll_params *pll_params); |