#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>
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,
* 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 {
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) +
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);
+
* 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
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
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
orr r6, r6, #0x1
str r6, [r3, #0x150]
+leave_2p5_on:
b do_wfi
do_audio_arm_clk:
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
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
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
nop
- pop {r4-r11}
+ pop {r4-r12}
/* Restore registers */
mov pc, lr