diff mbox

[08/11] u8500: Enabling power to MMC device on AB8500 V2

Message ID 1340037344-2497-9-git-send-email-mathieu.poirier@linaro.org
State Accepted
Commit 75dfe964cbe01ec089e4e3d470a86835776fe248
Headers show

Commit Message

Mathieu Poirier June 18, 2012, 4:35 p.m. UTC
From: "Mathieu J. Poirier" <mathieu.poirier@linaro.org>

Register mapping has changed on power control chip between
the first and second revision.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: John Rigby <john.rigby@linaro.org>
---
 arch/arm/cpu/armv7/u8500/cpu.c             |   89 ++++++++++++++++++++--------
 arch/arm/include/asm/arch-u8500/hardware.h |   22 ++++++-
 board/st-ericsson/snowball/snowball.c      |    5 ++
 3 files changed, 88 insertions(+), 28 deletions(-)
diff mbox

Patch

diff --git a/arch/arm/cpu/armv7/u8500/cpu.c b/arch/arm/cpu/armv7/u8500/cpu.c
index 593199c..02bb332 100644
--- a/arch/arm/cpu/armv7/u8500/cpu.c
+++ b/arch/arm/cpu/armv7/u8500/cpu.c
@@ -36,11 +36,19 @@ 
 #define CPUID_DB8500V2		0x412fc091
 #define ASICID_DB8500V11	0x008500A1
 
-static unsigned int read_asicid(void)
+static unsigned int read_asicid(void);
+
+static inline unsigned int read_cpuid(void)
 {
-	unsigned int *address = (void *)U8500_BOOTROM_BASE
-				+ U8500_BOOTROM_ASIC_ID_OFFSET;
-	return readl(address);
+	unsigned int val;
+
+	/* Main ID register (MIDR) */
+	asm("mrc        p15, 0, %0, c0, c0, 0"
+	   : "=r" (val)
+	   :
+	   : "cc");
+
+	return val;
 }
 
 static int cpu_is_u8500v11(void)
@@ -53,6 +61,18 @@  static int cpu_is_u8500v2(void)
 	return read_cpuid() == CPUID_DB8500V2;
 }
 
+static unsigned int read_asicid(void)
+{
+	unsigned int *address;
+
+	if (cpu_is_u8500v2())
+		address = (void *) U8500_ASIC_ID_LOC_V2;
+	else
+		address = (void *) U8500_ASIC_ID_LOC_ED_V1;
+
+	return readl(address);
+}
+
 #ifdef CONFIG_ARCH_CPU_INIT
 /*
  * SOC specific cpu init
@@ -68,22 +88,22 @@  int arch_cpu_init(void)
 
 #ifdef CONFIG_MMC
 
-#define LDO_VAUX3_MASK		0x3
-#define LDO_VAUX3_ENABLE	0x1
-#define VAUX3_VOLTAGE_2_9V	0xd
-
-#define AB8500_REGU_CTRL2	0x4
-#define AB8500_REGU_VRF1VAUX3_REGU_REG	0x040A
-#define AB8500_REGU_VRF1VAUX3_SEL_REG	0x0421
-
 int u8500_mmc_power_init(void)
 {
 	int ret;
-	int val;
+	int enable, voltage;
+	int ab8500_revision;
 
-	if (!cpu_is_u8500v11())
+	if (!cpu_is_u8500v11() && !cpu_is_u8500v2())
 		return 0;
 
+	/* Get AB8500 revision */
+	ret = ab8500_read(AB8500_MISC, AB8500_REV_REG);
+	if (ret < 0)
+		goto out;
+
+	ab8500_revision = ret;
+
 	/*
 	 * On v1.1 HREF boards (HREF+), Vaux3 needs to be enabled for the SD
 	 * card to work.  This is done by enabling the regulators in the AB8500
@@ -95,33 +115,50 @@  int u8500_mmc_power_init(void)
 	 * Turn off and delay is required to have it work across soft reboots.
 	 */
 
-	ret = prcmu_i2c_read(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_REGU_REG);
+	/* Turn off (read-modify-write) */
+	ret = ab8500_read(AB8500_REGU_CTRL2,
+				AB8500_REGU_VRF1VAUX3_REGU_REG);
 	if (ret < 0)
 		goto out;
 
-	val = ret;
+	enable = ret;
 
 	/* Turn off */
-	ret = prcmu_i2c_write(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_REGU_REG,
-							val & ~LDO_VAUX3_MASK);
+	ret = ab8500_write(AB8500_REGU_CTRL2,
+			AB8500_REGU_VRF1VAUX3_REGU_REG,
+			enable & ~LDO_VAUX3_ENABLE_MASK);
 	if (ret < 0)
 		goto out;
 
 	udelay(10 * 1000);
 
