From 31f9d4635bde3f03bc6dbac01d4c0fb0da9d06d7 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 22 Nov 2011 16:02:17 +0200 Subject: [PATCH 1/7] omap_hsmmc: consider MMC_PM_KEEP_POWER on suspend/resume When an mmc card has the MMC_PM_KEEP_POWER flag, it shouldn't be powered off on suspend (and thus doesn't have to be powered-on on resume) While on it, change the suspend flow a bit, to make it a bit easier to follow. Signed-off-by: Eliad Peller Acked-by: Chris Ball Signed-off-by: Tony Lindgren --- drivers/mmc/host/omap_hsmmc.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 101cd31c8220..6784fbbc337d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2176,13 +2176,7 @@ static int omap_hsmmc_suspend(struct device *dev) cancel_work_sync(&host->mmc_carddetect_work); ret = mmc_suspend_host(host->mmc); - if (ret == 0) { - omap_hsmmc_disable_irq(host); - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); - if (host->got_dbclk) - clk_disable(host->dbclk); - } else { + if (ret) { host->suspended = 0; if (host->pdata->resume) { ret = host->pdata->resume(&pdev->dev, @@ -2191,9 +2185,20 @@ static int omap_hsmmc_suspend(struct device *dev) dev_dbg(mmc_dev(host->mmc), "Unmask interrupt failed\n"); } + goto err; } - pm_runtime_put_sync(host->dev); + + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) { + omap_hsmmc_disable_irq(host); + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); + } + if (host->got_dbclk) + clk_disable(host->dbclk); + } +err: + pm_runtime_put_sync(host->dev); return ret; } @@ -2213,7 +2218,8 @@ static int omap_hsmmc_resume(struct device *dev) if (host->got_dbclk) clk_enable(host->dbclk); - omap_hsmmc_conf_bus_power(host); + if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER)) + omap_hsmmc_conf_bus_power(host); if (host->pdata->resume) { ret = host->pdata->resume(&pdev->dev, host->slot_id); From 6fdc75de7d0554134890d33a0a6f5e18c7503c01 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 22 Nov 2011 16:02:18 +0200 Subject: [PATCH 2/7] ARM: OMAP: hsmmc: add pm_caps field Add pm_caps field to omap2_hsmmc_info and omap_mmc_slot_data structs, so we will be able to indicate mmc pm capabilities in the board file. Signed-off-by: Eliad Peller Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/hsmmc.c | 1 + arch/arm/mach-omap2/hsmmc.h | 1 + arch/arm/plat-omap/include/plat/mmc.h | 1 + drivers/mmc/host/omap_hsmmc.c | 2 ++ 4 files changed, 5 insertions(+) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index f4a1020559a7..97dfedce084b 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -296,6 +296,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc->slots[0].name = hc_name; mmc->nr_slots = 1; mmc->slots[0].caps = c->caps; + mmc->slots[0].pm_caps = c->pm_caps; mmc->slots[0].internal_clock = !c->ext_clock; mmc->dma_mask = 0xffffffff; if (cpu_is_omap44xx()) diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index f757e78d4d4f..c4409730c4bb 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -12,6 +12,7 @@ struct omap2_hsmmc_info { u8 mmc; /* controller 1/2/3 */ u32 caps; /* 4/8 wires and any additional host * capabilities OR'd (ref. linux/mmc/host.h) */ + u32 pm_caps; /* PM capabilities */ bool transceiver; /* MMC-2 option */ bool ext_clock; /* use external pin for input clock */ bool cover_only; /* No card detect - just cover switch */ diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index 94cf70afb236..f75946c3293d 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -96,6 +96,7 @@ struct omap_mmc_platform_data { */ u8 wires; /* Used for the MMC driver on omap1 and 2420 */ u32 caps; /* Used for the MMC driver on 2430 and later */ + u32 pm_caps; /* PM capabilities of the mmc */ /* * nomux means "standard" muxing is wrong on this board, and diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 6784fbbc337d..f0d792183b8e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1988,6 +1988,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) if (mmc_slot(host).nonremovable) mmc->caps |= MMC_CAP_NONREMOVABLE; + mmc->pm_caps = mmc_slot(host).pm_caps; + omap_hsmmc_conf_bus_power(host); /* Select DMA lines */ From fac1d933f4691d59eb5f6ec02bb8eae8d5c68297 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 22 Nov 2011 16:02:19 +0200 Subject: [PATCH 3/7] ARM: OMAP: hsmmc: board-sdp4430: declare support for MMC_PM_KEEP_POWER Declare support for keeping the power of the wlan chip while suspended. this is needed for Wakeup-On-Wireless. Signed-off-by: Eliad Peller Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-4430sdp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c index 515646886b59..ba23224963d0 100644 --- a/arch/arm/mach-omap2/board-4430sdp.c +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -404,6 +404,7 @@ static struct omap2_hsmmc_info mmc[] = { { .mmc = 5, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD, + .pm_caps = MMC_PM_KEEP_POWER, .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, .ocr_mask = MMC_VDD_165_195, From e62245ba1caaf78d6fe2619266939c8e7caa150c Mon Sep 17 00:00:00 2001 From: Igor Grinberg Date: Tue, 29 Nov 2011 11:37:48 +0200 Subject: [PATCH 4/7] ARM: OMAP: hsmmc: Add support for MMC 2 setup for AM35x AM35x MMC 2 controller has internal clock loopback setting which cannot be utilized without this patch and thus SDIO devices connected to this controller and depend on this setting will fail to initialize. Signed-off-by: Igor Grinberg [tony@atomide.com: updated comments] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/hsmmc.c | 42 ++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 97dfedce084b..59830d0eeb55 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -171,6 +171,17 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot, } } +static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) +{ + u32 reg; + + if (mmc->slots[0].internal_clock) { + reg = omap_ctrl_readl(control_devconf1_offset); + reg |= OMAP2_MMCSDIO2ADPCLKISEL; + omap_ctrl_writel(reg, control_devconf1_offset); + } +} + static void hsmmc23_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { @@ -179,16 +190,19 @@ static void hsmmc23_before_set_reg(struct device *dev, int slot, if (mmc->slots[0].remux) mmc->slots[0].remux(dev, slot, power_on); - if (power_on) { - /* Only MMC2 supports a CLKIN */ - if (mmc->slots[0].internal_clock) { - u32 reg; + if (power_on) + hsmmc2_select_input_clk_src(mmc); +} - reg = omap_ctrl_readl(control_devconf1_offset); - reg |= OMAP2_MMCSDIO2ADPCLKISEL; - omap_ctrl_writel(reg, control_devconf1_offset); - } - } +static int am35x_hsmmc2_set_power(struct device *dev, int slot, + int power_on, int vdd) +{ + struct omap_mmc_platform_data *mmc = dev->platform_data; + + if (power_on) + hsmmc2_select_input_clk_src(mmc); + + return 0; } static int nop_mmc_set_power(struct device *dev, int slot, int power_on, @@ -339,9 +353,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, */ mmc->slots[0].ocr_mask = c->ocr_mask; - if (cpu_is_omap3517() || cpu_is_omap3505()) - mmc->slots[0].set_power = nop_mmc_set_power; - else + if (!cpu_is_omap3517() && !cpu_is_omap3505()) mmc->slots[0].features |= HSMMC_HAS_PBIAS; if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0)) @@ -364,6 +376,9 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, } } + if (cpu_is_omap3517() || cpu_is_omap3505()) + mmc->slots[0].set_power = nop_mmc_set_power; + /* OMAP3630 HSMMC1 supports only 4-bit */ if (cpu_is_omap3630() && (c->caps & MMC_CAP_8_BIT_DATA)) { @@ -373,6 +388,9 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, } break; case 2: + if (cpu_is_omap3517() || cpu_is_omap3505()) + mmc->slots[0].set_power = am35x_hsmmc2_set_power; + if (c->ext_clock) c->transceiver = 1; if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) { From a15164f13fb3f0f70849c2a099ff0af7b2924ba1 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Thu, 17 Nov 2011 22:39:40 +0100 Subject: [PATCH 5/7] ARM: OMAP: hsmmc: Add support for non-OMAP pins The Devkit8000 uses a TWL4030 pin for card detection. Thats why the error: _omap_mux_init_gpio: Could not set gpio192 occurs. This patch checks that the pin is on OMAP before calling omap_mux_init_gpio. Signed-off-by: Thomas Weber [tony@atomide.com: updated comments] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/hsmmc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 59830d0eeb55..997b33d76418 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -214,10 +214,12 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, int controller_nr) { - if (gpio_is_valid(mmc_controller->slots[0].switch_pin)) + if (gpio_is_valid(mmc_controller->slots[0].switch_pin) && + (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES)) omap_mux_init_gpio(mmc_controller->slots[0].switch_pin, OMAP_PIN_INPUT_PULLUP); - if (gpio_is_valid(mmc_controller->slots[0].gpio_wp)) + if (gpio_is_valid(mmc_controller->slots[0].gpio_wp) && + (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES)) omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp, OMAP_PIN_INPUT_PULLUP); if (cpu_is_omap34xx()) { From e89715a7e48d505f42813a4e3ee0f0efb49832ba Mon Sep 17 00:00:00 2001 From: Abhilash K V Date: Fri, 9 Dec 2011 12:27:36 -0800 Subject: [PATCH 6/7] ARM: OMAP: hsmmc: Support for AM3517 MMC1 voltages This patch fixes the following error message which appears while intializing MMC1 on the AM3517 EVM base-board: mmc0: host doesn't support card's voltages mmc0: error -22 whilst initialising SD card The ocr_mask, which enumerates the volatges supported by the MMC card was not being indicated before, assuming that a separate Vcc regulator maybe another controllable regulator driver would be doing this. This patch statically specifies a subset of the voltages supported by the MMC driver, which are provided by the current fixed voltage regulator on AM3517 EVM. Signed-off-by: Vaibhav Hiremath Signed-off-by: Abhilash K V Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/hsmmc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 997b33d76418..bd844af13af5 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -353,7 +353,15 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, * * temporary HACK: ocr_mask instead of fixed supply */ - mmc->slots[0].ocr_mask = c->ocr_mask; + if (cpu_is_omap3505() || cpu_is_omap3517()) + mmc->slots[0].ocr_mask = MMC_VDD_165_195 | + MMC_VDD_26_27 | + MMC_VDD_27_28 | + MMC_VDD_29_30 | + MMC_VDD_30_31 | + MMC_VDD_31_32; + else + mmc->slots[0].ocr_mask = c->ocr_mask; if (!cpu_is_omap3517() && !cpu_is_omap3505()) mmc->slots[0].features |= HSMMC_HAS_PBIAS; From dd6facfc0ee3e5875b39a5f368af266395171996 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Fri, 9 Dec 2011 12:27:55 -0800 Subject: [PATCH 7/7] ARM: OMAP: hsmmc: Add support for AM3517EVM base-board MMC slot Add support for base-board MMC slot Signed-off-by: Vaibhav Hiremath Signed-off-by: Abhilash K V [tony@atomide.com: updated subject] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-am3517evm.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index d314f033c9df..f7df8d35ee90 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include "mux.h" #include "control.h" +#include "hsmmc.h" #define AM35XX_EVM_MDIO_FREQUENCY (1000000) @@ -455,6 +457,23 @@ static void am3517_evm_hecc_init(struct ti_hecc_platform_data *pdata) static struct omap_board_config_kernel am3517_evm_config[] __initdata = { }; +static struct omap2_hsmmc_info mmc[] = { + { + .mmc = 1, + .caps = MMC_CAP_4_BIT_DATA, + .gpio_cd = 127, + .gpio_wp = 126, + }, + { + .mmc = 2, + .caps = MMC_CAP_4_BIT_DATA, + .gpio_cd = 128, + .gpio_wp = 129, + }, + {} /* Terminator */ +}; + + static void __init am3517_evm_init(void) { omap_board_config = am3517_evm_config; @@ -483,6 +502,9 @@ static void __init am3517_evm_init(void) /* MUSB */ am3517_evm_musb_init(); + + /* MMC init function */ + omap2_hsmmc_init(mmc); } MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")