ARM: tegra: reset io dpd mode
Bitan Biswas [Thu, 12 Jul 2012 13:03:37 +0000 (18:03 +0530)]
Bootloader io dpd settings are cleared during kernel initialization

bug 758856

Change-Id: Ic6d5250a5ae127bb45ab37b9200ca06c8d1f11a2
Signed-off-by: Bitan Biswas <bbiswas@nvidia.com>
Reviewed-on: http://git-master/r/115395
Reviewed-by: Simone Willett <swillett@nvidia.com>
Tested-by: Simone Willett <swillett@nvidia.com>

Rebase-Id: R2a63cb307f02dc2870e73c6a9fcc73e8c76dca32

arch/arm/mach-tegra/pm-t2.c
arch/arm/mach-tegra/pm-t3.c
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/pm.h

index 831412b..3d96f39 100644 (file)
@@ -384,3 +384,9 @@ int tegra_io_dpd_init(void)
        return 0;
 }
 EXPORT_SYMBOL(tegra_io_dpd_init);
+
+void tegra_bl_io_dpd_cleanup()
+{
+}
+EXPORT_SYMBOL(tegra_bl_io_dpd_cleanup);
+
index d220279..a99abe2 100644 (file)
@@ -516,14 +516,16 @@ struct tegra_io_dpd tegra_list_io_dpd[] = {
        IO_DPD_INFO("sdhci-tegra.3",    1,      3), /* SDMMC4 */
 };
 
+/* we want to cleanup bootloader io dpd setting in kernel */
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+
 #ifdef CONFIG_PM_SLEEP
 struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev)
 {
        int i;
        const char *name = dev ? dev_name(dev) : NULL;
        if (name) {
-               for (i = 0; i < (sizeof(tegra_list_io_dpd) /
-                       sizeof(struct tegra_io_dpd)); i++) {
+               for (i = 0; i < ARRAY_SIZE(tegra_list_io_dpd); i++) {
                        if (!(strncmp(tegra_list_io_dpd[i].name, name,
                                strlen(name)))) {
                                return &tegra_list_io_dpd[i];
@@ -535,7 +537,6 @@ struct tegra_io_dpd *tegra_io_dpd_get(struct device *dev)
        return NULL;
 }
 
-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
 static DEFINE_SPINLOCK(tegra_io_dpd_lock);
 
 void tegra_io_dpd_enable(struct tegra_io_dpd *hnd)
@@ -641,3 +642,39 @@ EXPORT_SYMBOL(tegra_io_dpd_get);
 EXPORT_SYMBOL(tegra_io_dpd_enable);
 EXPORT_SYMBOL(tegra_io_dpd_disable);
 EXPORT_SYMBOL(tegra_io_dpd_init);
+
+struct io_dpd_reg_info {
+       u32 req_reg_off;
+       u8 dpd_code_lsb;
+};
+
+static struct io_dpd_reg_info t3_io_dpd_req_regs[] = {
+       {0x1b8, 30},
+       {0x1c0, 5},
+};
+
+/* io dpd off request code */
+#define IO_DPD_CODE_OFF                1
+
+/* cleans io dpd settings from bootloader during kernel init */
+void tegra_bl_io_dpd_cleanup()
+{
+       int i;
+       unsigned int dpd_mask;
+       unsigned int dpd_status;
+
+       pr_info("Clear bootloader IO dpd settings\n");
+       /* clear all dpd requests from bootloader */
+       for (i = 0; i < ARRAY_SIZE(t3_io_dpd_req_regs); i++) {
+               dpd_mask = ((1 << t3_io_dpd_req_regs[i].dpd_code_lsb) - 1);
+               dpd_mask |= (IO_DPD_CODE_OFF <<
+                       t3_io_dpd_req_regs[i].dpd_code_lsb);
+               writel(dpd_mask, pmc + t3_io_dpd_req_regs[i].req_reg_off);
+               /* dpd status register is next to req reg in tegra3 */
+               dpd_status = readl(pmc +
+                       (t3_io_dpd_req_regs[i].req_reg_off + 4));
+       }
+       return;
+}
+EXPORT_SYMBOL(tegra_bl_io_dpd_cleanup);
+
index 13d2c97..9f6d088 100644 (file)
@@ -1202,6 +1202,10 @@ out:
 
        iram_cpu_lp2_mask = tegra_cpu_lp2_mask;
        iram_cpu_lp1_mask = tegra_cpu_lp1_mask;
+
+       /* clear io dpd settings before kernel */
+       tegra_bl_io_dpd_cleanup();
+
 fail:
 #endif
        if (plat->suspend_mode == TEGRA_SUSPEND_NONE)
index d729d5d..46ffd3a 100644 (file)
@@ -67,6 +67,9 @@ struct tegra_suspend_platform_data {
        unsigned int cpu_resume_boost;  /* CPU frequency resume boost in kHz */
 };
 
+/* clears io dpd settings before kernel code */
+void tegra_bl_io_dpd_cleanup(void);
+
 unsigned long tegra_cpu_power_good_time(void);
 unsigned long tegra_cpu_power_off_time(void);
 unsigned long tegra_cpu_lp2_min_residency(void);