From: Ranjani Vaidyanathan Date: Fri, 2 Nov 2012 21:11:38 +0000 (-0500) Subject: ENGR00232327 MX6SL-Optimize board level suspend power X-Git-Tag: v3.0.35-fsl~292 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=914f7466db0ca87b0cfce04c1b64d6d96f9cfa9e;p=karo-tx-linux.git 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 --- 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;