]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00139274-1 [MX6]Enable suspend/resume feature
authorAnson Huang <b20788@freescale.com>
Mon, 18 Jul 2011 04:54:13 +0000 (12:54 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:09:19 +0000 (14:09 +0200)
Enable suspend/resume feature for MX6q

echo standby > /sys/power/state -> wait mode;
echo mem > /sys/power/state -> stop mode;

Currentlu only support debug uart as wakeup source;

Signed-off-by: Anson Huang <b20788@freescale.com>
16 files changed:
arch/arm/mach-mx6/Kconfig
arch/arm/mach-mx6/Makefile
arch/arm/mach-mx6/board-mx6q_sabreauto.c
arch/arm/mach-mx6/cpu.c
arch/arm/mach-mx6/devices-imx6q.h
arch/arm/mach-mx6/devices.c
arch/arm/mach-mx6/mx6q_suspend.S [new file with mode: 0644]
arch/arm/mach-mx6/plat_hotplug.c
arch/arm/mach-mx6/platsmp.c
arch/arm/mach-mx6/pm.c [new file with mode: 0644]
arch/arm/mach-mx6/system.c
arch/arm/plat-mxc/devices/Kconfig
arch/arm/plat-mxc/devices/Makefile
arch/arm/plat-mxc/devices/platform-imx-pm.c [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/devices-common.h
arch/arm/plat-mxc/include/mach/imx-pm.h [new file with mode: 0644]

index 265439983cb0515060b88e12fe8c8d2e5a677beb..5619c7eb1794c5a6dce8c0a7cdc4884a6623c088 100644 (file)
@@ -39,6 +39,7 @@ config MACH_MX6Q_SABREAUTO
        select IMX_HAVE_PLATFORM_IMX_OCOTP
        select IMX_HAVE_PLATFORM_IMX2_WDT
        select IMX_HAVE_PLATFORM_IMX_SNVS_RTC
+       select IMX_HAVE_PLATFORM_IMX_PM
        help
          Include support for i.MX 6Quad SABRE Automotive Infotainment platform. This includes specific
          configurations for the board and its peripherals.
index 99b5623f3fad78e338043e037ec734086317ab57..094b2cfd77736251b70dd9495c4f406eee52abb1 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h1.o
+obj-y   := cpu.o mm.o system.o devices.o dummy_gpio.o irq.o bus_freq.o usb_dr.o usb_h1.o pm.o
 
-obj-$(CONFIG_ARCH_MX6) += clock.o
+obj-$(CONFIG_ARCH_MX6) += clock.o mx6q_suspend.o
 obj-$(CONFIG_MACH_MX6Q_SABREAUTO) += board-mx6q_sabreauto.o
 obj-$(CONFIG_SMP) += plat_hotplug.o platsmp.o headsmp.o localtimer.o
index 0b1e967b8802a2b4a8d40894b5658501ef0bc49e..4bba7a49b0ff5346a521b3001f4fd8c5993b4a0e 100644 (file)
@@ -505,6 +505,20 @@ static struct imx_ipuv3_platform_data ipu_data[] = {
        },
 };
 
+static void sabreauto_suspend_enter(void)
+{
+       /* suspend preparation */
+}
+
+static void sabreauto_suspend_exit(void)
+{
+       /* resmue resore */
+}
+static const struct pm_platform_data mx6q_sabreauto_pm_data __initconst = {
+       .name = "imx_pm",
+       .suspend_enter = sabreauto_suspend_enter,
+       .suspend_exit = sabreauto_suspend_exit,
+};
 /*!
  * Board specific initialization.
  */
@@ -537,6 +551,7 @@ static void __init mx6_board_init(void)
        imx6q_add_anatop_thermal_imx(1, &mx6q_sabreauto_anatop_thermal_data);
        imx6q_init_fec();
 
+       imx6q_add_pm_imx(0, &mx6q_sabreauto_pm_data);
        imx6q_add_sdhci_usdhc_imx(3, &mx6q_sabreauto_sd4_data);
        imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabreauto_sd3_data);
        imx_add_viv_gpu("gc2000", &imx6_gc2000_data, &imx6q_gc2000_pdata);
