summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRanjani Vaidyanathan <Ranjani.Vaidyanathan@freescale.com>2014-03-04 15:31:59 -0600
committerRanjani Vaidyanathan <Ranjani.Vaidyanathan@freescale.com>2014-03-05 16:48:39 -0600
commit85012e446fbe78f7c9af118fe25a62cf97a5d2f9 (patch)
tree7b09657fa935fb2a33c74ee6f0c44d92fd26175c /arch
parent04c1d380f64f4cacb6f4be6add3874860ca5eb31 (diff)
ENGR00299939-2 ARM: imx6sl: Add dummy LDO2p5 regulator to support VBUS wakeup
LDO2p5 cannot be disabled in low power idle mode when the USB driver enables VBUS wakeup. To identify when LDO2p5 can be disabled add a dummy regulator that the USB driver will enable when VBUS wakeup is required. This patch ensures that the low power idle code checks the status of the dummy ldo2p5 regulator before disabling LDO2p5. Signed-off-by: Ranjani Vaidyanathan <Ranjani.Vaidyanathan@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sl.c90
-rw-r--r--arch/arm/mach-imx/imx6sl_wfi.S49
2 files changed, 118 insertions, 21 deletions
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
index 6b98392d10e8..573a4076da6d 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sl.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -12,6 +12,9 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
#include <asm/cpuidle.h>
#include <asm/fncpy.h>
#include <asm/mach/map.h>
@@ -32,9 +35,18 @@ extern void restore_ttbr1(unsigned long ttbr1);
static void __iomem *iomux_base;
static void *wfi_iram_base;
+static struct regulator *vbus_ldo;
+
+static struct regulator_dev *ldo2p5_dummy_regulator_rdev;
+static struct regulator_init_data ldo2p5_dummy_initdata = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+};
+static int ldo2p5_dummy_enable;
void (*imx6sl_wfi_in_iram_fn)(void *wfi_iram_base,
- void *iomux_addr, u32 audio_mode) = NULL;
+ bool vbus_ldo, u32 audio_mode) = NULL;
static int imx6sl_enter_wait(struct cpuidle_device *dev,
@@ -49,7 +61,7 @@ static int imx6sl_enter_wait(struct cpuidle_device *dev,
* Also float DDR IO pads.
*/
ttbr1 = save_ttbr1();
- imx6sl_wfi_in_iram_fn(wfi_iram_base, iomux_base,
+ imx6sl_wfi_in_iram_fn(wfi_iram_base, regulator_is_enabled(vbus_ldo),
audio_bus_freq_mode);
restore_ttbr1(ttbr1);
} else {
@@ -96,6 +108,10 @@ int __init imx6sl_cpuidle_init(void)
iomux_base = of_iomap(node, 0);
WARN(!iomux_base, "unable to map iomux registers\n");
+ vbus_ldo = regulator_get(NULL, "ldo2p5-dummy");
+ if (IS_ERR(vbus_ldo))
+ vbus_ldo = NULL;
+
iram_paddr = MX6SL_WFI_IRAM_ADDR;
/* Calculate the virtual address of the code */
wfi_iram_base = (void *)IMX_IO_P2V(MX6Q_IRAM_TLB_BASE_ADDR) +
@@ -106,3 +122,73 @@ int __init imx6sl_cpuidle_init(void)
return cpuidle_register(&imx6sl_cpuidle_driver, NULL);
}
+
+static int imx_ldo2p5_dummy_enable(struct regulator_dev *rdev)
+{
+ ldo2p5_dummy_enable = 1;
+
+ return 0;
+}
+
+static int imx_ldo2p5_dummy_disable(struct regulator_dev *rdev)
+{
+ ldo2p5_dummy_enable = 0;
+
+ return 0;
+}
+
+static int imx_ldo2p5_dummy_is_enable(struct regulator_dev *rdev)
+{
+ return ldo2p5_dummy_enable;
+}
+
+
+static struct regulator_ops ldo2p5_dummy_ops = {
+ .enable = imx_ldo2p5_dummy_enable,
+ .disable = imx_ldo2p5_dummy_disable,
+ .is_enabled = imx_ldo2p5_dummy_is_enable,
+};
+
+static struct regulator_desc ldo2p5_dummy_desc = {
+ .name = "ldo2p5-dummy",
+ .id = -1,
+ .type = REGULATOR_VOLTAGE,
+ .owner = THIS_MODULE,
+ .ops = &ldo2p5_dummy_ops,
+};
+
+static int ldo2p5_dummy_probe(struct platform_device *pdev)
+{
+ struct regulator_config config = { };
+ int ret;
+
+ config.dev = &pdev->dev;
+ config.init_data = &ldo2p5_dummy_initdata;
+ config.of_node = pdev->dev.of_node;
+
+ ldo2p5_dummy_regulator_rdev = regulator_register(&ldo2p5_dummy_desc, &config);
+ if (IS_ERR(ldo2p5_dummy_regulator_rdev)) {
+ ret = PTR_ERR(ldo2p5_dummy_regulator_rdev);
+ dev_err(&pdev->dev, "Failed to register dummy ldo2p5 regulator: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id imx_ldo2p5_dummy_ids[] = {
+ { .compatible = "fsl,imx6-dummy-ldo2p5" },
+};
+MODULE_DEVICE_TABLE(of, imx_ldo2p5_dummy_ids);
+
+static struct platform_driver ldo2p5_dummy_driver = {
+ .probe = ldo2p5_dummy_probe,
+ .driver = {
+ .name = "ldo2p5-dummy",
+ .owner = THIS_MODULE,
+ .of_match_table = imx_ldo2p5_dummy_ids,
+ },
+};
+
+module_platform_driver(ldo2p5_dummy_driver);
+
diff --git a/arch/arm/mach-imx/imx6sl_wfi.S b/arch/arm/mach-imx/imx6sl_wfi.S
index 20afe0256f5f..f8556e67631e 100644
--- a/arch/arm/mach-imx/imx6sl_wfi.S
+++ b/arch/arm/mach-imx/imx6sl_wfi.S
@@ -155,15 +155,17 @@ fifo_reset2_wait:
* Make sure DDR is in self-refresh.
* IRQs are already disabled.
* r0: WFI IRAMcode base address.
- * r1: IOMUX base address
+ * r1: 1 if vbus_ldo (ldo2p5) cannot be disabled
* r2: 1 if in audio_bus_freq_mode
*/
.align 3
ENTRY(imx6sl_low_power_wfi)
- push {r4-r11}
+ push {r4-r12}
mx6sl_lpm_wfi:
+ /* Can LDO2p5 be disabled */
+ mov r12, r1
/* Store audio_bus_freq_mode */
mov r11, r2
@@ -402,6 +404,17 @@ podf_loop:
bic r6, r6, #0x2
str r6, [r3, #0x110]
+ /*
+ * Set the OSC bias current to -37.5%
+ * to drop the power on VDDHIGH.
+ */
+ ldr r6, [r3, #0x150]
+ orr r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+ cmp r12, #0x1
+ beq leave_2p5_on
+
/* Enable the weak 2P5 */
ldr r6, [r3, #0x130]
orr r6, r6, #0x40000
@@ -412,14 +425,6 @@ podf_loop:
bic r6, r6, #0x1
str r6, [r3, #0x130]
- /*
- * Set the OSC bias current to -37.5%
- * to drop the power on VDDHIGH.
- */
- ldr r6, [r3, #0x150]
- orr r6, r6, #0xC000
- str r6, [r3, #0x150]
-
/* Enable low power bandgap */
ldr r6, [r3, #0x260]
orr r6, r6, #0x20
@@ -448,6 +453,7 @@ podf_loop:
orr r6, r6, #0x1
str r6, [r3, #0x150]
+leave_2p5_on:
b do_wfi
do_audio_arm_clk:
@@ -497,6 +503,9 @@ podf_loop1:
cmp r7, #0x1
bne skip_analog_restore
+ cmp r12, #1
+ beq ldo2p5_not_disabled
+
/* Power up the regular bandgap. */
ldr r6, [r3, #0x150]
bic r6, r6, #0x1
@@ -515,14 +524,6 @@ podf_loop1:
bic r6, r6, #0x20
str r6, [r3, #0x260]
- /*
- * Set the OSC bias current to max
- * value for normal operation.
- */
- ldr r6, [r3, #0x150]
- bic r6, r6, #0xC000
- str r6, [r3, #0x150]
-
/* Enable main 2p5. */
ldr r6, [r3, #0x130]
orr r6, r6, #0x1
@@ -540,6 +541,16 @@ loop_2p5:
bic r6, r6, #0x40000
str r6, [r3, #0x130]
+ldo2p5_not_disabled:
+ /*
+ * Set the OSC bias current to max
+ * value for normal operation.
+ */
+ ldr r6, [r3, #0x150]
+ bic r6, r6, #0xC000
+ str r6, [r3, #0x150]
+
+
/* Enable 1p1 brown out. */
ldr r6, [r3, #0x110]
orr r6, r6, #0x2
@@ -683,7 +694,7 @@ poll_dvfs_clear_1:
nop
- pop {r4-r11}
+ pop {r4-r12}
/* Restore registers */
mov pc, lr