-	/* Set the voltage to 2.9V */
-	ret = prcmu_i2c_write(AB8500_REGU_CTRL2,
-				AB8500_REGU_VRF1VAUX3_SEL_REG,
-				VAUX3_VOLTAGE_2_9V);
+	/* Set the voltage to 2.91 V or 2.9 V without overriding VRF1 value */
+	ret = ab8500_read(AB8500_REGU_CTRL2,
+			AB8500_REGU_VRF1VAUX3_SEL_REG);
 	if (ret < 0)
 		goto out;
 
-	val = val & ~LDO_VAUX3_MASK;
-	val = val | LDO_VAUX3_ENABLE;
+	voltage = ret;
+
+	if (ab8500_revision < 0x20) {
+		voltage &= ~LDO_VAUX3_SEL_MASK;
+		voltage |= LDO_VAUX3_SEL_2V9;
+	} else {
+		voltage &= ~LDO_VAUX3_V2_SEL_MASK;
+		voltage |= LDO_VAUX3_V2_SEL_2V91;
+	}
+
+	ret = ab8500_write(AB8500_REGU_CTRL2,
+			AB8500_REGU_VRF1VAUX3_SEL_REG, voltage);
+	if (ret < 0)
+		goto out;
 
 	/* Turn on the supply */
-	ret = prcmu_i2c_write(AB8500_REGU_CTRL2,
-				AB8500_REGU_VRF1VAUX3_REGU_REG, val);
+	enable &= ~LDO_VAUX3_ENABLE_MASK;
+	enable |= LDO_VAUX3_ENABLE_VAL;
+
+	ret = ab8500_write(AB8500_REGU_CTRL2,
+			AB8500_REGU_VRF1VAUX3_REGU_REG, enable);
 
 out:
 	return ret;
diff --git a/arch/arm/include/asm/arch-u8500/hardware.h b/arch/arm/include/asm/arch-u8500/hardware.h
index 8044ac3..ee03419 100644
--- a/arch/arm/include/asm/arch-u8500/hardware.h
+++ b/arch/arm/include/asm/arch-u8500/hardware.h
@@ -77,11 +77,21 @@ 
 #define U8500_CLKRST1_BASE	(U8500_PER1_BASE + 0xf000)
 
 /* Last page of Boot ROM */
-#define U8500_BOOTROM_BASE      0x9001f000
-#define U8500_BOOTROM_ASIC_ID_OFFSET    0x0ff4
+#define U8500_BOOTROM_BASE      0x90000000
+#define U8500_ASIC_ID_LOC_ED_V1 (U8500_BOOTROM_BASE + 0x1FFF4)
+#define U8500_ASIC_ID_LOC_V2    (U8500_BOOTROM_BASE + 0x1DBF4)
 
 /* AB8500 specifics */
+
+/* address bank */
+#define AB8500_REGU_CTRL2	0x0004
 #define AB8500_MISC		0x0010
+
+/* registers */
+#define AB8500_REGU_VRF1VAUX3_REGU_REG	0x040A
+#define AB8500_REGU_VRF1VAUX3_SEL_REG	0x0421
+#define AB8500_REV_REG			0x1080
+
 #define AB8500_GPIO_SEL2_REG	0x1001
 #define AB8500_GPIO_DIR2_REG	0x1011
 #define AB8500_GPIO_DIR4_REG	0x1013
@@ -89,4 +99,12 @@ 
 #define AB8500_GPIO_OUT2_REG	0x1021
 #define AB8500_GPIO_OUT4_REG	0x1023
 
+#define LDO_VAUX3_ENABLE_MASK	0x3
+#define LDO_VAUX3_ENABLE_VAL	0x1
+#define LDO_VAUX3_SEL_MASK	0xf
+#define LDO_VAUX3_SEL_2V9	0xd
+#define LDO_VAUX3_V2_SEL_MASK	0x7
+#define LDO_VAUX3_V2_SEL_2V91	0x7
+
+
 #endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/board/st-ericsson/snowball/snowball.c b/board/st-ericsson/snowball/snowball.c
index bc95c50..2c01bc1 100644
--- a/board/st-ericsson/snowball/snowball.c
+++ b/board/st-ericsson/snowball/snowball.c
@@ -27,6 +27,7 @@ 
 #include <asm/arch/db8500_pincfg.h>
 #include <asm/arch/prcmu.h>
 #include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
 
 #include "db8500_pins.h"
 
@@ -268,5 +269,9 @@  int board_late_init(void)
 	if ((raise_ab8500_gpio16() < 0))
 		printf("error: cant' raise GPIO16\n");
 
+#ifdef CONFIG_MMC
+	u8500_mmc_power_init();
+#endif /* CONFIG_MMC */
+
 	return 0;
 }