aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2011-02-12 21:24:32 -0500
committerColin Cross <ccross@android.com>2011-02-21 03:16:47 -0500
commit9743b38969790d33b077ab80b175ea63a0398703 (patch)
tree5f264886b0fef728534ff6a29a9d82579edb6111 /arch
parent7a281284125fe8704ea16fd1ca243971b7c0a105 (diff)
ARM: tegra: clock: Add function to set SDMMC tap delay
The SDMMC controllers have extra bits in the clock source register that adjust the delay between the clock and data to compenstate for delays on the PCB. The values need to be set from the clock code so the clock can be locked during the read-modify-write on the clock source register. Acked-by: Olof Johansson <olof@lixom.net> Signed-off-by: Colin Cross <ccross@android.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/clock.c14
-rw-r--r--arch/arm/mach-tegra/clock.h1
-rw-r--r--arch/arm/mach-tegra/include/mach/clk.h2
-rw-r--r--arch/arm/mach-tegra/tegra2_clocks.c19
4 files changed, 36 insertions, 0 deletions
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
index f1f9c6d36bd2..165aa9c748f6 100644
--- a/arch/arm/mach-tegra/clock.c
+++ b/arch/arm/mach-tegra/clock.c
@@ -390,6 +390,20 @@ void __init tegra_init_clock(void)
390 tegra2_init_clocks(); 390 tegra2_init_clocks();
391} 391}
392 392
393/*
394 * The SDMMC controllers have extra bits in the clock source register that
395 * adjust the delay between the clock and data to compenstate for delays
396 * on the PCB.
397 */
398void tegra_sdmmc_tap_delay(struct clk *c, int delay)
399{
400 unsigned long flags;
401
402 spin_lock_irqsave(&c->spinlock, flags);
403 tegra2_sdmmc_tap_delay(c, delay);
404 spin_unlock_irqrestore(&c->spinlock, flags);
405}
406
393#ifdef CONFIG_DEBUG_FS 407#ifdef CONFIG_DEBUG_FS
394 408
395static int __clk_lock_all_spinlocks(void) 409static int __clk_lock_all_spinlocks(void)
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
index ebe6ea8b0575..688316abc64e 100644
--- a/arch/arm/mach-tegra/clock.h
+++ b/arch/arm/mach-tegra/clock.h
@@ -155,5 +155,6 @@ int clk_reparent(struct clk *c, struct clk *parent);
155void tegra_clk_init_from_table(struct tegra_clk_init_table *table); 155void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
156unsigned long clk_get_rate_locked(struct clk *c); 156unsigned long clk_get_rate_locked(struct clk *c);
157int clk_set_rate_locked(struct clk *c, unsigned long rate); 157int clk_set_rate_locked(struct clk *c, unsigned long rate);
158void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
158 159
159#endif 160#endif
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
index fa7f9ca1fdbd..c8baf8f80d23 100644
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ b/arch/arm/mach-tegra/include/mach/clk.h
@@ -26,4 +26,6 @@ void tegra_periph_reset_deassert(struct clk *c);
26void tegra_periph_reset_assert(struct clk *c); 26void tegra_periph_reset_assert(struct clk *c);
27 27
28unsigned long clk_get_rate_all_locked(struct clk *c); 28unsigned long clk_get_rate_all_locked(struct clk *c);
29void tegra_sdmmc_tap_delay(struct clk *c, int delay);
30
29#endif 31#endif
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c
index 7f7068714049..b85d2c75fb3c 100644
--- a/arch/arm/mach-tegra/tegra2_clocks.c
+++ b/arch/arm/mach-tegra/tegra2_clocks.c
@@ -74,6 +74,10 @@
74#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF 74#define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF
75#define PERIPH_CLK_SOURCE_DIV_SHIFT 0 75#define PERIPH_CLK_SOURCE_DIV_SHIFT 0
76 76
77#define SDMMC_CLK_INT_FB_SEL (1 << 23)
78#define SDMMC_CLK_INT_FB_DLY_SHIFT 16
79#define SDMMC_CLK_INT_FB_DLY_MASK (0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
80
77#define PLL_BASE 0x0 81#define PLL_BASE 0x0
78#define PLL_BASE_BYPASS (1<<31) 82#define PLL_BASE_BYPASS (1<<31)
79#define PLL_BASE_ENABLE (1<<30) 83#define PLL_BASE_ENABLE (1<<30)
@@ -1052,6 +1056,21 @@ static struct clk_ops tegra_periph_clk_ops = {
1052 .reset = &tegra2_periph_clk_reset, 1056 .reset = &tegra2_periph_clk_reset,
1053}; 1057};
1054 1058
1059/* The SDMMC controllers have extra bits in the clock source register that
1060 * adjust the delay between the clock and data to compenstate for delays
1061 * on the PCB. */
1062void tegra2_sdmmc_tap_delay(struct clk *c, int delay)
1063{
1064 u32 reg;
1065
1066 delay = clamp(delay, 0, 15);
1067 reg = clk_readl(c->reg);
1068 reg &= ~SDMMC_CLK_INT_FB_DLY_MASK;
1069 reg |= SDMMC_CLK_INT_FB_SEL;
1070 reg |= delay << SDMMC_CLK_INT_FB_DLY_SHIFT;
1071 clk_writel(reg, c->reg);
1072}
1073
1055/* External memory controller clock ops */ 1074/* External memory controller clock ops */
1056static void tegra2_emc_clk_init(struct clk *c) 1075static void tegra2_emc_clk_init(struct clk *c)
1057{ 1076{