[RFC] Save HSMMC registers if core is powered off

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I've noticed that if the core power domain gets powered off during
suspend, the MMC registers get reset. Which, among other things causes
the MMC host controller code to turn on VMMC1 even if no MMC card is
present.

I'm not sure if this is the right place to put this code. It also
doesn't work. If any of the __raw_readl commands execute, the board will
hang on a suspend attempt (assuming the core domain will be powered
off.) Strangely, the __raw_writel commands don't cause problems (other
than writing 0s to all the MMC registers.)

My platform is an OMAP3430 on a rev B7 Beagleboard. The patch is against
omap/pm.
---
 arch/arm/mach-omap2/Makefile            |    1 +
 arch/arm/mach-omap2/hsmmc.c             |   73 +++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm34xx.c            |    5 ++
 arch/arm/plat-omap/include/mach/hsmmc.h |   15 ++++++
 4 files changed, 94 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-omap2/hsmmc.c
 create mode 100644 arch/arm/plat-omap/include/mach/hsmmc.h

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index c58bab4..4dd8ec0 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -24,6 +24,7 @@ obj-y					+= pm.o
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
 obj-$(CONFIG_ARCH_OMAP24XX)		+= sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= hsmmc.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 endif
 
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
new file mode 100644
index 0000000..9ac6f91
--- /dev/null
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -0,0 +1,73 @@
+/*
+ * HSMMC context save/restore functions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+
+#include <mach/mmc.h>
+
+#define HSMMC_SYSCONFIG	0x0010
+#define HSMMC_CON	0x002c
+#define HSMMC_HCTL	0x0128
+#define HSMMC_SYSCTL	0x012c
+#define HSMMC_IE	0x0134
+#define HSMMC_ISE	0x0138
+
+static const void __iomem *instances[] = {
+	OMAP2_IO_ADDRESS(OMAP2_MMC1_BASE),
+	OMAP2_IO_ADDRESS(OMAP2_MMC2_BASE),
+	OMAP2_IO_ADDRESS(OMAP3_MMC3_BASE),
+};
+
+struct omap3_hsmmc_regs {
+	u32 sysconfig;
+	u32 con;
+	u32 hctl;
+	u32 sysctl;
+	u32 ie;
+	u32 ise;
+};
+
+static struct omap3_hsmmc_regs hsmmc_context[ARRAY_SIZE(instances)];
+
+static void hsmmc_write_reg(int id, int idx, u32 val)
+{
+	__raw_writel(val, instances[id] + idx);
+}
+
+static u32 hsmmc_read_reg(int id, int idx)
+{
+	return 0;//__raw_readl(instances[id] + idx);
+}
+
+void omap3_hsmmc_save_context(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(instances); i++) {
+		hsmmc_context[i].sysconfig = hsmmc_read_reg(i, HSMMC_SYSCONFIG);
+		hsmmc_context[i].con = hsmmc_read_reg(i, HSMMC_CON);
+		hsmmc_context[i].hctl = hsmmc_read_reg(i, HSMMC_HCTL);
+		hsmmc_context[i].sysctl = hsmmc_read_reg(i, HSMMC_SYSCTL);
+		hsmmc_context[i].ie = hsmmc_read_reg(i, HSMMC_IE);
+		hsmmc_context[i].ise = hsmmc_read_reg(i, HSMMC_ISE);
+	}
+}
+
+void omap3_hsmmc_restore_context(void)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(instances); i++) {
+		hsmmc_write_reg(i, HSMMC_SYSCONFIG, hsmmc_context[i].sysconfig);
+		hsmmc_write_reg(i, HSMMC_CON, hsmmc_context[i].con);
+		hsmmc_write_reg(i, HSMMC_HCTL, hsmmc_context[i].hctl);
+		hsmmc_write_reg(i, HSMMC_SYSCTL, hsmmc_context[i].sysctl);
+		hsmmc_write_reg(i, HSMMC_IE, hsmmc_context[i].ie);
+		hsmmc_write_reg(i, HSMMC_ISE, hsmmc_context[i].ise);
+	}
+}
diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c
index 7474cfa..b2393c5 100644
--- a/arch/arm/mach-omap2/pm34xx.c
+++ b/arch/arm/mach-omap2/pm34xx.c
@@ -41,6 +41,7 @@
 #include <mach/sdrc.h>
 #include <mach/dma.h>
 #include <mach/gpmc.h>
+#include <mach/hsmmc.h>
 #include <mach/dma.h>
 #include <asm/tlbflush.h>
 
@@ -148,6 +149,8 @@ static void omap3_core_save_context(void)
 	omap3_intc_save_context();
 	/* Save the GPMC context */
 	omap3_gpmc_save_context();
+	/* Save the HSMMC context */
+	omap3_hsmmc_save_context();
 	/* Save the system control module context, padconf already save above*/
 	omap3_control_save_context();
 	omap_dma_global_context_save();
@@ -159,6 +162,8 @@ static void omap3_core_restore_context(void)
 	omap3_control_restore_context();
 	/* Restore the GPMC context */
 	omap3_gpmc_restore_context();
+	/* Restore the HSMMC context */
+	omap3_hsmmc_restore_context();
 	/* Restore the interrupt controller context */
 	omap3_intc_restore_context();
 	omap_dma_global_context_restore();
diff --git a/arch/arm/plat-omap/include/mach/hsmmc.h b/arch/arm/plat-omap/include/mach/hsmmc.h
new file mode 100644
index 0000000..ae3caee
--- /dev/null
+++ b/arch/arm/plat-omap/include/mach/hsmmc.h
@@ -0,0 +1,15 @@
+/*
+ * HSMMC save/restore logic for OMAP3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __OMAP3_HSMMC_H
+#define __OMAP3_HSMMC_H
+
+extern void omap3_hsmmc_save_context(void);
+extern void omap3_hsmmc_restore_context(void);
+
+#endif
-- 
1.6.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux