]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00232327 MX6SL-Optimize board level suspend power
authorRanjani Vaidyanathan <ra5478@freescale.com>
Fri, 2 Nov 2012 21:11:38 +0000 (16:11 -0500)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:39 +0000 (08:35 +0200)
Improve the board level suspend power by configuring
various IOMUX pads to low power state.

Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
arch/arm/mach-mx6/board-mx6sl_arm2.c
arch/arm/mach-mx6/board-mx6sl_common.h
arch/arm/mach-mx6/board-mx6sl_evk.c
arch/arm/mach-mx6/pm.c
arch/arm/plat-mxc/devices/platform-imx-pm.c
arch/arm/plat-mxc/include/mach/iomux-v3.h
arch/arm/plat-mxc/iomux-v3.c

index 477ea8c2b33e30596cff37e60ad731c157622447..a7f20edf524fc78f712ed17df440733fccdc731a 100755 (executable)
@@ -75,6 +75,8 @@
 static int spdc_sel;
 static int max17135_regulator_init(struct max17135 *max17135);
 static struct clk *extern_audio_root;
+static void mx6sl_suspend_enter(void);
+static void mx6sl_suspend_exit(void);
 
 extern char *gp_reg_id;
 extern char *soc_reg_id;
@@ -623,7 +625,6 @@ static inline void mx6_arm2_init_uart(void)
 static int mx6sl_arm2_fec_phy_init(struct phy_device *phydev)
 {
        int val;
-
        /* power on FEC phy and reset phy */
        gpio_request(MX6_BRD_FEC_PWR_EN, "fec-pwr");
        gpio_direction_output(MX6_BRD_FEC_PWR_EN, 0);
@@ -636,7 +637,6 @@ static int mx6sl_arm2_fec_phy_init(struct phy_device *phydev)
        if (val & BMCR_PDOWN) {
                phy_write(phydev, 0x0, (val & ~BMCR_PDOWN));
        }
-
        return 0;
 }
 
@@ -728,8 +728,6 @@ static void epdc_enable_pins(void)
 
 static void epdc_disable_pins(void)
 {
-       /* Configure MUX settings for EPDC pins to
-        * GPIO and drive to 0. */
        mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_epdc_disable_pads, \
                                ARRAY_SIZE(mx6sl_brd_epdc_disable_pads));
 
@@ -970,7 +968,7 @@ static void spdc_enable_pins(void)
 
 static void spdc_disable_pins(void)
 {
-       /* Configure MUX settings for SPDC pins to
+       /* Configure MUX settings for EPDC pins to
         * GPIO and drive to 0. */
        mxc_iomux_v3_setup_multiple_pads(mx6sl_brd_spdc_disable_pads, \
                                ARRAY_SIZE(mx6sl_brd_spdc_disable_pads));
@@ -1120,6 +1118,12 @@ static struct platform_device lcd_wvga_device = {
        .name = "lcd_seiko",
 };
 
+static const struct pm_platform_data mx6sl_arm2_pm_data __initconst = {
+       .name           = "imx_pm",
+       .suspend_enter = mx6sl_suspend_enter,
+       .suspend_exit = mx6sl_suspend_exit,
+};
+
 static int mx6sl_arm2_keymap[] = {
        KEY(0, 0, KEY_SELECT),
        KEY(0, 1, KEY_BACK),
@@ -1178,6 +1182,33 @@ static void mx6_snvs_poweroff(void)
        writel(value | 0x60, mx6_snvs_base + SNVS_LPCR);
 }
 
+static void mx6sl_suspend_enter()
+{
+       iomux_v3_cfg_t *p = suspend_enter_pads;
+       int i;
+
+       /* Set PADCTRL to 0 for all IOMUX. */
+       for (i = 0; i < ARRAY_SIZE(suspend_enter_pads); i++) {
+               suspend_exit_pads[i] = *p;
+               *p &= ~MUX_PAD_CTRL_MASK;
+               /* Enable the Pull down and the keeper
+                 * Set the drive strength to 0.
+                 */
+               *p |= ((u64)0x3000 << MUX_PAD_CTRL_SHIFT);
+               p++;
+       }
+       mxc_iomux_v3_get_multiple_pads(suspend_exit_pads,
+                       ARRAY_SIZE(suspend_exit_pads));
+       mxc_iomux_v3_setup_multiple_pads(suspend_enter_pads,
+                       ARRAY_SIZE(suspend_enter_pads));
+}
+
+static void mx6sl_suspend_exit()
+{
+       mxc_iomux_v3_setup_multiple_pads(suspend_exit_pads,
+                       ARRAY_SIZE(suspend_exit_pads));
+}
+
 /*!
  * Board specific initialization.
  */
@@ -1267,6 +1298,7 @@ static void __init mx6_arm2_init(void)
        imx6q_add_perfmon(0);
        imx6q_add_perfmon(1);
        imx6q_add_perfmon(2);
+       imx6q_add_pm_imx(0, &mx6sl_arm2_pm_data);
 
        pm_power_off = mx6_snvs_poweroff;
 }