index 685646793dbcd68d0d40a3cea490d3b8d715cace..f0e1d77d35ced6401474e9431ca8675020fc07f7 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/module.h>
+#include <linux/iram_alloc.h>
 #include <mach/hardware.h>
 #include <linux/iram_alloc.h>
 #include <asm/io.h>
index fe408c60c0d437cb0d64770bf1ebeff56b58efda..488ae599759ec76fb1a35699eda8d61d7bebb662 100644 (file)
@@ -111,3 +111,7 @@ extern const struct imx_otp_data imx6q_otp_data __initconst;
 extern const struct imx_imx2_wdt_data imx6q_imx2_wdt_data[] __initconst;
 #define imx6q_add_imx2_wdt(id, pdata)   \
        imx_add_imx2_wdt(&imx6q_imx2_wdt_data[id])
+
+extern const struct imx_pm_imx_data imx6q_pm_imx_data __initconst;
+#define imx6q_add_pm_imx(id, pdata)    \
+       imx_add_pm_imx(&imx6q_pm_imx_data, pdata)
index f40b5a4d7456130bf8ed0502ba7e977c127bed79..996de31d49338fe73982777d0b430167870e59fb 100644 (file)
 #include <mach/hardware.h>
 #include <mach/gpio.h>
 
-static struct resource mxc_anatop_resources[] = {
-       {
-               .start = ANATOP_BASE_ADDR,
-               .end = ANATOP_BASE_ADDR + SZ_4K - 1,
-               .flags = IORESOURCE_MEM,
-       },
-       {
-               .start = MXC_INT_ANATOP_TEMPSNSR,
-               .end = MXC_INT_ANATOP_TEMPSNSR,
-               .flags = IORESOURCE_IRQ,
-       },
-};
-
-struct platform_device anatop_thermal_device = {
-       .name = "anatop_thermal",
-       .id = 1,
-       .num_resources = ARRAY_SIZE(mxc_anatop_resources),
-       .resource = mxc_anatop_resources,
-};
-
-
 static struct mxc_gpio_port mxc_gpio_ports[] = {
        {
                .chip.label = "gpio-0",
diff --git a/arch/arm/mach-mx6/mx6q_suspend.S b/arch/arm/mach-mx6/mx6q_suspend.S
new file mode 100644 (file)
index 0000000..d39ff7c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/linkage.h>
+
+#define ARM_CTRL_DCACHE     1 << 2
+#define ARM_CTRL_ICACHE     1 << 12
+#define ARM_AUXCR_L2EN      1 << 1
+
+/*
+ *  mx6q_suspend
+ *
+ *  Suspend the processor (eg, wait for interrupt).
+ *  Set the DDR into Self Refresh
+ *  IRQs are already disabled.
+ */
+ENTRY(mx6q_suspend)
+       stmfd   sp!, {r0-r4}     @ Save registers
+       dsb
+       wfi
+       ldmfd   sp!, {r0-r4}
+       .type   mx6q_do_suspend, #object
+ENTRY(mx6q_do_suspend)
+       .word   mx6q_suspend
+       .size   mx6q_suspend, . - mx6q_suspend
index a0d94908765cca4711c268ed3336b9ac6dc67274..6ef057f6865ab36aaa303bf5313d46add848e38c 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <linux/io.h>
+#include "src-reg.h"
+#include <linux/sched.h>
 #include <asm/cacheflush.h>
 
 
@@ -34,7 +38,30 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
+       void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
+       unsigned int val;
+
+       if (cpu == 0) {
+               printk(KERN_ERR "CPU0 can't be disabled!\n");
+               return;
+       }
+       flush_cache_all();
+       dsb();
+
+       /*
+        * we're ready for shutdown now, so do it
+        */
+       val = readl(src_base + SRC_SCR_OFFSET);
+       val &= ~(1 << (BP_SRC_SCR_CORES_DBG_RST + cpu));
+       writel(val, src_base + SRC_SCR_OFFSET);
 
+       for (;;) {
+               /*
+                * Execute WFI
+                */
+               cpu_do_idle();
+               printk(KERN_INFO "CPU%u: spurious wakeup call\n", cpu);
+       }
 }
 
 int platform_cpu_disable(unsigned int cpu)
index a49e3cca3cc4c9ba0ca3312dd3e7318541ddf01d..66ab4e60dfe267eb44e832ab3892b293a4190cf2 100644 (file)
@@ -61,7 +61,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        unsigned long boot_entry;
        void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
-       unsigned long timeout;
        int val;
 
         /*
diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c
new file mode 100644 (file)
index 0000000..0d30bdf
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ *  Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+#include <linux/regulator/machine.h>
+#include <linux/proc_fs.h>
+#include <linux/iram_alloc.h>
+#include <linux/fsl_devices.h>
+#include <asm/mach-types.h>
+#include <asm/cacheflush.h>
+#include <asm/tlb.h>
+#include <asm/delay.h>
+#include <asm/mach/map.h>
+#include <mach/hardware.h>
+#include <mach/imx-pm.h>
+#ifdef CONFIG_ARCH_MX61
+#include <mach/iomux-mx6q.h>
+#endif
+#include "crm_regs.h"
+
+#define SCU_CTRL_OFFSET                0x00
+#define GPC_IMR1_OFFSET                0x08
+#define GPC_IMR2_OFFSET                0x0c
+#define GPC_IMR3_OFFSET                0x10
+#define GPC_IMR4_OFFSET                0x14
+#define GPC_PGC_CPU_PUPSCR_OFFSET      0x2a4
+#define GPC_PGC_CPU_PDNSCR_OFFSET      0x2a8
+#define UART_UCR3_OFFSET               0x88
+#define UART_USR1_OFFSET               0x94
+#define UART_UCR3_AWAKEN               (1 << 4)
+#define UART_USR1_AWAKE                        (1 << 4)
+static struct clk *cpu_clk;
+static struct pm_platform_data *pm_data;
+
+#if defined(CONFIG_CPU_FREQ)
+static int org_freq;
+extern int set_cpu_freq(int wp);
+#endif
+
+extern void mx6q_suspend(u32 m4if_addr);
+static struct device *pm_dev;
+struct clk *gpc_dvfs_clk;
+void *suspend_iram_base;
+void (*suspend_in_iram)(void *sdclk_iomux_addr) = NULL;
+void __iomem *suspend_param1;
+
+static void __iomem *scu_base;
+static void __iomem *gpc_base;
+static u32 ccm_clpcr, scu_ctrl;
+static u32 gpc_imr[4], gpc_cpu_pup, gpc_cpu_pdn;
+
+static void mx6_suspend_store()
+{
+       /* save some settings before suspend */
+       ccm_clpcr = __raw_readl(MXC_CCM_CLPCR);
+       scu_ctrl = __raw_readl(scu_base + SCU_CTRL_OFFSET);
+       gpc_imr[0] = __raw_readl(gpc_base + GPC_IMR1_OFFSET);
+       gpc_imr[1] = __raw_readl(gpc_base + GPC_IMR2_OFFSET);
+       gpc_imr[2] = __raw_readl(gpc_base + GPC_IMR3_OFFSET);
+       gpc_imr[3] = __raw_readl(gpc_base + GPC_IMR4_OFFSET);
+       gpc_cpu_pup = __raw_readl(gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
+       gpc_cpu_pdn = __raw_readl(gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
+}
+
+static void mx6_suspend_restore()
+{
+       /* restore settings after suspend */
+       __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+       __raw_writel(scu_ctrl, scu_base + SCU_CTRL_OFFSET);
+       __raw_writel(gpc_imr[0], gpc_base + GPC_IMR1_OFFSET);
+       __raw_writel(gpc_imr[1], gpc_base + GPC_IMR2_OFFSET);
+       __raw_writel(gpc_imr[2], gpc_base + GPC_IMR3_OFFSET);
+       __raw_writel(gpc_imr[3], gpc_base + GPC_IMR4_OFFSET);
+       __raw_writel(gpc_cpu_pup, gpc_base + GPC_PGC_CPU_PUPSCR_OFFSET);
+       __raw_writel(gpc_cpu_pdn, gpc_base + GPC_PGC_CPU_PDNSCR_OFFSET);
+}
+static int mx6_suspend_enter(suspend_state_t state)
+{
+       mx6_suspend_store();
+
+       switch (state) {
+       case PM_SUSPEND_MEM:
+               mxc_cpu_lp_set(STOP_POWER_OFF);
+               break;
+       case PM_SUSPEND_STANDBY:
+               mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (state == PM_SUSPEND_MEM) {
+               if (pm_data && pm_data->suspend_enter)
+                       pm_data->suspend_enter();
+
+               local_flush_tlb_all();
+               flush_cache_all();
+               outer_cache.flush_all();
+
+               suspend_in_iram(suspend_param1);
+
+               mx6_suspend_restore();
+               if (pm_data && pm_data->suspend_exit)
+                       pm_data->suspend_exit();
+       } else {
+                       cpu_do_idle();
+       }
+       return 0;
+}
+
+
+/*
+ * Called after processes are frozen, but before we shut down devices.
+ */
+static int mx6_suspend_prepare(void)
+{
+       return 0;
+}
+
+/*
+ * Called before devices are re-setup.
+ */
+static void mx6_suspend_finish(void)
+{
+#if defined(CONFIG_CPU_FREQ)
+       struct cpufreq_freqs freqs;
+
+       freqs.old = clk_get_rate(cpu_clk) / 1000;
+       freqs.new = org_freq / 1000;
+       freqs.cpu = 0;
+       freqs.flags = 0;
+
+       if (org_freq != clk_get_rate(cpu_clk)) {
+               set_cpu_freq(org_freq);
+               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+       }
+#endif
+}
+
+/*
+ * Called after devices are re-setup, but before processes are thawed.
+ */
+static void mx6_suspend_end(void)
+{
+}
+
+static int mx6_pm_valid(suspend_state_t state)
+{
+       return (state > PM_SUSPEND_ON && state <= PM_SUSPEND_MAX);
+}
+
+struct platform_suspend_ops mx6_suspend_ops = {
+       .valid = mx6_pm_valid,
+       .prepare = mx6_suspend_prepare,
+       .enter = mx6_suspend_enter,
+       .finish = mx6_suspend_finish,
+       .end = mx6_suspend_end,
+};
+
+static int __devinit mx6_pm_probe(struct platform_device *pdev)
+{
+       pm_dev = &pdev->dev;
+       pm_data = pdev->dev.platform_data;
+
+       return 0;
+}
+
+static struct platform_driver mx6_pm_driver = {
+       .driver = {
+                  .name = "imx_pm",
+                  },
+       .probe = mx6_pm_probe,
+};
+
+static int __init pm_init(void)
+{
+       unsigned long iram_paddr, cpaddr;
+
+       scu_base = IO_ADDRESS(SCU_BASE_ADDR);
+       gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+
+       pr_info("Static Power Management for Freescale i.MX6\n");
+
+       if (platform_driver_register(&mx6_pm_driver) != 0) {
+               printk(KERN_ERR "mx6_pm_driver register failed\n");
+               return -ENODEV;
+       }
+
+       suspend_set_ops(&mx6_suspend_ops);
+       /* Move suspend routine into iRAM */
+       cpaddr = (unsigned long)iram_alloc(SZ_4K, &iram_paddr);
+       /* Need to remap the area here since we want the memory region
+                to be executable. */
+       suspend_iram_base = __arm_ioremap(iram_paddr, SZ_4K,
+                                         MT_HIGH_VECTORS);
+       pr_info("cpaddr = %x suspend_iram_base=%x\n",
+               (unsigned int)cpaddr, (unsigned int)suspend_iram_base);
+
+       /*
+        * Need to run the suspend code from IRAM as the DDR needs
+        * to be put into self refresh mode manually.
+        */
+       memcpy((void *)cpaddr, mx6q_suspend, SZ_4K);
+
+       suspend_in_iram = (void *)suspend_iram_base;
+
+       cpu_clk = clk_get(NULL, "cpu_clk");
+       if (IS_ERR(cpu_clk)) {
+               printk(KERN_DEBUG "%s: failed to get cpu_clk\n", __func__);
+               return PTR_ERR(cpu_clk);
+       }
+       printk(KERN_INFO "PM driver module loaded\n");
+
+       return 0;
+}
+
+
+static void __exit pm_cleanup(void)
+{
+       /* Unregister the device structure */
+       platform_driver_unregister(&mx6_pm_driver);
+}
+
+module_init(pm_init);
+module_exit(pm_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("PM driver");
+MODULE_LICENSE("GPL");
+
index ba4091e9d2856874611f2e25691804d5ccf019bb..f18389bf26da2a91dc381978e095a33f6c8aa1c4 100644 (file)
 #include <mach/clock.h>
 #include <asm/proc-fns.h>
 #include <asm/system.h>
+#include "crm_regs.h"
+
+#define SCU_CTRL               0x00
+#define SCU_CONFIG             0x04
+#define SCU_CPU_STATUS         0x08
+#define SCU_INVALIDATE         0x0c
+#define SCU_FPGA_REVISION      0x10
+
+void gpc_enable_wakeup(unsigned int irq)
+{
+       void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+
+       if ((irq < 32) || (irq > 158))
+               printk(KERN_ERR "Invalid irq number!\n");
+
+       /* Enable wake up source */
+       __raw_writel(~(1 << (irq % 32)),
+               gpc_base + 0x8 + (irq / 32 - 1) * 4);
+
+}
+/* set cpu low power mode before WFI instruction */
+void mxc_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+{
+       void __iomem *scu_base = IO_ADDRESS(SCU_BASE_ADDR);
+       void __iomem *gpc_base = IO_ADDRESS(GPC_BASE_ADDR);
+       u32 scu_cr, ccm_clpcr;
+       int stop_mode = 0;
+
+       scu_cr = __raw_readl(scu_base + SCU_CTRL);
+       ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+
+       switch (mode) {
+       case WAIT_CLOCKED:
+               break;
+       case WAIT_UNCLOCKED:
+               ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+               break;
+       case WAIT_UNCLOCKED_POWER_OFF:
+       case STOP_POWER_OFF:
+               if (mode == WAIT_UNCLOCKED_POWER_OFF) {
+                       ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+                       ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
+                       ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+                       stop_mode = 0;
+               } else {
+                       ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+                       ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
+                       ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+                       ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+                       ccm_clpcr |= MXC_CCM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+                       stop_mode = 1;
+               }
+               /* scu standby enable, scu clk will be
+                * off after all cpu enter WFI */
+               scu_cr |= 0x20;
+               break;
+       case STOP_POWER_ON:
+               ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+               break;
+       default:
+               printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+               return;
+       }
+
+       if (stop_mode == 1) {
+               /* Mask all wake up source */
+               __raw_writel(0xFFFFFFFF, gpc_base + 0x8);
+               __raw_writel(0xFFFFFFFF, gpc_base + 0xC);
+               __raw_writel(0xFFFFFFFF, gpc_base + 0x10);
+               __raw_writel(0xFFFFFFFF, gpc_base + 0x14);
+               /* Power down and power up sequence */
+               __raw_writel(0xFFFFFFFF, gpc_base + 0x2a4);
+               __raw_writel(0xFFFFFFFF, gpc_base + 0x2a8);
+
+               gpc_enable_wakeup(MXC_INT_UART4_ANDED);
+       }
+
+       __raw_writel(scu_cr, scu_base + SCU_CTRL);
+       __raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+}
 
 void arch_idle(void)
 {
index 1307a4aaf06b0dbbcb2635e6ff3c9d53f1e0a09e..7c0e691277b11ad7acdbc100e0e907bf600a35a8 100755 (executable)
@@ -145,3 +145,6 @@ config IMX_HAVE_PLATFORM_FSL_OTG
 
 config IMX_HAVE_PLATFORM_FSL_USB_WAKEUP
        bool
+
+config IMX_HAVE_PLATFORM_IMX_PM
+       bool
index 43db7417c1bd8e0567dcde0e967ac6d753e475cb..ff11fa946fee04c00d9a2f726a62b39099fdd764 100755 (executable)
@@ -50,3 +50,4 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_VIV_GPU) +=  platform-viv_gpu.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_ANATOP_THERMAL) += platform-imx-anatop-thermal.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_OTG) += platform-fsl-usb2-otg.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB_WAKEUP) += platform-fsl-usb2-wakeup.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_PM) += platform-imx-pm.o
diff --git a/arch/arm/plat-mxc/devices/platform-imx-pm.c b/arch/arm/plat-mxc/devices/platform-imx-pm.c
new file mode 100644 (file)
index 0000000..f901e18
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <asm/sizes.h>
+#include <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#define imx_pm_imx_data_entry_single(soc)              \
+       {                                       \
+       }
+
+#ifdef CONFIG_SOC_IMX6Q
+const struct imx_pm_imx_data imx6q_pm_imx_data[] __initconst =
+       imx_pm_imx_data_entry_single(MX6Q);
+#endif
+
+struct platform_device *__init imx_add_pm_imx(
+               const struct imx_pm_imx_data *data,
+               const struct pm_platform_data *pdata)
+{
+       struct resource res[] = {
+               {
+                       .start = data->iobase,
+                       .end = data->iobase + SZ_4K - 1,
+                       .flags = IORESOURCE_MEM,
+               },
+       };
+
+       return imx_add_platform_device("imx_pm", 0,
+                       res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
index b37e876fc8ec2532cb47d059ef6f43e1bdd896dc..213e05c446f915ae21f4d67888b35e7d9312ee39 100755 (executable)
@@ -503,6 +503,16 @@ struct imx_dcp_data {
        resource_size_t irq2;
 };
 
+
+#include <mach/imx-pm.h>
+struct imx_pm_imx_data {
+       int id;
+       resource_size_t iobase;
+       resource_size_t irq;
+};
+struct platform_device *__init imx_add_pm_imx(
+               const struct imx_pm_imx_data *data,
+               const struct pm_platform_data *pdata);
 struct platform_device *__init imx_add_dcp(
 
 struct imx_fsl_usb2_otg_data {
diff --git a/arch/arm/plat-mxc/include/mach/imx-pm.h b/arch/arm/plat-mxc/include/mach/imx-pm.h
new file mode 100644 (file)
index 0000000..f6d375a
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __ASM_ARCH_IMX_PM_H
+#define __ASM_ARCH_IMX_PM_H
+
+/**
+ * struct pm_platform_data - optional platform data for pm on i.MX
+ *
+ */
+
+struct pm_platform_data {
+       char *name;
+       void (*suspend_enter) (void);
+       void (*suspend_exit) (void);
+};
+#endif /* __ASM_ARCH_IMX_PM_H */