summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRanjani Vaidyanathan <ra5478@freescale.com>2012-11-02 16:11:38 -0500
committerRanjani Vaidyanathan <ra5478@freescale.com>2012-11-05 16:35:08 -0600
commit30de6f2aa79c904848704271b7bab17d2f3c4805 (patch)
tree62ed07bf9dd6c4e833ab7accf66cb3c367e99004
parent24a51586c5a00ddf8b5e5de749f8269951f2de3f (diff)
ENGR00232327 MX6SL-Optimize board level suspend power
Improve the board level suspend power by configuring various IOMUX pads to low power state. Signed-off-by: Ranjani Vaidyanathan <ra5478@freescale.com>
-rwxr-xr-xarch/arm/mach-mx6/board-mx6sl_arm2.c42
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_common.h104
-rw-r--r--arch/arm/mach-mx6/board-mx6sl_evk.c39
-rw-r--r--arch/arm/mach-mx6/pm.c10
-rw-r--r--arch/arm/plat-mxc/devices/platform-imx-pm.c7
-rw-r--r--arch/arm/plat-mxc/include/mach/iomux-v3.h6
-rw-r--r--arch/arm/plat-mxc/iomux-v3.c46
7 files changed, 242 insertions, 12 deletions
diff --git a/arch/arm/mach-mx6/board-mx6sl_arm2.c b/arch/arm/mach-mx6/board-mx6sl_arm2.c
index 477ea8c2b33e..a7f20edf524f 100755
--- a/arch/arm/mach-mx6/board-mx6sl_arm2.c
+++ b/arch/arm/mach-mx6/board-mx6sl_arm2.c
@@ -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;
}
diff --git a/arch/arm/mach-mx6/board-mx6sl_common.h b/arch/arm/mach-mx6/board-mx6sl_common.h
index c432e0a661ba..a6e5e909c6a9 100644
--- a/arch/arm/mach-mx6/board-mx6sl_common.h
+++ b/arch/arm/mach-mx6/board-mx6sl_common.h
@@ -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, \
diff --git a/arch/arm/mach-mx6/board-mx6sl_evk.c b/arch/arm/mach-mx6/board-mx6sl_evk.c
index 4c9c4d36e740..47e8a8954c7d 100644
--- a/arch/arm/mach-mx6/board-mx6sl_evk.c
+++ b/arch/arm/mach-mx6/board-mx6sl_evk.c
@@ -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;
diff --git a/arch/arm/mach-mx6/pm.c b/arch/arm/mach-mx6/pm.c
index 18b8de8a8e87..a2a2798f93a0 100644
--- a/arch/arm/mach-mx6/pm.c
+++ b/arch/arm/mach-mx6/pm.c
@@ -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();
}
diff --git a/arch/arm/plat-mxc/devices/platform-imx-pm.c b/arch/arm/plat-mxc/devices/platform-imx-pm.c
index f901e18368c2..5b865ad48932 100644
--- a/arch/arm/plat-mxc/devices/platform-imx-pm.c
+++ b/arch/arm/plat-mxc/devices/platform-imx-pm.c
@@ -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)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
index c53028f984d1..8bdfe79785df 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
@@ -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);
/*
diff --git a/arch/arm/plat-mxc/iomux-v3.c b/arch/arm/plat-mxc/iomux-v3.c
index 85b7e176981b..b88208c10de9 100644
--- a/arch/arm/plat-mxc/iomux-v3.c
+++ b/arch/arm/plat-mxc/iomux-v3.c
@@ -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;