diff options
author | Jin Park <jinyoungp@nvidia.com> | 2011-03-16 22:59:31 +0900 |
---|---|---|
committer | Varun Colbert <vcolbert@nvidia.com> | 2011-04-04 17:57:51 -0700 |
commit | 8b81c1c918c289328df61b1e325a8019f9814d98 (patch) | |
tree | 87968a241a5fb66ae544a64a1386c9de9da399ac /arch/arm/mach-tegra | |
parent | 8014ff69b2b8a860840f04d26ad164ae8353b04d (diff) |
ARM: tegra: clocks: Add mux clock inputs to cdev1 and cdev2
For getting actual rate, add mux clock inputs to cdev1 and cdev2.
Change-Id: Ic42eb97a51bceb5249ca29938ac00f8add9ef032
Signed-off-by: Jin Park <jinyoungp@nvidia.com>
Reviewed-on: http://git-master/r/23187
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'arch/arm/mach-tegra')
-rw-r--r-- | arch/arm/mach-tegra/include/mach/pinmux.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-tegra/pinmux.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-tegra/tegra2_clocks.c | 96 |
3 files changed, 96 insertions, 23 deletions
diff --git a/arch/arm/mach-tegra/include/mach/pinmux.h b/arch/arm/mach-tegra/include/mach/pinmux.h index defd8775defa..b67c9fcd243e 100644 --- a/arch/arm/mach-tegra/include/mach/pinmux.h +++ b/arch/arm/mach-tegra/include/mach/pinmux.h @@ -218,6 +218,7 @@ struct tegra_pingroup_desc { extern const struct tegra_pingroup_desc tegra_soc_pingroups[]; extern const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[]; +int tegra_pinmux_get_func(enum tegra_pingroup pg); int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate); int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, diff --git a/arch/arm/mach-tegra/pinmux.c b/arch/arm/mach-tegra/pinmux.c index d94e348412f3..b58541009a77 100644 --- a/arch/arm/mach-tegra/pinmux.c +++ b/arch/arm/mach-tegra/pinmux.c @@ -227,6 +227,28 @@ static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config) return 0; } +int tegra_pinmux_get_func(enum tegra_pingroup pg) +{ + int mux = -1; + unsigned long reg; + unsigned long flags; + + if (pg < 0 || pg >= TEGRA_MAX_PINGROUP) + return -ERANGE; + + if (pingroups[pg].mux_reg < 0) + return -EINVAL; + + spin_lock_irqsave(&mux_lock, flags); + + reg = pg_readl(pingroups[pg].mux_reg); + mux = (reg >> pingroups[pg].mux_bit) & 0x3; + + spin_unlock_irqrestore(&mux_lock, flags); + + return mux; +} + int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate) { diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index c0bf72ee2a86..3777b2a9a43b 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -30,6 +30,7 @@ #include <mach/iomap.h> #include <mach/suspend.h> +#include <mach/pinmux.h> #include "clock.h" #include "fuse.h" @@ -1171,10 +1172,38 @@ static struct clk_ops tegra_audio_sync_clk_ops = { .set_parent = tegra2_audio_sync_clk_set_parent, }; -/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ +/* call this function after pinmux configuration */ +static void tegra2_cdev_clk_set_parent(struct clk *c) +{ + const struct clk_mux_sel *mux = 0; + const struct clk_mux_sel *sel; + enum tegra_pingroup pg = TEGRA_PINGROUP_CDEV1; + int val; + + /* Get pinmux setting for cdev1 and cdev2 from APB_MISC register */ + if (!strcmp(c->name, "clk_dev2")) + pg = TEGRA_PINGROUP_CDEV2; + + val = tegra_pinmux_get_func(pg); + for (sel = c->inputs; sel->input != NULL; sel++) { + if (val == sel->value) + mux = sel; + } + BUG_ON(!mux); + c->parent = mux->input; +} + +/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ static void tegra2_cdev_clk_init(struct clk *c) { + const struct clk_mux_sel *sel; + + /* Find max rate from inputs */ + for (sel = c->inputs; sel->input != NULL; sel++) { + c->max_rate = max(sel->input->max_rate, c->max_rate); + } + /* We could un-tristate the cdev1 or cdev2 pingroup here; this is * currently done in the pinmux code. */ c->state = ON; @@ -1185,6 +1214,12 @@ static void tegra2_cdev_clk_init(struct clk *c) static int tegra2_cdev_clk_enable(struct clk *c) { + if (!c->parent) { + /* Set parent from inputs */ + tegra2_cdev_clk_set_parent(c); + clk_enable(c->parent); + } + clk_writel(PERIPH_CLK_TO_ENB_BIT(c), CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); return 0; @@ -1670,28 +1705,6 @@ static struct clk tegra_clk_d = { }, }; -/* dap_mclk1, belongs to the cdev1 pingroup. */ -static struct clk tegra_dev1_clk = { - .name = "clk_dev1", - .ops = &tegra_cdev_clk_ops, - .rate = 26000000, - .max_rate = 26000000, - .u.periph = { - .clk_num = 94, - }, -}; - -/* dap_mclk2, belongs to the cdev2 pingroup. */ -static struct clk tegra_dev2_clk = { - .name = "clk_dev2", - .ops = &tegra_cdev_clk_ops, - .rate = 26000000, - .max_rate = 26000000, - .u.periph = { - .clk_num = 93, - }, -}; - /* initialized before peripheral clocks */ static struct clk_mux_sel mux_audio_sync_clk[8+1]; static const struct audio_sources { @@ -1850,6 +1863,43 @@ static struct clk tegra_clk_blink = { .ops = &tegra_blink_clk_ops, .max_rate = 32768, }; +static struct clk_mux_sel mux_dev1_clk[] = { + { .input = &tegra_clk_m, .value = 0 }, + { .input = &tegra_pll_a_out0, .value = 1 }, + { .input = &tegra_pll_m_out1, .value = 2 }, + { .input = &tegra_clk_audio, .value = 3 }, + { 0, 0 } +}; + +static struct clk_mux_sel mux_dev2_clk[] = { + { .input = &tegra_clk_m, .value = 0 }, + { .input = &tegra_clk_hclk, .value = 1 }, + { .input = &tegra_clk_pclk, .value = 2 }, + { .input = &tegra_pll_p_out4, .value = 3 }, + { 0, 0 } +}; + +/* dap_mclk1, belongs to the cdev1 pingroup. */ +static struct clk tegra_dev1_clk = { + .name = "clk_dev1", + .ops = &tegra_cdev_clk_ops, + .inputs = mux_dev1_clk, + .u.periph = { + .clk_num = 94, + }, + .flags = MUX, +}; + +/* dap_mclk2, belongs to the cdev2 pingroup. */ +static struct clk tegra_dev2_clk = { + .name = "clk_dev2", + .ops = &tegra_cdev_clk_ops, + .inputs = mux_dev2_clk, + .u.periph = { + .clk_num = 93, + }, + .flags = MUX, +}; static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { { .input = &tegra_pll_m, .value = 0}, |