]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
MLK-10188 arm: imx: Add dummy LDO2p5 regulator for VBUS wakeup
authorBai Ping <b51503@freescale.com>
Fri, 30 Jan 2015 10:56:40 +0000 (18:56 +0800)
committerBai Ping <b51503@freescale.com>
Mon, 2 Feb 2015 18:05:55 +0000 (02:05 +0800)
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>
arch/arm/boot/dts/imx6sl.dtsi
arch/arm/mach-imx/cpuidle-imx6sl.c
arch/arm/mach-imx/imx6sl_lpm_wfi.S

index 1c3fa3581f6ee5d0646a5d519b5c3887dba3ffa1..323754f7cbfe0db39327b57bbfc9dd826164d74b 100644 (file)
                };
        };
 
+       reg_vbus_wakeup: usb_vbus_wakeup {
+               compatible = "fsl,imx6-dummy-ldo2p5";
+       };
+
        soc {
                #address-cells = <1>;
                #size-cells = <1>;
                                compatible = "fsl,imx6sl-usbmisc", "fsl,imx6q-usbmisc";
                                reg = <0x02184800 0x200>;
                                clocks = <&clks IMX6SL_CLK_USBOH3>;
+                               vbus-wakeup-supply = <&reg_vbus_wakeup>;
                        };
 
                        fec: ethernet@02188000 {
index c05f0b0e3ea049986ca7e04bb9c7026a01a3bf61..ee1550060948a8a3b15ca0693ca0c5867c65b91c 100644 (file)
@@ -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);
index c10dbd565cbb37ed6fc4b9fbf82889588ecacd27..439556f7a24373cf5509171267e2f4883b201783 100644 (file)
@@ -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