summaryrefslogtreecommitdiff
path: root/arch/arm/mach-tegra
diff options
context:
space:
mode:
authorJin Park <jinyoungp@nvidia.com>2011-03-16 22:59:31 +0900
committerVarun Colbert <vcolbert@nvidia.com>2011-04-04 17:57:51 -0700
commit8b81c1c918c289328df61b1e325a8019f9814d98 (patch)
tree87968a241a5fb66ae544a64a1386c9de9da399ac /arch/arm/mach-tegra
parent8014ff69b2b8a860840f04d26ad164ae8353b04d (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.h1
-rw-r--r--arch/arm/mach-tegra/pinmux.c22
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c96
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},