index c432e0a661bab420b2230a2a6366bec44eb116f3..a6e5e909c6a907b1d7b88368aaa9d98bdc1fc483 100644 (file)
@@ -395,6 +395,110 @@ static iomux_v3_cfg_t mx6sl_brd_elan_pads[] = {
        MX6SL_PAD_KEY_COL6__GPIO_4_4,           /* RST */
 };
 
+static iomux_v3_cfg_t suspend_enter_pads[] = {
+       /* Audio pads. */
+       MX6SL_PAD_AUD_MCLK__GPIO_1_6,
+       MX6SL_PAD_AUD_RXC__GPIO_1_1,
+       MX6SL_PAD_AUD_RXD__GPIO_1_2,
+       MX6SL_PAD_AUD_RXFS__GPIO_1_0,
+       MX6SL_PAD_AUD_TXC__GPIO_1_3,
+       MX6SL_PAD_AUD_TXD__GPIO_1_5,
+       MX6SL_PAD_AUD_TXFS__GPIO_1_4,
+       /* ECSPI pads. */
+       MX6SL_PAD_ECSPI1_MISO__GPIO_4_10,
+       MX6SL_PAD_ECSPI1_MOSI__GPIO_4_9,
+       MX6SL_PAD_ECSPI1_SCLK__GPIO_4_8,
+       MX6SL_PAD_ECSPI1_SS0__GPIO_4_11,
+       MX6SL_PAD_ECSPI2_SCLK__GPIO_4_12,
+       /* FEC pad*/
+       MX6SL_PAD_FEC_CRS_DV__GPIO_4_25,
+       MX6SL_PAD_FEC_MDC__GPIO_4_23,
+       MX6SL_PAD_FEC_MDIO__GPIO_4_20,
+       MX6SL_PAD_FEC_REF_CLK__GPIO_4_26,
+       MX6SL_PAD_FEC_RXD0__GPIO_4_17,
+       MX6SL_PAD_FEC_RXD1__GPIO_4_18,
+       MX6SL_PAD_FEC_TXD0__GPIO_4_24,
+       MX6SL_PAD_FEC_TXD1__GPIO_4_16,
+       MX6SL_PAD_FEC_TX_CLK__GPIO_4_21,
+       MX6SL_PAD_FEC_TX_EN__GPIO_4_22,
+       /* I2C pads */
+       MX6SL_PAD_I2C1_SCL__GPIO_3_12,
+       MX6SL_PAD_I2C1_SDA__GPIO_3_13,
+       MX6SL_PAD_I2C2_SCL__GPIO_3_14,
+       MX6SL_PAD_I2C2_SDA__GPIO_3_15,
+       /* LCD pads*/
+       MX6SL_PAD_LCD_CLK__GPIO_2_15,
+       MX6SL_PAD_LCD_DAT0__GPIO_2_20,
+       MX6SL_PAD_LCD_DAT1__GPIO_2_21,
+       MX6SL_PAD_LCD_DAT2__GPIO_2_22,
+       MX6SL_PAD_LCD_DAT3__GPIO_2_23,
+       MX6SL_PAD_LCD_DAT4__GPIO_2_24,
+       MX6SL_PAD_LCD_DAT5__GPIO_2_25,
+       MX6SL_PAD_LCD_DAT10__GPIO_2_30,
+       MX6SL_PAD_LCD_DAT11__GPIO_2_31,
+       MX6SL_PAD_LCD_DAT12__GPIO_3_0,
+       MX6SL_PAD_LCD_DAT13__GPIO_3_1,
+       MX6SL_PAD_LCD_DAT14__GPIO_3_2,
+       MX6SL_PAD_LCD_DAT15__GPIO_3_3,
+       MX6SL_PAD_LCD_DAT16__GPIO_3_4,
+       MX6SL_PAD_LCD_DAT17__GPIO_3_5,
+       MX6SL_PAD_LCD_DAT18__GPIO_3_6,
+       MX6SL_PAD_LCD_DAT19__GPIO_3_7,
+       MX6SL_PAD_LCD_DAT20__GPIO_3_8,
+       MX6SL_PAD_LCD_DAT21__GPIO_3_9,
+       MX6SL_PAD_LCD_DAT22__GPIO_3_10,
+       MX6SL_PAD_LCD_DAT23__GPIO_3_11,
+       /* PWM pads */
+       MX6SL_PAD_PWM1__GPIO_3_23,
+       /* SD pads. */
+       MX6SL_PAD_SD1_CLK__GPIO_5_15,
+       MX6SL_PAD_SD1_CMD__GPIO_5_14,
+       MX6SL_PAD_SD1_DAT0__GPIO_5_11,
+       MX6SL_PAD_SD1_DAT1__GPIO_5_8,
+       MX6SL_PAD_SD1_DAT2__GPIO_5_13,
+       MX6SL_PAD_SD1_DAT3__GPIO_5_6,
+       MX6SL_PAD_SD1_DAT4__GPIO_5_12,
+       MX6SL_PAD_SD1_DAT5__GPIO_5_9,
+       MX6SL_PAD_SD1_DAT6__GPIO_5_7,
+       MX6SL_PAD_SD1_DAT7__GPIO_5_10,
+       MX6SL_PAD_SD2_CLK__GPIO_5_5,
+       MX6SL_PAD_SD2_CMD__GPIO_5_4,
+       MX6SL_PAD_SD2_DAT0__GPIO_5_1,
+       MX6SL_PAD_SD2_DAT1__GPIO_4_30,
+       MX6SL_PAD_SD2_DAT2__GPIO_5_3,
+       MX6SL_PAD_SD2_DAT3__GPIO_4_28,
+       MX6SL_PAD_SD2_DAT4__GPIO_5_2,
+       MX6SL_PAD_SD2_DAT5__GPIO_4_31,
+       MX6SL_PAD_SD2_DAT6__GPIO_4_29,
+       MX6SL_PAD_SD2_DAT7__GPIO_5_0,
+       MX6SL_PAD_SD3_CLK__GPIO_5_18,
+       MX6SL_PAD_SD3_CMD__GPIO_5_21,
+       MX6SL_PAD_SD3_DAT0__GPIO_5_19,
+       MX6SL_PAD_SD3_DAT1__GPIO_5_20,
+       MX6SL_PAD_SD3_DAT2__GPIO_5_16,
+       MX6SL_PAD_SD3_DAT3__GPIO_5_17,
+       /* USBOTG ID pin */
+       MX6SL_PAD_EPDC_PWRCOM__GPIO_2_11,
+       MX6SL_PAD_HSIC_STROBE__GPIO_3_20,
+       MX6SL_PAD_HSIC_DAT__GPIO_3_19,
+       /* Key row/column */
+       MX6SL_PAD_KEY_COL0__GPIO_3_24,
+       MX6SL_PAD_KEY_COL1__GPIO_3_26,
+       MX6SL_PAD_KEY_COL2__GPIO_3_28,
+       MX6SL_PAD_KEY_COL3__GPIO_3_30,
+       MX6SL_PAD_KEY_COL6__GPIO_4_4,
+       MX6SL_PAD_KEY_COL7__GPIO_4_6,
+       MX6SL_PAD_KEY_ROW0__GPIO_3_25,
+       MX6SL_PAD_KEY_ROW1__GPIO_3_27,
+       MX6SL_PAD_KEY_ROW2__GPIO_3_29,
+       MX6SL_PAD_KEY_ROW3__GPIO_3_31,
+       MX6SL_PAD_KEY_ROW4__GPIO_4_1,
+       MX6SL_PAD_KEY_ROW5__GPIO_4_3,
+       MX6SL_PAD_KEY_ROW6__GPIO_4_5,
+};
+
+static iomux_v3_cfg_t suspend_exit_pads[ARRAY_SIZE(suspend_enter_pads)];
+
 #define MX6SL_USDHC_8BIT_PAD_SETTING(id, speed)        \
 mx6sl_sd##id##_##speed##mhz[] = {              \
        MX6SL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ,   \
