summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorBai Ping <b51503@freescale.com>2015-01-30 18:56:40 +0800
committerBai Ping <b51503@freescale.com>2015-02-03 02:05:55 +0800
commita0bd5ae4e401a3363f7d63bccb5b22dafb64b9d6 (patch)
tree9924cbd9b97eda58b5aa46266125b80bd90b9fde /arch/arm/mach-imx
parent2e6207e3506c5b270d21c3763e0eaa77b6ac55cb (diff)
MLK-10188 arm: imx: Add dummy LDO2p5 regulator for 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 is copied from commit 7d849e4d9ebca3c as code the structure has changed too many. directly cherry-pick has too many conflicts to resolve Signed-off-by: Bai Ping <b51503@freescale.com>
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sl.c87
-rw-r--r--arch/arm/mach-imx/imx6sl_lpm_wfi.S11
2 files changed, 96 insertions, 2 deletions
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
index c05f0b0e3ea0..ee1550060948 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sl.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -8,6 +8,10 @@
#include <linux/cpuidle.h>
#include <linux/module.h>
+#include <linux/platform_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/proc-fns.h>
@@ -45,15 +49,25 @@ static const u32 imx6sl_mmdc_io_offset[] __initconst = {
0x330, 0x334, 0x320, /*SDCKE0, SDCK1, RESET */
};
+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;
+
static void (*imx6sl_wfi_in_iram_fn)(void __iomem *iram_vbase,
- int audio_mode);
+ int audio_mode, bool vbus_ldo);
static int imx6sl_enter_wait(struct cpuidle_device *dev,
struct cpuidle_driver *drv, int index)
{
imx6q_set_lpm(WAIT_UNCLOCKED);
if (audio_bus_freq_mode || ultra_low_bus_freq_mode) {
- imx6sl_wfi_in_iram_fn(wfi_iram_base, audio_bus_freq_mode);
+ imx6sl_wfi_in_iram_fn(wfi_iram_base, audio_bus_freq_mode,
+ regulator_is_enabled(vbus_ldo));
} else {
/*
* Software workaround for ERR005311, see function
@@ -96,6 +110,10 @@ int __init imx6sl_cpuidle_init(void)
const u32 *mmdc_offset_array;
u32 wfi_code_size;
+ vbus_ldo = regulator_get(NULL, "ldo2p5-dummy");
+ if (IS_ERR(vbus_ldo))
+ vbus_ldo = NULL;
+
wfi_iram_base = (void *)(iram_tlb_base_addr + MX6_CPUIDLE_IRAM_ADDR_OFFSET);
/* Make sure wif_iram_base is 8 byte aligned. */
@@ -124,3 +142,68 @@ 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(ofm, 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_lpm_wfi.S b/arch/arm/mach-imx/imx6sl_lpm_wfi.S
index c10dbd565cbb..439556f7a243 100644
--- a/arch/arm/mach-imx/imx6sl_lpm_wfi.S
+++ b/arch/arm/mach-imx/imx6sl_lpm_wfi.S
@@ -292,6 +292,13 @@ check_done:
orr r6, r6, #0xc000
str r6, [r10, #0x150]
+ /*
+ * if the usb VBUS wakeup is enabled, skip
+ * disable main 2p5.
+ */
+ cmp r2, #0x1
+ beq anatop_enter_done
+
/* Enable the week 2p5 */
ldr r6, [r10, #0x130]
orr r6, r6, #0x40000
@@ -350,6 +357,8 @@ anatop_enter_done:
cmp r4, #0x0
beq skip_anatop_restore
+ cmp r2, #0x1
+ beq ldo2p5_not_disabled
/*
* Regular bandgap will not be disabled
* in LDO-enabled mode as it is required
@@ -407,6 +416,7 @@ skip_bandgap_restore:
bic r6, r6, #0x40000
str r6, [r10, #0x130]
+ldo2p5_not_disabled:
/*
* Set the OSC bias current to max
* value for normal operation.
@@ -618,6 +628,7 @@ poll_dvfs_set:
* imx6sl_low_power_wfi code
* r0: wfi code base address
* r1: audio_bus_freq mode stat
+ * r2: vbus_ldo status
* r4: used for store the PLLs state
* r11: used for saving the ARM_PODF origin value
* r12: used for saving AHB_PODF origin value