summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorWen Yi <wyi@nvidia.com>2012-06-20 21:42:13 -0700
committerSimone Willett <swillett@nvidia.com>2012-07-16 17:20:28 -0700
commit5e07056dc8b922b8b43a01b60a949c1dda75d9a9 (patch)
treebd8a99dc9e78be49ec0613779535f4dfdd2c466e /arch
parent5a34d0584c5a45547c6733e177a0aa0c93dc1884 (diff)
arm: tegra: sd: enable sd dpd
This is a WAR solution that allows for the turning on SD DPD feature. The original issue is that enabling SD DPD immediately after device comes out of LP0 causes ULPI disconnect. The root cause of that is not known. The WAR is to delay the enabling of SD DPD for 100ms after device comes out of LP0. Bug 929628 Change-Id: I3c5e35ace422e5441535c2c0fe18545b53bbddc4 Signed-off-by: Wen Yi <wyi@nvidia.com> (cherry picked from commit bffb7b917d52a3523af80db21322ec7ba5fd33f9) Reviewed-on: http://git-master/r/113392 Reviewed-by: Simone Willett <swillett@nvidia.com> Tested-by: Simone Willett <swillett@nvidia.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-tegra/board-cardhu.c2
-rw-r--r--arch/arm/mach-tegra/board-enterprise.c2
-rw-r--r--arch/arm/mach-tegra/board-kai.c2
-rw-r--r--arch/arm/mach-tegra/board-p1852.c2
-rw-r--r--arch/arm/mach-tegra/include/mach/io_dpd.h30
-rw-r--r--arch/arm/mach-tegra/pm-t2.c12
-rw-r--r--arch/arm/mach-tegra/pm-t3.c52
-rw-r--r--arch/arm/mach-tegra/pm.h9
8 files changed, 84 insertions, 27 deletions
diff --git a/arch/arm/mach-tegra/board-cardhu.c b/arch/arm/mach-tegra/board-cardhu.c
index 1fa3f4f82ef2..f8fb5c528cbd 100644
--- a/arch/arm/mach-tegra/board-cardhu.c
+++ b/arch/arm/mach-tegra/board-cardhu.c
@@ -50,6 +50,7 @@
#include <mach/irqs.h>
#include <mach/pinmux.h>
#include <mach/iomap.h>
+#include <mach/io_dpd.h>
#include <mach/io.h>
#include <mach/i2s.h>
#include <mach/tegra_asoc_pdata.h>
@@ -1386,6 +1387,7 @@ static void __init tegra_cardhu_init(void)
cardhu_uart_init();
platform_add_devices(cardhu_devices, ARRAY_SIZE(cardhu_devices));
tegra_ram_console_debug_init();
+ tegra_io_dpd_init();
cardhu_sdhci_init();
cardhu_regulator_init();
cardhu_dtv_init();
diff --git a/arch/arm/mach-tegra/board-enterprise.c b/arch/arm/mach-tegra/board-enterprise.c
index 9c8890ed96cf..e703b56fd939 100644
--- a/arch/arm/mach-tegra/board-enterprise.c
+++ b/arch/arm/mach-tegra/board-enterprise.c
@@ -48,6 +48,7 @@
#include <mach/pinmux.h>
#include <mach/iomap.h>
#include <mach/io.h>
+#include <mach/io_dpd.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/usb_phy.h>
@@ -969,6 +970,7 @@ static void __init tegra_enterprise_init(void)
platform_add_devices(enterprise_devices, ARRAY_SIZE(enterprise_devices));
tegra_ram_console_debug_init();
enterprise_regulator_init();
+ tegra_io_dpd_init();
enterprise_sdhci_init();
#ifdef CONFIG_TEGRA_EDP_LIMITS
enterprise_edp_init();
diff --git a/arch/arm/mach-tegra/board-kai.c b/arch/arm/mach-tegra/board-kai.c
index bf4ae415072d..07fbccfd8138 100644
--- a/arch/arm/mach-tegra/board-kai.c
+++ b/arch/arm/mach-tegra/board-kai.c
@@ -50,6 +50,7 @@
#include <mach/pinmux.h>
#include <mach/iomap.h>
#include <mach/io.h>
+#include <mach/io_dpd.h>
#include <mach/i2s.h>
#include <mach/tegra_rt5640_pdata.h>
#include <asm/mach-types.h>
@@ -870,6 +871,7 @@ static void __init tegra_kai_init(void)
kai_audio_init();
platform_add_devices(kai_devices, ARRAY_SIZE(kai_devices));
tegra_ram_console_debug_init();
+ tegra_io_dpd_init();
kai_sdhci_init();
kai_regulator_init();
kai_suspend_init();
diff --git a/arch/arm/mach-tegra/board-p1852.c b/arch/arm/mach-tegra/board-p1852.c
index ce7768e19594..5e7aea1c486d 100644
--- a/arch/arm/mach-tegra/board-p1852.c
+++ b/arch/arm/mach-tegra/board-p1852.c
@@ -43,6 +43,7 @@
#include <mach/irqs.h>
#include <mach/pinmux.h>
#include <mach/iomap.h>
+#include <mach/io_dpd.h>
#include <mach/io.h>
#include <mach/pci.h>
#include <mach/audio.h>
@@ -592,6 +593,7 @@ static void __init tegra_p1852_init(void)
p1852_gpio_init();
p1852_uart_init();
p1852_usb_init();
+ tegra_io_dpd_init();
p1852_sdhci_init();
p1852_spi_init();
platform_add_devices(p1852_devices, ARRAY_SIZE(p1852_devices));
diff --git a/arch/arm/mach-tegra/include/mach/io_dpd.h b/arch/arm/mach-tegra/include/mach/io_dpd.h
index 8d153792b798..6eb05c3f1b93 100644
--- a/arch/arm/mach-tegra/include/mach/io_dpd.h
+++ b/arch/arm/mach-tegra/include/mach/io_dpd.h
@@ -1,7 +1,7 @@
/*
* arch/arm/mach-tegra/include/mach/io_dpd.h
*
- * Copyright (C) 2012 NVIDIA Corporation.
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -16,25 +16,23 @@
#ifndef __MACH_TEGRA_IO_DPD_H
#define __MACH_TEGRA_IO_DPD_H
+#include <linux/delay.h>
+
+/* Tegra io dpd entry - for each supported driver */
+struct tegra_io_dpd {
+ const char *name; /* driver name */
+ u8 io_dpd_reg_index; /* io dpd register index */
+ u8 io_dpd_bit; /* bit position for driver in dpd register */
+ u8 need_delay_dpd; /* work around to delay dpd after lp0*/
+ struct delayed_work delay_dpd;
+ struct mutex delay_lock;
+};
+
/* Tegra io dpd APIs */
-#ifdef CONFIG_PM_SLEEP
struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev); /* get handle */
void tegra_io_dpd_enable(struct tegra_io_dpd *hnd); /* enable dpd */
void tegra_io_dpd_disable(struct tegra_io_dpd *hnd); /* disable dpd */
-#else
-static inline struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev)
-{
- return NULL;
-}
-static inline void tegra_io_dpd_enable(struct tegra_io_dpd *hnd)
-{
- /* Do nothing */
-}
-static inline void tegra_io_dpd_disable(struct tegra_io_dpd *hnd)
-{
- /* Do nothing */
-}
-#endif
+int tegra_io_dpd_init(void);
#endif /* end __MACH_TEGRA_IO_DPD_H */
diff --git a/arch/arm/mach-tegra/pm-t2.c b/arch/arm/mach-tegra/pm-t2.c
index 7ddbb2125595..3ecd27167883 100644
--- a/arch/arm/mach-tegra/pm-t2.c
+++ b/arch/arm/mach-tegra/pm-t2.c
@@ -3,7 +3,7 @@
*
* Tegra 2 LP0 scratch register preservation
*
- * Copyright (c) 2009-2011, NVIDIA Corporation.
+ * Copyright (c) 2009-2012, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -357,6 +357,8 @@ void __init tegra2_lp0_suspend_init(void)
wmb();
}
+#ifdef CONFIG_PM_SLEEP
+
struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev)
{
return NULL;
@@ -374,3 +376,11 @@ void tegra_io_dpd_disable(struct tegra_io_dpd *hnd)
return;
}
EXPORT_SYMBOL(tegra_io_dpd_disable);
+
+#endif
+
+int tegra_io_dpd_init(void)
+{
+ return 0;
+}
+EXPORT_SYMBOL(tegra_io_dpd_init);
diff --git a/arch/arm/mach-tegra/pm-t3.c b/arch/arm/mach-tegra/pm-t3.c
index 89041c41c389..32a260e2dd43 100644
--- a/arch/arm/mach-tegra/pm-t3.c
+++ b/arch/arm/mach-tegra/pm-t3.c
@@ -31,6 +31,7 @@
#include <mach/gpio.h>
#include <mach/iomap.h>
#include <mach/irqs.h>
+#include <mach/io_dpd.h>
#include <asm/cpu_pm.h>
#include <asm/hardware/gic.h>
@@ -456,6 +457,7 @@ struct tegra_io_dpd tegra_list_io_dpd[] = {
IO_DPD_INFO("sdhci-tegra.3", 1, 3), /* SDMMC4 */
};
+#ifdef CONFIG_PM_SLEEP
struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev)
{
int i;
@@ -473,7 +475,6 @@ struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev)
((name) ? name : "NULL"));
return NULL;
}
-EXPORT_SYMBOL(tegra_io_dpd_get);
static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
static DEFINE_SPINLOCK(tegra_io_dpd_lock);
@@ -507,7 +508,6 @@ void tegra_io_dpd_enable(struct tegra_io_dpd *hnd)
spin_unlock(&tegra_io_dpd_lock);
return;
}
-EXPORT_SYMBOL(tegra_io_dpd_enable);
void tegra_io_dpd_disable(struct tegra_io_dpd *hnd)
{
@@ -533,4 +533,52 @@ void tegra_io_dpd_disable(struct tegra_io_dpd *hnd)
spin_unlock(&tegra_io_dpd_lock);
return;
}
+
+static void tegra_io_dpd_delayed_disable(struct work_struct *work)
+{
+ struct tegra_io_dpd *hnd = container_of(
+ to_delayed_work(work), struct tegra_io_dpd, delay_dpd);
+ tegra_io_dpd_disable(hnd);
+ hnd->need_delay_dpd = 0;
+}
+
+int tegra_io_dpd_init(void)
+{
+ int i;
+ for (i = 0;
+ i < (sizeof(tegra_list_io_dpd) / sizeof(struct tegra_io_dpd));
+ i++) {
+ INIT_DELAYED_WORK(&(tegra_list_io_dpd[i].delay_dpd),
+ tegra_io_dpd_delayed_disable);
+ mutex_init(&(tegra_list_io_dpd[i].delay_lock));
+ tegra_list_io_dpd[i].need_delay_dpd = 0;
+ }
+ return 0;
+}
+
+#else
+
+int tegra_io_dpd_init(void)
+{
+ return 0;
+}
+
+void tegra_io_dpd_enable(struct tegra_io_dpd *hnd)
+{
+}
+
+void tegra_io_dpd_disable(struct tegra_io_dpd *hnd)
+{
+}
+
+struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev)
+{
+ return NULL;
+}
+
+#endif
+
+EXPORT_SYMBOL(tegra_io_dpd_get);
+EXPORT_SYMBOL(tegra_io_dpd_enable);
EXPORT_SYMBOL(tegra_io_dpd_disable);
+EXPORT_SYMBOL(tegra_io_dpd_init);
diff --git a/arch/arm/mach-tegra/pm.h b/arch/arm/mach-tegra/pm.h
index 421b21ac9342..65e816c7abc0 100644
--- a/arch/arm/mach-tegra/pm.h
+++ b/arch/arm/mach-tegra/pm.h
@@ -2,7 +2,7 @@
* arch/arm/mach-tegra/include/mach/pm.h
*
* Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2010-2012 NVIDIA Corporation
+ * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved.
*
* Author:
* Colin Cross <ccross@google.com>
@@ -67,13 +67,6 @@ struct tegra_suspend_platform_data {
unsigned int cpu_resume_boost; /* CPU frequency resume boost in kHz */
};
-/* Tegra io dpd entry - for each supported driver */
-struct tegra_io_dpd {
- const char *name; /* driver name */
- u8 io_dpd_reg_index; /* io dpd register index */
- u8 io_dpd_bit; /* bit position for driver in dpd register */
-};
-
unsigned long tegra_cpu_power_good_time(void);
unsigned long tegra_cpu_power_off_time(void);
unsigned long tegra_cpu_lp2_min_residency(void);