index 4c9c4d36e7409aa2cbff14bceebc670db150677e..47e8a8954c7d90f61aa179c79f03386f6f95ec84 100644 (file)
@@ -77,6 +77,9 @@
 
 static int spdc_sel;
 static int max17135_regulator_init(struct max17135 *max17135);
+static void mx6sl_evk_suspend_enter(void);
+static void mx6sl_evk_suspend_exit(void);
+
 struct clk *extern_audio_root;
 
 extern char *gp_reg_id;
@@ -122,6 +125,12 @@ enum sd_pad_mode {
        SD_PAD_MODE_HIGH_SPEED,
 };
 
+static const struct pm_platform_data mx6sl_evk_pm_data __initconst = {
+       .name           = "imx_pm",
+       .suspend_enter = mx6sl_evk_suspend_enter,
+       .suspend_exit = mx6sl_evk_suspend_exit,
+};
+
 static int __init csi_setup(char *__unused)
 {
        csi_enabled = 1;
@@ -1411,6 +1420,35 @@ static void __init uart2_init(void)
                                        ARRAY_SIZE(mx6sl_uart2_pads));
        imx6sl_add_imx_uart(1, &mx6sl_evk_uart1_data);
 }
+
+static void mx6sl_evk_suspend_enter()
+{
+       iomux_v3_cfg_t *p = suspend_enter_pads;
+       int i;
+
+       /* Set PADCTRL to 0 for all IOMUX. */
+       for (i = 0; i < ARRAY_SIZE(suspend_enter_pads); i++) {
+               suspend_exit_pads[i] = *p;
+               *p &= ~MUX_PAD_CTRL_MASK;
+               /* Enable the Pull down and the keeper
+                 * Set the drive strength to 0.
+                 */
+               *p |= ((u64)0x3000 << MUX_PAD_CTRL_SHIFT);
+               p++;
+       }
+       mxc_iomux_v3_get_multiple_pads(suspend_exit_pads,
+                       ARRAY_SIZE(suspend_exit_pads));
+       mxc_iomux_v3_setup_multiple_pads(suspend_enter_pads,
+                       ARRAY_SIZE(suspend_enter_pads));
+
+}
+
+static void mx6sl_evk_suspend_exit()
+{
+       mxc_iomux_v3_setup_multiple_pads(suspend_exit_pads,
+                       ARRAY_SIZE(suspend_exit_pads));
+}
+
 /*!
  * Board specific initialization.
  */
@@ -1539,6 +1577,7 @@ static void __init mx6_evk_init(void)
        /* Register charger chips */
        platform_device_register(&evk_max8903_charger_1);
        pm_power_off = mx6_snvs_poweroff;
+       imx6q_add_pm_imx(0, &mx6sl_evk_pm_data);
 }
 
 extern void __iomem *twd_base;
index 18b8de8a8e870e86126d911fca314ed46c2d8b08..a2a2798f93a0d721e3de5a7343fe56bc01473d1b 100644 (file)
@@ -343,8 +343,6 @@ static int mx6_suspend_enter(suspend_state_t state)
        }
 
        if (state == PM_SUSPEND_MEM || state == PM_SUSPEND_STANDBY) {
-               if (pm_data && pm_data->suspend_enter)
-                       pm_data->suspend_enter();
 
                local_flush_tlb_all();
                flush_cache_all();
@@ -355,9 +353,15 @@ static int mx6_suspend_enter(suspend_state_t state)
                        save_gic_cpu_state(0, &gcs);
                }
 
+               if (pm_data && pm_data->suspend_enter)
+                       pm_data->suspend_enter();
+
                suspend_in_iram(state, (unsigned long)iram_paddr,
                        (unsigned long)suspend_iram_base, cpu_type);
 
+               if (pm_data && pm_data->suspend_exit)
+                       pm_data->suspend_exit();
+
                /* Reset the RBC counter. */
                /* All interrupts should be masked before the
                  * RBC counter is reset.
@@ -397,8 +401,6 @@ static int mx6_suspend_enter(suspend_state_t state)
                __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
                        anatop_base + HW_ANADIG_ANA_MISC0_CLR);
 
-               if (pm_data && pm_data->suspend_exit)
-                       pm_data->suspend_exit();
        } else {
                        cpu_do_idle();
        }
index f901e18368c2a24a69aca3e00c77b387f79fb13c..5b865ad48932bb794b0b0331d6555e7b513c98c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved.
  */
 
 /*
@@ -30,6 +30,11 @@ const struct imx_pm_imx_data imx6q_pm_imx_data[] __initconst =
        imx_pm_imx_data_entry_single(MX6Q);
 #endif
 
+#ifdef CONFIG_SOC_IMX6SL
+const struct imx_pm_imx_data imx6sl_pm_imx_data[] __initconst =
+       imx_pm_imx_data_entry_single(MX6SL);
+#endif
+
 struct platform_device *__init imx_add_pm_imx(
                const struct imx_pm_imx_data *data,
                const struct pm_platform_data *pdata)
index c53028f984d1c72323c1fad17eae20178104e533..8bdfe79785df5a428797b9b8901a765715d5307e 100644 (file)
@@ -161,14 +161,16 @@ typedef u64 iomux_v3_cfg_t;
 #define GPIO_PORTF     (5 << GPIO_PORT_SHIFT)
 
 /*
- * setups a single pad in the iomuxer
+ * read/write a single pad in the iomuxer
  */
+int mxc_iomux_v3_get_pad(iomux_v3_cfg_t *pad);
 int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad);
 
 /*
- * setups mutliple pads
+ * read/write mutliple pads
  * convenient way to call the above function with tables
  */
+ int mxc_iomux_v3_get_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count);
 int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count);
 
 /*
index 85b7e176981b94c978a8204129b64b0da9ea50fa..b88208c10de972b2f83aa19038910705be0c3a49 100644 (file)
@@ -56,6 +56,36 @@ int mxc_iomux_v3_setup_pad(iomux_v3_cfg_t pad)
 }
 EXPORT_SYMBOL(mxc_iomux_v3_setup_pad);
 
+/*
+ * Read a single pad in the iomuxer
+ */
+int mxc_iomux_v3_get_pad(iomux_v3_cfg_t *pad)
+{
+       u32 mux_ctrl_ofs = (*pad & MUX_CTRL_OFS_MASK) >> MUX_CTRL_OFS_SHIFT;
+       u32 pad_ctrl_ofs = (*pad & MUX_PAD_CTRL_OFS_MASK)
+                                               >> MUX_PAD_CTRL_OFS_SHIFT;
+       u32 sel_input_ofs = (*pad & MUX_SEL_INPUT_OFS_MASK)
+                                               >> MUX_SEL_INPUT_OFS_SHIFT;
+       u32 mux_mode = 0;
+       u32 sel_input = 0;
+       u32 pad_ctrl = 0;
+       iomux_v3_cfg_t pad_info = 0;
+
+       mux_mode = __raw_readl(base + mux_ctrl_ofs) & 0xFF;
+       pad_ctrl = __raw_readl(base + pad_ctrl_ofs) & 0x1FFFF;
+       sel_input = __raw_readl(base + sel_input_ofs) & 0x7;
+
+       pad_info = (((iomux_v3_cfg_t)mux_mode << MUX_MODE_SHIFT) | \
+               ((iomux_v3_cfg_t)pad_ctrl << MUX_PAD_CTRL_SHIFT) | \
+               ((iomux_v3_cfg_t)sel_input << MUX_SEL_INPUT_SHIFT));
+
+       *pad &= ~(MUX_MODE_MASK | MUX_PAD_CTRL_MASK | MUX_SEL_INPUT_MASK);
+       *pad |= pad_info;
+
+       return 0;
+}
+
+
 int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
 {
        iomux_v3_cfg_t *p = pad_list;
@@ -72,6 +102,22 @@ int mxc_iomux_v3_setup_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
 }
 EXPORT_SYMBOL(mxc_iomux_v3_setup_multiple_pads);
 
+/*
+ * Read multiple pads in the iomuxer
+ */
+int mxc_iomux_v3_get_multiple_pads(iomux_v3_cfg_t *pad_list, unsigned count)
+{
+       iomux_v3_cfg_t *p = pad_list;
+       int i;
+
+       for (i = 0; i < count; i++) {
+               mxc_iomux_v3_get_pad(p);
+               p++;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(mxc_iomux_v3_get_multiple_pads);
+
 void mxc_iomux_set_gpr_register(int group, int start_bit, int num_bits, int value)
 {
        int i = 0;