Re: [PATCH 00/17] omap_hsmmc: regulator usage cleanup and fixes
Hi Kishon, Thanks for taking a look at the regulator code. Do you have a public git repository so I can pull your patches instead of cherry picking 1-by-1? /Andi 2015-07-29 13:09 GMT+02:00 Kishon Vijay Abraham I kis...@ti.com: This patch series does the following *) Uses devm_regulator_get_optional() for vmmc and then removes the CONFIG_REGULATOR check altogether. *) return on -EPROBE_DEFER *) enable/disable vmmc_aux regulator based on prior state This series is in preparation for implementing the voltage switch sequence so that UHS cards can be supported. Did basic read/write test in J6, J6 Eco, Beagle-x15, AM437x EVM, Beaglebone black, OMAP5 uEVM and OMAP4 PANDA. Kishon Vijay Abraham I (16): mmc: host: omap_hsmmc: use devm_regulator_get_optional() for vmmc mmc: host: omap_hsmmc: return error from omap_hsmmc_reg_get on -EPROBE_DEFER mmc: host: omap_hsmmc: cleanup omap_hsmmc_reg_get() mmc: host: omap_hsmmc: use the ocrmask provided by the vmmc regulator mmc: host: omap_hsmmc: use mmc_host's vmmc and vqmmc mmc: host: omap_hsmmc: remove unnecessary pbias set_voltage mmc: host: omap_hsmmc: return error if any of the regulator APIs fail mmc: host: omap_hsmmc: add separate functions for enable/disable supply mmc: host: omap_hsmmc: add separate function to set pbias mmc: host: omap_hsmmc: avoid pbias regulator enable on power off mmc: host: omap_hsmmc: don't use -set_power to set initial regulator state ARM: dts: am57xx-beagle-x15: Fix regulator populated in MMC1 dt node mmc: host: omap_hsmmc: enable/disable vmmc_aux regulator based on prior state mmc: host: omap_hsmmc: use regulator_is_enabled to find pbias status mmc: host: omap_hsmmc: use ios-vdd for setting vmmc voltage mmc: host: omap_hsmmc: remove CONFIG_REGULATOR check Roger Quadros (1): mmc: host: omap_hsmmc: use mmc_of_parse_voltage to get ocr_avail .../devicetree/bindings/mmc/ti-omap-hsmmc.txt |2 + arch/arm/boot/dts/am57xx-beagle-x15.dts|1 - drivers/mmc/host/omap_hsmmc.c | 333 +--- 3 files changed, 216 insertions(+), 120 deletions(-) -- 1.7.9.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/3] mmc: host: omap_hsmmc: Add custom card detect irq handler
Hi Vignesh, Generally I don't like this patch, it will make it harder, not easier, to maintain the omap hsmmc driver. Also given that the bug occurs rarely, people will be reluctant to clean it up later or accept patches. see also comments below 2015-06-22 15:18 GMT+02:00 Vignesh R vigne...@ti.com: On Sunday 21 June 2015 04:15 AM, Andreas Fenkart wrote: I haven't managed to produce a hang without this patch Reproducing this hang is not straight forward. It takes 40-50 card insertion/removal to see this case (sometimes even 100 tries). see also comments below 2015-06-16 12:37 GMT+02:00 Vignesh R vigne...@ti.com: Usually when there is an error in transfer, DTO/CTO or other error interrupts are raised. But if the card is unplugged in the middle of a data transfer, it is observed that, neither completion(success) or timeout(error) interrupts are raised. Hence, the mmc-core is waiting for-ever for the transfer to complete. This results failure to recognise sd card on the next insertion. The only way to solve this is to introduce code to detect this condition and recover on card insertion (in hsmmc specific cd_irq). Hence, introduce cd_irq and add code to clear mmc_request that is pending from the failed transaction. Signed-off-by: Vignesh R vigne...@ti.com --- drivers/mmc/host/omap_hsmmc.c | 73 ++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index fb4bfefd9250..ec1fff3c0c9c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -221,6 +221,12 @@ struct omap_hsmmc_host { #define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_hsmmc_platform_data*pdata; + /* +* flag to determine whether card was removed during data +* transfer +*/ + booltransfer_incomplete; + /* return MMC cover switch state, can be NULL if not supported. * @@ -867,6 +873,26 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req } /* + * Cleanup incomplete card removal sequence. This will make sure the + * next card enumeration is clean. + */ +static void omap_hsmmc_request_clear(struct omap_hsmmc_host *host, +struct mmc_request *mrq) +{ + unsigned long flags; + + spin_lock_irqsave(host-irq_lock, flags); + host-req_in_progress = 0; + host-dma_ch = -1; + spin_unlock_irqrestore(host-irq_lock, flags); + + mmc_request_done(host-mmc, mrq); + if (host-mmc-card) + mmc_card_set_removed(host-mmc-card); + host-mrq = NULL; +} + +/* * Notify the transfer complete to MMC core */ static void @@ -1248,6 +1274,47 @@ static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) return IRQ_HANDLED; } +/* + * irq handler to notify the core about card insertion/removal + */ +static irqreturn_t omap_hsmmc_cd_irq(int irq, void *dev_id) +{ Move this code to 'omap_hsmmc_get_cd' function. Or rather clear any pending transfer upon '.init_card/omap_hsmmc_init_card' I tried using omap_hsmmc_init initially, but here is the problem: card inserted -- cd_irq_isr-- schedule mmc_rescan() --- after some time --- mmc_rescan() -- mmc_sd_alive() -- -- card removed --- mmc_send_status -- mmc_wait_for_req()-- wait_for_completion() ^^^ Here the mmc_rescan thread waits forever because, it doesn't get timeout interrupt for the cmd/req it sent (because card was removed). ok, I see But calls to omap_hsmmc_card_init or omap_hsmmc_get_cd are in the same mmc_rescan thread. Hence, moving the recovery code to init_card does not help. what about clearing any pending transfer in - mmc_gpio_cd_irqt, or - mmc_detect_change e.g. trigger the later mentioned .card_event callback from those functions, instead mmc_rescan? Then you can install your omap_hsmmc_request_clear as the card_event callback. This makes your custom isr handler redundant, actually your isr handler became standard. I guess other hosts also have some housekeeping upon unexpected card removals. So I guess there is some generic code to this problem. Did you check? I did try to find generic code in mmc-core, but couldn't find any. However, I did see some driver specific cleanups related to unexpected card removal in sdhci.c. sdhci handles this in .card_event call back. This does not help in my case as .card_event is also called from mmc_rescan. I think cleanup code (in sdhci driver) for unexpected card removal was introduced when .card_event call was outside mmc_rescan. interesting + struct omap_hsmmc_host *host = mmc_priv(dev_id); + int carddetect = mmc_gpio_get_cd(host-mmc); + struct mmc_request *mrq = host-mrq; + + /* +* If the card was removed in the middle of data
[PATCH] Documentation: dt: update ti,am33xx-hsmmc swakeup workaround
Before 5b83b2234be6733cf the driver was hard coding the wakeup irq to be active low. The generic pm wakeirq does not override the active high/low parameter, hence it must be specified correctly in the device tree. Mind that SDIO IRQ is active low as defined in the SDIO specification Signed-off-by: Andreas Fenkart afenk...@gmail.com --- Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index 76bf087..74166a0 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -102,7 +102,7 @@ not every application needs SDIO irq, e.g. MMC cards. pinctrl-1 = mmc1_idle; pinctrl-2 = mmc1_sleep; ... - interrupts-extended = intc 64 gpio2 28 0; + interrupts-extended = intc 64 gpio2 28 GPIO_ACTIVE_LOW; }; mmc1_idle : pinmux_cirq_pin { -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] mmc: omap_hsmmc: call omap_hsmmc_set_power directly
If no pdata.set_power was set by the platform code, the driver was updating pdata with its own fallback function. This is a no-no since pdata shall be read-only. This patch pushes the check 'pdata-set_power != NULL' down into the fallback functions. If pdata.set_power is really set, it calls them and exits, otherwise the fallback code is used. Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 32 +--- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b2b411d..fe7cee5 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -213,7 +213,6 @@ struct omap_hsmmc_host { int context_loss; int protect_card; int reqs_blocked; - int use_reg; int req_in_progress; unsigned long clk_rate; unsigned intflags; @@ -262,6 +261,9 @@ static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) platform_get_drvdata(to_platform_device(dev)); int ret = 0; + if (mmc_pdata(host)-set_power) + return mmc_pdata(host)-set_power(dev, power_on, vdd); + /* * If we don't see a Vcc regulator, assume it's a fixed * voltage always-on regulator. @@ -344,6 +346,9 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) struct regulator *reg; int ocr_value = 0; + if (mmc_pdata(host)-set_power) + return 0; + reg = devm_regulator_get(host-dev, vmmc); if (IS_ERR(reg)) { dev_err(host-dev, unable to get vmmc regulator %ld\n, @@ -363,7 +368,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) } } } - mmc_pdata(host)-set_power = omap_hsmmc_set_power; /* Allow an aux regulator */ reg = devm_regulator_get_optional(host-dev, vmmc_aux); @@ -383,8 +387,8 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) (host-vcc_aux regulator_is_enabled(host-vcc_aux))) { int vdd = ffs(mmc_pdata(host)-ocr_mask) - 1; - mmc_pdata(host)-set_power(host-dev, 1, vdd); - mmc_pdata(host)-set_power(host-dev, 0, 0); + omap_hsmmc_set_power(host-dev, 1, vdd); + omap_hsmmc_set_power(host-dev, 0, 0); } return 0; @@ -392,7 +396,8 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) { - mmc_pdata(host)-set_power = NULL; + if (mmc_pdata(host)-set_power) + return; } static inline int omap_hsmmc_have_reg(void) @@ -1148,11 +1153,11 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) clk_disable_unprepare(host-dbclk); /* Turn the power off */ - ret = mmc_pdata(host)-set_power(host-dev, 0, 0); + ret = omap_hsmmc_set_power(host-dev, 0, 0); /* Turn the power ON with given VDD 1.8 or 3.0v */ if (!ret) - ret = mmc_pdata(host)-set_power(host-dev, 1, vdd); + ret = omap_hsmmc_set_power(host-dev, 1, vdd); pm_runtime_get_sync(host-dev); if (host-dbclk) clk_prepare_enable(host-dbclk); @@ -1551,10 +1556,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (ios-power_mode != host-power_mode) { switch (ios-power_mode) { case MMC_POWER_OFF: - mmc_pdata(host)-set_power(host-dev, 0, 0); + omap_hsmmc_set_power(host-dev, 0, 0); break; case MMC_POWER_UP: - mmc_pdata(host)-set_power(host-dev, 1, ios-vdd); + omap_hsmmc_set_power(host-dev, 1, ios-vdd); break; case MMC_POWER_ON: do_send_init_stream = 1; @@ -2077,11 +2082,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) goto err_irq; } - if (omap_hsmmc_have_reg() !mmc_pdata(host)-set_power) { + if (omap_hsmmc_have_reg()) { ret = omap_hsmmc_reg_get(host); if (ret) goto err_irq; - host-use_reg = 1; } mmc-ocr_avail = mmc_pdata(host)-ocr_mask; @@ -2124,8 +2128,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) err_slot_name: mmc_remove_host(mmc); - if (host-use_reg) - omap_hsmmc_reg_put(host); + omap_hsmmc_reg_put(host); err_irq: device_init_wakeup(pdev-dev, false); if (host-tx_chan) @@ -2149,8 +2152,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev
[PATCH v2 0/2] mmc: omap_hsmmc: omap_hsmmc_set_power cleanup
v2: - add empty omap_hsmmc_set_power in case CONFIG_REGULATOR is undefined Andreas Fenkart (2): mmc: omap_hsmmc: call omap_hsmmc_set_power directly mmc: omap_hsmmc: regulator automatically released by devm drivers/mmc/host/omap_hsmmc.c | 39 +-- 1 file changed, 17 insertions(+), 22 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/2] mmc: omap_hsmmc: regulator automatically released by devm
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 12 1 file changed, 12 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 806867b..ec1bcc7 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -394,12 +394,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) return 0; } -static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) -{ - if (mmc_pdata(host)-set_power) - return; -} - static inline int omap_hsmmc_have_reg(void) { return 1; @@ -417,10 +411,6 @@ static inline int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) return -EINVAL; } -static inline void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) -{ -} - static inline int omap_hsmmc_have_reg(void) { return 0; @@ -2133,7 +2123,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) err_slot_name: mmc_remove_host(mmc); - omap_hsmmc_reg_put(host); err_irq: device_init_wakeup(pdev-dev, false); if (host-tx_chan) @@ -2157,7 +2146,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) pm_runtime_get_sync(host-dev); mmc_remove_host(host-mmc); - omap_hsmmc_reg_put(host); if (host-tx_chan) dma_release_channel(host-tx_chan); -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/2] mmc: omap_hsmmc: call omap_hsmmc_set_power directly
If no pdata.set_power was set by the platform code, the driver was updating pdata with its own fallback function. This is a no-no since pdata shall be read-only. This patch pushes the check 'pdata-set_power != NULL' down into the fallback functions. If pdata.set_power is really set, it calls them and exits, otherwise the fallback code is used. Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 37 ++--- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b2b411d..806867b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -213,7 +213,6 @@ struct omap_hsmmc_host { int context_loss; int protect_card; int reqs_blocked; - int use_reg; int req_in_progress; unsigned long clk_rate; unsigned intflags; @@ -262,6 +261,9 @@ static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) platform_get_drvdata(to_platform_device(dev)); int ret = 0; + if (mmc_pdata(host)-set_power) + return mmc_pdata(host)-set_power(dev, power_on, vdd); + /* * If we don't see a Vcc regulator, assume it's a fixed * voltage always-on regulator. @@ -344,6 +346,9 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) struct regulator *reg; int ocr_value = 0; + if (mmc_pdata(host)-set_power) + return 0; + reg = devm_regulator_get(host-dev, vmmc); if (IS_ERR(reg)) { dev_err(host-dev, unable to get vmmc regulator %ld\n, @@ -363,7 +368,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) } } } - mmc_pdata(host)-set_power = omap_hsmmc_set_power; /* Allow an aux regulator */ reg = devm_regulator_get_optional(host-dev, vmmc_aux); @@ -383,8 +387,8 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) (host-vcc_aux regulator_is_enabled(host-vcc_aux))) { int vdd = ffs(mmc_pdata(host)-ocr_mask) - 1; - mmc_pdata(host)-set_power(host-dev, 1, vdd); - mmc_pdata(host)-set_power(host-dev, 0, 0); + omap_hsmmc_set_power(host-dev, 1, vdd); + omap_hsmmc_set_power(host-dev, 0, 0); } return 0; @@ -392,7 +396,8 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) { - mmc_pdata(host)-set_power = NULL; + if (mmc_pdata(host)-set_power) + return; } static inline int omap_hsmmc_have_reg(void) @@ -402,6 +407,11 @@ static inline int omap_hsmmc_have_reg(void) #else +static int omap_hsmmc_set_power(struct device *dev, int power_on, int vdd) +{ + return 0; +} + static inline int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) { return -EINVAL; @@ -1148,11 +1158,11 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) clk_disable_unprepare(host-dbclk); /* Turn the power off */ - ret = mmc_pdata(host)-set_power(host-dev, 0, 0); + ret = omap_hsmmc_set_power(host-dev, 0, 0); /* Turn the power ON with given VDD 1.8 or 3.0v */ if (!ret) - ret = mmc_pdata(host)-set_power(host-dev, 1, vdd); + ret = omap_hsmmc_set_power(host-dev, 1, vdd); pm_runtime_get_sync(host-dev); if (host-dbclk) clk_prepare_enable(host-dbclk); @@ -1551,10 +1561,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (ios-power_mode != host-power_mode) { switch (ios-power_mode) { case MMC_POWER_OFF: - mmc_pdata(host)-set_power(host-dev, 0, 0); + omap_hsmmc_set_power(host-dev, 0, 0); break; case MMC_POWER_UP: - mmc_pdata(host)-set_power(host-dev, 1, ios-vdd); + omap_hsmmc_set_power(host-dev, 1, ios-vdd); break; case MMC_POWER_ON: do_send_init_stream = 1; @@ -2077,11 +2087,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) goto err_irq; } - if (omap_hsmmc_have_reg() !mmc_pdata(host)-set_power) { + if (omap_hsmmc_have_reg()) { ret = omap_hsmmc_reg_get(host); if (ret) goto err_irq; - host-use_reg = 1; } mmc-ocr_avail = mmc_pdata(host)-ocr_mask; @@ -2124,8 +2133,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) err_slot_name
[PATCH 2/2] mmc: omap_hsmmc: regulator automatically released by devm
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 12 1 file changed, 12 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index fe7cee5..9761e12 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -394,12 +394,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) return 0; } -static void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) -{ - if (mmc_pdata(host)-set_power) - return; -} - static inline int omap_hsmmc_have_reg(void) { return 1; @@ -412,10 +406,6 @@ static inline int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) return -EINVAL; } -static inline void omap_hsmmc_reg_put(struct omap_hsmmc_host *host) -{ -} - static inline int omap_hsmmc_have_reg(void) { return 0; @@ -2128,7 +2118,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) err_slot_name: mmc_remove_host(mmc); - omap_hsmmc_reg_put(host); err_irq: device_init_wakeup(pdev-dev, false); if (host-tx_chan) @@ -2152,7 +2141,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) pm_runtime_get_sync(host-dev); mmc_remove_host(host-mmc); - omap_hsmmc_reg_put(host); if (host-tx_chan) dma_release_channel(host-tx_chan); -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/3] mmc: host: omap_hsmmc: Fix DTO and DCRC handling
Hi Vignesh, 2015-06-16 12:37 GMT+02:00 Vignesh R vigne...@ti.com: From: Kishon Vijay Abraham I kis...@ti.com DTO/DCRC errors were not being informed to the mmc core since commit ae4bf788ee9b (mmc: omap_hsmmc: consolidate error report handling of HSMMC IRQ). This commit made sure 'end_trans' is never set on DTO/DCRC errors. This is because after this commit 'host-data' is checked after it has been cleared to NULL by omap_hsmmc_dma_cleanup(). Because 'end_trans' is never set, omap_hsmmc_xfer_done() is never invoked making core layer not to be aware of DTO/DCRC errors. Because of this any command invoked after DTO/DCRC error leads to a hang. Fix this by checking for 'host-data' before it is actually cleared. This really fixes the problem, thanks for the analysis TESTED-BY Fixes: ae4bf788ee9b (mmc: omap_hsmmc: consolidate error report handling of HSMMC IRQ) CC: sta...@vger.kernel.org Signed-off-by: Kishon Vijay Abraham I kis...@ti.com Signed-off-by: Vignesh R vigne...@ti.com --- drivers/mmc/host/omap_hsmmc.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 9df2b6801f76..d0abdffb0d7c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1062,6 +1062,10 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) if (status (CTO_EN | CCRC_EN)) end_cmd = 1; + if (host-data || host-response_busy) { + end_trans = !end_cmd; + host-response_busy = 0; + } if (status (CTO_EN | DTO_EN)) hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); else if (status (CCRC_EN | DCRC_EN)) @@ -1081,10 +1085,6 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) } dev_dbg(mmc_dev(host-mmc), AC12 err: 0x%x\n, ac12); } - if (host-data || host-response_busy) { - end_trans = !end_cmd; - host-response_busy = 0; - } } OMAP_HSMMC_WRITE(host-base, STAT, status); -- 2.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in
Re: [PATCH 2/3] mmc: host: omap_hsmmc: Handle BADA, DEB and CEB interrupts
TESTED-BY 2015-06-16 12:37 GMT+02:00 Vignesh R vigne...@ti.com: Sometimes BADA, DEB or CEB error interrupts occur when sd card is unplugged during data transfer. These interrupts are currently ignored by the interrupt handler. But, this results in card not being recognised on subsequent insertion. This is because mmcqd is waiting forever for the data transfer(for which error occurred) to complete. Fix this, by reporting BADA, DEB, CEB errors to mmc-core as -EILSEQ, so that the core can do appropriate handling. Signed-off-by: Vignesh R vigne...@ti.com --- drivers/mmc/host/omap_hsmmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index d0abdffb0d7c..fb4bfefd9250 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1068,7 +1068,8 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) } if (status (CTO_EN | DTO_EN)) hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd); - else if (status (CCRC_EN | DCRC_EN)) + else if (status (CCRC_EN | DCRC_EN | DEB_EN | CEB_EN | + BADA_EN)) hsmmc_command_incomplete(host, -EILSEQ, end_cmd); if (status ACE_EN) { -- 2.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in
Re: [PATCH 3/3] mmc: host: omap_hsmmc: Add custom card detect irq handler
I haven't managed to produce a hang without this patch see also comments below 2015-06-16 12:37 GMT+02:00 Vignesh R vigne...@ti.com: Usually when there is an error in transfer, DTO/CTO or other error interrupts are raised. But if the card is unplugged in the middle of a data transfer, it is observed that, neither completion(success) or timeout(error) interrupts are raised. Hence, the mmc-core is waiting for-ever for the transfer to complete. This results failure to recognise sd card on the next insertion. The only way to solve this is to introduce code to detect this condition and recover on card insertion (in hsmmc specific cd_irq). Hence, introduce cd_irq and add code to clear mmc_request that is pending from the failed transaction. Signed-off-by: Vignesh R vigne...@ti.com --- drivers/mmc/host/omap_hsmmc.c | 73 ++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index fb4bfefd9250..ec1fff3c0c9c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -221,6 +221,12 @@ struct omap_hsmmc_host { #define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_hsmmc_platform_data*pdata; + /* +* flag to determine whether card was removed during data +* transfer +*/ + booltransfer_incomplete; + /* return MMC cover switch state, can be NULL if not supported. * @@ -867,6 +873,26 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req } /* + * Cleanup incomplete card removal sequence. This will make sure the + * next card enumeration is clean. + */ +static void omap_hsmmc_request_clear(struct omap_hsmmc_host *host, +struct mmc_request *mrq) +{ + unsigned long flags; + + spin_lock_irqsave(host-irq_lock, flags); + host-req_in_progress = 0; + host-dma_ch = -1; + spin_unlock_irqrestore(host-irq_lock, flags); + + mmc_request_done(host-mmc, mrq); + if (host-mmc-card) + mmc_card_set_removed(host-mmc-card); + host-mrq = NULL; +} + +/* * Notify the transfer complete to MMC core */ static void @@ -1248,6 +1274,47 @@ static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) return IRQ_HANDLED; } +/* + * irq handler to notify the core about card insertion/removal + */ +static irqreturn_t omap_hsmmc_cd_irq(int irq, void *dev_id) +{ Move this code to 'omap_hsmmc_get_cd' function. Or rather clear any pending transfer upon '.init_card/omap_hsmmc_init_card' I guess other hosts also have some housekeeping upon unexpected card removals. So I guess there is some generic code to this problem. Did you check? + struct omap_hsmmc_host *host = mmc_priv(dev_id); + int carddetect = mmc_gpio_get_cd(host-mmc); + struct mmc_request *mrq = host-mrq; + + /* +* If the card was removed in the middle of data transfer last +* time, the TC/CC/timeout interrupt is not raised due to which +* mmc_request is not cleared. Hence, this card insertion will +* still see pending mmc_request. Clear the request to make sure +* that this card enumeration is successful. +*/ + if (!carddetect mrq host-transfer_incomplete) { + omap_hsmmc_disable_irq(host); + dev_info(host-dev, +card removed during transfer last time\n); + hsmmc_command_incomplete(host, -ENOMEDIUM, 1); + omap_hsmmc_request_clear(host, host-mrq); + dev_info(host-dev, recovery done\n); + } + host-transfer_incomplete = false; + + mmc_detect_change(host-mmc, (HZ * 200) / 1000); + + /* +* The current mmc_request is usually null before card removal +* sequence is complete. It may not be null if TC/CC interrupt +* never happens due to removal of card during a data +* transfer. Set a flag to indicate mmc_request was not null +* in order to do cleanup on next card insertion. +*/ + if (carddetect mrq) + host-transfer_incomplete = true; + + return IRQ_HANDLED; +} + static void omap_hsmmc_dma_callback(void *param) { struct omap_hsmmc_host *host = param; @@ -1918,7 +1985,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) struct mmc_host *mmc; struct omap_hsmmc_host *host = NULL; struct resource *res; - int ret, irq; + int ret, irq, len; const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; @@ -1980,6 +2047,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (ret) goto
[PATCH v2] mmc: sdio: add reset callback to bus operations
Some drivers schedule automatic hw resets. An example is mwifiex, which schedules a card reset if the command handler between driver and card firmware becomes out of sync Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/core/sdio.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index ce6cc47..01255ef 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1064,6 +1064,12 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) return mmc_sdio_power_restore(host); } +static int mmc_sdio_reset(struct mmc_host *host) +{ + mmc_power_cycle(host, host-card-ocr); + return mmc_sdio_power_restore(host); +} + static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, @@ -1074,6 +1080,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = { .runtime_resume = mmc_sdio_runtime_resume, .power_restore = mmc_sdio_power_restore, .alive = mmc_sdio_alive, + .reset = mmc_sdio_reset, }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mmc: pwrseq: dt: example with reset clock and active low pin
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt index a462c50..ce0e767 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt +++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.txt @@ -21,5 +21,7 @@ Example: sdhci0_pwrseq { compatible = mmc-pwrseq-simple; - reset-gpios = gpio1 12 0; + reset-gpios = gpio1 12 GPIO_ACTIVE_LOW; + clocks = clk_32768_ck; + clock-names = ext_clock; } -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mmc: sdio: add reset callback to bus operations
Some drivers schedule automatic hw resets. An example is mwifiex, which schedules a card reset if the command handler between driver and card firmware becomes out of sync Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/core/sdio.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index ce6cc47..01255ef 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -1064,6 +1064,12 @@ static int mmc_sdio_runtime_resume(struct mmc_host *host) return mmc_sdio_power_restore(host); } +static int mmc_sdio_reset(struct mmc_host *host) +{ + mmc_power_cycle(host, host-card-ocr); + return mmc_sdio_power_restore(host); +} + static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, @@ -1074,6 +1080,7 @@ static const struct mmc_bus_ops mmc_sdio_ops = { .runtime_resume = mmc_sdio_runtime_resume, .power_restore = mmc_sdio_power_restore, .alive = mmc_sdio_alive, + .reset = mmc_sdio_reset, }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] ARM: OMAP2: HSMMC: explicit fields to declare cover/card detect pin
board-rx51 has no card detect pin in the mmc slot, but can detect that the (cell-phone) cover has been removed and the card is accessible. The semantics between cover/card detect differ, the gpio on the slot informs you after the card has been removed, cover removal does not necessarily mean that the card has been removed. This means different code paths are necessary. To complete this we also want different fields in the platform data for cover and card detect. This separation is not pushed all the way down into struct omap2_hsmmc_info which is used to initialize the platform data. If we did that we had to go over all board files and set the new gpio_cod pin to -EINVAL. If we forget one board or some out-of-tree archicture forgets that the default '0' is used which is a valid pin number. Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 33 drivers/mmc/host/omap_hsmmc.c| 11 ++- include/linux/platform_data/hsmmc-omap.h | 6 ++ 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index dc6e79c..9a8611a 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -150,9 +150,13 @@ static int nop_mmc_set_power(struct device *dev, int power_on, int vdd) static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data *mmc_controller, int controller_nr) { - if (gpio_is_valid(mmc_controller-switch_pin) - (mmc_controller-switch_pin OMAP_MAX_GPIO_LINES)) - omap_mux_init_gpio(mmc_controller-switch_pin, + if (gpio_is_valid(mmc_controller-gpio_cd) + (mmc_controller-gpio_cd OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-gpio_cd, + OMAP_PIN_INPUT_PULLUP); + if (gpio_is_valid(mmc_controller-gpio_cod) + (mmc_controller-gpio_cod OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-gpio_cod, OMAP_PIN_INPUT_PULLUP); if (gpio_is_valid(mmc_controller-gpio_wp) (mmc_controller-gpio_wp OMAP_MAX_GPIO_LINES)) @@ -250,15 +254,20 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc-internal_clock = !c-ext_clock; mmc-reg_offset = 0; - mmc-switch_pin = c-gpio_cd; + if (c-cover_only) { + /* detect if mobile phone cover removed */ + mmc-gpio_cd = -EINVAL; + mmc-gpio_cod = c-gpio_cd; + } else { + /* card detect pin on the mmc socket itself */ + mmc-gpio_cd = c-gpio_cd; + mmc-gpio_cod = -EINVAL; + } mmc-gpio_wp = c-gpio_wp; mmc-remux = c-remux; mmc-init_card = c-init_card; - if (c-cover_only) - mmc-cover = 1; - if (c-nonremovable) mmc-nonremovable = 1; @@ -358,7 +367,15 @@ void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) if (!mmc_pdata) continue; - mmc_pdata-switch_pin = c-gpio_cd; + if (c-cover_only) { + /* detect if mobile phone cover removed */ + mmc_pdata-gpio_cd = -EINVAL; + mmc_pdata-gpio_cod = c-gpio_cd; + } else { + /* card detect pin on the mmc socket itself */ + mmc_pdata-gpio_cd = c-gpio_cd; + mmc_pdata-gpio_cod = -EINVAL; + } mmc_pdata-gpio_wp = c-gpio_wp; res = omap_device_register(pdev); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 053cd38..265391f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -427,15 +427,15 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, { int ret; - if (pdata-cover gpio_is_valid(pdata-switch_pin)) { - ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0); + if (gpio_is_valid(pdata-gpio_cod)) { + ret = mmc_gpio_request_cd(mmc, pdata-gpio_cod, 0); if (ret) return ret; host-get_cover_state = omap_hsmmc_get_cover_state; mmc_gpio_set_cd_isr(mmc, omap_hsmmc_cover_irq); - } else if (!pdata-cover gpio_is_valid(pdata-switch_pin)) { - ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0); + } else if (gpio_is_valid(pdata-gpio_cd)) { + ret = mmc_gpio_request_cd(mmc, pdata-gpio_cd, 0); if (ret) return ret; @@ -1932,7 +1932,8 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) if (of_find_property(np, ti,dual-volt, NULL)) pdata-controller_flags
Re: [PATCH 0/6] mmc: omap_hsmmc: simplify cover/card detect logic
2015-03-04 6:31 GMT+01:00 NeilBrown ne...@suse.de: On Tue, 3 Mar 2015 13:28:12 +0100 Andreas Fenkart afenk...@gmail.com wrote: While cover detect is only used by one platform (rx51), it complicates the card detect logic. By separating the code paths they both become easier to understand and maintain Patches have been tested by reverting: 95bebb5696ab 'mmc: omap_hsmmc: use mmc_of_parse to parse common mmc configuration' otherwise gpio detection is handled by mmc_of_parse Wouldn't it make more sense to put this core in mmc/core rather than in just one host controller? Yes, I would very welcome that, since it would free the omap_hsmmc of the 'protection' mechanism that makes the driver clumsy. But as an initial step separating cover from card detect already seems enough for this series. Another thought was, that since only one platform is using it, the prospect of getting it merged into the core was minimal. That way it would be available to all hosts, and you wouldn't need to revert that patch. Oh sorry, seems I was unclear. I definitely do not want to revert that patch permanently, the opposite is true, I very much welcome it. Thanks for your work by the way. I only reverted it temporarily so I could test that the card detect logic still works with legacy board files, non-device-tree platforms. But since mmc_of_parse is setting the card detect pin, my changes could not be tested with my device-tree platform (bbone). So I reverted the above patch only for testing, afterwards I rebased the patches on top of it, before submitting Andreas -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/6] mmc: omap_hsmmc: use distinctive code paths for cover / card detect logic
Mobile phones (some) have no card detect pin, but can detect if the cover is removed. The purpose is the same; detect if card is being added/removed, but the details differ. When the cover is removed, it does not mean the card is gone. But it might, since it is accessible now. It's like a warning. All the driver does is to limit write access to the card, see protect_card flag. In contrast, card detect notifies us after the fact, e.g. card is gone, card is inserted. We can't take precautions, but we can rely on those events, -- the card is really gone, or do scan the card. To summarize there is not much code sharing between cover and card detect, it only increases confusion. By splitting, both will be simplified in a followup patch. Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 56 +-- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 77ad471..38239fb 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -230,9 +230,6 @@ struct omap_hsmmc_host { */ int (*get_cover_state)(struct device *dev); - /* Card detection IRQs */ - int card_detect_irq; - int (*card_detect)(struct device *dev); }; @@ -422,6 +419,7 @@ static inline int omap_hsmmc_have_reg(void) #endif static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id); +static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id); static int omap_hsmmc_gpio_init(struct mmc_host *mmc, struct omap_hsmmc_host *host, @@ -429,20 +427,20 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, { int ret; - if (gpio_is_valid(pdata-switch_pin)) { - if (pdata-cover) - host-get_cover_state = - omap_hsmmc_get_cover_state; - else - host-card_detect = omap_hsmmc_card_detect; - host-card_detect_irq = - gpio_to_irq(pdata-switch_pin); - mmc_gpio_set_cd_isr(mmc, omap_hsmmc_detect); + if (pdata-cover gpio_is_valid(pdata-switch_pin)) { ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0); if (ret) return ret; - } else { - pdata-switch_pin = -EINVAL; + + host-get_cover_state = omap_hsmmc_get_cover_state; + mmc_gpio_set_cd_isr(mmc, omap_hsmmc_cover_irq); + } else if (!pdata-cover gpio_is_valid(pdata-switch_pin)) { + ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0); + if (ret) + return ret; + + host-card_detect = omap_hsmmc_card_detect; + mmc_gpio_set_cd_isr(mmc, omap_hsmmc_detect); } if (gpio_is_valid(pdata-gpio_wp)) { @@ -1236,15 +1234,37 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) } /* - * irq handler to notify the core about card insertion/removal + * irq handler when (cell-phone) cover is mounted/removed */ -static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) +static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; int carddetect; sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); + if (host-card_detect) { + carddetect = host-card_detect(host-dev); + } else { + omap_hsmmc_protect_card(host); + carddetect = -ENOSYS; + } + + if (carddetect) + mmc_detect_change(host-mmc, (HZ * 200) / 1000); + else + mmc_detect_change(host-mmc, (HZ * 50) / 1000); + return IRQ_HANDLED; +} + +/* + * irq handler to notify the core about card insertion/removal + */ +static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) +{ + struct omap_hsmmc_host *host = dev_id; + int carddetect; + if (host-card_detect) carddetect = host-card_detect(host-dev); else { @@ -2164,9 +2184,9 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (ret 0) goto err_slot_name; } - if (host-card_detect_irq host-get_cover_state) { + if (host-get_cover_state) { ret = device_create_file(mmc-class_dev, - dev_attr_cover_switch); +dev_attr_cover_switch); if (ret 0) goto err_slot_name; } -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/6] ARM: OMAP2: HSMMC: platform_data: explicit gpio_cover / gpio_cd fields
Cover detection and card detection are not equivalent, cover detection is like a warning that something might happen (cover removed, card is accessible), card detection a notification that something has happened. You could use both in parallel. Technically this is not possible, since there is only one gpio for both and a 'cover' flag to indicate either or. With this commit we push that de-multiplexing of that gpio + flag out of the driver into the platform specific init code. It's not pushed down into omap2_hsmmc_info which is used to initialize the platform data, since we would have to go over all board files and set the new gpio_cover pin to -EINVAL. That would be dangerous since '0' is a valid pin number. FYI: only board-rx51 uses cover_only detection Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 33 drivers/mmc/host/omap_hsmmc.c| 11 ++- include/linux/platform_data/hsmmc-omap.h | 6 ++ 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index dc6e79c..0e54aac 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -150,9 +150,13 @@ static int nop_mmc_set_power(struct device *dev, int power_on, int vdd) static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data *mmc_controller, int controller_nr) { - if (gpio_is_valid(mmc_controller-switch_pin) - (mmc_controller-switch_pin OMAP_MAX_GPIO_LINES)) - omap_mux_init_gpio(mmc_controller-switch_pin, + if (gpio_is_valid(mmc_controller-gpio_cd) + (mmc_controller-gpio_cd OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-gpio_cd, + OMAP_PIN_INPUT_PULLUP); + if (gpio_is_valid(mmc_controller-gpio_cover) + (mmc_controller-gpio_cover OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-gpio_cover, OMAP_PIN_INPUT_PULLUP); if (gpio_is_valid(mmc_controller-gpio_wp) (mmc_controller-gpio_wp OMAP_MAX_GPIO_LINES)) @@ -250,15 +254,20 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc-internal_clock = !c-ext_clock; mmc-reg_offset = 0; - mmc-switch_pin = c-gpio_cd; + if (c-cover_only) { + /* detect if mobile phone cover removed */ + mmc-gpio_cd = -EINVAL; + mmc-gpio_cover = c-gpio_cd; + } else { + /* card detect pin on the mmc socket itself */ + mmc-gpio_cd = c-gpio_cd; + mmc-gpio_cover = -EINVAL; + } mmc-gpio_wp = c-gpio_wp; mmc-remux = c-remux; mmc-init_card = c-init_card; - if (c-cover_only) - mmc-cover = 1; - if (c-nonremovable) mmc-nonremovable = 1; @@ -358,7 +367,15 @@ void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) if (!mmc_pdata) continue; - mmc_pdata-switch_pin = c-gpio_cd; + if (c-cover_only) { + /* detect if mobile phone cover removed */ + mmc_pdata-gpio_cd = -EINVAL; + mmc_pdata-gpio_cover = c-gpio_cd; + } else { + /* card detect pin on the mmc socket itself */ + mmc_pdata-gpio_cd = c-gpio_cd; + mmc_pdata-gpio_cover = -EINVAL; + } mmc_pdata-gpio_wp = c-gpio_wp; res = omap_device_register(pdev); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 38239fb..ed68e55 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -427,15 +427,15 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, { int ret; - if (pdata-cover gpio_is_valid(pdata-switch_pin)) { - ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0); + if (gpio_is_valid(pdata-gpio_cover)) { + ret = mmc_gpio_request_cd(mmc, pdata-gpio_cover, 0); if (ret) return ret; host-get_cover_state = omap_hsmmc_get_cover_state; mmc_gpio_set_cd_isr(mmc, omap_hsmmc_cover_irq); - } else if (!pdata-cover gpio_is_valid(pdata-switch_pin)) { - ret = mmc_gpio_request_cd(mmc, pdata-switch_pin, 0); + } else if (gpio_is_valid(pdata-gpio_cd)) { + ret = mmc_gpio_request_cd(mmc, pdata-gpio_cd, 0); if (ret) return ret; @@ -1932,7 +1932,8 @@ static struct omap_hsmmc_platform_data *of_get_hsmmc_pdata(struct device *dev) if (of_find_property(np, ti,dual-volt, NULL)) pdata-controller_flags |= OMAP_HSMMC_SUPPORTS_DUAL_VOLT
[PATCH 5/6] mmc: omap_hsmmc: simplify card/cover detect isr
strip the card dectet logic from cover detect isr and vice versa the generic mmc_gpio_cd_irqt isr, uses 200ms on removal/insertion, hence that should be fine here as well Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 27 +++ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index ed68e55..4f6fbe5 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1239,21 +1239,11 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - int carddetect; sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); - if (host-card_detect) { - carddetect = host-card_detect(host-dev); - } else { - omap_hsmmc_protect_card(host); - carddetect = -ENOSYS; - } - - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); + omap_hsmmc_protect_card(host); + mmc_detect_change(host-mmc, (HZ * 200) / 1000); return IRQ_HANDLED; } @@ -1263,19 +1253,8 @@ static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - int carddetect; - - if (host-card_detect) - carddetect = host-card_detect(host-dev); - else { - omap_hsmmc_protect_card(host); - carddetect = -ENOSYS; - } - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); + mmc_detect_change(host-mmc, (HZ * 200) / 1000); return IRQ_HANDLED; } -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/6] mmc: omap_hsmmc: use slot-gpio functions to manage read-only pin directly
The indirection via omap_hsmmc_get_ro and omap_hsmmc_get_wp is redundant. Also dropped setting gpio_wp to EINVAL since platform date is read-only Untested: no device with ro pin was available, but change is fairly simple Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 23 +-- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2276d58..77ad471 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -234,8 +234,6 @@ struct omap_hsmmc_host { int card_detect_irq; int (*card_detect)(struct device *dev); - int (*get_ro)(struct device *dev); - }; struct omap_mmc_of_data { @@ -252,13 +250,6 @@ static int omap_hsmmc_card_detect(struct device *dev) return mmc_gpio_get_cd(host-mmc); } -static int omap_hsmmc_get_wp(struct device *dev) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - - return mmc_gpio_get_ro(host-mmc); -} - static int omap_hsmmc_get_cover_state(struct device *dev) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -455,12 +446,9 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, } if (gpio_is_valid(pdata-gpio_wp)) { - host-get_ro = omap_hsmmc_get_wp; ret = mmc_gpio_request_ro(mmc, pdata-gpio_wp); if (ret) return ret; - } else { - pdata-gpio_wp = -EINVAL; } return 0; @@ -1637,15 +1625,6 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) return host-card_detect(host-dev); } -static int omap_hsmmc_get_ro(struct mmc_host *mmc) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - if (!host-get_ro) - return -ENOSYS; - return host-get_ro(host-dev); -} - static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) { struct omap_hsmmc_host *host = mmc_priv(mmc); @@ -1811,7 +1790,7 @@ static struct mmc_host_ops omap_hsmmc_ops = { .request = omap_hsmmc_request, .set_ios = omap_hsmmc_set_ios, .get_cd = omap_hsmmc_get_cd, - .get_ro = omap_hsmmc_get_ro, + .get_ro = mmc_gpio_get_ro, .init_card = omap_hsmmc_init_card, .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/6] mmc: omap_hsmmc: simplify cover/card detect logic
These patches are trying to clean up the cover/card detect logic. Mobile phones (some) have no card detect pin, but can detect if the cover is removed. The purpose is the same; detect if card is being added/removed, but the details differ. When the cover is removed, it does not mean the card is gone. But it might, since it is accessible now. It's like a warning. All the driver does is to limit write access to the card, see protect_card flag. In contrast, card detect notifies us after the fact, e.g. card is gone, card is inserted. While cover detect is only used by one platform (rx51), it complicates the card detect logic. By separating the code paths they both become easier to understand and maintain Patches have been tested by reverting: 95bebb5696ab 'mmc: omap_hsmmc: use mmc_of_parse to parse common mmc configuration' otherwise gpio detection is handled by mmc_of_parse compile tested OMAP2: CONFIG_MACH_OMAP2_TUSB6010=y CONFIG_MACH_OMAP3_BEAGLE=y CONFIG_MACH_DEVKIT8000=y CONFIG_MACH_OMAP_LDP=y CONFIG_MACH_OMAP3530_LV_SOM=y CONFIG_MACH_OMAP3_TORPEDO=y CONFIG_MACH_OVERO=y CONFIG_MACH_OMAP3517EVM=y CONFIG_MACH_CRANEBOARD=y CONFIG_MACH_OMAP3_PANDORA=y CONFIG_MACH_TOUCHBOOK=y CONFIG_MACH_OMAP_3430SDP=y CONFIG_MACH_NOKIA_N810=y CONFIG_MACH_NOKIA_N810_WIMAX=y CONFIG_MACH_NOKIA_N8X0=y CONFIG_MACH_NOKIA_RX51=y CONFIG_MACH_CM_T35=y CONFIG_MACH_CM_T3517=y CONFIG_MACH_CM_T3730=y CONFIG_MACH_SBC3530=y CONFIG_MACH_TI8168EVM=y CONFIG_MACH_TI8148EVM=y Andreas Fenkart (6): mmc: omap_hsmmc: remove unused fields from struct omap_hsmmc_host mmc: omap_hsmmc: use slot-gpio functions to manage read-only pin directly mmc: omap_hsmmc: use distinctive code paths for cover / card detect logic ARM: OMAP2: HSMMC: platform_data: explicit gpio_cover / gpio_cd fields mmc: omap_hsmmc: simplify card/cover detect isr mmc: omap_hsmmc: use generic slot-gpio isr to manage card detect pin arch/arm/mach-omap2/hsmmc.c | 33 + drivers/mmc/host/omap_hsmmc.c| 80 +--- include/linux/platform_data/hsmmc-omap.h | 6 +-- 3 files changed, 48 insertions(+), 71 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/6] mmc: omap_hsmmc: remove unused fields from struct omap_hsmmc_host
addon to: 09108968b7b72b6083a3bfc8f8259a74ed57255e mmc: omap_hsmmc: remove prepare/complete system suspend support Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 4 1 file changed, 4 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 8d87e08..2276d58 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -222,10 +222,6 @@ struct omap_hsmmc_host { struct omap_hsmmc_next next_data; struct omap_hsmmc_platform_data*pdata; - /* To handle board related suspend/resume functionality for MMC */ - int (*suspend)(struct device *dev); - int (*resume)(struct device *dev); - /* return MMC cover switch state, can be NULL if not supported. * * possible return values: -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/6] mmc: omap_hsmmc: use generic slot-gpio isr to manage card detect pin
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 13 - 1 file changed, 13 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4f6fbe5..0c3368e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -418,7 +418,6 @@ static inline int omap_hsmmc_have_reg(void) #endif -static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id); static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id); static int omap_hsmmc_gpio_init(struct mmc_host *mmc, @@ -440,7 +439,6 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, return ret; host-card_detect = omap_hsmmc_card_detect; - mmc_gpio_set_cd_isr(mmc, omap_hsmmc_detect); } if (gpio_is_valid(pdata-gpio_wp)) { @@ -1247,17 +1245,6 @@ static irqreturn_t omap_hsmmc_cover_irq(int irq, void *dev_id) return IRQ_HANDLED; } -/* - * irq handler to notify the core about card insertion/removal - */ -static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) -{ - struct omap_hsmmc_host *host = dev_id; - - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - return IRQ_HANDLED; -} - static void omap_hsmmc_dma_callback(void *param) { struct omap_hsmmc_host *host = param; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFC PATCH 2/3] mmc: omap_hsmmc: add tuning support
2014-11-13 13:56 GMT+01:00 Kishon Vijay Abraham I kis...@ti.com: From: Balaji T K balaj...@ti.com MMC tuning procedure is required to support SD card UHS1-SDR104 mode and EMMC HS200 mode. The tuning function omap_execute_tuning() will only be called by the MMC/SD core if the corresponding speed modes are supported by the OMAP silicon which is set in the mmc host caps field. Signed-off-by: Viswanath Puttagunta vi...@ti.com Signed-off-by: Sourav Poddar sourav.pod...@ti.com [ kis...@ti.com : Set the functional clock to 192MHz if the contoller supports HS200 ] Signed-off-by: Kishon Vijay Abraham I kis...@ti.com --- drivers/mmc/host/omap_hsmmc.c | 325 - 1 file changed, 322 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2e42ed3..675bd31d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -22,6 +22,7 @@ #include linux/dmaengine.h #include linux/seq_file.h #include linux/sizes.h +#include linux/slab.h #include linux/interrupt.h #include linux/delay.h #include linux/dma-mapping.h @@ -47,6 +48,7 @@ /* OMAP HSMMC Host Controller Registers */ #define OMAP_HSMMC_SYSSTATUS 0x0014 #define OMAP_HSMMC_CON 0x002C +#define OMAP_HSMMC_DLL 0x0034 #define OMAP_HSMMC_SDMASA 0x0100 #define OMAP_HSMMC_BLK 0x0104 #define OMAP_HSMMC_ARG 0x0108 @@ -100,6 +102,7 @@ #define CLKEXTFREE (1 16) #define CTPL (1 11) #define DW8(1 5) +#define BRR(1 5) #define OD 0x1 #define STAT_CLEAR 0x #define INIT_STREAM_CMD0x @@ -129,6 +132,20 @@ #define CERR_EN(1 28) #define BADA_EN(1 29) +#define V1V8_SIGEN (1 19) +#define AC12_SCLK_SEL (1 23) +#define AC12_UHSMC_MASK(7 16) +#define AC12_UHSMC_SDR50 (2 16) +#define AC12_UHSMC_SDR104 (3 16) +#define DLL_LOCK (1 0) +#define DLL_CALIB (1 1) +#define DLL_UNLOCK_STICKY (1 2) +#define DLL_SWT(1 20) +#define DLL_FORCE_SR_C_MASK(0x7F 13) +#define DLL_FORCE_SR_C_SHIFT 13 +#define DLL_FORCE_VALUE(1 12) +#define DLL_RESET (1 31) + #define INT_EN_MASK (BADA_EN | CERR_EN | ACE_EN | DEB_EN | DCRC_EN |\ DTO_EN | CIE_EN | CEB_EN | CCRC_EN | CTO_EN | \ BRR_EN | BWR_EN | TC_EN | CC_EN) @@ -143,18 +160,23 @@ #define SDR50 (1 0) #define SDR104 (1 1) #define DDR50 (1 2) +#define CAPA2_TSDR50 (1 13) #define MMC_AUTOSUSPEND_DELAY 100 #define MMC_TIMEOUT_MS 20 /* 20 mSec */ #define MMC_TIMEOUT_US 2 /* 2 micro Sec */ #define OMAP_MMC_MIN_CLOCK 40 #define OMAP_MMC_MAX_CLOCK 5200 +#define MAX_PHASE_DELAY0x7F #define DRIVER_NAMEomap_hsmmc #define VDD_1V8180 /* 18 uV */ #define VDD_3V0300 /* 30 uV */ #define VDD_165_195(ffs(MMC_VDD_165_195) - 1) +#define EMMC_HSDDR_SD_SDR25_MAX5200 +#define SD_SDR50_MAX_FREQ 10400 + /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -198,6 +220,7 @@ struct omap_hsmmc_host { void__iomem *base; resource_size_t mapbase; spinlock_t irq_lock; /* Prevent races with irq handler */ + struct completion buf_ready; unsigned intdma_len; unsigned intdma_sg_idx; unsigned char bus_mode; @@ -224,6 +247,13 @@ struct omap_hsmmc_host { #define AUTO_CMD23 (1 0)/* Auto CMD23 support */ #define HSMMC_SDIO_IRQ_ENABLED (1 1)/* SDIO irq enabled */ #define HSMMC_WAKE_IRQ_ENABLED (1 2) + + u32 *tuning_data; + int tuning_size; + int tuning_done; + int tuning_fsrc; + u32 tuning_uhsmc; + u32 tuning_opcode; struct omap_hsmmc_next next_data; struct omap_mmc_platform_data *pdata; }; @@ -233,6 +263,48 @@ struct omap_mmc_of_data { u8 controller_flags; }; +static const u32 ref_tuning_4bits[] = { + 0x00FF0FFF, 0xCCC3CCFF, 0xFFCC3CC3, 0xEFFEFFFE, + 0xDDFFDFFF, 0xFBFFFBFF, 0xFF7FFFBF, 0xEFBDF777, + 0xF0FFF0FF, 0x3CCCFC0F, 0xCFCC33CC, 0xEEFFEFFF, + 0xFDFFFDFF, 0xFFBFFFDF, 0xFFF7FFBB, 0xDE7B7FF7 +}; + +static const u32 ref_tuning_8bits[]
[PATCH v4 10/10] omap_hsmmc: remove unused slot_id parameter
omap_hsmmc only supports one slot. So slot id is always zero, and slot id was never used in the callbacks anyway Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +- arch/arm/mach-omap2/hsmmc.c | 21 - arch/arm/mach-omap2/hsmmc.h | 2 +- drivers/mmc/host/omap_hsmmc.c| 65 +++- include/linux/platform_data/hsmmc-omap.h | 14 ++ 5 files changed, 40 insertions(+), 64 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 0a8ac84..3d5040f 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -484,7 +484,7 @@ static struct omap_mux_partition *partition; * Current flows to eMMC when eMMC is off and the data lines are pulled up, * so pull them down. N.B. we pull 8 lines because we are using 8 lines. */ -static void rx51_mmc2_remux(struct device *dev, int slot, int power_on) +static void rx51_mmc2_remux(struct device *dev, int power_on) { if (power_on) omap_mux_write_array(partition, rx51_mmc2_on_mux); diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 4e2896a..dc6e79c 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -33,14 +33,14 @@ static u16 control_devconf1_offset; #define HSMMC_NAME_LEN 9 -static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, - int power_on, int vdd) +static void omap_hsmmc1_before_set_reg(struct device *dev, + int power_on, int vdd) { u32 reg, prog_io; struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-remux) - mmc-remux(dev, slot, power_on); + mmc-remux(dev, power_on); /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the @@ -86,8 +86,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, } } -static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, -int power_on, int vdd) +static void omap_hsmmc1_after_set_reg(struct device *dev, int power_on, int vdd) { u32 reg; @@ -122,20 +121,18 @@ static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) omap_ctrl_writel(reg, control_devconf1_offset); } -static void hsmmc2_before_set_reg(struct device *dev, int slot, - int power_on, int vdd) +static void hsmmc2_before_set_reg(struct device *dev, int power_on, int vdd) { struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-remux) - mmc-remux(dev, slot, power_on); + mmc-remux(dev, power_on); if (power_on) hsmmc2_select_input_clk_src(mmc); } -static int am35x_hsmmc2_set_power(struct device *dev, int slot, - int power_on, int vdd) +static int am35x_hsmmc2_set_power(struct device *dev, int power_on, int vdd) { struct omap_hsmmc_platform_data *mmc = dev-platform_data; @@ -145,8 +142,7 @@ static int am35x_hsmmc2_set_power(struct device *dev, int slot, return 0; } -static int nop_mmc_set_power(struct device *dev, int slot, int power_on, - int vdd) +static int nop_mmc_set_power(struct device *dev, int power_on, int vdd) { return 0; } @@ -250,7 +246,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, snprintf(hc_name, (HSMMC_NAME_LEN + 1), mmc%islot%i, c-mmc, 1); mmc-name = hc_name; - mmc-nr_slots = 1; mmc-caps = c-caps; mmc-internal_clock = !c-ext_clock; mmc-reg_offset = 0; diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 30c78c1..148cd9b 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -23,7 +23,7 @@ struct omap2_hsmmc_info { struct platform_device *pdev; /* mmc controller instance */ int ocr_mask; /* temporary HACK */ /* Remux (pad configuration) when powering on/off */ - void (*remux)(struct device *dev, int slot, int power_on); + void (*remux)(struct device *dev, int power_on); /* init some special card */ void (*init_card)(struct mmc_card *card); }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f4f1bcd..82b40b8 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -207,7 +207,6 @@ struct omap_hsmmc_host { int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; - int
[PATCH v4 09/10] omap_hsmmc: Remove unnecessary callbacks from platform data
These callbacks are set during driver probe and not from the platform init, -- evtl. they had been for oamp 1/2 -- for omap3 they are local functions of the driver. These indirection could be dropped altogether in favor of regular function calls TODO Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c| 75 +++- include/linux/platform_data/hsmmc-omap.h | 18 2 files changed, 45 insertions(+), 48 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 8a216c9..f4f1bcd 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -221,6 +221,25 @@ struct omap_hsmmc_host { #define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_hsmmc_platform_data*pdata; + + /* To handle board related suspend/resume functionality for MMC */ + int (*suspend)(struct device *dev, int slot); + int (*resume)(struct device *dev, int slot); + + /* return MMC cover switch state, can be NULL if not supported. +* +* possible return values: +* 0 - closed +* 1 - open +*/ + int (*get_cover_state)(struct device *dev, int slot); + + /* Card detection IRQs */ + int card_detect_irq; + + int (*card_detect)(struct device *dev, int slot); + int (*get_ro)(struct device *dev, int slot); + }; struct omap_mmc_of_data { @@ -262,18 +281,16 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_hsmmc_platform_data *mmc = host-pdata; - disable_irq(mmc-card_detect_irq); + disable_irq(host-card_detect_irq); return 0; } static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_hsmmc_platform_data *mmc = host-pdata; - enable_irq(mmc-card_detect_irq); + enable_irq(host-card_detect_irq); return 0; } @@ -456,11 +473,11 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, if (gpio_is_valid(pdata-switch_pin)) { if (pdata-cover) - pdata-get_cover_state = - omap_hsmmc_get_cover_state; + host-get_cover_state = + omap_hsmmc_get_cover_state; else - pdata-card_detect = omap_hsmmc_card_detect; - pdata-card_detect_irq = + host-card_detect = omap_hsmmc_card_detect; + host-card_detect_irq = gpio_to_irq(pdata-switch_pin); ret = gpio_request(pdata-switch_pin, mmc_cd); if (ret) @@ -473,7 +490,7 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, } if (gpio_is_valid(pdata-gpio_wp)) { - pdata-get_ro = omap_hsmmc_get_wp; + host-get_ro = omap_hsmmc_get_wp; ret = gpio_request(pdata-gpio_wp, mmc_wp); if (ret) goto err_free_cd; @@ -795,8 +812,8 @@ int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) { int r = 1; - if (mmc_pdata(host)-get_cover_state) - r = mmc_pdata(host)-get_cover_state(host-dev, host-slot_id); + if (host-get_cover_state) + r = host-get_cover_state(host-dev, host-slot_id); return r; } @@ -1263,11 +1280,11 @@ err: /* Protect the card while the cover is open */ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) { - if (!mmc_pdata(host)-get_cover_state) + if (!host-get_cover_state) return; host-reqs_blocked = 0; - if (mmc_pdata(host)-get_cover_state(host-dev, host-slot_id)) { + if (host-get_cover_state(host-dev, host-slot_id)) { if (host-protect_card) { dev_info(host-dev, %s: cover is closed, card is now accessible\n, @@ -1290,13 +1307,12 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_hsmmc_platform_data *pdata = host-pdata; int carddetect; sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); - if (pdata-card_detect) - carddetect = pdata-card_detect(host-dev, host-slot_id); + if (host-card_detect) + carddetect = host-card_detect(host-dev, host-slot_id); else { omap_hsmmc_protect_card(host); carddetect = -ENOSYS; @@ -1672,18 +1688,18 @@ static int
[PATCH v4 00/10] ARM: OMAP1/2+: MMC: separate platform data for mmc and mmc hs driver
v4: - rework patch descriptions - dropped patch removing unused defines in mach-omap2/mmc.h - rebase 3.18.0-rc3 - compile test omap1 and omap2 compile tested OMAP1: CONFIG_MACH_OMAP_INNOVATOR=y CONFIG_MACH_OMAP_H2=y CONFIG_MACH_OMAP_H3=y CONFIG_MACH_HERALD=y CONFIG_MACH_OMAP_OSK=y CONFIG_MACH_OMAP_PERSEUS2=y CONFIG_MACH_OMAP_FSAMPLE=y CONFIG_MACH_VOICEBLUE=y CONFIG_MACH_OMAP_PALMTE=y CONFIG_MACH_OMAP_PALMZ71=y CONFIG_MACH_OMAP_PALMTT=y CONFIG_MACH_SX1=y CONFIG_MACH_NOKIA770=y CONFIG_MACH_AMS_DELTA=y CONFIG_MACH_OMAP_GENERIC=y OMAP2: CONFIG_MACH_OMAP2_TUSB6010=y CONFIG_MACH_OMAP3_BEAGLE=y CONFIG_MACH_DEVKIT8000=y CONFIG_MACH_OMAP_LDP=y CONFIG_MACH_OMAP3530_LV_SOM=y CONFIG_MACH_OMAP3_TORPEDO=y CONFIG_MACH_OVERO=y CONFIG_MACH_OMAP3517EVM=y CONFIG_MACH_CRANEBOARD=y CONFIG_MACH_OMAP3_PANDORA=y CONFIG_MACH_TOUCHBOOK=y CONFIG_MACH_OMAP_3430SDP=y CONFIG_MACH_NOKIA_N810=y CONFIG_MACH_NOKIA_N810_WIMAX=y CONFIG_MACH_NOKIA_N8X0=y CONFIG_MACH_NOKIA_RX51=y CONFIG_MACH_CM_T35=y CONFIG_MACH_CM_T3517=y CONFIG_MACH_CM_T3730=y CONFIG_MACH_SBC3530=y CONFIG_MACH_TI8168EVM=y CONFIG_MACH_TI8148EVM=y Andreas Fenkart (10): ARM: OMAP2: MMC: include mmc-omap platform header directly ARM: OMAP1/2+: MMC: separate platform data for mmc and mmc hs driver omap_hsmmc: remove unused fields in platform_data omap_hsmmc: remove un-initialized callbacks from platform data omap_hsmmc: remove never read power_saving field in omap2_hsmmc_info omap_hsmmc: remove unused get_context_loss_count callback omap_hsmmc: remove unnecessary omap_hsmmc_slot_data indirection omap_hsmmc: pass mmc_priv struct to gpio init / free omap_hsmmc: Remove unnecessary callbacks from platform data omap_hsmmc: remove unused slot_id parameter arch/arm/mach-omap2/board-n8x0.c | 2 + arch/arm/mach-omap2/board-rx51-peripherals.c | 4 +- arch/arm/mach-omap2/hsmmc.c| 158 +--- arch/arm/mach-omap2/hsmmc.h| 9 +- arch/arm/mach-omap2/mmc.h | 10 - arch/arm/mach-omap2/omap4-common.c | 1 - arch/arm/mach-omap2/omap_hwmod_2430_data.c | 4 +- .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 - arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 4 +- drivers/mmc/host/omap_hsmmc.c | 282 ++--- include/linux/platform_data/hsmmc-omap.h | 90 +++ include/linux/platform_data/mmc-omap.h | 27 -- 16 files changed, 312 insertions(+), 304 deletions(-) create mode 100644 include/linux/platform_data/hsmmc-omap.h -- 2.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 03/10] omap_hsmmc: remove unused fields in platform_data
platform data is built from omap2_hsmmc_info, remove all fields that are never set in omap_hsmmc_info, hence never copied to platform data. Note that the omap_hsmmc driver is not affected by this patch those fields were completely unused. Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 14 -- arch/arm/mach-omap2/hsmmc.h | 6 -- include/linux/platform_data/hsmmc-omap.h | 19 --- 3 files changed, 39 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 9edd759..75b75b9 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -263,9 +263,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-max_freq = c-max_freq; mmc-reg_offset = 0; mmc-get_context_loss_count = hsmmc_get_context_loss; @@ -281,18 +279,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, if (c-nonremovable) mmc-slots[0].nonremovable = 1; - if (c-power_saving) - mmc-slots[0].power_saving = 1; - - if (c-no_off) - mmc-slots[0].no_off = 1; - - if (c-no_off_init) - mmc-slots[0].no_regulator_off_init = c-no_off_init; - - if (c-vcc_aux_disable_is_sleep) - mmc-slots[0].vcc_aux_disable_is_sleep = 1; - /* * NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 7f2e790..bdc8870 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -12,23 +12,17 @@ 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 */ booltransceiver;/* MMC-2 option */ boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ boolnonremovable; /* Nonremovable e.g. eMMC */ boolpower_saving; /* Try to sleep or power off when possible */ - boolno_off; /* power_saving and power is not to go off */ - boolno_off_init;/* no power off when not in MMC sleep state */ - boolvcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */ booldeferred; /* mmc needs a deferred probe */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ char*name; /* or NULL for default */ struct platform_device *pdev; /* mmc controller instance */ int ocr_mask; /* temporary HACK */ - int max_freq; /* maximum clock, if constrained by external -* circuitry, or 0 for default */ /* Remux (pad configuration) when powering on/off */ void (*remux)(struct device *dev, int slot, int power_on); /* init some special card */ diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 7dd42e5..11d7ed9 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -73,16 +73,9 @@ struct omap_hsmmc_platform_data { * 4/8 wires and any additional host capabilities * need to OR'd all capabilities (ref. linux/mmc/host.h) */ - 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 -* that board-specific code handled it before common init logic. -*/ - unsigned nomux:1; - /* switch pin can be for card detect (default) or card cover */ unsigned cover:1; @@ -92,18 +85,9 @@ struct omap_hsmmc_platform_data { /* nonremovable e.g. eMMC */ unsigned nonremovable:1; - /* Try to sleep or power off when possible */ - unsigned power_saving:1; - - /* If using power_saving and the MMC power is not to go off */ - unsigned no_off:1; - /* eMMC does not handle power off when not in sleep state */ unsigned no_regulator_off_init:1; - /* Regulator off
[PATCH v4 04/10] omap_hsmmc: remove un-initialized callbacks from platform data
these callbacks are not set, probably legacy omap 1/2 features Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c| 15 +-- include/linux/platform_data/hsmmc-omap.h | 9 - 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4957c5f..03e8e9a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2204,18 +2204,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) goto err_irq; } - if (pdata-init != NULL) { - if (pdata-init(pdev-dev) != 0) { - dev_err(mmc_dev(host-mmc), - Unable to configure MMC IRQs\n); - goto err_irq; - } - } - if (omap_hsmmc_have_reg() !mmc_slot(host).set_power) { ret = omap_hsmmc_reg_get(host); if (ret) - goto err_reg; + goto err_irq; host-use_reg = 1; } @@ -2278,9 +2270,6 @@ err_slot_name: err_irq_cd: if (host-use_reg) omap_hsmmc_reg_put(host); -err_reg: - if (host-pdata-cleanup) - host-pdata-cleanup(pdev-dev); err_irq: if (host-tx_chan) dma_release_channel(host-tx_chan); @@ -2306,8 +2295,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) mmc_remove_host(host-mmc); if (host-use_reg) omap_hsmmc_reg_put(host); - if (host-pdata-cleanup) - host-pdata-cleanup(pdev-dev); if (host-tx_chan) dma_release_channel(host-tx_chan); diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 11d7ed9..7e70e15 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -47,14 +47,6 @@ struct omap_hsmmc_platform_data { * maximum frequency on the MMC bus */ unsigned int max_freq; - /* switch the bus to a new slot */ - int (*switch_slot)(struct device *dev, int slot); - /* initialize board-specific MMC functionality, can be NULL if -* not supported */ - int (*init)(struct device *dev); - void (*cleanup)(struct device *dev); - void (*shutdown)(struct device *dev); - /* To handle board related suspend/resume functionality for MMC */ int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); @@ -97,7 +89,6 @@ struct omap_hsmmc_platform_data { int switch_pin; /* gpio (card detect) */ int gpio_wp;/* gpio (write protect) */ - int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); int (*set_power)(struct device *dev, int slot, int power_on, int vdd); int (*get_ro)(struct device *dev, int slot); -- 2.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 05/10] omap_hsmmc: remove never read power_saving field in omap2_hsmmc_info
these fields are never read, probably an unimplemented feature or superseded by pm_runtime Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/board-rx51-peripherals.c | 2 -- arch/arm/mach-omap2/hsmmc.h | 1 - 2 files changed, 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index ddfc8df..0a8ac84 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -500,7 +500,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = { .cover_only = true, .gpio_cd= 160, .gpio_wp= -EINVAL, - .power_saving = true, }, { .name = internal, @@ -510,7 +509,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = { .gpio_cd= -EINVAL, .gpio_wp= -EINVAL, .nonremovable = true, - .power_saving = true, .remux = rx51_mmc2_remux, }, {} /* Terminator */ diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index bdc8870..30c78c1 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -16,7 +16,6 @@ struct omap2_hsmmc_info { boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ boolnonremovable; /* Nonremovable e.g. eMMC */ - boolpower_saving; /* Try to sleep or power off when possible */ booldeferred; /* mmc needs a deferred probe */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ -- 2.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 02/10] ARM: OMAP1/2+: MMC: separate platform data for mmc and mmc hs driver
- omap mmc driver supports multiplexing, omap_mmc_hs doesn't this leads to one of the major confusions in the omap_hsmmc driver - platform data should be read-only for the driver most callbacks are not set by the omap3 platform init code while still required. So they are set from the driver probe function, which is against the paradigm that platform-data should not be modified by the driver typical examples are card_detect, read_only callbacks un-bundling by searching for driver name \omap_hsmmc in the arch/arm folder. omap_hsmmc_platform_data is not initialized directly, but from omap2_hsmmc_info, which is defined in a separate header file not touched by this patch hwmod includes platform headers to declare features of the platform. All the declared features are prefixed OMAP_HSMMC. There is no need to include platform header from hwmod other except for feature defines Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c| 26 ++-- arch/arm/mach-omap2/omap_hwmod_2430_data.c | 4 +- .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 4 +- drivers/mmc/host/omap_hsmmc.c | 28 ++-- include/linux/platform_data/hsmmc-omap.h | 149 + include/linux/platform_data/mmc-omap.h | 27 10 files changed, 192 insertions(+), 70 deletions(-) create mode 100644 include/linux/platform_data/hsmmc-omap.h diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 73e28ac..9edd759 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -16,7 +16,7 @@ #include linux/gpio.h #include linux/mmc/host.h #include linux/platform_data/gpio-omap.h -#include linux/platform_data/mmc-omap.h +#include linux/platform_data/hsmmc-omap.h #include soc.h #include omap_device.h @@ -48,7 +48,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { u32 reg, prog_io; - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -121,7 +121,7 @@ static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, } } -static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) +static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) { u32 reg; @@ -136,7 +136,7 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) static void hsmmc2_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -148,7 +148,7 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, 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; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -162,8 +162,8 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, return 0; } -static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, - int controller_nr) +static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data + *mmc_controller, int controller_nr) { if (gpio_is_valid(mmc_controller-slots[0].switch_pin) (mmc_controller-slots[0].switch_pin OMAP_MAX_GPIO_LINES)) @@ -244,7 +244,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, } static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, - struct omap_mmc_platform_data *mmc) + struct omap_hsmmc_platform_data *mmc) { char *hc_name; @@ -369,7 +369,7 @@ static int omap_hsmmc_done; void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) { struct platform_device *pdev; - struct omap_mmc_platform_data *mmc_pdata; + struct omap_hsmmc_platform_data *mmc_pdata; int res; if (omap_hsmmc_done != 1) @@ -409,12 +409,12 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, struct omap_device *od; struct
[PATCH v4 06/10] omap_hsmmc: remove unused get_context_loss_count callback
trigger of this callback has been removed in 0a82e06e6183 Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 12 include/linux/platform_data/hsmmc-omap.h | 3 --- 2 files changed, 15 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 75b75b9..c65efc3 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -33,17 +33,6 @@ static u16 control_devconf1_offset; #define HSMMC_NAME_LEN 9 -#if defined(CONFIG_ARCH_OMAP3) defined(CONFIG_PM) - -static int hsmmc_get_context_loss(struct device *dev) -{ - return omap_pm_get_dev_context_loss_count(dev); -} - -#else -#define hsmmc_get_context_loss NULL -#endif - static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { @@ -265,7 +254,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc-slots[0].caps = c-caps; mmc-slots[0].internal_clock = !c-ext_clock; mmc-reg_offset = 0; - mmc-get_context_loss_count = hsmmc_get_context_loss; mmc-slots[0].switch_pin = c-gpio_cd; mmc-slots[0].gpio_wp = c-gpio_wp; diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 7e70e15..35d494f 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -51,9 +51,6 @@ struct omap_hsmmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); - /* Return context loss count due to PM states changing */ - int (*get_context_loss_count)(struct device *dev); - /* Integrating attributes from the omap_hwmod layer */ u8 controller_flags; -- 2.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 01/10] ARM: OMAP2: MMC: include mmc-omap platform header directly
Only a few files really need that platform header. When later splitting omap_mmc_platform_data into omap_mmc and omap_mmc_hs, those files declaring an hs mmc platform data will have to change the platform include, which is a good sanity check. Also removing omap242x_init_mmc, which is not used anywhere, checked with grep. Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/board-n8x0.c| 2 ++ arch/arm/mach-omap2/hsmmc.c | 3 ++- arch/arm/mach-omap2/mmc.h | 10 -- arch/arm/mach-omap2/omap4-common.c | 1 - arch/arm/mach-omap2/omap_hwmod_2430_data.c | 2 +- arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 2 +- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 - arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 2 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 2 +- arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 2 +- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 2 +- 11 files changed, 10 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 97767a2..e0ad64f 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -21,8 +21,10 @@ #include linux/i2c.h #include linux/spi/spi.h #include linux/usb/musb.h +#include linux/mmc/host.h #include linux/platform_data/spi-omap2-mcspi.h #include linux/platform_data/mtd-onenand-omap2.h +#include linux/platform_data/mmc-omap.h #include linux/mfd/menelaus.h #include sound/tlv320aic3x.h diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 07d4c7b..73e28ac 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -14,14 +14,15 @@ #include linux/string.h #include linux/delay.h #include linux/gpio.h +#include linux/mmc/host.h #include linux/platform_data/gpio-omap.h +#include linux/platform_data/mmc-omap.h #include soc.h #include omap_device.h #include omap-pm.h #include mux.h -#include mmc.h #include hsmmc.h #include control.h diff --git a/arch/arm/mach-omap2/mmc.h b/arch/arm/mach-omap2/mmc.h index 0cd4b08..30d39b9 100644 --- a/arch/arm/mach-omap2/mmc.h +++ b/arch/arm/mach-omap2/mmc.h @@ -1,5 +1,3 @@ -#include linux/mmc/host.h -#include linux/platform_data/mmc-omap.h #define OMAP24XX_NR_MMC2 #define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE @@ -7,14 +5,6 @@ #define OMAP4_MMC_REG_OFFSET 0x100 -#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) -void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data); -#else -static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) -{ -} -#endif - struct omap_hwmod; int omap_msdi_reset(struct omap_hwmod *oh); diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 16b20ce..b7cb44a 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -36,7 +36,6 @@ #include soc.h #include iomap.h #include common.h -#include mmc.h #include prminst44xx.h #include prcm_mpu44xx.h #include omap4-sar-layout.h diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index c2555cb..cd95e82 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -15,12 +15,12 @@ #include linux/i2c-omap.h #include linux/platform_data/asoc-ti-mcbsp.h +#include linux/platform_data/mmc-omap.h #include linux/platform_data/spi-omap2-mcspi.h #include linux/omap-dma.h #include plat/dmtimer.h #include omap_hwmod.h -#include mmc.h #include l3_2xxx.h #include soc.h diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index a579b89..bf8c12d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -15,10 +15,10 @@ */ #include linux/platform_data/gpio-omap.h +#include linux/platform_data/mmc-omap.h #include linux/platform_data/spi-omap2-mcspi.h #include omap_hwmod.h #include i2c.h -#include mmc.h #include wd_timer.h #include cm33xx.h #include prm33xx.h diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index 6b406ca..0cf7b56 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -27,7 +27,6 @@ #include prm33xx.h #include prm-regbits-33xx.h #include i2c.h -#include mmc.h #include wd_timer.h #include omap_hwmod_33xx_43xx_common_data.h diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 2a78b09..5f244a9 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -18,6 +18,7 @@ #include linux/i2c
[PATCH v4 07/10] omap_hsmmc: remove unnecessary omap_hsmmc_slot_data indirection
omap_hsmmc supports only one slot per controller, see OMAP_MMC_MAX_SLOTS. This unnecessary indirection leads to confusion in the omap_hsmmc driver. For example the card_detect callback is not installed by platform code but from the driver probe function. So it should be a field of omap_hsmmc_host. But since it is declared under the platform slot while the drivers struct omap_hsmmc_host has no slot abstraction, this looks like a bug, especially when not familiar that this driver only supports 1 slot anyway. Either we should add a slot abstraction to omap_hsmmc_host or remove it from the platform data struct. Removed since slot multiplexing is an un-implemented feature Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 88 drivers/mmc/host/omap_hsmmc.c| 175 --- include/linux/platform_data/hsmmc-omap.h | 100 +- 3 files changed, 181 insertions(+), 182 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index c65efc3..4e2896a 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -39,8 +39,8 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, u32 reg, prog_io; struct omap_hsmmc_platform_data *mmc = dev-platform_data; - if (mmc-slots[0].remux) - mmc-slots[0].remux(dev, slot, power_on); + if (mmc-remux) + mmc-remux(dev, slot, power_on); /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the @@ -62,7 +62,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1); } - if (mmc-slots[0].internal_clock) { + if (mmc-internal_clock) { reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); reg |= OMAP2_MMCSDIO1ADPCLKISEL; omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0); @@ -115,7 +115,7 @@ static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) u32 reg; reg = omap_ctrl_readl(control_devconf1_offset); - if (mmc-slots[0].internal_clock) + if (mmc-internal_clock) reg |= OMAP2_MMCSDIO2ADPCLKISEL; else reg = ~OMAP2_MMCSDIO2ADPCLKISEL; @@ -127,8 +127,8 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, { struct omap_hsmmc_platform_data *mmc = dev-platform_data; - if (mmc-slots[0].remux) - mmc-slots[0].remux(dev, slot, power_on); + if (mmc-remux) + mmc-remux(dev, slot, power_on); if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -154,14 +154,14 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data *mmc_controller, int controller_nr) { - 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) - (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 (gpio_is_valid(mmc_controller-switch_pin) + (mmc_controller-switch_pin OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-switch_pin, + OMAP_PIN_INPUT_PULLUP); + if (gpio_is_valid(mmc_controller-gpio_wp) + (mmc_controller-gpio_wp OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-gpio_wp, + OMAP_PIN_INPUT_PULLUP); if (cpu_is_omap34xx()) { if (controller_nr == 0) { omap_mux_init_signal(sdmmc1_clk, @@ -170,7 +170,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data OMAP_PIN_INPUT_PULLUP); omap_mux_init_signal(sdmmc1_dat0, OMAP_PIN_INPUT_PULLUP); - if (mmc_controller-slots[0].caps + if (mmc_controller-caps (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) { omap_mux_init_signal(sdmmc1_dat1, OMAP_PIN_INPUT_PULLUP); @@ -179,7 +179,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data omap_mux_init_signal(sdmmc1_dat3
[PATCH v4 08/10] omap_hsmmc: pass mmc_priv struct to gpio init / free
this is needed when installing callbacks in the host struct and not in the platform data, e.g. cover detect irq should be stored in omap_hsmmc_host and not platform data Acked-by: Tony Lindgren t...@atomide.com Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c | 22 -- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 291b9e1..8a216c9 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -449,7 +449,8 @@ static inline int omap_hsmmc_have_reg(void) #endif -static int omap_hsmmc_gpio_init(struct omap_hsmmc_platform_data *pdata) +static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, + struct omap_hsmmc_platform_data *pdata) { int ret; @@ -494,7 +495,8 @@ err_free_sp: return ret; } -static void omap_hsmmc_gpio_free(struct omap_hsmmc_platform_data *pdata) +static void omap_hsmmc_gpio_free(struct omap_hsmmc_host *host, +struct omap_hsmmc_platform_data *pdata) { if (gpio_is_valid(pdata-gpio_wp)) gpio_free(pdata-gpio_wp); @@ -2064,14 +2066,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - ret = omap_hsmmc_gpio_init(pdata); - if (ret) - goto err; - mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), pdev-dev); if (!mmc) { ret = -ENOMEM; - goto err_alloc; + goto err; } host= mmc_priv(mmc); @@ -2088,6 +2086,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) host-next_data.cookie = 1; host-pbias_enabled = 0; + ret = omap_hsmmc_gpio_init(host, pdata); + if (ret) + goto err_gpio; + platform_set_drvdata(pdev, host); if (pdev-dev.of_node) @@ -2283,9 +2285,9 @@ err_irq: if (host-dbclk) clk_disable_unprepare(host-dbclk); err1: + omap_hsmmc_gpio_free(host, pdata); +err_gpio: mmc_free_host(mmc); -err_alloc: - omap_hsmmc_gpio_free(pdata); err: return ret; } @@ -2309,7 +2311,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) if (host-dbclk) clk_disable_unprepare(host-dbclk); - omap_hsmmc_gpio_free(host-pdata); + omap_hsmmc_gpio_free(host, host-pdata); mmc_free_host(host-mmc); return 0; -- 2.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/3] ARM: OMAP2+: use separate platform data for omap3 and omap 1/2 driver
- mmci driver supports multiple slots, omap_hsmmc only one this leads to one of the major confusions in the omap_hsmmc driver - platform data should be read-only for the driver most callbacks are not set by the omap3 platform init code while being required by the driver, leading to the fact that they are set by the driver during it's probe function typical example are card detect / read only detect callbacks un-bundling by searching for driver name \omap_hsmmc in the arch/arm folder. omap_hsmmc_platform_data is not initialized directly, but from omap2_hsmmc_info, which is defined in a separate header file not touched by this patch additionally hwmod is used to initialize platform data. use omap_mmc_dev_attr as a key which hwmod uses omap_hsmmc driver. since all possible values assigned to omap_mmc_dev_attr.flags are hsmmc specific: #define OMAP_HSMMC_SUPPORTS_DUAL_VOLT BIT(0) #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1) #define OMAP_HSMMC_SWAKEUP_MISSING BIT(2) Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 73e28ac..9edd759 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -16,7 +16,7 @@ #include linux/gpio.h #include linux/mmc/host.h #include linux/platform_data/gpio-omap.h -#include linux/platform_data/mmc-omap.h +#include linux/platform_data/hsmmc-omap.h #include soc.h #include omap_device.h @@ -48,7 +48,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { u32 reg, prog_io; - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -121,7 +121,7 @@ static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, } } -static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) +static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) { u32 reg; @@ -136,7 +136,7 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) static void hsmmc2_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -148,7 +148,7 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, 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; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -162,8 +162,8 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, return 0; } -static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, - int controller_nr) +static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data + *mmc_controller, int controller_nr) { if (gpio_is_valid(mmc_controller-slots[0].switch_pin) (mmc_controller-slots[0].switch_pin OMAP_MAX_GPIO_LINES)) @@ -244,7 +244,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, } static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, - struct omap_mmc_platform_data *mmc) + struct omap_hsmmc_platform_data *mmc) { char *hc_name; @@ -369,7 +369,7 @@ static int omap_hsmmc_done; void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) { struct platform_device *pdev; - struct omap_mmc_platform_data *mmc_pdata; + struct omap_hsmmc_platform_data *mmc_pdata; int res; if (omap_hsmmc_done != 1) @@ -409,12 +409,12 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, struct omap_device *od; struct platform_device *pdev; char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; - struct omap_mmc_platform_data *mmc_data; - struct omap_mmc_dev_attr *mmc_dev_attr; + struct omap_hsmmc_platform_data *mmc_data; + struct omap_hsmmc_dev_attr *mmc_dev_attr; char *name; int res; - mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); + mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL); if (!mmc_data) { pr_err(Cannot allocate memory for mmc device!\n); return; @@ -464,7 +464,7 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo
[PATCH v3 0/3] ARM: OMAP2+: MMC: use separate platform data for omap3 and omap 1/2 driver
v3: - fix compile break, by include proper platform header tested with these architectures CONFIG_MACH_OMAP2_TUSB6010=y CONFIG_MACH_OMAP3_BEAGLE=y CONFIG_MACH_DEVKIT8000=y CONFIG_MACH_OMAP_LDP=y CONFIG_MACH_OMAP3530_LV_SOM=y CONFIG_MACH_OMAP3_TORPEDO=y CONFIG_MACH_OVERO=y CONFIG_MACH_OMAP3517EVM=y CONFIG_MACH_CRANEBOARD=y CONFIG_MACH_OMAP3_PANDORA=y CONFIG_MACH_TOUCHBOOK=y CONFIG_MACH_OMAP_3430SDP=y CONFIG_MACH_NOKIA_N810=y CONFIG_MACH_NOKIA_N810_WIMAX=y CONFIG_MACH_NOKIA_N8X0=y CONFIG_MACH_NOKIA_RX51=y CONFIG_MACH_CM_T35=y CONFIG_MACH_CM_T3517=y CONFIG_MACH_CM_T3730=y CONFIG_MACH_SBC3530=y CONFIG_MACH_TI8168EVM=y CONFIG_MACH_TI8148EVM=y - dropped all patches simplifying the hsmmc-omap platform struct, will resubmit once the platform data split is successful Andreas Fenkart (3): ARM: OMAP2+: remove unused defines from mach-omap2/mmc header ARM: OMAP2+: include mmc-omap platform directly in hwmod data files ARM: OMAP2+: use separate platform data for omap3 and omap 1/2 driver arch/arm/mach-omap2/board-n8x0.c | 2 + arch/arm/mach-omap2/hsmmc.c| 27 ++-- arch/arm/mach-omap2/mmc.h | 14 -- arch/arm/mach-omap2/omap4-common.c | 1 - arch/arm/mach-omap2/omap_hwmod_2430_data.c | 4 +- .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 - arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 8 +- arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_54xx_data.c | 4 +- arch/arm/mach-omap2/omap_hwmod_7xx_data.c | 4 +- drivers/mmc/host/omap_hsmmc.c | 28 ++-- include/linux/platform_data/hsmmc-omap.h | 152 + include/linux/platform_data/mmc-omap.h | 24 14 files changed, 198 insertions(+), 83 deletions(-) create mode 100644 include/linux/platform_data/hsmmc-omap.h -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/3] ARM: OMAP2+: include mmc-omap platform directly in hwmod data files
When splitting platform data of omap mmc/hsmmc driver it will allow to check which hwomod uses easily by looking at which header is included Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index aead77a..fa70d1c 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -21,8 +21,10 @@ #include linux/i2c.h #include linux/spi/spi.h #include linux/usb/musb.h +#include linux/mmc/host.h #include linux/platform_data/spi-omap2-mcspi.h #include linux/platform_data/mtd-onenand-omap2.h +#include linux/platform_data/mmc-omap.h #include linux/mfd/menelaus.h #include sound/tlv320aic3x.h diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 07d4c7b..73e28ac 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -14,14 +14,15 @@ #include linux/string.h #include linux/delay.h #include linux/gpio.h +#include linux/mmc/host.h #include linux/platform_data/gpio-omap.h +#include linux/platform_data/mmc-omap.h #include soc.h #include omap_device.h #include omap-pm.h #include mux.h -#include mmc.h #include hsmmc.h #include control.h diff --git a/arch/arm/mach-omap2/mmc.h b/arch/arm/mach-omap2/mmc.h index ea4fddf..6799fa5 100644 --- a/arch/arm/mach-omap2/mmc.h +++ b/arch/arm/mach-omap2/mmc.h @@ -1,5 +1,3 @@ -#include linux/mmc/host.h -#include linux/platform_data/mmc-omap.h #define OMAP24XX_NR_MMC2 diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c index 539e810..9d8dc85 100644 --- a/arch/arm/mach-omap2/omap4-common.c +++ b/arch/arm/mach-omap2/omap4-common.c @@ -35,7 +35,6 @@ #include soc.h #include iomap.h #include common.h -#include mmc.h #include prminst44xx.h #include prcm_mpu44xx.h #include omap4-sar-layout.h diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c index 6d1b609..29450da 100644 --- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c @@ -15,13 +15,13 @@ #include linux/i2c-omap.h #include linux/platform_data/asoc-ti-mcbsp.h +#include linux/platform_data/mmc-omap.h #include linux/platform_data/spi-omap2-mcspi.h #include linux/omap-dma.h #include linux/platform_data/mailbox-omap.h #include plat/dmtimer.h #include omap_hwmod.h -#include mmc.h #include l3_2xxx.h #include soc.h diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c index a579b89..bf8c12d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c @@ -15,10 +15,10 @@ */ #include linux/platform_data/gpio-omap.h +#include linux/platform_data/mmc-omap.h #include linux/platform_data/spi-omap2-mcspi.h #include omap_hwmod.h #include i2c.h -#include mmc.h #include wd_timer.h #include cm33xx.h #include prm33xx.h diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c index 6b406ca..0cf7b56 100644 --- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c @@ -27,7 +27,6 @@ #include prm33xx.h #include prm-regbits-33xx.h #include i2c.h -#include mmc.h #include wd_timer.h #include omap_hwmod_33xx_43xx_common_data.h diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index 1cd0cfd..70b14fe 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -18,6 +18,7 @@ #include linux/i2c-omap.h #include linux/power/smartreflex.h #include linux/platform_data/gpio-omap.h +#include linux/platform_data/mmc-omap.h #include linux/omap-dma.h #include l3_3xxx.h @@ -37,7 +38,6 @@ #include cm-regbits-34xx.h #include i2c.h -#include mmc.h #include wd_timer.h #include serial.h diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 41e54f7..1107926 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -22,6 +22,7 @@ #include linux/io.h #include linux/platform_data/gpio-omap.h +#include linux/platform_data/mmc-omap.h #include linux/power/smartreflex.h #include linux/i2c-omap.h @@ -39,7 +40,6 @@ #include prm44xx.h #include prm-regbits-44xx.h #include i2c.h -#include mmc.h #include wd_timer.h /* Base offset for all OMAP4 interrupts external to MPUSS */ diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c index 1103aa0..13bf6a7 100644 --- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c @@ -19,6 +19,7 @@ #include linux/io.h #include linux/platform_data/gpio-omap.h +#include linux/platform_data/mmc-omap.h #include linux/power/smartreflex.h #include linux/i2c-omap.h
[PATCH v3 1/3] ARM: OMAP2+: remove unused defines from mach-omap2/mmc header
build tested for these architectures CONFIG_MACH_OMAP2_TUSB6010=y CONFIG_MACH_OMAP3_BEAGLE=y CONFIG_MACH_DEVKIT8000=y CONFIG_MACH_OMAP_LDP=y CONFIG_MACH_OMAP3530_LV_SOM=y CONFIG_MACH_OMAP3_TORPEDO=y CONFIG_MACH_OVERO=y CONFIG_MACH_OMAP3517EVM=y CONFIG_MACH_CRANEBOARD=y CONFIG_MACH_OMAP3_PANDORA=y CONFIG_MACH_TOUCHBOOK=y CONFIG_MACH_OMAP_3430SDP=y CONFIG_MACH_NOKIA_N810=y CONFIG_MACH_NOKIA_N810_WIMAX=y CONFIG_MACH_NOKIA_N8X0=y CONFIG_MACH_NOKIA_RX51=y CONFIG_MACH_CM_T35=y CONFIG_MACH_CM_T3517=y CONFIG_MACH_CM_T3730=y CONFIG_MACH_SBC3530=y CONFIG_MACH_TI8168EVM=y CONFIG_MACH_TI8148EVM=y Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/mmc.h b/arch/arm/mach-omap2/mmc.h index 0cd4b08..ea4fddf 100644 --- a/arch/arm/mach-omap2/mmc.h +++ b/arch/arm/mach-omap2/mmc.h @@ -2,18 +2,6 @@ #include linux/platform_data/mmc-omap.h #define OMAP24XX_NR_MMC2 -#define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE -#define OMAP2_MMC1_BASE0x4809c000 - -#define OMAP4_MMC_REG_OFFSET 0x100 - -#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) -void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data); -#else -static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data) -{ -} -#endif struct omap_hwmod; int omap_msdi_reset(struct omap_hwmod *oh); -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/9] omap_hsmmc: remove un-initialized callbacks from platform data
these callbacks are not set, probably legacy omap 1/2 features Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5f2b5b7..f68ac1a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2204,18 +2204,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) goto err_irq; } - if (pdata-init != NULL) { - if (pdata-init(pdev-dev) != 0) { - dev_err(mmc_dev(host-mmc), - Unable to configure MMC IRQs\n); - goto err_irq; - } - } - if (omap_hsmmc_have_reg() !mmc_slot(host).set_power) { ret = omap_hsmmc_reg_get(host); if (ret) - goto err_reg; + goto err_irq; host-use_reg = 1; } @@ -2278,9 +2270,6 @@ err_slot_name: err_irq_cd: if (host-use_reg) omap_hsmmc_reg_put(host); -err_reg: - if (host-pdata-cleanup) - host-pdata-cleanup(pdev-dev); err_irq: if (host-tx_chan) dma_release_channel(host-tx_chan); @@ -2306,8 +2295,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) mmc_remove_host(host-mmc); if (host-use_reg) omap_hsmmc_reg_put(host); - if (host-pdata-cleanup) - host-pdata-cleanup(pdev-dev); if (host-tx_chan) dma_release_channel(host-tx_chan); diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 026efb6..2807786 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -45,14 +45,6 @@ struct omap_hsmmc_platform_data { * maximum frequency on the MMC bus */ unsigned int max_freq; - /* switch the bus to a new slot */ - int (*switch_slot)(struct device *dev, int slot); - /* initialize board-specific MMC functionality, can be NULL if -* not supported */ - int (*init)(struct device *dev); - void (*cleanup)(struct device *dev); - void (*shutdown)(struct device *dev); - /* To handle board related suspend/resume functionality for MMC */ int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); @@ -95,7 +87,6 @@ struct omap_hsmmc_platform_data { int switch_pin; /* gpio (card detect) */ int gpio_wp;/* gpio (write protect) */ - int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); int (*set_power)(struct device *dev, int slot, int power_on, int vdd); int (*get_ro)(struct device *dev, int slot); -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/9] omap_hsmmc: remove unused fields in platform_data
platform data is built from omap2_hsmmc_info, remove all fields that are never set in omap_hsmmc_info, hence never copied to platform data. Note that the omap_hsmmc driver never used any of these fields, they were completely unused compile tested for these platforms CONFIG_MACH_OMAP3_BEAGLE=y CONFIG_MACH_DEVKIT8000=y CONFIG_MACH_OMAP_LDP=y CONFIG_MACH_OMAP3530_LV_SOM=y CONFIG_MACH_OMAP3_TORPEDO=y CONFIG_MACH_OVERO=y CONFIG_MACH_OMAP3517EVM=y CONFIG_MACH_CRANEBOARD=y CONFIG_MACH_OMAP3_PANDORA=y CONFIG_MACH_TOUCHBOOK=y CONFIG_MACH_OMAP_3430SDP=y CONFIG_MACH_NOKIA_RX51=y CONFIG_MACH_CM_T35=y CONFIG_MACH_CM_T3517=y CONFIG_MACH_CM_T3730=y CONFIG_MACH_SBC3530=y Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index e3555f2..1c10402 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -262,9 +262,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-max_freq = c-max_freq; mmc-reg_offset = 0; mmc-get_context_loss_count = hsmmc_get_context_loss; @@ -280,18 +278,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, if (c-nonremovable) mmc-slots[0].nonremovable = 1; - if (c-power_saving) - mmc-slots[0].power_saving = 1; - - if (c-no_off) - mmc-slots[0].no_off = 1; - - if (c-no_off_init) - mmc-slots[0].no_regulator_off_init = c-no_off_init; - - if (c-vcc_aux_disable_is_sleep) - mmc-slots[0].vcc_aux_disable_is_sleep = 1; - /* * NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 7f2e790..bdc8870 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -12,23 +12,17 @@ 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 */ booltransceiver;/* MMC-2 option */ boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ boolnonremovable; /* Nonremovable e.g. eMMC */ boolpower_saving; /* Try to sleep or power off when possible */ - boolno_off; /* power_saving and power is not to go off */ - boolno_off_init;/* no power off when not in MMC sleep state */ - boolvcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */ booldeferred; /* mmc needs a deferred probe */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ char*name; /* or NULL for default */ struct platform_device *pdev; /* mmc controller instance */ int ocr_mask; /* temporary HACK */ - int max_freq; /* maximum clock, if constrained by external -* circuitry, or 0 for default */ /* Remux (pad configuration) when powering on/off */ void (*remux)(struct device *dev, int slot, int power_on); /* init some special card */ diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index cb91db4..026efb6 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -30,8 +30,6 @@ #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1) #define OMAP_HSMMC_SWAKEUP_MISSING BIT(2) -struct mmc_card; - struct omap_hsmmc_dev_attr { u8 flags; }; @@ -73,16 +71,9 @@ struct omap_hsmmc_platform_data { * 4/8 wires and any additional host capabilities * need to OR'd all capabilities (ref. linux/mmc/host.h) */ - 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 -* that board-specific code handled it before common init logic. -*/ - unsigned nomux:1; - /* switch pin can be for card detect (default) or card cover */ unsigned cover:1; @@ -92,25 +83,13 @@ struct omap_hsmmc_platform_data { /* nonremovable e.g. eMMC */ unsigned nonremovable:1
[PATCH v2 5/9] omap_hsmmc: remove unused get_context_loss_count callback
trigger of this callback has been removed in 0a82e06e6183 Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 1c10402..312f13d 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -32,17 +32,6 @@ static u16 control_devconf1_offset; #define HSMMC_NAME_LEN 9 -#if defined(CONFIG_ARCH_OMAP3) defined(CONFIG_PM) - -static int hsmmc_get_context_loss(struct device *dev) -{ - return omap_pm_get_dev_context_loss_count(dev); -} - -#else -#define hsmmc_get_context_loss NULL -#endif - static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { @@ -264,7 +253,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc-slots[0].caps = c-caps; mmc-slots[0].internal_clock = !c-ext_clock; mmc-reg_offset = 0; - mmc-get_context_loss_count = hsmmc_get_context_loss; mmc-slots[0].switch_pin = c-gpio_cd; mmc-slots[0].gpio_wp = c-gpio_wp; diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 2807786..dc44dfb 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -49,9 +49,6 @@ struct omap_hsmmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); - /* Return context loss count due to PM states changing */ - int (*get_context_loss_count)(struct device *dev); - /* Integrating attributes from the omap_hwmod layer */ u8 controller_flags; -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/9] unshare and simplify omap_hsmmc platform struct
v2: - replace erroneous mmci by omap1/2 - add description to all patches - full compile check with: CONFIG_MACH_OMAP3_BEAGLE=y CONFIG_MACH_DEVKIT8000=y CONFIG_MACH_OMAP_LDP=y CONFIG_MACH_OMAP3530_LV_SOM=y CONFIG_MACH_OMAP3_TORPEDO=y CONFIG_MACH_OVERO=y CONFIG_MACH_OMAP3517EVM=y CONFIG_MACH_CRANEBOARD=y CONFIG_MACH_OMAP3_PANDORA=y CONFIG_MACH_TOUCHBOOK=y CONFIG_MACH_OMAP_3430SDP=y CONFIG_MACH_NOKIA_RX51=y CONFIG_MACH_CM_T35=y CONFIG_MACH_CM_T3517=y CONFIG_MACH_CM_T3730=y CONFIG_MACH_SBC3530=y - reorganized and added more patches, hence no blank ack added Andreas Fenkart (9): omap_hsmmc: use separate platform data for ompa3 and omap 1/2 driver omap_hsmmc: remove unused fields in platform_data omap_hsmmc: remove un-initialized callbacks from platform data omap_hsmmc: remove un-ready power_saving field in omap2_hsmmc_info omap_hsmmc: remove unused get_context_loss_count callback omap_hsmmc: remove unnecessary omap_hsmmc_slot_data indirection omap_hsmmc: pass mmc_priv struct to gpio init / free omap_hsmmc: Remove unnecessary callbacks from platform data omap_hsmmc: remove unused slot_id parameter arch/arm/mach-omap2/board-rx51-peripherals.c | 4 +- arch/arm/mach-omap2/hsmmc.c| 155 +-- arch/arm/mach-omap2/hsmmc.h| 9 +- arch/arm/mach-omap2/mmc.h | 6 +- .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 6 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 6 +- drivers/mmc/host/omap_hsmmc.c | 282 ++--- include/linux/platform_data/hsmmc-omap.h | 88 +++ 8 files changed, 299 insertions(+), 257 deletions(-) create mode 100644 include/linux/platform_data/hsmmc-omap.h -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 9/9] omap_hsmmc: remove unused slot_id parameter
omap_hsmmc only supports one slot. So slot id is always zero, and slot id is never used in the callbacks Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index 0a8ac84..3d5040f 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -484,7 +484,7 @@ static struct omap_mux_partition *partition; * Current flows to eMMC when eMMC is off and the data lines are pulled up, * so pull them down. N.B. we pull 8 lines because we are using 8 lines. */ -static void rx51_mmc2_remux(struct device *dev, int slot, int power_on) +static void rx51_mmc2_remux(struct device *dev, int power_on) { if (power_on) omap_mux_write_array(partition, rx51_mmc2_on_mux); diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index a535cd3..bdc0402 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -32,14 +32,14 @@ static u16 control_devconf1_offset; #define HSMMC_NAME_LEN 9 -static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, - int power_on, int vdd) +static void omap_hsmmc1_before_set_reg(struct device *dev, + int power_on, int vdd) { u32 reg, prog_io; struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-remux) - mmc-remux(dev, slot, power_on); + mmc-remux(dev, power_on); /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the @@ -85,8 +85,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, } } -static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, -int power_on, int vdd) +static void omap_hsmmc1_after_set_reg(struct device *dev, int power_on, int vdd) { u32 reg; @@ -121,20 +120,18 @@ static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) omap_ctrl_writel(reg, control_devconf1_offset); } -static void hsmmc2_before_set_reg(struct device *dev, int slot, - int power_on, int vdd) +static void hsmmc2_before_set_reg(struct device *dev, int power_on, int vdd) { struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-remux) - mmc-remux(dev, slot, power_on); + mmc-remux(dev, power_on); if (power_on) hsmmc2_select_input_clk_src(mmc); } -static int am35x_hsmmc2_set_power(struct device *dev, int slot, - int power_on, int vdd) +static int am35x_hsmmc2_set_power(struct device *dev, int power_on, int vdd) { struct omap_hsmmc_platform_data *mmc = dev-platform_data; @@ -144,8 +141,7 @@ static int am35x_hsmmc2_set_power(struct device *dev, int slot, return 0; } -static int nop_mmc_set_power(struct device *dev, int slot, int power_on, - int vdd) +static int nop_mmc_set_power(struct device *dev, int power_on, int vdd) { return 0; } @@ -249,7 +245,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, snprintf(hc_name, (HSMMC_NAME_LEN + 1), mmc%islot%i, c-mmc, 1); mmc-name = hc_name; - mmc-nr_slots = 1; mmc-caps = c-caps; mmc-internal_clock = !c-ext_clock; mmc-reg_offset = 0; diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 30c78c1..148cd9b 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -23,7 +23,7 @@ struct omap2_hsmmc_info { struct platform_device *pdev; /* mmc controller instance */ int ocr_mask; /* temporary HACK */ /* Remux (pad configuration) when powering on/off */ - void (*remux)(struct device *dev, int slot, int power_on); + void (*remux)(struct device *dev, int power_on); /* init some special card */ void (*init_card)(struct mmc_card *card); }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 0a1398a..c063882 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -207,7 +207,6 @@ struct omap_hsmmc_host { int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; - int slot_id; int response_busy; int context_loss; int protect_card; @@ -223,8 +222,8 @@ struct omap_hsmmc_host { struct omap_hsmmc_platform_data*pdata; /* To handle board related suspend/resume functionality for MMC */ - int (*suspend)(struct device *dev, int slot); - int
[PATCH v2 7/9] omap_hsmmc: pass mmc_priv struct to gpio init / free
this is needed when installing callbacks in the host struct and not in the platform data, e.g. cover detect irq should be stored in omap_hsmmc_host and not platform data Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index d05b7f3..f8cd3b3 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -449,7 +449,8 @@ static inline int omap_hsmmc_have_reg(void) #endif -static int omap_hsmmc_gpio_init(struct omap_hsmmc_platform_data *pdata) +static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, + struct omap_hsmmc_platform_data *pdata) { int ret; @@ -494,7 +495,8 @@ err_free_sp: return ret; } -static void omap_hsmmc_gpio_free(struct omap_hsmmc_platform_data *pdata) +static void omap_hsmmc_gpio_free(struct omap_hsmmc_host *host, +struct omap_hsmmc_platform_data *pdata) { if (gpio_is_valid(pdata-gpio_wp)) gpio_free(pdata-gpio_wp); @@ -2054,14 +2056,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - ret = omap_hsmmc_gpio_init(pdata); - if (ret) - goto err; - mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), pdev-dev); if (!mmc) { ret = -ENOMEM; - goto err_alloc; + goto err; } host= mmc_priv(mmc); @@ -2078,6 +2076,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) host-next_data.cookie = 1; host-pbias_enabled = 0; + ret = omap_hsmmc_gpio_init(host, pdata); + if (ret) + goto err_gpio; + platform_set_drvdata(pdev, host); if (pdev-dev.of_node) @@ -2283,9 +2285,9 @@ err_irq: if (host-dbclk) clk_disable_unprepare(host-dbclk); err1: + omap_hsmmc_gpio_free(host, pdata); +err_gpio: mmc_free_host(mmc); -err_alloc: - omap_hsmmc_gpio_free(pdata); err: return ret; } @@ -2309,7 +2311,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) if (host-dbclk) clk_disable_unprepare(host-dbclk); - omap_hsmmc_gpio_free(host-pdata); + omap_hsmmc_gpio_free(host, host-pdata); mmc_free_host(host-mmc); return 0; -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/9] omap_hsmmc: remove un-ready power_saving field in omap2_hsmmc_info
these fields are never read, probably an unimplemented feature or superseded by pm_runtime Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index ddfc8df..0a8ac84 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -500,7 +500,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = { .cover_only = true, .gpio_cd= 160, .gpio_wp= -EINVAL, - .power_saving = true, }, { .name = internal, @@ -510,7 +509,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = { .gpio_cd= -EINVAL, .gpio_wp= -EINVAL, .nonremovable = true, - .power_saving = true, .remux = rx51_mmc2_remux, }, {} /* Terminator */ diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index bdc8870..30c78c1 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -16,7 +16,6 @@ struct omap2_hsmmc_info { boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ boolnonremovable; /* Nonremovable e.g. eMMC */ - boolpower_saving; /* Try to sleep or power off when possible */ booldeferred; /* mmc needs a deferred probe */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 6/9] omap_hsmmc: remove unnecessary omap_hsmmc_slot_data indirection
omap_hsmmc supports only one slot per controller, see OMAP_MMC_MAX_SLOTS. This unnecessary indirection leads to confusion in the omap_hsmmc driver. For example the card_detect callback is not installed by platform code but from the driver probe function. So it should be a field of omap_hsmmc_host. But since it is declared under the platform slot while the drivers struct omap_hsmmc_host has no slot abstraction, this looks like a bug, especially when not familiar that this driver only supports 1 slot anyway. Either we should add a slot abstraction to omap_hsmmc_host or remove it from the platform data struct. Removed since slot support is an un-implemented feature Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 312f13d..a535cd3 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -38,8 +38,8 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, u32 reg, prog_io; struct omap_hsmmc_platform_data *mmc = dev-platform_data; - if (mmc-slots[0].remux) - mmc-slots[0].remux(dev, slot, power_on); + if (mmc-remux) + mmc-remux(dev, slot, power_on); /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the @@ -61,7 +61,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, omap_ctrl_writel(reg, OMAP243X_CONTROL_DEVCONF1); } - if (mmc-slots[0].internal_clock) { + if (mmc-internal_clock) { reg = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); reg |= OMAP2_MMCSDIO1ADPCLKISEL; omap_ctrl_writel(reg, OMAP2_CONTROL_DEVCONF0); @@ -114,7 +114,7 @@ static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) u32 reg; reg = omap_ctrl_readl(control_devconf1_offset); - if (mmc-slots[0].internal_clock) + if (mmc-internal_clock) reg |= OMAP2_MMCSDIO2ADPCLKISEL; else reg = ~OMAP2_MMCSDIO2ADPCLKISEL; @@ -126,8 +126,8 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, { struct omap_hsmmc_platform_data *mmc = dev-platform_data; - if (mmc-slots[0].remux) - mmc-slots[0].remux(dev, slot, power_on); + if (mmc-remux) + mmc-remux(dev, slot, power_on); if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -153,14 +153,14 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data *mmc_controller, int controller_nr) { - 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) - (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 (gpio_is_valid(mmc_controller-switch_pin) + (mmc_controller-switch_pin OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-switch_pin, + OMAP_PIN_INPUT_PULLUP); + if (gpio_is_valid(mmc_controller-gpio_wp) + (mmc_controller-gpio_wp OMAP_MAX_GPIO_LINES)) + omap_mux_init_gpio(mmc_controller-gpio_wp, + OMAP_PIN_INPUT_PULLUP); if (cpu_is_omap34xx()) { if (controller_nr == 0) { omap_mux_init_signal(sdmmc1_clk, @@ -169,7 +169,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data OMAP_PIN_INPUT_PULLUP); omap_mux_init_signal(sdmmc1_dat0, OMAP_PIN_INPUT_PULLUP); - if (mmc_controller-slots[0].caps + if (mmc_controller-caps (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) { omap_mux_init_signal(sdmmc1_dat1, OMAP_PIN_INPUT_PULLUP); @@ -178,7 +178,7 @@ static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data omap_mux_init_signal(sdmmc1_dat3, OMAP_PIN_INPUT_PULLUP); } - if (mmc_controller-slots[0].caps + if (mmc_controller-caps MMC_CAP_8_BIT_DATA) { omap_mux_init_signal(sdmmc1_dat4
[PATCH v2 1/9] omap_hsmmc: use separate platform data for ompa3 and omap 1/2 driver
- mmci driver supports multiple slots, omap_hsmmc only one this leads to one of the major confusions in the omap_hsmmc driver - platform data should be read-only for the driver most callbacks are not set by the omap3 platform init code while being required by the driver, leading to the fact that they are set by the driver during it's probe function typical example are card detect / read only detect callbacks un-bundling by searching for driver name \omap_hsmmc in the arch/arm folder. omap_hsmmc_platform_data is not initialized directly, but from omap2_hsmmc_info, which is defined in a separate header file not touched by this patch Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 07d4c7b..e3555f2 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -47,7 +47,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { u32 reg, prog_io; - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -120,7 +120,7 @@ static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, } } -static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) +static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) { u32 reg; @@ -135,7 +135,7 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) static void hsmmc2_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -147,7 +147,7 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, 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; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -161,8 +161,8 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, return 0; } -static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, - int controller_nr) +static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data + *mmc_controller, int controller_nr) { if (gpio_is_valid(mmc_controller-slots[0].switch_pin) (mmc_controller-slots[0].switch_pin OMAP_MAX_GPIO_LINES)) @@ -243,7 +243,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, } static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, - struct omap_mmc_platform_data *mmc) + struct omap_hsmmc_platform_data *mmc) { char *hc_name; @@ -368,7 +368,7 @@ static int omap_hsmmc_done; void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) { struct platform_device *pdev; - struct omap_mmc_platform_data *mmc_pdata; + struct omap_hsmmc_platform_data *mmc_pdata; int res; if (omap_hsmmc_done != 1) @@ -408,12 +408,12 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, struct omap_device *od; struct platform_device *pdev; char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; - struct omap_mmc_platform_data *mmc_data; - struct omap_mmc_dev_attr *mmc_dev_attr; + struct omap_hsmmc_platform_data *mmc_data; + struct omap_hsmmc_dev_attr *mmc_dev_attr; char *name; int res; - mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); + mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL); if (!mmc_data) { pr_err(Cannot allocate memory for mmc device!\n); return; @@ -463,7 +463,7 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, } res = platform_device_add_data(pdev, mmc_data, - sizeof(struct omap_mmc_platform_data)); + sizeof(struct omap_hsmmc_platform_data)); if (res) { pr_err(Could not add pdata for %s\n, name); goto put_pdev; diff --git a/arch/arm/mach-omap2/mmc.h b/arch/arm/mach-omap2/mmc.h index 0cd4b08..db28c14 100644 --- a/arch/arm/mach-omap2/mmc.h +++ b/arch/arm/mach-omap2/mmc.h @@ -1,5 +1,5 @@ #include linux/mmc/host.h -#include linux/platform_data/mmc-omap.h +#include linux/platform_data/hsmmc-omap.h #define
[PATCH v2 8/9] omap_hsmmc: Remove unnecessary callbacks from platform data
These callbacks are set during driver probe and not from the platform init, -- evtl. they had been for oamp 1/2 -- for omap3 they are local functions of the driver. These indirection could be dropped altogether in favor of regular function calls TODO Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f8cd3b3..0a1398a 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -221,6 +221,25 @@ struct omap_hsmmc_host { #define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_hsmmc_platform_data*pdata; + + /* To handle board related suspend/resume functionality for MMC */ + int (*suspend)(struct device *dev, int slot); + int (*resume)(struct device *dev, int slot); + + /* return MMC cover switch state, can be NULL if not supported. +* +* possible return values: +* 0 - closed +* 1 - open +*/ + int (*get_cover_state)(struct device *dev, int slot); + + /* Card detection IRQs */ + int card_detect_irq; + + int (*card_detect)(struct device *dev, int slot); + int (*get_ro)(struct device *dev, int slot); + }; struct omap_mmc_of_data { @@ -262,18 +281,16 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot) static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_hsmmc_platform_data *mmc = host-pdata; - disable_irq(mmc-card_detect_irq); + disable_irq(host-card_detect_irq); return 0; } static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_hsmmc_platform_data *mmc = host-pdata; - enable_irq(mmc-card_detect_irq); + enable_irq(host-card_detect_irq); return 0; } @@ -456,11 +473,11 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, if (gpio_is_valid(pdata-switch_pin)) { if (pdata-cover) - pdata-get_cover_state = - omap_hsmmc_get_cover_state; + host-get_cover_state = + omap_hsmmc_get_cover_state; else - pdata-card_detect = omap_hsmmc_card_detect; - pdata-card_detect_irq = + host-card_detect = omap_hsmmc_card_detect; + host-card_detect_irq = gpio_to_irq(pdata-switch_pin); ret = gpio_request(pdata-switch_pin, mmc_cd); if (ret) @@ -473,7 +490,7 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host, } if (gpio_is_valid(pdata-gpio_wp)) { - pdata-get_ro = omap_hsmmc_get_wp; + host-get_ro = omap_hsmmc_get_wp; ret = gpio_request(pdata-gpio_wp, mmc_wp); if (ret) goto err_free_cd; @@ -795,8 +812,8 @@ int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) { int r = 1; - if (mmc_pdata(host)-get_cover_state) - r = mmc_pdata(host)-get_cover_state(host-dev, host-slot_id); + if (host-get_cover_state) + r = host-get_cover_state(host-dev, host-slot_id); return r; } @@ -1263,11 +1280,11 @@ err: /* Protect the card while the cover is open */ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) { - if (!mmc_pdata(host)-get_cover_state) + if (!host-get_cover_state) return; host-reqs_blocked = 0; - if (mmc_pdata(host)-get_cover_state(host-dev, host-slot_id)) { + if (host-get_cover_state(host-dev, host-slot_id)) { if (host-protect_card) { dev_info(host-dev, %s: cover is closed, card is now accessible\n, @@ -1290,13 +1307,12 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_hsmmc_platform_data *pdata = host-pdata; int carddetect; sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); - if (pdata-card_detect) - carddetect = pdata-card_detect(host-dev, host-slot_id); + if (host-card_detect) + carddetect = host-card_detect(host-dev, host-slot_id); else { omap_hsmmc_protect_card(host); carddetect = -ENOSYS; @@ -1672,18 +1688,18 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) { struct omap_hsmmc_host *host = mmc_priv(mmc); - if (!mmc_pdata(host)-card_detect) + if (!host-card_detect) return -ENOSYS; - return mmc_pdata(host
[PATCH 0/6] unshare and simplify omap_hsmmc platform struct
mmci and omap_hsmmc share very little fields in the platform struct. unsharing significantly simplifies the omap_hsmmc driver Andreas Fenkart (6): omap_hsmmc: unshare platform data struct with mmci driver omap_hsmmc: remove unused callbacks from platform data struct omap_hsmmc: remove unused fields in platform_data omap_hsmmc: remove unused get_context_loss_count callback omap_hsmmc: remove un-initialized callbacks from platform data omap_hsmmc: remove un-initialized get_cover_state callback arch/arm/mach-omap2/hsmmc.c| 61 ++ arch/arm/mach-omap2/hsmmc.h| 10 -- arch/arm/mach-omap2/mmc.h | 6 +- .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 6 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 6 +- drivers/mmc/host/omap_hsmmc.c | 133 +++-- include/linux/platform_data/hsmmc-omap.h | 103 7 files changed, 142 insertions(+), 183 deletions(-) create mode 100644 include/linux/platform_data/hsmmc-omap.h -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/6] omap_hsmmc: remove unused callbacks from platform data struct
driver never references these fields Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 9 - arch/arm/mach-omap2/hsmmc.h | 4 drivers/mmc/host/omap_hsmmc.c| 9 - include/linux/platform_data/hsmmc-omap.h | 4 4 files changed, 26 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index e3555f2..d599195 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -49,9 +49,6 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, u32 reg, prog_io; struct omap_hsmmc_platform_data *mmc = dev-platform_data; - if (mmc-slots[0].remux) - mmc-slots[0].remux(dev, slot, power_on); - /* * Assume we power both OMAP VMMC1 (for CMD, CLK, DAT0..3) and the * card with Vcc regulator (from twl4030 or whatever). OMAP has both @@ -137,9 +134,6 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, { struct omap_hsmmc_platform_data *mmc = dev-platform_data; - if (mmc-slots[0].remux) - mmc-slots[0].remux(dev, slot, power_on); - if (power_on) hsmmc2_select_input_clk_src(mmc); } @@ -271,9 +265,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc-slots[0].switch_pin = c-gpio_cd; mmc-slots[0].gpio_wp = c-gpio_wp; - mmc-slots[0].remux = c-remux; - mmc-slots[0].init_card = c-init_card; - if (c-cover_only) mmc-slots[0].cover = 1; diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 7f2e790..a8bc0c2 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -29,10 +29,6 @@ struct omap2_hsmmc_info { int ocr_mask; /* temporary HACK */ int max_freq; /* maximum clock, if constrained by external * circuitry, or 0 for default */ - /* Remux (pad configuration) when powering on/off */ - void (*remux)(struct device *dev, int slot, int power_on); - /* init some special card */ - void (*init_card)(struct mmc_card *card); }; #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5f2b5b7..02f3438 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1682,14 +1682,6 @@ static int omap_hsmmc_get_ro(struct mmc_host *mmc) return mmc_slot(host).get_ro(host-dev, 0); } -static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - if (mmc_slot(host).init_card) - mmc_slot(host).init_card(card); -} - static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct omap_hsmmc_host *host = mmc_priv(mmc); @@ -1838,7 +1830,6 @@ static const struct mmc_host_ops omap_hsmmc_ops = { .set_ios = omap_hsmmc_set_ios, .get_cd = omap_hsmmc_get_cd, .get_ro = omap_hsmmc_get_ro, - .init_card = omap_hsmmc_init_card, .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, }; diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index cb91db4..7620c21 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -116,19 +116,15 @@ struct omap_hsmmc_platform_data { int switch_pin; /* gpio (card detect) */ int gpio_wp;/* gpio (write protect) */ - int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); int (*set_power)(struct device *dev, int slot, int power_on, int vdd); int (*get_ro)(struct device *dev, int slot); - void (*remux)(struct device *dev, int slot, int power_on); /* Call back before enabling / disabling regulators */ void (*before_set_reg)(struct device *dev, int slot, int power_on, int vdd); /* Call back after enabling / disabling regulators */ void (*after_set_reg)(struct device *dev, int slot, int power_on, int vdd); - /* if we have special card, init it using this callback */ - void (*init_card)(struct mmc_card *card); /* return MMC cover switch state, can be NULL if not supported. * -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/6] omap_hsmmc: remove un-initialized callbacks from platform data
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- drivers/mmc/host/omap_hsmmc.c| 15 +-- include/linux/platform_data/hsmmc-omap.h | 8 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 02f3438..465c34e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2195,18 +2195,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) goto err_irq; } - if (pdata-init != NULL) { - if (pdata-init(pdev-dev) != 0) { - dev_err(mmc_dev(host-mmc), - Unable to configure MMC IRQs\n); - goto err_irq; - } - } - if (omap_hsmmc_have_reg() !mmc_slot(host).set_power) { ret = omap_hsmmc_reg_get(host); if (ret) - goto err_reg; + goto err_irq; host-use_reg = 1; } @@ -2269,9 +2261,6 @@ err_slot_name: err_irq_cd: if (host-use_reg) omap_hsmmc_reg_put(host); -err_reg: - if (host-pdata-cleanup) - host-pdata-cleanup(pdev-dev); err_irq: if (host-tx_chan) dma_release_channel(host-tx_chan); @@ -2297,8 +2286,6 @@ static int omap_hsmmc_remove(struct platform_device *pdev) mmc_remove_host(host-mmc); if (host-use_reg) omap_hsmmc_reg_put(host); - if (host-pdata-cleanup) - host-pdata-cleanup(pdev-dev); if (host-tx_chan) dma_release_channel(host-tx_chan); diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 28b8cff..066075c 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -45,14 +45,6 @@ struct omap_hsmmc_platform_data { * maximum frequency on the MMC bus */ unsigned int max_freq; - /* switch the bus to a new slot */ - int (*switch_slot)(struct device *dev, int slot); - /* initialize board-specific MMC functionality, can be NULL if -* not supported */ - int (*init)(struct device *dev); - void (*cleanup)(struct device *dev); - void (*shutdown)(struct device *dev); - /* To handle board related suspend/resume functionality for MMC */ int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/6] omap_hsmmc: remove unused fields in platform_data
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 13 - arch/arm/mach-omap2/hsmmc.h | 5 - include/linux/platform_data/hsmmc-omap.h | 24 3 files changed, 42 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index d599195..2f202bf 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -256,7 +256,6 @@ 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-max_freq = c-max_freq; mmc-reg_offset = 0; @@ -271,18 +270,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, if (c-nonremovable) mmc-slots[0].nonremovable = 1; - if (c-power_saving) - mmc-slots[0].power_saving = 1; - - if (c-no_off) - mmc-slots[0].no_off = 1; - - if (c-no_off_init) - mmc-slots[0].no_regulator_off_init = c-no_off_init; - - if (c-vcc_aux_disable_is_sleep) - mmc-slots[0].vcc_aux_disable_is_sleep = 1; - /* * NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index a8bc0c2..b18059b 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -12,15 +12,10 @@ 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 */ booltransceiver;/* MMC-2 option */ boolext_clock; /* use external pin for input clock */ boolcover_only; /* No card detect - just cover switch */ boolnonremovable; /* Nonremovable e.g. eMMC */ - boolpower_saving; /* Try to sleep or power off when possible */ - boolno_off; /* power_saving and power is not to go off */ - boolno_off_init;/* no power off when not in MMC sleep state */ - boolvcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */ booldeferred; /* mmc needs a deferred probe */ int gpio_cd;/* or -EINVAL */ int gpio_wp;/* or -EINVAL */ diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index 7620c21..b80460d 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -30,8 +30,6 @@ #define OMAP_HSMMC_BROKEN_MULTIBLOCK_READ BIT(1) #define OMAP_HSMMC_SWAKEUP_MISSING BIT(2) -struct mmc_card; - struct omap_hsmmc_dev_attr { u8 flags; }; @@ -73,16 +71,9 @@ struct omap_hsmmc_platform_data { * 4/8 wires and any additional host capabilities * need to OR'd all capabilities (ref. linux/mmc/host.h) */ - 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 -* that board-specific code handled it before common init logic. -*/ - unsigned nomux:1; - /* switch pin can be for card detect (default) or card cover */ unsigned cover:1; @@ -92,25 +83,13 @@ struct omap_hsmmc_platform_data { /* nonremovable e.g. eMMC */ unsigned nonremovable:1; - /* Try to sleep or power off when possible */ - unsigned power_saving:1; - - /* If using power_saving and the MMC power is not to go off */ - unsigned no_off:1; - /* eMMC does not handle power off when not in sleep state */ unsigned no_regulator_off_init:1; - /* Regulator off remapped to sleep */ - unsigned vcc_aux_disable_is_sleep:1; - /* we can put the features above into this variable */ #define HSMMC_HAS_PBIAS(1 0) #define HSMMC_HAS_UPDATED_RESET(1 1) #define HSMMC_HAS_HSPE_SUPPORT (1 2) -#define MMC_OMAP7XX(1 3) -#define MMC_OMAP15XX (1 4) -#define MMC_OMAP16XX (1 5) unsigned features; int switch_pin; /* gpio (card detect) */ @@ -141,8 +120,5 @@ struct omap_hsmmc_platform_data { int card_detect_irq; int
[PATCH 4/6] omap_hsmmc: remove unused get_context_loss_count callback
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 12 include/linux/platform_data/hsmmc-omap.h | 3 --- 2 files changed, 15 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 2f202bf..9ed9f70 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -32,17 +32,6 @@ static u16 control_devconf1_offset; #define HSMMC_NAME_LEN 9 -#if defined(CONFIG_ARCH_OMAP3) defined(CONFIG_PM) - -static int hsmmc_get_context_loss(struct device *dev) -{ - return omap_pm_get_dev_context_loss_count(dev); -} - -#else -#define hsmmc_get_context_loss NULL -#endif - static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { @@ -259,7 +248,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc-slots[0].internal_clock = !c-ext_clock; mmc-max_freq = c-max_freq; mmc-reg_offset = 0; - mmc-get_context_loss_count = hsmmc_get_context_loss; mmc-slots[0].switch_pin = c-gpio_cd; mmc-slots[0].gpio_wp = c-gpio_wp; diff --git a/include/linux/platform_data/hsmmc-omap.h b/include/linux/platform_data/hsmmc-omap.h index b80460d..28b8cff 100644 --- a/include/linux/platform_data/hsmmc-omap.h +++ b/include/linux/platform_data/hsmmc-omap.h @@ -57,9 +57,6 @@ struct omap_hsmmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); - /* Return context loss count due to PM states changing */ - int (*get_context_loss_count)(struct device *dev); - /* Integrating attributes from the omap_hwmod layer */ u8 controller_flags; -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/6] omap_hsmmc: remove un-initialized get_cover_state callback
Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c | 3 -- arch/arm/mach-omap2/hsmmc.h | 1 - drivers/mmc/host/omap_hsmmc.c| 83 ++-- include/linux/platform_data/hsmmc-omap.h | 10 4 files changed, 4 insertions(+), 93 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 9ed9f70..068ccf5 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -252,9 +252,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc-slots[0].switch_pin = c-gpio_cd; mmc-slots[0].gpio_wp = c-gpio_wp; - if (c-cover_only) - mmc-slots[0].cover = 1; - if (c-nonremovable) mmc-slots[0].nonremovable = 1; diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index b18059b..1c4a363 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -14,7 +14,6 @@ struct omap2_hsmmc_info { * capabilities OR'd (ref. linux/mmc/host.h) */ booltransceiver;/* MMC-2 option */ boolext_clock; /* use external pin for input clock */ - boolcover_only; /* No card detect - just cover switch */ boolnonremovable; /* Nonremovable e.g. eMMC */ booldeferred; /* mmc needs a deferred probe */ int gpio_cd;/* or -EINVAL */ diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 465c34e..a558c87 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -248,15 +248,6 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot) return gpio_get_value_cansleep(mmc-slots[0].gpio_wp); } -static int omap_hsmmc_get_cover_state(struct device *dev, int slot) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_hsmmc_platform_data *mmc = host-pdata; - - /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc-slots[0].switch_pin); -} - #ifdef CONFIG_PM static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) @@ -454,11 +445,7 @@ static int omap_hsmmc_gpio_init(struct omap_hsmmc_platform_data *pdata) int ret; if (gpio_is_valid(pdata-slots[0].switch_pin)) { - if (pdata-slots[0].cover) - pdata-slots[0].get_cover_state = - omap_hsmmc_get_cover_state; - else - pdata-slots[0].card_detect = omap_hsmmc_card_detect; + pdata-slots[0].card_detect = omap_hsmmc_card_detect; pdata-slots[0].card_detect_irq = gpio_to_irq(pdata-slots[0].switch_pin); ret = gpio_request(pdata-slots[0].switch_pin, mmc_cd); @@ -786,29 +773,6 @@ static void send_init_stream(struct omap_hsmmc_host *host) enable_irq(host-irq); } -static inline -int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) -{ - int r = 1; - - if (mmc_slot(host).get_cover_state) - r = mmc_slot(host).get_cover_state(host-dev, host-slot_id); - return r; -} - -static ssize_t -omap_hsmmc_show_cover_switch(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); - struct omap_hsmmc_host *host = mmc_priv(mmc); - - return sprintf(buf, %s\n, - omap_hsmmc_cover_is_closed(host) ? closed : open); -} - -static DEVICE_ATTR(cover_switch, S_IRUGO, omap_hsmmc_show_cover_switch, NULL); - static ssize_t omap_hsmmc_show_slot_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -1256,30 +1220,6 @@ err: return ret; } -/* Protect the card while the cover is open */ -static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) -{ - if (!mmc_slot(host).get_cover_state) - return; - - host-reqs_blocked = 0; - if (mmc_slot(host).get_cover_state(host-dev, host-slot_id)) { - if (host-protect_card) { - dev_info(host-dev, %s: cover is closed, -card is now accessible\n, -mmc_hostname(host-mmc)); - host-protect_card = 0; - } - } else { - if (!host-protect_card) { - dev_info(host-dev, %s: cover is open, -card is now inaccessible\n, -mmc_hostname(host-mmc)); - host-protect_card = 1; - } - } -} - /* * irq handler to notify the core about card insertion/removal */ @@ -1289,15 +1229,10 @@ static irqreturn_t omap_hsmmc_detect
[PATCH 1/6] omap_hsmmc: unshare platform data struct with mmci driver
- mmci driver supports multiple slots, omap_hsmmc only one this leads to one of the major confusions in the omap_hsmmc driver - platform data should be read-only for the driver most callbacks are not set by the platform init code while being required by the driver, leading to the fact that they are set by the driver during it's probe function typical example are card detect / read only detect callbacks Signed-off-by: Andreas Fenkart afenk...@gmail.com --- arch/arm/mach-omap2/hsmmc.c| 24 ++-- arch/arm/mach-omap2/mmc.h | 6 +- .../mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c | 6 +- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 6 +- drivers/mmc/host/omap_hsmmc.c | 28 ++-- include/linux/platform_data/hsmmc-omap.h | 152 + 6 files changed, 187 insertions(+), 35 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index 07d4c7b..e3555f2 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -47,7 +47,7 @@ static void omap_hsmmc1_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { u32 reg, prog_io; - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -120,7 +120,7 @@ static void omap_hsmmc1_after_set_reg(struct device *dev, int slot, } } -static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) +static void hsmmc2_select_input_clk_src(struct omap_hsmmc_platform_data *mmc) { u32 reg; @@ -135,7 +135,7 @@ static void hsmmc2_select_input_clk_src(struct omap_mmc_platform_data *mmc) static void hsmmc2_before_set_reg(struct device *dev, int slot, int power_on, int vdd) { - struct omap_mmc_platform_data *mmc = dev-platform_data; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (mmc-slots[0].remux) mmc-slots[0].remux(dev, slot, power_on); @@ -147,7 +147,7 @@ static void hsmmc2_before_set_reg(struct device *dev, int slot, 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; + struct omap_hsmmc_platform_data *mmc = dev-platform_data; if (power_on) hsmmc2_select_input_clk_src(mmc); @@ -161,8 +161,8 @@ static int nop_mmc_set_power(struct device *dev, int slot, int power_on, return 0; } -static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, - int controller_nr) +static inline void omap_hsmmc_mux(struct omap_hsmmc_platform_data + *mmc_controller, int controller_nr) { if (gpio_is_valid(mmc_controller-slots[0].switch_pin) (mmc_controller-slots[0].switch_pin OMAP_MAX_GPIO_LINES)) @@ -243,7 +243,7 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, } static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, - struct omap_mmc_platform_data *mmc) + struct omap_hsmmc_platform_data *mmc) { char *hc_name; @@ -368,7 +368,7 @@ static int omap_hsmmc_done; void omap_hsmmc_late_init(struct omap2_hsmmc_info *c) { struct platform_device *pdev; - struct omap_mmc_platform_data *mmc_pdata; + struct omap_hsmmc_platform_data *mmc_pdata; int res; if (omap_hsmmc_done != 1) @@ -408,12 +408,12 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, struct omap_device *od; struct platform_device *pdev; char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN]; - struct omap_mmc_platform_data *mmc_data; - struct omap_mmc_dev_attr *mmc_dev_attr; + struct omap_hsmmc_platform_data *mmc_data; + struct omap_hsmmc_dev_attr *mmc_dev_attr; char *name; int res; - mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); + mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL); if (!mmc_data) { pr_err(Cannot allocate memory for mmc device!\n); return; @@ -463,7 +463,7 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, } res = platform_device_add_data(pdev, mmc_data, - sizeof(struct omap_mmc_platform_data)); + sizeof(struct omap_hsmmc_platform_data)); if (res) { pr_err(Could not add pdata for %s\n, name); goto put_pdev; diff --git a/arch/arm/mach-omap2/mmc.h b/arch/arm/mach-omap2/mmc.h index 0cd4b08
Re: [PATCH v14 1/6] mmc: omap_hsmmc: Enable SDIO interrupt
Hi Florian 2014-08-24 10:26 GMT+02:00 Florian Vaussard florian.vauss...@epfl.ch: Hi Andreas, On 05/29/2014 10:28 AM, Andreas Fenkart wrote: There have been various patches floating around for enabling the SDIO IRQ for hsmmc, but none of them ever got merged. [...] For now, only support SDIO interrupt if we are booted with a separate wake-irq configued via device tree. This is because omaps need the wake-irq for idle states, and some omaps need special quirks. And we don't want to add new legacy mux platform init code callbacks any longer as we are moving to DT based booting anyways. To use it, you need to specify the wake-irq using the interrupts-extended property. First, thanks a lot for your tenacity on this patchset, this was a long needed feature. I enabled the SDIO interrupt, and got the throughput of my 88W8686-based chip multiplied by 15. Nice! I just have an issue with the wake-up path, and maybe you could help me. According to the DM3730 TRM, the MMC2 has the SWAKEUP path. So first I tried to give the same wake-irq as the MMC's one, but omap_hsmmc_configure_wake_irq() fails to request it, as they are not IRQF_SHARED. Why can't it be shared? So I used the DAT1 for the wake-irq (see patch below), and things are working. But I get ~2000 wake-irq per seconds, even without any activity on the WiFi. As a result, the driver is ping-ponging between omap_hsmmc_runtime_suspend() and omap_hsmmc_runtime_resume(), causing kworker to eat most of my CPU. Am I missing something obvious? Thanks! Florian -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/3 resend] omap_hsmmc: reuse mmc/slot-gpio functions
Hi, I would like to reuse mmc_of_parse for standard mmc features: - cd-gpios / wp-gpios - bus-width - max-frequency - keep-power-in-suspend - enable-sdio-wakeup - ti,non-removable, evtl. Currently these are open-coded in of_get_hsmmc_pdata. I tried removing them from of_get_hsmmc_pdata and call mmc_of_parse at the end of the probe function: @@ -2241,8 +2264,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_protect_card(host); + mmc_of_parse(host-mmc); mmc_add_host(mmc); This could work transparently for most features but definitely not for cd-gpios/wp-gpios. Pls can somebody have a look at the followup patches? I tried an intermediate step mapping card detect / read-only detect onto mmc/slot-gpio, that are used by mmc_of_parse. I don't have card detect/read-only detect pins, so patches are untested, :-( Do we need cover_detect functionality or could it be merged with card detect? Another issue is 'ti,non-removable' which could be mappend to stanadard 'non-removable' if 'no_regulator_off_init' was handled in a different way. if (of_find_property(np, ti,non-removable, NULL)) { pdata-slots[0].nonremovable = true; pdata-slots[0].no_regulator_off_init = true; } /Andreas Andreas Fenkart (3): omap_hsmmc: reuse mmc/slot-gpio for write protect detection omap_hsmmc: separate card_detect/cover detect logic omap_hsmmc: reuse mmc/slot-gpio for card detect instead of open-coded version drivers/mmc/host/omap_hsmmc.c | 172 ++--- include/linux/platform_data/mmc-omap.h | 6 +- 2 files changed, 73 insertions(+), 105 deletions(-) -- 2.0.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3 resend] omap_hsmmc: reuse mmc/slot-gpio for write protect detection
Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2f944d7..1c10e6c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -36,6 +36,7 @@ #include linux/mmc/host.h #include linux/mmc/core.h #include linux/mmc/mmc.h +#include linux/mmc/slot-gpio.h #include linux/io.h #include linux/irq.h #include linux/gpio.h @@ -239,15 +240,6 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) return !gpio_get_value_cansleep(mmc-slots[0].switch_pin); } -static int omap_hsmmc_get_wp(struct device *dev, int slot) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host-pdata; - - /* NOTE: assumes write protect signal is active-high */ - return gpio_get_value_cansleep(mmc-slots[0].gpio_wp); -} - static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -449,7 +441,8 @@ static inline int omap_hsmmc_have_reg(void) #endif -static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) +static int omap_hsmmc_gpio_init(struct mmc_host *mmc, + struct omap_mmc_platform_data *pdata) { int ret; @@ -471,31 +464,31 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) pdata-slots[0].switch_pin = -EINVAL; if (gpio_is_valid(pdata-slots[0].gpio_wp)) { - pdata-slots[0].get_ro = omap_hsmmc_get_wp; - ret = gpio_request(pdata-slots[0].gpio_wp, mmc_wp); - if (ret) - goto err_free_cd; - ret = gpio_direction_input(pdata-slots[0].gpio_wp); - if (ret) - goto err_free_wp; - } else - pdata-slots[0].gpio_wp = -EINVAL; + /* copy paste from from mmc_of_parse */ + ret = mmc_gpio_request_ro(mmc, pdata-slots[0].gpio_wp); + if (ret 0) { + dev_err(pdata-dev, + Failed to request WP GPIO: %d!\n, ret); + goto err; + } else { + dev_info(pdata-dev, Got WP GPIO #%d.\n, +pdata-slots[0].gpio_wp); + } + } return 0; -err_free_wp: - gpio_free(pdata-slots[0].gpio_wp); -err_free_cd: +err: if (gpio_is_valid(pdata-slots[0].switch_pin)) err_free_sp: gpio_free(pdata-slots[0].switch_pin); return ret; } -static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) +static void omap_hsmmc_gpio_free(struct mmc_host *mmc, +struct omap_mmc_platform_data *pdata) { - if (gpio_is_valid(pdata-slots[0].gpio_wp)) - gpio_free(pdata-slots[0].gpio_wp); + mmc_gpio_free_ro(mmc); if (gpio_is_valid(pdata-slots[0].switch_pin)) gpio_free(pdata-slots[0].switch_pin); } @@ -1673,15 +1666,6 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) return mmc_slot(host).card_detect(host-dev, host-slot_id); } -static int omap_hsmmc_get_ro(struct mmc_host *mmc) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - if (!mmc_slot(host).get_ro) - return -ENOSYS; - return mmc_slot(host).get_ro(host-dev, 0); -} - static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) { struct omap_hsmmc_host *host = mmc_priv(mmc); @@ -1837,7 +1821,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = { .request = omap_hsmmc_request, .set_ios = omap_hsmmc_set_ios, .get_cd = omap_hsmmc_get_cd, - .get_ro = omap_hsmmc_get_ro, + .get_ro = mmc_gpio_get_ro, .init_card = omap_hsmmc_init_card, .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, }; @@ -2063,16 +2047,15 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - ret = omap_hsmmc_gpio_init(pdata); - if (ret) - goto err; - mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), pdev-dev); if (!mmc) { - ret = -ENOMEM; - goto err_alloc; + return -ENOMEM; } + ret = omap_hsmmc_gpio_init(mmc, pdata); + if (ret) + goto err; + host= mmc_priv(mmc); host-mmc = mmc; host-pdata = pdata; @@ -2302,10 +2285,9 @@ err_irq: if (host-dbclk) clk_disable_unprepare(host-dbclk); err1: - mmc_free_host(mmc); -err_alloc: - omap_hsmmc_gpio_free(pdata); + omap_hsmmc_gpio_free(mmc, pdata); err: + mmc_free_host(mmc); return ret; } @@ -2330,7 +2312,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) if (host
[PATCH 3/3 resend] omap_hsmmc: reuse mmc/slot-gpio for card detect instead of open-coded version
Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1b9f279..25aafa6 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -231,15 +231,6 @@ struct omap_mmc_of_data { static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); -static int omap_hsmmc_card_detect(struct device *dev, int slot) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host-pdata; - - /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc-slots[0].switch_pin); -} - static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -256,7 +247,7 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_mmc_platform_data *mmc = host-pdata; - disable_irq(mmc-slots[0].card_detect_irq); + disable_irq(mmc-slots[0].cover_detect_irq); return 0; } @@ -265,7 +256,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_mmc_platform_data *mmc = host-pdata; - enable_irq(mmc-slots[0].card_detect_irq); + enable_irq(mmc-slots[0].cover_detect_irq); return 0; } @@ -458,23 +449,26 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, if (ret) return ret; ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + if (ret) { + gpio_free(pdata-slots[0].switch_pin); + return ret; + } } else { - pdata-slots[0].card_detect = omap_hsmmc_card_detect; - pdata-slots[0].card_detect_irq = - gpio_to_irq(pdata-slots[0].switch_pin); - - ret = gpio_request(pdata-slots[0].switch_pin, - mmc_cd); - if (ret) + /* copy paste from from mmc_of_parse */ + ret = mmc_gpio_request_cd(mmc, + pdata-slots[0].switch_pin, + 0); + if (ret 0) { + dev_err(pdata-dev, + Failed to request CD GPIO #%d: %d!\n, + pdata-slots[0].switch_pin, ret); return ret; - ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + } else { + dev_info(pdata-dev, Got CD GPIO #%d.\n, + pdata-slots[0].switch_pin); + } } - } else - pdata-slots[0].switch_pin = -EINVAL; + } if (gpio_is_valid(pdata-slots[0].gpio_wp)) { /* copy paste from from mmc_of_parse */ @@ -492,8 +486,9 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, return 0; err: - if (gpio_is_valid(pdata-slots[0].switch_pin)) -err_free_sp: + mmc_gpio_free_cd(mmc); + if (gpio_is_valid(pdata-slots[0].switch_pin) + (pdata-slots[0].cover)) gpio_free(pdata-slots[0].switch_pin); return ret; } @@ -501,8 +496,11 @@ err_free_sp: static void omap_hsmmc_gpio_free(struct mmc_host *mmc, struct omap_mmc_platform_data *pdata) { + mmc_gpio_free_cd(mmc); mmc_gpio_free_ro(mmc); - if (gpio_is_valid(pdata-slots[0].switch_pin)) + + if (gpio_is_valid(pdata-slots[0].switch_pin) + (pdata-slots[0].cover)) gpio_free(pdata-slots[0].switch_pin); } @@ -1289,24 +1287,13 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) /* * irq handler to notify the core about card insertion/removal */ -static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) +static irqreturn_t omap_hsmmc_cover_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_mmc_slot_data *slot = mmc_slot(host); - int carddetect; - - if (slot-card_detect) { - carddetect = slot-card_detect(host-dev, host-slot_id); - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); - } else
[PATCH 2/3 resend] omap_hsmmc: separate card_detect/cover detect logic
assuming cover is the door like thing on cameras that needs to be closed after replacing sd cards. card detect is a gpio connected to sdio slot. in a follow up patch card_detect will be replaced by generic mmc/slot-gpio a git bisect patch Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1c10e6c..1b9f279 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -447,19 +447,32 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, int ret; if (gpio_is_valid(pdata-slots[0].switch_pin)) { - if (pdata-slots[0].cover) + if (pdata-slots[0].cover) { pdata-slots[0].get_cover_state = omap_hsmmc_get_cover_state; - else + pdata-slots[0].cover_detect_irq = + gpio_to_irq(pdata-slots[0].switch_pin); + + ret = gpio_request(pdata-slots[0].switch_pin, + mmc_cd); + if (ret) + return ret; + ret = gpio_direction_input(pdata-slots[0].switch_pin); + if (ret) + goto err_free_sp; + } else { pdata-slots[0].card_detect = omap_hsmmc_card_detect; - pdata-slots[0].card_detect_irq = + pdata-slots[0].card_detect_irq = gpio_to_irq(pdata-slots[0].switch_pin); - ret = gpio_request(pdata-slots[0].switch_pin, mmc_cd); - if (ret) - return ret; - ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + + ret = gpio_request(pdata-slots[0].switch_pin, + mmc_cd); + if (ret) + return ret; + ret = gpio_direction_input(pdata-slots[0].switch_pin); + if (ret) + goto err_free_sp; + } } else pdata-slots[0].switch_pin = -EINVAL; @@ -1282,19 +1295,18 @@ static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) struct omap_mmc_slot_data *slot = mmc_slot(host); int carddetect; - sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); - - if (slot-card_detect) + if (slot-card_detect) { carddetect = slot-card_detect(host-dev, host-slot_id); - else { + if (carddetect) + mmc_detect_change(host-mmc, (HZ * 200) / 1000); + else + mmc_detect_change(host-mmc, (HZ * 50) / 1000); + } else { + sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); omap_hsmmc_protect_card(host); - carddetect = -ENOSYS; + mmc_detect_change(host-mmc, (HZ * 200) / 1000); } - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); return IRQ_HANDLED; } diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h index 7fe0c14..d113005 100644 --- a/include/linux/platform_data/mmc-omap.h +++ b/include/linux/platform_data/mmc-omap.h @@ -136,6 +136,7 @@ struct omap_mmc_platform_data { * 0 - closed * 1 - open */ + int cover_detect_irq; int (*get_cover_state)(struct device *dev, int slot); const char *name; -- 2.0.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/3 resend] omap_hsmmc: reuse mmc/slot-gpio functions
Hi, I would like to reuse mmc_of_parse for standard mmc features: - cd-gpios / wp-gpios - bus-width - max-frequency - keep-power-in-suspend - enable-sdio-wakeup - ti,non-removable, evtl. Currently these are open-coded in of_get_hsmmc_pdata. I tried removing them from of_get_hsmmc_pdata and call mmc_of_parse at the end of the probe function: @@ -2241,8 +2264,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_protect_card(host); + mmc_of_parse(host-mmc); mmc_add_host(mmc); This could work transparently for most features but definitely not for cd-gpios/wp-gpios. Pls can somebody have a look at the followup patches? I tried an intermediate step mapping card detect / read-only detect onto mmc/slot-gpio, that are used by mmc_of_parse. I don't have card detect/read-only detect pins, so patches are untested, :-( Do we need cover_detect functionality or could it be merged with card detect? Another issue is 'ti,non-removable' which could be mappend to stanadard 'non-removable' if 'no_regulator_off_init' was handled in a different way. if (of_find_property(np, ti,non-removable, NULL)) { pdata-slots[0].nonremovable = true; pdata-slots[0].no_regulator_off_init = true; } /Andreas Andreas Fenkart (3): omap_hsmmc: reuse mmc/slot-gpio for write protect detection omap_hsmmc: separate card_detect/cover detect logic omap_hsmmc: reuse mmc/slot-gpio for card detect instead of open-coded version drivers/mmc/host/omap_hsmmc.c | 172 ++--- include/linux/platform_data/mmc-omap.h | 6 +- 2 files changed, 73 insertions(+), 105 deletions(-) -- 2.0.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3 resend] omap_hsmmc: reuse mmc/slot-gpio for card detect instead of open-coded version
Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1b9f279..25aafa6 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -231,15 +231,6 @@ struct omap_mmc_of_data { static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); -static int omap_hsmmc_card_detect(struct device *dev, int slot) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host-pdata; - - /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc-slots[0].switch_pin); -} - static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -256,7 +247,7 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_mmc_platform_data *mmc = host-pdata; - disable_irq(mmc-slots[0].card_detect_irq); + disable_irq(mmc-slots[0].cover_detect_irq); return 0; } @@ -265,7 +256,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_mmc_platform_data *mmc = host-pdata; - enable_irq(mmc-slots[0].card_detect_irq); + enable_irq(mmc-slots[0].cover_detect_irq); return 0; } @@ -458,23 +449,26 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, if (ret) return ret; ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + if (ret) { + gpio_free(pdata-slots[0].switch_pin); + return ret; + } } else { - pdata-slots[0].card_detect = omap_hsmmc_card_detect; - pdata-slots[0].card_detect_irq = - gpio_to_irq(pdata-slots[0].switch_pin); - - ret = gpio_request(pdata-slots[0].switch_pin, - mmc_cd); - if (ret) + /* copy paste from from mmc_of_parse */ + ret = mmc_gpio_request_cd(mmc, + pdata-slots[0].switch_pin, + 0); + if (ret 0) { + dev_err(pdata-dev, + Failed to request CD GPIO #%d: %d!\n, + pdata-slots[0].switch_pin, ret); return ret; - ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + } else { + dev_info(pdata-dev, Got CD GPIO #%d.\n, + pdata-slots[0].switch_pin); + } } - } else - pdata-slots[0].switch_pin = -EINVAL; + } if (gpio_is_valid(pdata-slots[0].gpio_wp)) { /* copy paste from from mmc_of_parse */ @@ -492,8 +486,9 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, return 0; err: - if (gpio_is_valid(pdata-slots[0].switch_pin)) -err_free_sp: + mmc_gpio_free_cd(mmc); + if (gpio_is_valid(pdata-slots[0].switch_pin) + (pdata-slots[0].cover)) gpio_free(pdata-slots[0].switch_pin); return ret; } @@ -501,8 +496,11 @@ err_free_sp: static void omap_hsmmc_gpio_free(struct mmc_host *mmc, struct omap_mmc_platform_data *pdata) { + mmc_gpio_free_cd(mmc); mmc_gpio_free_ro(mmc); - if (gpio_is_valid(pdata-slots[0].switch_pin)) + + if (gpio_is_valid(pdata-slots[0].switch_pin) + (pdata-slots[0].cover)) gpio_free(pdata-slots[0].switch_pin); } @@ -1289,24 +1287,13 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) /* * irq handler to notify the core about card insertion/removal */ -static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) +static irqreturn_t omap_hsmmc_cover_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_mmc_slot_data *slot = mmc_slot(host); - int carddetect; - - if (slot-card_detect) { - carddetect = slot-card_detect(host-dev, host-slot_id); - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); - } else
[PATCH 1/3 resend] omap_hsmmc: reuse mmc/slot-gpio for write protect detection
Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2f944d7..1c10e6c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -36,6 +36,7 @@ #include linux/mmc/host.h #include linux/mmc/core.h #include linux/mmc/mmc.h +#include linux/mmc/slot-gpio.h #include linux/io.h #include linux/irq.h #include linux/gpio.h @@ -239,15 +240,6 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) return !gpio_get_value_cansleep(mmc-slots[0].switch_pin); } -static int omap_hsmmc_get_wp(struct device *dev, int slot) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host-pdata; - - /* NOTE: assumes write protect signal is active-high */ - return gpio_get_value_cansleep(mmc-slots[0].gpio_wp); -} - static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -449,7 +441,8 @@ static inline int omap_hsmmc_have_reg(void) #endif -static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) +static int omap_hsmmc_gpio_init(struct mmc_host *mmc, + struct omap_mmc_platform_data *pdata) { int ret; @@ -471,31 +464,31 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) pdata-slots[0].switch_pin = -EINVAL; if (gpio_is_valid(pdata-slots[0].gpio_wp)) { - pdata-slots[0].get_ro = omap_hsmmc_get_wp; - ret = gpio_request(pdata-slots[0].gpio_wp, mmc_wp); - if (ret) - goto err_free_cd; - ret = gpio_direction_input(pdata-slots[0].gpio_wp); - if (ret) - goto err_free_wp; - } else - pdata-slots[0].gpio_wp = -EINVAL; + /* copy paste from from mmc_of_parse */ + ret = mmc_gpio_request_ro(mmc, pdata-slots[0].gpio_wp); + if (ret 0) { + dev_err(pdata-dev, + Failed to request WP GPIO: %d!\n, ret); + goto err; + } else { + dev_info(pdata-dev, Got WP GPIO #%d.\n, +pdata-slots[0].gpio_wp); + } + } return 0; -err_free_wp: - gpio_free(pdata-slots[0].gpio_wp); -err_free_cd: +err: if (gpio_is_valid(pdata-slots[0].switch_pin)) err_free_sp: gpio_free(pdata-slots[0].switch_pin); return ret; } -static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) +static void omap_hsmmc_gpio_free(struct mmc_host *mmc, +struct omap_mmc_platform_data *pdata) { - if (gpio_is_valid(pdata-slots[0].gpio_wp)) - gpio_free(pdata-slots[0].gpio_wp); + mmc_gpio_free_ro(mmc); if (gpio_is_valid(pdata-slots[0].switch_pin)) gpio_free(pdata-slots[0].switch_pin); } @@ -1673,15 +1666,6 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) return mmc_slot(host).card_detect(host-dev, host-slot_id); } -static int omap_hsmmc_get_ro(struct mmc_host *mmc) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - if (!mmc_slot(host).get_ro) - return -ENOSYS; - return mmc_slot(host).get_ro(host-dev, 0); -} - static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) { struct omap_hsmmc_host *host = mmc_priv(mmc); @@ -1837,7 +1821,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = { .request = omap_hsmmc_request, .set_ios = omap_hsmmc_set_ios, .get_cd = omap_hsmmc_get_cd, - .get_ro = omap_hsmmc_get_ro, + .get_ro = mmc_gpio_get_ro, .init_card = omap_hsmmc_init_card, .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, }; @@ -2063,16 +2047,15 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - ret = omap_hsmmc_gpio_init(pdata); - if (ret) - goto err; - mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), pdev-dev); if (!mmc) { - ret = -ENOMEM; - goto err_alloc; + return -ENOMEM; } + ret = omap_hsmmc_gpio_init(mmc, pdata); + if (ret) + goto err; + host= mmc_priv(mmc); host-mmc = mmc; host-pdata = pdata; @@ -2302,10 +2285,9 @@ err_irq: if (host-dbclk) clk_disable_unprepare(host-dbclk); err1: - mmc_free_host(mmc); -err_alloc: - omap_hsmmc_gpio_free(pdata); + omap_hsmmc_gpio_free(mmc, pdata); err: + mmc_free_host(mmc); return ret; } @@ -2330,7 +2312,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) if (host
[PATCH 2/3 resend] omap_hsmmc: separate card_detect/cover detect logic
assuming cover is the door like thing on cameras that needs to be closed after replacing sd cards. card detect is a gpio connected to sdio slot. in a follow up patch card_detect will be replaced by generic mmc/slot-gpio a git bisect patch Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1c10e6c..1b9f279 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -447,19 +447,32 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, int ret; if (gpio_is_valid(pdata-slots[0].switch_pin)) { - if (pdata-slots[0].cover) + if (pdata-slots[0].cover) { pdata-slots[0].get_cover_state = omap_hsmmc_get_cover_state; - else + pdata-slots[0].cover_detect_irq = + gpio_to_irq(pdata-slots[0].switch_pin); + + ret = gpio_request(pdata-slots[0].switch_pin, + mmc_cd); + if (ret) + return ret; + ret = gpio_direction_input(pdata-slots[0].switch_pin); + if (ret) + goto err_free_sp; + } else { pdata-slots[0].card_detect = omap_hsmmc_card_detect; - pdata-slots[0].card_detect_irq = + pdata-slots[0].card_detect_irq = gpio_to_irq(pdata-slots[0].switch_pin); - ret = gpio_request(pdata-slots[0].switch_pin, mmc_cd); - if (ret) - return ret; - ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + + ret = gpio_request(pdata-slots[0].switch_pin, + mmc_cd); + if (ret) + return ret; + ret = gpio_direction_input(pdata-slots[0].switch_pin); + if (ret) + goto err_free_sp; + } } else pdata-slots[0].switch_pin = -EINVAL; @@ -1282,19 +1295,18 @@ static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) struct omap_mmc_slot_data *slot = mmc_slot(host); int carddetect; - sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); - - if (slot-card_detect) + if (slot-card_detect) { carddetect = slot-card_detect(host-dev, host-slot_id); - else { + if (carddetect) + mmc_detect_change(host-mmc, (HZ * 200) / 1000); + else + mmc_detect_change(host-mmc, (HZ * 50) / 1000); + } else { + sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); omap_hsmmc_protect_card(host); - carddetect = -ENOSYS; + mmc_detect_change(host-mmc, (HZ * 200) / 1000); } - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); return IRQ_HANDLED; } diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h index 7fe0c14..d113005 100644 --- a/include/linux/platform_data/mmc-omap.h +++ b/include/linux/platform_data/mmc-omap.h @@ -136,6 +136,7 @@ struct omap_mmc_platform_data { * 0 - closed * 1 - open */ + int cover_detect_irq; int (*get_cover_state)(struct device *dev, int slot); const char *name; -- 2.0.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/3] omap_hsmmc: reuse mmc/slot-gpio for write protect detection
Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2f944d7..1c10e6c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -36,6 +36,7 @@ #include linux/mmc/host.h #include linux/mmc/core.h #include linux/mmc/mmc.h +#include linux/mmc/slot-gpio.h #include linux/io.h #include linux/irq.h #include linux/gpio.h @@ -239,15 +240,6 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot) return !gpio_get_value_cansleep(mmc-slots[0].switch_pin); } -static int omap_hsmmc_get_wp(struct device *dev, int slot) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host-pdata; - - /* NOTE: assumes write protect signal is active-high */ - return gpio_get_value_cansleep(mmc-slots[0].gpio_wp); -} - static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -449,7 +441,8 @@ static inline int omap_hsmmc_have_reg(void) #endif -static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) +static int omap_hsmmc_gpio_init(struct mmc_host *mmc, + struct omap_mmc_platform_data *pdata) { int ret; @@ -471,31 +464,31 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) pdata-slots[0].switch_pin = -EINVAL; if (gpio_is_valid(pdata-slots[0].gpio_wp)) { - pdata-slots[0].get_ro = omap_hsmmc_get_wp; - ret = gpio_request(pdata-slots[0].gpio_wp, mmc_wp); - if (ret) - goto err_free_cd; - ret = gpio_direction_input(pdata-slots[0].gpio_wp); - if (ret) - goto err_free_wp; - } else - pdata-slots[0].gpio_wp = -EINVAL; + /* copy paste from from mmc_of_parse */ + ret = mmc_gpio_request_ro(mmc, pdata-slots[0].gpio_wp); + if (ret 0) { + dev_err(pdata-dev, + Failed to request WP GPIO: %d!\n, ret); + goto err; + } else { + dev_info(pdata-dev, Got WP GPIO #%d.\n, +pdata-slots[0].gpio_wp); + } + } return 0; -err_free_wp: - gpio_free(pdata-slots[0].gpio_wp); -err_free_cd: +err: if (gpio_is_valid(pdata-slots[0].switch_pin)) err_free_sp: gpio_free(pdata-slots[0].switch_pin); return ret; } -static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) +static void omap_hsmmc_gpio_free(struct mmc_host *mmc, +struct omap_mmc_platform_data *pdata) { - if (gpio_is_valid(pdata-slots[0].gpio_wp)) - gpio_free(pdata-slots[0].gpio_wp); + mmc_gpio_free_ro(mmc); if (gpio_is_valid(pdata-slots[0].switch_pin)) gpio_free(pdata-slots[0].switch_pin); } @@ -1673,15 +1666,6 @@ static int omap_hsmmc_get_cd(struct mmc_host *mmc) return mmc_slot(host).card_detect(host-dev, host-slot_id); } -static int omap_hsmmc_get_ro(struct mmc_host *mmc) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - if (!mmc_slot(host).get_ro) - return -ENOSYS; - return mmc_slot(host).get_ro(host-dev, 0); -} - static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) { struct omap_hsmmc_host *host = mmc_priv(mmc); @@ -1837,7 +1821,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = { .request = omap_hsmmc_request, .set_ios = omap_hsmmc_set_ios, .get_cd = omap_hsmmc_get_cd, - .get_ro = omap_hsmmc_get_ro, + .get_ro = mmc_gpio_get_ro, .init_card = omap_hsmmc_init_card, .enable_sdio_irq = omap_hsmmc_enable_sdio_irq, }; @@ -2063,16 +2047,15 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - ret = omap_hsmmc_gpio_init(pdata); - if (ret) - goto err; - mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), pdev-dev); if (!mmc) { - ret = -ENOMEM; - goto err_alloc; + return -ENOMEM; } + ret = omap_hsmmc_gpio_init(mmc, pdata); + if (ret) + goto err; + host= mmc_priv(mmc); host-mmc = mmc; host-pdata = pdata; @@ -2302,10 +2285,9 @@ err_irq: if (host-dbclk) clk_disable_unprepare(host-dbclk); err1: - mmc_free_host(mmc); -err_alloc: - omap_hsmmc_gpio_free(pdata); + omap_hsmmc_gpio_free(mmc, pdata); err: + mmc_free_host(mmc); return ret; } @@ -2330,7 +2312,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) if (host
[PATCH 0/3] omap_hsmmc: reuse mmc/slot-gpio functions
Hi Balaji, I'm trying to reuse mmc_of_parse for parsing standard mmc features: - cd-gpios / wp-gpios - bus-width - max-frequency - keep-power-in-suspend - enable-sdio-wakeup - ti,non-removable, evtl. Currently these are open-coded in of_get_hsmmc_pdata. I tried removing them all from of_get_hsmmc_pdata and call mmc_of_parse at the end of the probe function: @@ -2241,8 +2264,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_protect_card(host); + mmc_of_parse(host-mmc); mmc_add_host(mmc); This should work transparently for most features except, cd-gpios/wp-gpios. Pls can you have a look at the followup patches? I tried an intermediate step mapping card detect / read-only detect onto mmc/slot-gpio that are used by mmc_of_parse. I don't have card detect/read-only detect pins, :-( Do we still need cover_detect functionality or could it be merged with card detect? Another issue is 'ti,non-removable' which could be mappend to 'non-removable' if 'no_regulator_off_init' could be handled in a different way. if (of_find_property(np, ti,non-removable, NULL)) { pdata-slots[0].nonremovable = true; pdata-slots[0].no_regulator_off_init = true; } thanks, Andreas Andreas Fenkart (3): omap_hsmmc: reuse mmc/slot-gpio for write protect detection omap_hsmmc: separate card_detect/cover detect logic omap_hsmmc: reuse mmc/slot-gpio for card detect instead of open-coded version drivers/mmc/host/omap_hsmmc.c | 172 ++--- include/linux/platform_data/mmc-omap.h | 6 +- 2 files changed, 73 insertions(+), 105 deletions(-) -- 2.0.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] omap_hsmmc: separate card_detect/cover detect logic
assuming cover is the door like thing on cameras that needs to be closed after replacing sd cards. card detect is a gpio connected to sdio slot. in a follow up patch card_detect will be replaced by generic mmc/slot-gpio a git bisect patch Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1c10e6c..1b9f279 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -447,19 +447,32 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, int ret; if (gpio_is_valid(pdata-slots[0].switch_pin)) { - if (pdata-slots[0].cover) + if (pdata-slots[0].cover) { pdata-slots[0].get_cover_state = omap_hsmmc_get_cover_state; - else + pdata-slots[0].cover_detect_irq = + gpio_to_irq(pdata-slots[0].switch_pin); + + ret = gpio_request(pdata-slots[0].switch_pin, + mmc_cd); + if (ret) + return ret; + ret = gpio_direction_input(pdata-slots[0].switch_pin); + if (ret) + goto err_free_sp; + } else { pdata-slots[0].card_detect = omap_hsmmc_card_detect; - pdata-slots[0].card_detect_irq = + pdata-slots[0].card_detect_irq = gpio_to_irq(pdata-slots[0].switch_pin); - ret = gpio_request(pdata-slots[0].switch_pin, mmc_cd); - if (ret) - return ret; - ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + + ret = gpio_request(pdata-slots[0].switch_pin, + mmc_cd); + if (ret) + return ret; + ret = gpio_direction_input(pdata-slots[0].switch_pin); + if (ret) + goto err_free_sp; + } } else pdata-slots[0].switch_pin = -EINVAL; @@ -1282,19 +1295,18 @@ static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) struct omap_mmc_slot_data *slot = mmc_slot(host); int carddetect; - sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); - - if (slot-card_detect) + if (slot-card_detect) { carddetect = slot-card_detect(host-dev, host-slot_id); - else { + if (carddetect) + mmc_detect_change(host-mmc, (HZ * 200) / 1000); + else + mmc_detect_change(host-mmc, (HZ * 50) / 1000); + } else { + sysfs_notify(host-mmc-class_dev.kobj, NULL, cover_switch); omap_hsmmc_protect_card(host); - carddetect = -ENOSYS; + mmc_detect_change(host-mmc, (HZ * 200) / 1000); } - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); return IRQ_HANDLED; } diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h index 7fe0c14..d113005 100644 --- a/include/linux/platform_data/mmc-omap.h +++ b/include/linux/platform_data/mmc-omap.h @@ -136,6 +136,7 @@ struct omap_mmc_platform_data { * 0 - closed * 1 - open */ + int cover_detect_irq; int (*get_cover_state)(struct device *dev, int slot); const char *name; -- 2.0.0 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/3] omap_hsmmc: reuse mmc/slot-gpio for card detect instead of open-coded version
Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1b9f279..25aafa6 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -231,15 +231,6 @@ struct omap_mmc_of_data { static void omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host); -static int omap_hsmmc_card_detect(struct device *dev, int slot) -{ - struct omap_hsmmc_host *host = dev_get_drvdata(dev); - struct omap_mmc_platform_data *mmc = host-pdata; - - /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc-slots[0].switch_pin); -} - static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -256,7 +247,7 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_mmc_platform_data *mmc = host-pdata; - disable_irq(mmc-slots[0].card_detect_irq); + disable_irq(mmc-slots[0].cover_detect_irq); return 0; } @@ -265,7 +256,7 @@ static int omap_hsmmc_resume_cdirq(struct device *dev, int slot) struct omap_hsmmc_host *host = dev_get_drvdata(dev); struct omap_mmc_platform_data *mmc = host-pdata; - enable_irq(mmc-slots[0].card_detect_irq); + enable_irq(mmc-slots[0].cover_detect_irq); return 0; } @@ -458,23 +449,26 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, if (ret) return ret; ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + if (ret) { + gpio_free(pdata-slots[0].switch_pin); + return ret; + } } else { - pdata-slots[0].card_detect = omap_hsmmc_card_detect; - pdata-slots[0].card_detect_irq = - gpio_to_irq(pdata-slots[0].switch_pin); - - ret = gpio_request(pdata-slots[0].switch_pin, - mmc_cd); - if (ret) + /* copy paste from from mmc_of_parse */ + ret = mmc_gpio_request_cd(mmc, + pdata-slots[0].switch_pin, + 0); + if (ret 0) { + dev_err(pdata-dev, + Failed to request CD GPIO #%d: %d!\n, + pdata-slots[0].switch_pin, ret); return ret; - ret = gpio_direction_input(pdata-slots[0].switch_pin); - if (ret) - goto err_free_sp; + } else { + dev_info(pdata-dev, Got CD GPIO #%d.\n, + pdata-slots[0].switch_pin); + } } - } else - pdata-slots[0].switch_pin = -EINVAL; + } if (gpio_is_valid(pdata-slots[0].gpio_wp)) { /* copy paste from from mmc_of_parse */ @@ -492,8 +486,9 @@ static int omap_hsmmc_gpio_init(struct mmc_host *mmc, return 0; err: - if (gpio_is_valid(pdata-slots[0].switch_pin)) -err_free_sp: + mmc_gpio_free_cd(mmc); + if (gpio_is_valid(pdata-slots[0].switch_pin) + (pdata-slots[0].cover)) gpio_free(pdata-slots[0].switch_pin); return ret; } @@ -501,8 +496,11 @@ err_free_sp: static void omap_hsmmc_gpio_free(struct mmc_host *mmc, struct omap_mmc_platform_data *pdata) { + mmc_gpio_free_cd(mmc); mmc_gpio_free_ro(mmc); - if (gpio_is_valid(pdata-slots[0].switch_pin)) + + if (gpio_is_valid(pdata-slots[0].switch_pin) + (pdata-slots[0].cover)) gpio_free(pdata-slots[0].switch_pin); } @@ -1289,24 +1287,13 @@ static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) /* * irq handler to notify the core about card insertion/removal */ -static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) +static irqreturn_t omap_hsmmc_cover_detect(int irq, void *dev_id) { struct omap_hsmmc_host *host = dev_id; - struct omap_mmc_slot_data *slot = mmc_slot(host); - int carddetect; - - if (slot-card_detect) { - carddetect = slot-card_detect(host-dev, host-slot_id); - if (carddetect) - mmc_detect_change(host-mmc, (HZ * 200) / 1000); - else - mmc_detect_change(host-mmc, (HZ * 50) / 1000); - } else
Re: mwifiex card reset
2014-07-01 17:09 GMT+02:00 Doug Anderson diand...@chromium.org: +Olof who posted the patch that Yuvaraj referenced. On Tue, Jul 1, 2014 at 5:20 AM, Yuvaraj Cd yuvaraj.l...@gmail.com wrote: On Tue, Jul 1, 2014 at 12:27 PM, James Cameron qu...@laptop.org wrote: On Mon, Jun 30, 2014 at 11:44:29PM -0700, Bing Zhao wrote: I may have missed something, but doesn't the MMC_POWER_OFF and MMC_POWER_ON|UP handling in controller driver help? Anyway the clocks/GPIOs/regulators are sort of platform dependent. Would it be better putting it in /arch/arm/mach-x/? Wouldn't device tree for mmc be better? I have come across same problem.Below is the thread in which more discussions happened on this. http://patchwork.ozlabs.org/patch/312444/ I am adding few more those who are interested in this solution. Thanks to Yuvaraj for referencing the old thread. http://www.spinics.net/lists/linux-mmc/msg26564.html Quite a read indeed Meanwhile I got a working prototype for omap_hsmmc/mwifiex based on this series: http://www.spinics.net/lists/linux-mmc/msg27228.html I will post my patches, once the FDT format is set in stone, and Ulf has had some time to work on v2 of his series. -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: mwifiex card reset
Hi Bing, 2014-07-01 8:44 GMT+02:00 Bing Zhao bz...@marvell.com: [snip] Yes, a helper might be the best solution. It could even be a generic one, that just takes any number of clocks, reset GPIOs and regulators and takes care for sequencing them. However, we need to reference that helper from the mwifiex driver, for two reasons. a) we need to make sure the reset helper gets to do its job before the mwifiex driver scans the SDIO bus, and b) the reset helper needs to be called when the mmc host controller wants to do a card reset. Hence, we'll need some sort of internal API for this, and a phandle in dts. I wonder whether that glue logic might be better off living in the mmc core, as mwifiex might well be interfaced to other hosts? I may have missed something, but doesn't the MMC_POWER_OFF and MMC_POWER_ON|UP handling in controller driver help? Anyway the clocks/GPIOs/regulators are sort of platform dependent. Would it be better putting it in /arch/arm/mach-x/? what about usb? the mwifiex can also be connected via usb to the host, isn't the reset logic the same in that case, independent of sdio -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/3] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x.
Hi, 2013-11-19 16:59 GMT+01:00 Balaji T K balaj...@ti.com: On Tuesday 19 November 2013 09:19 PM, Tony Lindgren wrote: * Balaji T K balaj...@ti.com [131118 08:23]: On Monday 18 November 2013 05:45 PM, Andreas Fenkart wrote: 2013/11/18 Michael Trimarchi mich...@amarulasolutions.com: On Mon, Nov 18, 2013 at 8:53 AM, Andreas Fenkart afenk...@gmail.com wrote: static int omap_hsmmc_card_detect(struct device *dev, int slot) { struct omap_hsmmc_host *host = dev_get_drvdata(dev); @@ -452,10 +474,25 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) } else pdata-slots[0].gpio_wp = -EINVAL; + if (gpio_is_valid(pdata-slots[0].gpio_cirq)) { + pdata-slots[0].sdio_irq = + gpio_to_irq(pdata-slots[0].gpio_cirq); What is this? re-assign the platform data? Seems like, I didn't pay attention to this. Simply kept in line how the write protection/read only pins are managed. I'd rather not change this part, or not changing it as part of adding sdio IRQ support it. Maybe somebody else on the list can explain why the platform data contains elements that are modified during runtime. - set_power / get_ro function callbacks - ocr_mask. Hi, few params were passed via platform data in non-DT case and never cached in internal data structure, with non-dt support going away soon, I am planning to cleanup pdata usage in the driver when it gets to DT only support. any news on this? I'd like to reuse generic mmc_of_parse, kind of difficult with the current driver state -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: mwifiex card reset
2014-06-28 9:23 GMT+02:00 Tony Lindgren t...@atomide.com: * James Cameron qu...@laptop.org [140628 08:24]: On Fri, Jun 27, 2014 at 04:39:42PM +0200, Andreas Fenkart wrote: I have an mwifiex module(sd8787) behind omap_hsmmc(am33xx-soc) The module is non-removable wired fix to soc. Now the wifi module needs 2 clocks; one is a sleep clock the other used when not sleeping. While the sleep clock is fixed, @32 kHz, the system clock can be one out of several values, but can be be derived automatically from the sleep clock. But this requires the clock to be present when the wifi module comes out of reset. ref 1) Another problem is software reboot, at initial power on the wifi card will react to mmc discovery. After a software reset of the host it will not, because it has already been discovered and didn't notice the host rebooted, unless we reset it as well. While this seems obvious, the problem is that the reset is needed before the card can be discovered. Which means we cannot move the reset logic into the mwifiex driver, since that driver has not yet been selected through vendor/product id. we had same problem with sd8787 and a different system design. we added reset-gpios property [1] and used it in sdhci-pxav3.c [2] as sdhci_pxav3_toggle_reset_gpio() 1. http://code.coreboot.org/p/openfirmware/source/tree/HEAD/cpu/arm/olpc/sdhci.fth#L104 2. http://dev.laptop.org/git/olpc-kernel/tree/drivers/mmc/host/sdhci-pxav3.c?h=arm-3.5#n229 the reset logic: gpiod_set_value(card-gpiod_reset, 0); clk_enable(card-sleep_clock); udelay(1000); gpiod_set_value(card-gpiod_reset, 1); The idea so far was to extend the device-tree node of the mmc slot by some reset leafs; mmc { ti,non-removable; .. peripheral-clocks = clk clk2 ...; peripheral-reset-gpios = gpio0 1 1 gpio1 2 3 ...; } in mmc_add_host, all clocks will be enabled and gpios be pulled low for 1 msec we used 5ms. Is this a feasible solution? Another related issue, is the card reset in mwifiex driver: static void sdio_card_reset_worker(struct work_struct *work) { struct mmc_host *target = reset_host; pr_err(Resetting card...\n); mmc_remove_host(target); /* 20ms delay is based on experiment with sdhci controller */ mdelay(20); mmc_add_host(target); } static DECLARE_WORK(card_reset_work, sdio_card_reset_worker); There are obviously a lot of problems with this, e.g. custom debugfs entries created in the driver will be lost. But sometimes this code might avert disaster in case the command handlers between driver and firmware lost synchronization How could this be done in a better way? i'm interested as well. Wouldn't it be best to have the mwifiex properly handle the reset GPIOs and idle status pins? doesn't work see ref 1) above Those are not part of the SDIO spec AFAIK, and the mmc controller should not need to care about those. Also, at least omaps also have an issue where suspend won't work with mwifiex loaded FYI. first command after resume needs to be cmd52, not cmd53 as the driver would by default. it's another issue Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
mwifiex card reset
I have an mwifiex module(sd8787) behind omap_hsmmc(am33xx-soc) The module is non-removable wired fix to soc. Now the wifi module needs 2 clocks; one is a sleep clock the other used when not sleeping. While the sleep clock is fixed, @32 kHz, the system clock can be one out of several values, but can be be derived automatically from the sleep clock. But this requires the clock to be present when the wifi module comes out of reset. Another problem is software reboot, at initial power on the wifi card will react to mmc discovery. After a software reset of the host it will not, because it has already been disvovered and didn't notice the host rebooted, unless we reset it as well. While this seems obvious, the problem is that the reset is needed before the card can be discovered. Which means we cannot move the reset logic into the mwifiex driver, since that driver has not yet been selected through vendor/product id. the reset logic: gpiod_set_value(card-gpiod_reset, 0); clk_enable(card-sleep_clock); udelay(1000); gpiod_set_value(card-gpiod_reset, 1); The idea so far was to extend the device-tree node of the mmc slot by some reset leafs; mmc { ti,non-removable; .. peripheral-clocks = clk clk2 ...; peripheral-reset-gpios = gpio0 1 1 gpio1 2 3 ...; } in mmc_add_host, all clocks will be enabled and gpios be pulled low for 1 msec Is this a feasible solution? Another related issue, is the card reset in mwifiex driver: static void sdio_card_reset_worker(struct work_struct *work) { struct mmc_host *target = reset_host; pr_err(Resetting card...\n); mmc_remove_host(target); /* 20ms delay is based on experiment with sdhci controller */ mdelay(20); mmc_add_host(target); } static DECLARE_WORK(card_reset_work, sdio_card_reset_worker); There are obviously a lot of problems with this, e.g. custom debugfs entries created in the driver will be lost. But sometimes this code might avert disaster in case the command handlers between driver and firmware lost synchronization How could this be done in a better way? -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v14 0/6] mmc: omap_hsmmc: Enable SDIO IRQ
Hi Balaji, Tony, Ulf, all v14 - drop all ifdef/endif introduced by v13 -- rely on pinctrl_lookup_state to prevent ifdef CONFIG_PM -- benefit: all code is compile tested no matter the configuration -- drawback: require wake_irq/pinctrl configuration even when runtime suspend is not configured - drop runtime state from debugfs output - rebased onto current mmc-next 06732b84b4cf v13 - fix compile breaks if !CONFIG_PM - additional patch: install dummy pm runtime hooks if !CONFIG_PM_RUNTIME v12 - drop !CONFIG_OF compile break only exists when #undef CONFIG_OF after include headers 1/7(Sebastian Reichel) - do not emit falling back to polling if wake_irq not specified since MMC does not need it, and it might confuse users only emit if pinmux default/idle is not present or claiming the irq failed 2/7(Balaji) - dropped out-of-tree patches 6/7(Balaji) - mention ti,am33xx-hsmmc compatible section in bindings documentation 1/5 v11 - split !CONFIG_OF compile break into separate patch - enable IWE/CLKEXTFREE in CON/HCTL register needed for omap4 - '' vs '' in omap_hsmmc_resume, 1/5 (Andreas Müller) - #define DLEV_DAT instead of BIT(21) 2/5 (Balaji) - pinctrl_pm_select_default_state() removed, 4/5 (Balaji) - drop _irqsave/_irqrestore from omap_hsmmc_wake_irq handler since it can't be preempted by same priority omap_hsmmc_irq handler 1/5(Joel Fernandes) - replace devres_open_group by explicit devm_free calls 1/5 (Balaji) - disable_irq_nosync wake_irq since we handle it thread safe 1/5 (Balaji) - drop 'gpio_dat1' pinctrl states and rework documentation 5/5 (Balaji) v10 - bug fix on multi-core, untested - incorporated changes from Balaji - use devres / RAII mechanism to configure wake_up / sdio irq capabilities - drop pinctrl state 'active' rely on driver-model states 'default', 'idle' - add specific 'gpio_dat1' state for am335x SWAKEUP hack - reorganized patches; +1 patch multi-core bugfix / +1 for pinctrl - rebased 455c6fdbd21916 / cherry-picks from mmc-next v9 - extended comment about why wake-irq is needed - drop double '(' ')' around card_detect_irq - drop final '.' in in subject line of patch v8 - rebased on top of Tony Lindgrent...@atomide.com changes - improved changelog describing the earlier work - improved wakeup irq setup - works for am3730 es platform now - my changes on top: - compile tested with #undef CONFIG_OF - disable wake_irq in handler to prevent infinite loop - fixed typo and added comment about wake-irq v7 - rebase on 3.14.0-rc3-49726-g77e15ec - split omap_hsmmc_pin_init due to regression on omap-3730 platform v6 - rebase on Linux 3.13-rc3 - reformatting debugfs v5 - fix compile error introduced by last minute one line fix v4: - switch to interrupts-extended format - drop ti,swakeup-missing flag convert to comaptible section v3: - removed gpio_irq from platform_data v2: - incorparated changes as suggested by reviewers - simplified workaround for am335x, gpio will now only wake the module from runtime suspend, not handle the sdio irq itself Andreas Fenkart (6): mmc: omap_hsmmc: Enable SDIO interrupt mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state mmc: omap_hsmmc: enable wakeup event for sdio OMAP4 mmc: omap_hsmmc: abort runtime suspend if pending sdio irq detected mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 54 drivers/mmc/host/omap_hsmmc.c | 283 ++-- include/linux/platform_data/mmc-omap.h |1 + 3 files changed, 317 insertions(+), 21 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v14 5/6] mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks
These are predefined states of the driver model. When not present, as if not set in the device tree, they become no-ops. Explicitly selecting the default state is not needed since the device core layer sets pin mux to default state before probe. This is not the simplest implementation, on AM335x at least, we could switch to idle at any point in the suspend hook, only the default state needs to be set before writing to the irq registers or an IRQ might get lost. Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 2408ec9..0febb17 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1998,7 +1998,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; - struct pinctrl *pinctrl; const struct omap_mmc_of_data *data; void __iomem *base; @@ -,11 +2221,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_disable_irq(host); - pinctrl = devm_pinctrl_get_select_default(pdev-dev); - if (IS_ERR(pinctrl)) - dev_warn(pdev-dev, - pins are not configured from the driver\n); - /* * For now, only support SDIO interrupt if we have a separate * wake-up interrupt configured from device tree. This is because @@ -2428,10 +2422,15 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) goto abort; } + pinctrl_pm_select_idle_state(dev); + WARN_ON(host-flags HSMMC_WAKE_IRQ_ENABLED); enable_irq(host-wake_irq); host-flags |= HSMMC_WAKE_IRQ_ENABLED; + } else { + pinctrl_pm_select_idle_state(dev); } + abort: spin_unlock_irqrestore(host-irq_lock, flags); return ret; @@ -2455,9 +2454,14 @@ static int omap_hsmmc_runtime_resume(struct device *dev) host-flags = ~HSMMC_WAKE_IRQ_ENABLED; } + pinctrl_pm_select_default_state(host-dev); + + /* irq lost, if pinmux incorrect */ OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, CIRQ_EN); OMAP_HSMMC_WRITE(host-base, IE, CIRQ_EN); + } else { + pinctrl_pm_select_default_state(host-dev); } spin_unlock_irqrestore(host-irq_lock, flags); return 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v14 3/6] mmc: omap_hsmmc: enable wakeup event for sdio OMAP4
From: Balaji T K balaj...@ti.com To detect sdio irqs properly without spurious events, OMAP4 needs IWE in CON and CTPL, CLKEXTFREE in HCTL to be set Tested-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Balaji T K balaj...@ti.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 332d3d2..b8be438 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -94,7 +94,10 @@ #define BCE(1 1) #define FOUR_BIT (1 1) #define HSPE (1 2) +#define IWE(1 24) #define DDR(1 19) +#define CLKEXTFREE (1 16) +#define CTPL (1 11) #define DW8(1 5) #define OD 0x1 #define STAT_CLEAR 0x @@ -687,6 +690,9 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) capa = VS18; } + if (host-mmc-caps MMC_CAP_SDIO_IRQ) + hctl |= IWE; + OMAP_HSMMC_WRITE(host-base, HCTL, OMAP_HSMMC_READ(host-base, HCTL) | hctl); @@ -1684,19 +1690,23 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct omap_hsmmc_host *host = mmc_priv(mmc); - u32 irq_mask; + u32 irq_mask, con; unsigned long flags; spin_lock_irqsave(host-irq_lock, flags); + con = OMAP_HSMMC_READ(host-base, CON); irq_mask = OMAP_HSMMC_READ(host-base, ISE); if (enable) { host-flags |= HSMMC_SDIO_IRQ_ENABLED; irq_mask |= CIRQ_EN; + con |= CTPL | CLKEXTFREE; } else { host-flags = ~HSMMC_SDIO_IRQ_ENABLED; irq_mask = ~CIRQ_EN; + con = ~(CTPL | CLKEXTFREE); } + OMAP_HSMMC_WRITE(host-base, CON, con); OMAP_HSMMC_WRITE(host-base, IE, irq_mask); /* @@ -1746,6 +1756,8 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host) goto err; } + OMAP_HSMMC_WRITE(host-base, HCTL, +OMAP_HSMMC_READ(host-base, HCTL) | IWE); return 0; err: -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v14 4/6] mmc: omap_hsmmc: abort runtime suspend if pending sdio irq detected
On multicores, an sdio irq handler could be running in parallel to runtime suspend. In the worst case it could be waiting for the spinlock held by the runtime suspend. When runtime suspend is complete and the functional clock (fclk) turned off, the irq handler will continue and cause a SIGBUS on the first register access. Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b8be438..2408ec9 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -107,6 +107,9 @@ #define SRD(1 26) #define SOFTRESET (1 1) +/* PSTATE */ +#define DLEV_DAT(x)(1 (20 + (x))) + /* Interrupt masks for IE and ISE register */ #define CC_EN (1 0) #define TC_EN (1 1) @@ -2397,6 +2400,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) { struct omap_hsmmc_host *host; unsigned long flags; + int ret = 0; host = platform_get_drvdata(to_platform_device(dev)); omap_hsmmc_context_save(host); @@ -2408,14 +2412,29 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) /* disable sdio irq handling to prevent race */ OMAP_HSMMC_WRITE(host-base, ISE, 0); OMAP_HSMMC_WRITE(host-base, IE, 0); - OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); + + if (!(OMAP_HSMMC_READ(host-base, PSTATE) DLEV_DAT(1))) { + /* +* dat1 line low, pending sdio irq +* race condition: possible irq handler running on +* multi-core, abort +*/ + dev_dbg(dev, pending sdio irq, abort suspend\n); + OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); + OMAP_HSMMC_WRITE(host-base, ISE, CIRQ_EN); + OMAP_HSMMC_WRITE(host-base, IE, CIRQ_EN); + pm_runtime_mark_last_busy(dev); + ret = -EBUSY; + goto abort; + } WARN_ON(host-flags HSMMC_WAKE_IRQ_ENABLED); enable_irq(host-wake_irq); host-flags |= HSMMC_WAKE_IRQ_ENABLED; } +abort: spin_unlock_irqrestore(host-irq_lock, flags); - return 0; + return ret; } static int omap_hsmmc_runtime_resume(struct device *dev) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v14 2/6] mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state
Add SDIO IRQ entries to debugfs entry. Note that PSTATE shows current state of data lines, incl. SDIO IRQ pending Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 129569d..332d3d2 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -56,6 +56,7 @@ #define OMAP_HSMMC_RSP54 0x0118 #define OMAP_HSMMC_RSP76 0x011C #define OMAP_HSMMC_DATA0x0120 +#define OMAP_HSMMC_PSTATE 0x0124 #define OMAP_HSMMC_HCTL0x0128 #define OMAP_HSMMC_SYSCTL 0x012C #define OMAP_HSMMC_STAT0x0130 @@ -1815,13 +1816,23 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) struct mmc_host *mmc = s-private; struct omap_hsmmc_host *host = mmc_priv(mmc); - seq_printf(s, mmc%d:\n ctx_loss:\t%d\n\nregs:\n, - mmc-index, host-context_loss); + seq_printf(s, mmc%d:\n, mmc-index); + seq_printf(s, sdio irq mode\t%s\n, + (mmc-caps MMC_CAP_SDIO_IRQ) ? interrupt : polling); - pm_runtime_get_sync(host-dev); + if (mmc-caps MMC_CAP_SDIO_IRQ) { + seq_printf(s, sdio irq \t%s\n, + (host-flags HSMMC_SDIO_IRQ_ENABLED) ? enabled + : disabled); + } + seq_printf(s, ctx_loss:\t%d\n, host-context_loss); + pm_runtime_get_sync(host-dev); + seq_puts(s, \nregs:\n); seq_printf(s, CON:\t\t0x%08x\n, OMAP_HSMMC_READ(host-base, CON)); + seq_printf(s, PSTATE:\t\t0x%08x\n, + OMAP_HSMMC_READ(host-base, PSTATE)); seq_printf(s, HCTL:\t\t0x%08x\n, OMAP_HSMMC_READ(host-base, HCTL)); seq_printf(s, SYSCTL:\t\t0x%08x\n, -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [mmc:mmc-next 79/96] drivers/mmc/host/omap_hsmmc.c:1841:30: error: 'struct dev_pm_info' has no member named 'runtime_status'
2014-05-22 16:24 GMT+02:00 Tony Lindgren t...@atomide.com: * Chris Ball ch...@printf.net [140522 05:42]: Hi, On Thu, May 22 2014, Ulf Hansson wrote: I had a second look at Andreas Fenkart's patchset to enable SDIO irq for omap. Those needs an additional iteration, since there are unresolved dependencies to CONFIG_PM_RUNTIME (and possibly to other Kconfigs as well). Apparently I had all the needed Kconfigs enabled while I compile tested them. :-( Did you find this out with make randconfig? FYI after this patch I could deselect CONFIG_PM --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -111,7 +111,6 @@ config ARCH_OMAP2PLUS_TYPICAL select I2C_OMAP select MENELAUS if ARCH_OMAP2 select NEON if CPU_V7 - select PM_RUNTIME select REGULATOR select TWL4030_CORE if ARCH_OMAP3 || ARCH_OMAP4 select TWL4030_POWER if ARCH_OMAP3 || ARCH_OMAP4 I tried out doing a local re-base, to remove the related omap patches. If you remove the patches below you won't get any conflicts for omap_hsmmc. Can you do that? Andreas: mmc: omap_hsmmc: Enable SDIO interrupt mmc: omap_hsmmc: enable wakeup event for sdio OMAP4 mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state mmc: omap_hsmmc: abort runtime suspend if pending sdio irq detected mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Balaji: mmc: omap_hsmmc: use IS_ERR macro for error checking Done. Thanks! Andreas, can you fix this ASAP? Would be nice to have those working for v3.16 :) will send out updated patches soon Once you have updated patches available I'll include them also to my randconfig builds. Unless the Kconfig options are nested they are exposed after few builds typically. Regards, Tony -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 6/7] mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks
These are predefined states of the driver model. When not present, as if not set in the device tree, they become no-ops. Explicitly selecting the default state is not needed since the device core layer sets pin mux to default state before probe. This is not the simplest implementation, on AM335x at least, we could switch to idle at any point in the suspend hook, only the default state needs to be set before writing to the irq registers or an IRQ might get lost. Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index aafef29..760b0ac 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2008,7 +2008,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; - struct pinctrl *pinctrl; const struct omap_mmc_of_data *data; match = of_match_device(of_match_ptr(omap_mmc_of_match), pdev-dev); @@ -2234,11 +2233,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_disable_irq(host); - pinctrl = devm_pinctrl_get_select_default(pdev-dev); - if (IS_ERR(pinctrl)) - dev_warn(pdev-dev, - pins are not configured from the driver\n); - /* * For now, only support SDIO interrupt if we have a separate * wake-up interrupt configured from device tree. This is because @@ -2463,10 +2457,15 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) goto abort; } + pinctrl_pm_select_idle_state(dev); + WARN_ON(host-flags HSMMC_WAKE_IRQ_ENABLED); enable_irq(host-wake_irq); host-flags |= HSMMC_WAKE_IRQ_ENABLED; + } else { + pinctrl_pm_select_idle_state(dev); } + abort: spin_unlock_irqrestore(host-irq_lock, flags); return ret; @@ -2490,9 +2489,14 @@ static int omap_hsmmc_runtime_resume(struct device *dev) host-flags = ~HSMMC_WAKE_IRQ_ENABLED; } + pinctrl_pm_select_default_state(host-dev); + + /* irq lost, if pinmux incorrect */ OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, CIRQ_EN); OMAP_HSMMC_WRITE(host-base, IE, CIRQ_EN); + } else { + pinctrl_pm_select_default_state(host-dev); } spin_unlock_irqrestore(host-irq_lock, flags); return 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 2/7] mmc: omap_hsmmc: Enable SDIO interrupt
There have been various patches floating around for enabling the SDIO IRQ for hsmmc, but none of them ever got merged. Probably the reason for not merging the SDIO interrupt patches has been the lack of wake-up path for SDIO on some omaps that has also needed remuxing the SDIO DAT1 line to a GPIO making the patches complex. This patch adds the minimal SDIO IRQ support to hsmmc for omaps that do have the wake-up path. For those omaps, the DAT1 line need to have the wake-up enable bit set, and the wake-up interrupt is the same as for the MMC controller. This patch has been tested on am3730 es1.2 with mwifiex connected to MMC3 with mwifiex waking to Ethernet traffic from off-idle mode. Note that for omaps that do not have the SDIO wake-up path, this patch will not work for idle modes and further patches for remuxing DAT1 to GPIO are needed. Based on earlier patches [1][2] by David Vrabel david.vra...@csr.com, Steve Sakoman st...@sakoman.com For now, only support SDIO interrupt if we are booted with a separate wake-irq configued via device tree. This is because omaps need the wake-irq for idle states, and some omaps need special quirks. And we don't want to add new legacy mux platform init code callbacks any longer as we are moving to DT based booting anyways. To use it, you need to specify the wake-irq using the interrupts-extended property. [1] http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux.git;a=commitdiff_plain;h=010810d22f6f49ac03da4ba384969432e0320453 [2] http://comments.gmane.org/gmane.linux.kernel.mmc/20446 Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index ce80561..0233ba7 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -12,6 +12,7 @@ Required properties: Should be ti,omap3-hsmmc, for OMAP3 controllers Should be ti,omap3-pre-es3-hsmmc for OMAP3 controllers pre ES3.0 Should be ti,omap4-hsmmc, for OMAP4 controllers + Should be ti,am33xx-hsmmc, for AM335x controllers - ti,hwmods: Must be mmcn, n is controller instance starting 1 Optional properties: diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index c62d9dd..0125eea 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -29,6 +29,7 @@ #include linux/timer.h #include linux/clk.h #include linux/of.h +#include linux/of_irq.h #include linux/of_gpio.h #include linux/of_device.h #include linux/omap-dma.h @@ -36,6 +37,7 @@ #include linux/mmc/core.h #include linux/mmc/mmc.h #include linux/io.h +#include linux/irq.h #include linux/gpio.h #include linux/regulator/consumer.h #include linux/pinctrl/consumer.h @@ -106,6 +108,7 @@ #define TC_EN (1 1) #define BWR_EN (1 4) #define BRR_EN (1 5) +#define CIRQ_EN(1 8) #define ERR_EN (1 15) #define CTO_EN (1 16) #define CCRC_EN(1 17) @@ -140,7 +143,6 @@ #define VDD_3V0300 /* 30 uV */ #define VDD_165_195(ffs(MMC_VDD_165_195) - 1) -#define AUTO_CMD23 (1 1)/* Auto CMD23 support */ /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -200,6 +202,7 @@ struct omap_hsmmc_host { int slot_id; int response_busy; #ifdef CONFIG_PM + int wake_irq; int context_loss; #endif int protect_card; @@ -208,6 +211,9 @@ struct omap_hsmmc_host { int req_in_progress; unsigned long clk_rate; unsigned intflags; +#define AUTO_CMD23 (1 0)/* Auto CMD23 support */ +#define HSMMC_SDIO_IRQ_ENABLED (1 1)/* SDIO irq enabled */ +#define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_mmc_platform_data *pdata; }; @@ -512,27 +518,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, struct mmc_command *cmd) { - unsigned int irq_mask; + u32 irq_mask = INT_EN_MASK; + unsigned long flags; if (host-use_dma) - irq_mask = INT_EN_MASK ~(BRR_EN | BWR_EN); - else - irq_mask = INT_EN_MASK; + irq_mask = ~(BRR_EN | BWR_EN); /* Disable timeout for erases */ if (cmd-opcode == MMC_ERASE) irq_mask = ~DTO_EN; + spin_lock_irqsave(host-irq_lock, flags
[PATCH v13 0/7] mmc: omap_hsmmc: Enable SDIO IRQ
Hi Balaji, Tony, Ulf, all v13 - fix compile breaks if !CONFIG_PM - additional patch: install dummy pm runtime hooks if !CONFIG_PM_RUNTIME v12 - drop !CONFIG_OF compile break only exists when #undef CONFIG_OF after include headers 1/7(Sebastian Reichel) - do not emit falling back to polling if wake_irq not specified since MMC does not need it, and it might confuse users only emit if pinmux default/idle is not present or claiming the irq failed 2/7(Balaji) - dropped out-of-tree patches 6/7(Balaji) - mention ti,am33xx-hsmmc compatible section in bindings documentation 1/5 v11 - split !CONFIG_OF compile break into separate patch - enable IWE/CLKEXTFREE in CON/HCTL register needed for omap4 - '' vs '' in omap_hsmmc_resume, 1/5 (Andreas Müller) - #define DLEV_DAT instead of BIT(21) 2/5 (Balaji) - pinctrl_pm_select_default_state() removed, 4/5 (Balaji) - drop _irqsave/_irqrestore from omap_hsmmc_wake_irq handler since it can't be preempted by same priority omap_hsmmc_irq handler 1/5(Joel Fernandes) - replace devres_open_group by explicit devm_free calls 1/5 (Balaji) - disable_irq_nosync wake_irq since we handle it thread safe 1/5 (Balaji) - drop 'gpio_dat1' pinctrl states and rework documentation 5/5 (Balaji) v10 - bug fix on multi-core, untested - incorporated changes from Balaji - use devres / RAII mechanism to configure wake_up / sdio irq capabilities - drop pinctrl state 'active' rely on driver-model states 'default', 'idle' - add specific 'gpio_dat1' state for am335x SWAKEUP hack - reorganized patches; +1 patch multi-core bugfix / +1 for pinctrl - rebased 455c6fdbd21916 / cherry-picks from mmc-next v9 - extended comment about why wake-irq is needed - drop double '(' ')' around card_detect_irq - drop final '.' in in subject line of patch v8 - rebased on top of Tony Lindgrent...@atomide.com changes - improved changelog describing the earlier work - improved wakeup irq setup - works for am3730 es platform now - my changes on top: - compile tested with #undef CONFIG_OF - disable wake_irq in handler to prevent infinite loop - fixed typo and added comment about wake-irq v7 - rebase on 3.14.0-rc3-49726-g77e15ec - split omap_hsmmc_pin_init due to regression on omap-3730 platform v6 - rebase on Linux 3.13-rc3 - reformatting debugfs v5 - fix compile error introduced by last minute one line fix v4: - switch to interrupts-extended format - drop ti,swakeup-missing flag convert to comaptible section v3: - removed gpio_irq from platform_data v2: - incorparated changes as suggested by reviewers - simplified workaround for am335x, gpio will now only wake the module from runtime suspend, not handle the sdio irq itself Andreas Fenkart (7): mmc: omap_hsmmc: install dummy pm runtime hooks if !CONFIG_PM_RUNTIME mmc: omap_hsmmc: Enable SDIO interrupt mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state mmc: omap_hsmmc: enable wakeup event for sdio OMAP4 mmc: omap_hsmmc: abort runtime suspend if pending sdio irq detected mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 54 drivers/mmc/host/omap_hsmmc.c | 309 ++-- include/linux/platform_data/mmc-omap.h |1 + 3 files changed, 335 insertions(+), 29 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v13 7/7] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x
The am335x can't detect pending cirq in PM runtime suspend. This patch reconfigures dat1 as a GPIO before going to suspend. SDIO interrupts are detected with the GPIO, the GPIO will only wake the module from suspend, SDIO irq detection will still happen through the IP block. Idea of remuxing the pins by Tony Lindgren. Code contributions from Tony Lindgren and Balaji T K balaj...@ti.com Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index 0233ba7..76bf087 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -57,3 +57,56 @@ Examples: edma 25; dma-names = tx, rx; }; + +[workaround for missing swakeup on am33xx] + +This SOC is missing the swakeup line, it will not detect SDIO irq +while in suspend. + + -- + | PRCM | + -- + ^ | + swakeup | | fclk + | v + ----- - + | card | -- CIRQ -- | hsmmc | -- IRQ -- | CPU | + ----- - + +In suspend the fclk is off and the module is disfunctional. Even register reads +will fail. A small logic in the host will request fclk restore, when an +external event is detected. Once the clock is restored, the host detects the +event normally. Since am33xx doesn't have this line it never wakes from +suspend. + +The workaround is to reconfigure the dat1 line as a GPIO upon suspend. To make +this work, we need to set the named pinctrl states default and idle. +Prepare idle to remux dat1 as a gpio, and default to remux it back as sdio +dat1. The MMC driver will then toggle between idle and default state during +runtime. + +In summary: +1. select matching 'compatible' section, see example below. +2. specify pinctrl states default and idle, sleep is optional. +3. specify the gpio irq used for detecting sdio irq in suspend + +If configuration is incomplete, a warning message is emitted falling back to +polling. Also check the sdio irq mode in /sys/kernel/debug/mmc0/regs. Mind +not every application needs SDIO irq, e.g. MMC cards. + + mmc1: mmc@48060100 { + compatible = ti,am33xx-hsmmc; + ... + pinctrl-names = default, idle, sleep + pinctrl-0 = mmc1_pins; + pinctrl-1 = mmc1_idle; + pinctrl-2 = mmc1_sleep; + ... + interrupts-extended = intc 64 gpio2 28 0; + }; + + mmc1_idle : pinmux_cirq_pin { + pinctrl-single,pins = + 0x0f8 0x3f /* GPIO2_28 */ + ; + }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 760b0ac..1238506 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1752,15 +1752,25 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host) * and need to remux SDIO DAT1 to GPIO for wake-up from idle. */ if (host-pdata-controller_flags OMAP_HSMMC_SWAKEUP_MISSING) { - ret = -ENODEV; - devm_free_irq(host-dev, host-wake_irq, host); - goto err; + if (IS_ERR(host-dev-pins-default_state)) { + dev_info(host-dev, missing default pinctrl state\n); + ret = -EINVAL; + goto err_free_irq; + } + + if (IS_ERR(host-dev-pins-idle_state)) { + dev_info(host-dev, missing idle pinctrl state\n); + ret = -EINVAL; + goto err_free_irq; + } } OMAP_HSMMC_WRITE(host-base, HCTL, OMAP_HSMMC_READ(host-base, HCTL) | IWE); return 0; +err_free_irq: + devm_free_irq(host-dev, host-wake_irq, host); err: dev_warn(host-dev, no SDIO IRQ support, falling back to polling\n); host-wake_irq = 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 2/6] mmc: omap_hsmmc: enable wakeup event for sdio OMAP4
To detect sdio irqs properly without spurious events, OMAP4 needs IWE in CON and CTPL, CLKEXTFREE in HCTL to be set Tested-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Balaji T K balaj...@ti.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index edd53adc..4ee4645 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -93,7 +93,10 @@ #define BCE(1 1) #define FOUR_BIT (1 1) #define HSPE (1 2) +#define IWE(1 24) #define DDR(1 19) +#define CLKEXTFREE (1 16) +#define CTPL (1 11) #define DW8(1 5) #define OD 0x1 #define STAT_CLEAR 0x @@ -686,6 +689,9 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) capa = VS18; } + if (host-mmc-caps MMC_CAP_SDIO_IRQ) + hctl |= IWE; + OMAP_HSMMC_WRITE(host-base, HCTL, OMAP_HSMMC_READ(host-base, HCTL) | hctl); @@ -1682,19 +1688,23 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct omap_hsmmc_host *host = mmc_priv(mmc); - u32 irq_mask; + u32 irq_mask, con; unsigned long flags; spin_lock_irqsave(host-irq_lock, flags); + con = OMAP_HSMMC_READ(host-base, CON); irq_mask = OMAP_HSMMC_READ(host-base, ISE); if (enable) { host-flags |= HSMMC_SDIO_IRQ_ENABLED; irq_mask |= CIRQ_EN; + con |= CTPL | CLKEXTFREE; } else { host-flags = ~HSMMC_SDIO_IRQ_ENABLED; irq_mask = ~CIRQ_EN; + con = ~(CTPL | CLKEXTFREE); } + OMAP_HSMMC_WRITE(host-base, CON, con); OMAP_HSMMC_WRITE(host-base, IE, irq_mask); /* @@ -1744,6 +1754,8 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host) goto err; } + OMAP_HSMMC_WRITE(host-base, HCTL, +OMAP_HSMMC_READ(host-base, HCTL) | IWE); return 0; err: -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 1/6] mmc: omap_hsmmc: Enable SDIO interrupt
There have been various patches floating around for enabling the SDIO IRQ for hsmmc, but none of them ever got merged. Probably the reason for not merging the SDIO interrupt patches has been the lack of wake-up path for SDIO on some omaps that has also needed remuxing the SDIO DAT1 line to a GPIO making the patches complex. This patch adds the minimal SDIO IRQ support to hsmmc for omaps that do have the wake-up path. For those omaps, the DAT1 line need to have the wake-up enable bit set, and the wake-up interrupt is the same as for the MMC controller. This patch has been tested on am3730 es1.2 with mwifiex connected to MMC3 with mwifiex waking to Ethernet traffic from off-idle mode. Note that for omaps that do not have the SDIO wake-up path, this patch will not work for idle modes and further patches for remuxing DAT1 to GPIO are needed. Based on earlier patches [1][2] by David Vrabel david.vra...@csr.com, Steve Sakoman st...@sakoman.com For now, only support SDIO interrupt if we are booted with a separate wake-irq configued via device tree. This is because omaps need the wake-irq for idle states, and some omaps need special quirks. And we don't want to add new legacy mux platform init code callbacks any longer as we are moving to DT based booting anyways. To use it, you need to specify the wake-irq using the interrupts-extended property. [1] http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux.git;a=commitdiff_plain;h=010810d22f6f49ac03da4ba384969432e0320453 [2] http://comments.gmane.org/gmane.linux.kernel.mmc/20446 Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index ce80561..0233ba7 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -12,6 +12,7 @@ Required properties: Should be ti,omap3-hsmmc, for OMAP3 controllers Should be ti,omap3-pre-es3-hsmmc for OMAP3 controllers pre ES3.0 Should be ti,omap4-hsmmc, for OMAP4 controllers + Should be ti,am33xx-hsmmc, for AM335x controllers - ti,hwmods: Must be mmcn, n is controller instance starting 1 Optional properties: diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 32bcebd..edd53adc 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -29,6 +29,7 @@ #include linux/timer.h #include linux/clk.h #include linux/of.h +#include linux/of_irq.h #include linux/of_gpio.h #include linux/of_device.h #include linux/omap-dma.h @@ -36,6 +37,7 @@ #include linux/mmc/core.h #include linux/mmc/mmc.h #include linux/io.h +#include linux/irq.h #include linux/gpio.h #include linux/regulator/consumer.h #include linux/pinctrl/consumer.h @@ -106,6 +108,7 @@ #define TC_EN (1 1) #define BWR_EN (1 4) #define BRR_EN (1 5) +#define CIRQ_EN(1 8) #define ERR_EN (1 15) #define CTO_EN (1 16) #define CCRC_EN(1 17) @@ -140,7 +143,6 @@ #define VDD_3V0300 /* 30 uV */ #define VDD_165_195(ffs(MMC_VDD_165_195) - 1) -#define AUTO_CMD23 (1 1)/* Auto CMD23 support */ /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -194,6 +196,7 @@ struct omap_hsmmc_host { u32 sysctl; u32 capa; int irq; + int wake_irq; int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; @@ -206,6 +209,9 @@ struct omap_hsmmc_host { int req_in_progress; unsigned long clk_rate; unsigned intflags; +#define AUTO_CMD23 (1 0)/* Auto CMD23 support */ +#define HSMMC_SDIO_IRQ_ENABLED (1 1)/* SDIO irq enabled */ +#define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_mmc_platform_data *pdata; }; @@ -510,27 +516,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, struct mmc_command *cmd) { - unsigned int irq_mask; + u32 irq_mask = INT_EN_MASK; + unsigned long flags; if (host-use_dma) - irq_mask = INT_EN_MASK ~(BRR_EN | BWR_EN); - else - irq_mask = INT_EN_MASK; + irq_mask = ~(BRR_EN | BWR_EN); /* Disable timeout for erases */ if (cmd-opcode == MMC_ERASE) irq_mask = ~DTO_EN
[PATCH v11 0/6] mmc: omap_hsmmc: Enable SDIO IRQ
Hi Balaji, Tony, all v12 - drop !CONFIG_OF compile break only exists when #undef CONFIG_OF after include headers 1/7(Sebastian Reichel) - do not emit falling back to polling if wake_irq not specified since MMC does not need it, and it might confuse users only emit if pinmux default/idle is not present or claiming the irq failed 2/7(Balaji) - dropped out-of-tree patches 6/7(Balaji) - mention ti,am33xx-hsmmc compatible section in bindings documentation 1/5 v11 - split !CONFIG_OF compile break into separate patch - enable IWE/CLKEXTFREE in CON/HCTL register needed for omap4 - '' vs '' in omap_hsmmc_resume, 1/5 (Andreas Müller) - #define DLEV_DAT instead of BIT(21) 2/5 (Balaji) - pinctrl_pm_select_default_state() removed, 4/5 (Balaji) - drop _irqsave/_irqrestore from omap_hsmmc_wake_irq handler since it can't be preempted by same priority omap_hsmmc_irq handler 1/5(Joel Fernandes) - replace devres_open_group by explicit devm_free calls 1/5 (Balaji) - disable_irq_nosync wake_irq since we handle it thread safe 1/5 (Balaji) - drop 'gpio_dat1' pinctrl states and rework documentation 5/5 (Balaji) v10 - bug fix on multi-core, untested - incorporated changes from Balaji - use devres / RAII mechanism to configure wake_up / sdio irq capabilities - drop pinctrl state 'active' rely on driver-model states 'default', 'idle' - add specific 'gpio_dat1' state for am335x SWAKEUP hack - reorganized patches; +1 patch multi-core bugfix / +1 for pinctrl - rebased 455c6fdbd21916 / cherry-picks from mmc-next v9 - extended comment about why wake-irq is needed - drop double '(' ')' around card_detect_irq - drop final '.' in in subject line of patch v8 - rebased on top of Tony Lindgrent...@atomide.com changes - improved changelog describing the earlier work - improved wakeup irq setup - works for am3730 es platform now - my changes on top: - compile tested with #undef CONFIG_OF - disable wake_irq in handler to prevent infinite loop - fixed typo and added comment about wake-irq v7 - rebase on 3.14.0-rc3-49726-g77e15ec - split omap_hsmmc_pin_init due to regression on omap-3730 platform v6 - rebase on Linux 3.13-rc3 - reformatting debugfs v5 - fix compile error introduced by last minute one line fix v4: - switch to interrupts-extended format - drop ti,swakeup-missing flag convert to comaptible section v3: - removed gpio_irq from platform_data v2: - incorparated changes as suggested by reviewers - simplified workaround for am335x, gpio will now only wake the module from runtime suspend, not handle the sdio irq itself Andreas Fenkart (6): mmc: omap_hsmmc: Enable SDIO interrupt mmc: omap_hsmmc: enable wakeup event for sdio OMAP4 mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state mmc: omap_hsmmc: abort runtime suspend if pending sdio irq detected mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 54 drivers/mmc/host/omap_hsmmc.c | 280 ++-- include/linux/platform_data/mmc-omap.h |1 + 3 files changed, 314 insertions(+), 21 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 3/6] mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state
Add SDIO IRQ entries to debugfs entry. Note that PSTATE shows current state of data lines, incl. SDIO IRQ pending Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 4ee4645..1a9d31f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -56,6 +56,7 @@ #define OMAP_HSMMC_RSP54 0x0118 #define OMAP_HSMMC_RSP76 0x011C #define OMAP_HSMMC_DATA0x0120 +#define OMAP_HSMMC_PSTATE 0x0124 #define OMAP_HSMMC_HCTL0x0128 #define OMAP_HSMMC_SYSCTL 0x012C #define OMAP_HSMMC_STAT0x0130 @@ -1825,14 +1826,29 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) { struct mmc_host *mmc = s-private; struct omap_hsmmc_host *host = mmc_priv(mmc); + bool suspended; - seq_printf(s, mmc%d:\n ctx_loss:\t%d\n\nregs:\n, - mmc-index, host-context_loss); + seq_printf(s, mmc%d:\n, mmc-index); + seq_printf(s, sdio irq mode\t%s\n, + (mmc-caps MMC_CAP_SDIO_IRQ) ? interrupt : polling); - pm_runtime_get_sync(host-dev); + if (mmc-caps MMC_CAP_SDIO_IRQ) { + seq_printf(s, sdio irq \t%s\n, + (host-flags HSMMC_SDIO_IRQ_ENABLED) ? enabled + : disabled); + } + + suspended = host-dev-power.runtime_status != RPM_ACTIVE; + seq_printf(s, runtime state\t%s\n, (suspended ? idle : active)); + seq_printf(s, ctx_loss:\t%d\n, host-context_loss); + + pm_runtime_get_sync(host-dev); + seq_puts(s, \nregs:\n); seq_printf(s, CON:\t\t0x%08x\n, OMAP_HSMMC_READ(host-base, CON)); + seq_printf(s, PSTATE:\t\t0x%08x\n, + OMAP_HSMMC_READ(host-base, PSTATE)); seq_printf(s, HCTL:\t\t0x%08x\n, OMAP_HSMMC_READ(host-base, HCTL)); seq_printf(s, SYSCTL:\t\t0x%08x\n, -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 5/6] mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks
These are predefined states of the driver model. When not present, as if not set in the device tree, they become no-ops. Explicitly selecting the default state is not needed since the device core layer sets pin mux to default state before probe. This is not the simplest implementation, on AM335x at least, we could switch to idle at any point in the suspend hook, only the default state needs to be set before writing to the irq registers or an IRQ might get lost. Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 30365f5..3c8b183 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2002,7 +2002,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; - struct pinctrl *pinctrl; const struct omap_mmc_of_data *data; match = of_match_device(of_match_ptr(omap_mmc_of_match), pdev-dev); @@ -2226,11 +2225,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_disable_irq(host); - pinctrl = devm_pinctrl_get_select_default(pdev-dev); - if (IS_ERR(pinctrl)) - dev_warn(pdev-dev, - pins are not configured from the driver\n); - /* * For now, only support SDIO interrupt if we have a separate * wake-up interrupt configured from device tree. This is because @@ -2454,10 +2448,15 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) goto abort; } + pinctrl_pm_select_idle_state(dev); + WARN_ON(host-flags HSMMC_WAKE_IRQ_ENABLED); enable_irq(host-wake_irq); host-flags |= HSMMC_WAKE_IRQ_ENABLED; + } else { + pinctrl_pm_select_idle_state(dev); } + abort: spin_unlock_irqrestore(host-irq_lock, flags); return ret; @@ -2481,9 +2480,14 @@ static int omap_hsmmc_runtime_resume(struct device *dev) host-flags = ~HSMMC_WAKE_IRQ_ENABLED; } + pinctrl_pm_select_default_state(host-dev); + + /* irq lost, if pinmux incorrect */ OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, CIRQ_EN); OMAP_HSMMC_WRITE(host-base, IE, CIRQ_EN); + } else { + pinctrl_pm_select_default_state(host-dev); } spin_unlock_irqrestore(host-irq_lock, flags); return 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 4/6] mmc: omap_hsmmc: abort runtime suspend if pending sdio irq detected
On multicores, an sdio irq handler could be running in parallel to runtime suspend. In the worst case it could be waiting for the spinlock held by the runtime suspend. When runtime suspend is complete and the functional clock (fclk) turned off, the irq handler will continue and cause a SIGBUS on the first register access. Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 1a9d31f..30365f5 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -107,6 +107,9 @@ #define SRD(1 26) #define SOFTRESET (1 1) +/* PSTATE */ +#define DLEV_DAT(x)(1 (20 + (x))) + /* Interrupt masks for IE and ISE register */ #define CC_EN (1 0) #define TC_EN (1 1) @@ -2423,6 +2426,7 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) { struct omap_hsmmc_host *host; unsigned long flags; + int ret = 0; host = platform_get_drvdata(to_platform_device(dev)); omap_hsmmc_context_save(host); @@ -2434,14 +2438,29 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) /* disable sdio irq handling to prevent race */ OMAP_HSMMC_WRITE(host-base, ISE, 0); OMAP_HSMMC_WRITE(host-base, IE, 0); - OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); + + if (!(OMAP_HSMMC_READ(host-base, PSTATE) DLEV_DAT(1))) { + /* +* dat1 line low, pending sdio irq +* race condition: possible irq handler running on +* multi-core, abort +*/ + dev_dbg(dev, pending sdio irq, abort suspend\n); + OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); + OMAP_HSMMC_WRITE(host-base, ISE, CIRQ_EN); + OMAP_HSMMC_WRITE(host-base, IE, CIRQ_EN); + pm_runtime_mark_last_busy(dev); + ret = -EBUSY; + goto abort; + } WARN_ON(host-flags HSMMC_WAKE_IRQ_ENABLED); enable_irq(host-wake_irq); host-flags |= HSMMC_WAKE_IRQ_ENABLED; } +abort: spin_unlock_irqrestore(host-irq_lock, flags); - return 0; + return ret; } static int omap_hsmmc_runtime_resume(struct device *dev) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 6/6] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x
The am335x can't detect pending cirq in PM runtime suspend. This patch reconfigures dat1 as a GPIO before going to suspend. SDIO interrupts are detected with the GPIO, the GPIO will only wake the module from suspend, SDIO irq detection will still happen through the IP block. Idea of remuxing the pins by Tony Lindgren. Code contributions from Tony Lindgren and Balaji T K balaj...@ti.com Acked-by: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index 0233ba7..76bf087 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -57,3 +57,56 @@ Examples: edma 25; dma-names = tx, rx; }; + +[workaround for missing swakeup on am33xx] + +This SOC is missing the swakeup line, it will not detect SDIO irq +while in suspend. + + -- + | PRCM | + -- + ^ | + swakeup | | fclk + | v + ----- - + | card | -- CIRQ -- | hsmmc | -- IRQ -- | CPU | + ----- - + +In suspend the fclk is off and the module is disfunctional. Even register reads +will fail. A small logic in the host will request fclk restore, when an +external event is detected. Once the clock is restored, the host detects the +event normally. Since am33xx doesn't have this line it never wakes from +suspend. + +The workaround is to reconfigure the dat1 line as a GPIO upon suspend. To make +this work, we need to set the named pinctrl states default and idle. +Prepare idle to remux dat1 as a gpio, and default to remux it back as sdio +dat1. The MMC driver will then toggle between idle and default state during +runtime. + +In summary: +1. select matching 'compatible' section, see example below. +2. specify pinctrl states default and idle, sleep is optional. +3. specify the gpio irq used for detecting sdio irq in suspend + +If configuration is incomplete, a warning message is emitted falling back to +polling. Also check the sdio irq mode in /sys/kernel/debug/mmc0/regs. Mind +not every application needs SDIO irq, e.g. MMC cards. + + mmc1: mmc@48060100 { + compatible = ti,am33xx-hsmmc; + ... + pinctrl-names = default, idle, sleep + pinctrl-0 = mmc1_pins; + pinctrl-1 = mmc1_idle; + pinctrl-2 = mmc1_sleep; + ... + interrupts-extended = intc 64 gpio2 28 0; + }; + + mmc1_idle : pinmux_cirq_pin { + pinctrl-single,pins = + 0x0f8 0x3f /* GPIO2_28 */ + ; + }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 3c8b183..d22ac3f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1753,15 +1753,25 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host) * and need to remux SDIO DAT1 to GPIO for wake-up from idle. */ if (host-pdata-controller_flags OMAP_HSMMC_SWAKEUP_MISSING) { - ret = -ENODEV; - devm_free_irq(host-dev, host-wake_irq, host); - goto err; + if (IS_ERR(host-dev-pins-default_state)) { + dev_info(host-dev, missing default pinctrl state\n); + ret = -EINVAL; + goto err_free_irq; + } + + if (IS_ERR(host-dev-pins-idle_state)) { + dev_info(host-dev, missing idle pinctrl state\n); + ret = -EINVAL; + goto err_free_irq; + } } OMAP_HSMMC_WRITE(host-base, HCTL, OMAP_HSMMC_READ(host-base, HCTL) | IWE); return 0; +err_free_irq: + devm_free_irq(host-dev, host-wake_irq, host); err: dev_warn(host-dev, no SDIO IRQ support, falling back to polling\n); host-wake_irq = 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 0/7] mmc: omap_hsmmc: Enable SDIO IRQ.
Hi Balaji, Tony, all v11 - split !CONFIG_OF compile break into separate patch - enable IWE/CLKEXTFREE in CON/HCTL register needed for omap4 - '' vs '' in omap_hsmmc_resume, 1/5 (Andreas Müller) - #define DLEV_DAT instead of BIT(21) 2/5 (Balaji) - pinctrl_pm_select_default_state() removed, 4/5 (Balaji) - drop _irqsave/_irqrestore from omap_hsmmc_wake_irq handler since it can't be preempted by same priority omap_hsmmc_irq handler 1/5(Joel Fernandes) - replace devres_open_group by explicit devm_free calls 1/5 (Balaji) - disable_irq_nosync wake_irq since we handle it thread safe 1/5 (Balaji) - drop 'gpio_dat1' pinctrl states and rework documentation 5/5 (Balaji) v10 - bug fix on multi-core, untested - incorporated changes from Balaji - use devres / RAII mechanism to configure wake_up / sdio irq capabilities - drop pinctrl state 'active' rely on driver-model states 'default', 'idle' - add specific 'gpio_dat1' state for am335x SWAKEUP hack - reorganized patches; +1 patch multi-core bugfix / +1 for pinctrl - rebased 455c6fdbd21916 / cherry-picks from mmc-next v9 - extended comment about why wake-irq is needed - drop double '(' ')' around card_detect_irq - drop final '.' in in subject line of patch v8 - rebased on top of Tony Lindgrent...@atomide.com changes - improved changelog describing the earlier work - improved wakeup irq setup - works for am3730 es platform now - my changes on top: - compile tested with #undef CONFIG_OF - disable wake_irq in handler to prevent infinite loop - fixed typo and added comment about wake-irq v7 - rebase on 3.14.0-rc3-49726-g77e15ec - split omap_hsmmc_pin_init due to regression on omap-3730 platform v6 - rebase on Linux 3.13-rc3 - reformatting debugfs v5 - fix compile error introduced by last minute one line fix v4: - switch to interrupts-extended format - drop ti,swakeup-missing flag convert to comaptible section v3: - removed gpio_irq from platform_data v2: - incorparated changes as suggested by reviewers - simplified workaround for am335x, gpio will now only wake the module from runtime suspend, not handle the sdio irq itself Andreas Fenkart (6): mmc: omap_hsmmc: compile fix for !CONFIG_OF build mmc: omap_hsmmc: Enable SDIO interrupt mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state mmc: omap_hsmmc: abort runtime suspend if pending sdio irq detected mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x Balaji T K (1): mmc: omap_hsmmc: enable wakeup event for sdio OMAP4 .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 53 drivers/mmc/host/omap_hsmmc.c | 283 ++-- include/linux/platform_data/mmc-omap.h |1 + 3 files changed, 316 insertions(+), 21 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 1/7] mmc: omap_hsmmc: compile fix for !CONFIG_OF build
Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 8d07e2b..5042a15 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1864,6 +1864,7 @@ static inline struct omap_mmc_platform_data { return ERR_PTR(-EINVAL); } +#define omap_mmc_of_match NULL #endif static int omap_hsmmc_probe(struct platform_device *pdev) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 2/7] mmc: omap_hsmmc: Enable SDIO interrupt
There have been various patches floating around for enabling the SDIO IRQ for hsmmc, but none of them ever got merged. Probably the reason for not merging the SDIO interrupt patches has been the lack of wake-up path for SDIO on some omaps that has also needed remuxing the SDIO DAT1 line to a GPIO making the patches complex. This patch adds the minimal SDIO IRQ support to hsmmc for omaps that do have the wake-up path. For those omaps, the DAT1 line need to have the wake-up enable bit set, and the wake-up interrupt is the same as for the MMC controller. This patch has been tested on am3730 es1.2 with mwifiex connected to MMC3 with mwifiex waking to Ethernet traffic from off-idle mode. Note that for omaps that do not have the SDIO wake-up path, this patch will not work for idle modes and further patches for remuxing DAT1 to GPIO are needed. Based on earlier patches [1][2] by David Vrabel david.vra...@csr.com, Steve Sakoman st...@sakoman.com For now, only support SDIO interrupt if we are booted with a separate wake-irq configued via device tree. This is because omaps need the wake-irq for idle states, and some omaps need special quirks. And we don't want to add new legacy mux platform init code callbacks any longer as we are moving to DT based booting anyways. To use it, you need to specify the wake-irq using the interrupts-extended property. [1] http://www.sakoman.com/cgi-bin/gitweb.cgi?p=linux.git;a=commitdiff_plain;h=010810d22f6f49ac03da4ba384969432e0320453 [2] http://comments.gmane.org/gmane.linux.kernel.mmc/20446 Cc: Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5042a15..f43a69e 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -29,6 +29,7 @@ #include linux/timer.h #include linux/clk.h #include linux/of.h +#include linux/of_irq.h #include linux/of_gpio.h #include linux/of_device.h #include linux/omap-dma.h @@ -36,6 +37,7 @@ #include linux/mmc/core.h #include linux/mmc/mmc.h #include linux/io.h +#include linux/irq.h #include linux/gpio.h #include linux/regulator/consumer.h #include linux/pinctrl/consumer.h @@ -133,6 +135,7 @@ static void apply_clk_hack(struct device *dev) #define TC_EN (1 1) #define BWR_EN (1 4) #define BRR_EN (1 5) +#define CIRQ_EN(1 8) #define ERR_EN (1 15) #define CTO_EN (1 16) #define CCRC_EN(1 17) @@ -167,7 +170,6 @@ static void apply_clk_hack(struct device *dev) #define VDD_3V0300 /* 30 uV */ #define VDD_165_195(ffs(MMC_VDD_165_195) - 1) -#define AUTO_CMD23 (1 1)/* Auto CMD23 support */ /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -221,6 +223,7 @@ struct omap_hsmmc_host { u32 sysctl; u32 capa; int irq; + int wake_irq; int use_dma, dma_ch; struct dma_chan *tx_chan; struct dma_chan *rx_chan; @@ -233,6 +236,9 @@ struct omap_hsmmc_host { int req_in_progress; unsigned long clk_rate; unsigned intflags; +#define AUTO_CMD23 (1 0)/* Auto CMD23 support */ +#define HSMMC_SDIO_IRQ_ENABLED (1 1)/* SDIO irq enabled */ +#define HSMMC_WAKE_IRQ_ENABLED (1 2) struct omap_hsmmc_next next_data; struct omap_mmc_platform_data *pdata; }; @@ -537,27 +543,40 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host, struct mmc_command *cmd) { - unsigned int irq_mask; + u32 irq_mask = INT_EN_MASK; + unsigned long flags; if (host-use_dma) - irq_mask = INT_EN_MASK ~(BRR_EN | BWR_EN); - else - irq_mask = INT_EN_MASK; + irq_mask = ~(BRR_EN | BWR_EN); /* Disable timeout for erases */ if (cmd-opcode == MMC_ERASE) irq_mask = ~DTO_EN; + spin_lock_irqsave(host-irq_lock, flags); OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, irq_mask); + + /* latch pending CIRQ, but don't signal MMC core */ + if (host-flags HSMMC_SDIO_IRQ_ENABLED) + irq_mask |= CIRQ_EN; OMAP_HSMMC_WRITE(host-base, IE, irq_mask); + spin_unlock_irqrestore(host-irq_lock, flags); } static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) { - OMAP_HSMMC_WRITE(host-base, ISE, 0); - OMAP_HSMMC_WRITE(host
[PATCH v11 4/7] mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state
Add SDIO IRQ entries to debugfs entry. Note that PSTATE shows current state of data lines, incl. SDIO IRQ pending Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f76462d..14857d7 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -83,6 +83,7 @@ static void apply_clk_hack(struct device *dev) #define OMAP_HSMMC_RSP54 0x0118 #define OMAP_HSMMC_RSP76 0x011C #define OMAP_HSMMC_DATA0x0120 +#define OMAP_HSMMC_PSTATE 0x0124 #define OMAP_HSMMC_HCTL0x0128 #define OMAP_HSMMC_SYSCTL 0x012C #define OMAP_HSMMC_STAT0x0130 @@ -1854,14 +1855,29 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) { struct mmc_host *mmc = s-private; struct omap_hsmmc_host *host = mmc_priv(mmc); + bool suspended; - seq_printf(s, mmc%d:\n ctx_loss:\t%d\n\nregs:\n, - mmc-index, host-context_loss); + seq_printf(s, mmc%d:\n, mmc-index); + seq_printf(s, sdio irq mode\t%s\n, + (mmc-caps MMC_CAP_SDIO_IRQ) ? interrupt : polling); - pm_runtime_get_sync(host-dev); + if (mmc-caps MMC_CAP_SDIO_IRQ) { + seq_printf(s, sdio irq \t%s\n, + (host-flags HSMMC_SDIO_IRQ_ENABLED) ? enabled + : disabled); + } + + suspended = host-dev-power.runtime_status != RPM_ACTIVE; + seq_printf(s, runtime state\t%s\n, (suspended ? idle : active)); + seq_printf(s, ctx_loss:\t%d\n, host-context_loss); + + pm_runtime_get_sync(host-dev); + seq_puts(s, \nregs:\n); seq_printf(s, CON:\t\t0x%08x\n, OMAP_HSMMC_READ(host-base, CON)); + seq_printf(s, PSTATE:\t\t0x%08x\n, + OMAP_HSMMC_READ(host-base, PSTATE)); seq_printf(s, HCTL:\t\t0x%08x\n, OMAP_HSMMC_READ(host-base, HCTL)); seq_printf(s, SYSCTL:\t\t0x%08x\n, -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 3/7] mmc: omap_hsmmc: enable wakeup event for sdio OMAP4
From: Balaji T K balaj...@ti.com To detect sdio irqs properly without spurious events, OMAP4 needs IWE in CON and CTPL, CLKEXTFREE in HCTL to be set Signed-off-by: Balaji T K balaj...@ti.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index f43a69e..f76462d 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -120,7 +120,10 @@ static void apply_clk_hack(struct device *dev) #define BCE(1 1) #define FOUR_BIT (1 1) #define HSPE (1 2) +#define IWE(1 24) #define DDR(1 19) +#define CLKEXTFREE (1 16) +#define CTPL (1 11) #define DW8(1 5) #define OD 0x1 #define STAT_CLEAR 0x @@ -713,6 +716,9 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) capa = VS18; } + if (host-mmc-caps MMC_CAP_SDIO_IRQ) + hctl |= IWE; + OMAP_HSMMC_WRITE(host-base, HCTL, OMAP_HSMMC_READ(host-base, HCTL) | hctl); @@ -1709,19 +1715,23 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card) static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable) { struct omap_hsmmc_host *host = mmc_priv(mmc); - u32 irq_mask; + u32 irq_mask, con; unsigned long flags; spin_lock_irqsave(host-irq_lock, flags); + con = OMAP_HSMMC_READ(host-base, CON); irq_mask = OMAP_HSMMC_READ(host-base, ISE); if (enable) { host-flags |= HSMMC_SDIO_IRQ_ENABLED; irq_mask |= CIRQ_EN; + con |= CTPL | CLKEXTFREE; } else { host-flags = ~HSMMC_SDIO_IRQ_ENABLED; irq_mask = ~CIRQ_EN; + con = ~(CTPL | CLKEXTFREE); } + OMAP_HSMMC_WRITE(host-base, CON, con); OMAP_HSMMC_WRITE(host-base, IE, irq_mask); /* @@ -1773,6 +1783,8 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host) goto err; } + OMAP_HSMMC_WRITE(host-base, HCTL, +OMAP_HSMMC_READ(host-base, HCTL) | IWE); return 0; err: -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 7/7] mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x
The am335x can't detect pending cirq in PM runtime suspend. This patch reconfigures dat1 as a GPIO before going to suspend. SDIO interrupts are detected with the GPIO, the GPIO will only wake the module from suspend, SDIO irq detection will still happen through the IP block. Idea of remuxing the pins by Tony Lindgren. Code contributions from Tony Lindgren and Balaji T K balaj...@ti.com Signed-off-by: Andreas Fenkart afenk...@gmail.com Signed-off-by: Tony Lindgren t...@atomide.com Conflicts: drivers/mmc/host/omap_hsmmc.c diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt index ce80561..946bc5f 100644 --- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt @@ -56,3 +56,56 @@ Examples: edma 25; dma-names = tx, rx; }; + +[workaround for missing swakeup on am33xx] + +This SOC is missing the swakeup line, it will not detect SDIO irq +while in suspend. + + -- + | PRCM | + -- + ^ | + swakeup | | fclk + | v + ----- - + | card | -- CIRQ -- | hsmmc | -- IRQ -- | CPU | + ----- - + +In suspend the fclk is off and the module is disfunctional. Even register reads +will fail. A small logic in the host will request fclk restore, when an +external event is detected. Once the clock is restored, the host detects the +event normally. Since am33xx doesn't have this line it never wakes from +suspend. + +The workaround is to reconfigure the dat1 line as a GPIO upon suspend. To make +this work, we need to set the named pinctrl states default and idle. +Prepare idle to remux dat1 as a gpio, and default to remux it back as sdio +dat1. The MMC driver will then toggle between idle and default state during +runtime. + +In summary: +1. select matching 'compatible' section, see example below. +2. specify pinctrl states default and idle, sleep is optional. +3. specify the gpio irq used for detecting sdio irq in suspend + +If configuration is incomplete, a warning message is emitted falling back to +polling. Also check the sdio irq mode in /sys/kernel/debug/mmc0/regs. Mind +not every application needs SDIO irq, e.g. MMC cards. + + mmc1: mmc@48060100 { + compatible = ti,am33xx-hsmmc; + ... + pinctrl-names = default, idle, sleep + pinctrl-0 = mmc1_pins; + pinctrl-1 = mmc1_idle; + pinctrl-2 = mmc1_sleep; + ... + interrupts-extended = intc 64 gpio2 28 0; + }; + + mmc1_idle : pinmux_cirq_pin { + pinctrl-single,pins = + 0x0f8 0x3f /* GPIO2_28 */ + ; + }; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 5a321f98..497b2fc 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1782,15 +1782,25 @@ static int omap_hsmmc_configure_wake_irq(struct omap_hsmmc_host *host) * and need to remux SDIO DAT1 to GPIO for wake-up from idle. */ if (host-pdata-controller_flags OMAP_HSMMC_SWAKEUP_MISSING) { - ret = -ENODEV; - devm_free_irq(host-dev, host-wake_irq, host); - goto err; + if (IS_ERR(host-dev-pins-default_state)) { + dev_info(host-dev, missing default pinctrl state\n); + ret = -EINVAL; + goto err_free_irq; + } + + if (IS_ERR(host-dev-pins-idle_state)) { + dev_info(host-dev, missing idle pinctrl state\n); + ret = -EINVAL; + goto err_free_irq; + } } OMAP_HSMMC_WRITE(host-base, HCTL, OMAP_HSMMC_READ(host-base, HCTL) | IWE); return 0; +err_free_irq: + devm_free_irq(host-dev, host-wake_irq, host); err: dev_warn(host-dev, no SDIO IRQ support, falling back to polling\n); host-wake_irq = 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v11 6/7] mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks
These are predefined states of the driver model. When not present, as if not set in the device tree, they become no-ops. Explicitly selecting the default state is not needed since the device core layer sets pin mux to default state before probe. This is not the simplest implementation, on AM335x at least, we could switch to idle at any point in the suspend hook, only the default state needs to be set before writing to the irq registers or an IRQ might get lost. Signed-off-by: Andreas Fenkart afenk...@gmail.com diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 47a5982..5a321f98 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2032,7 +2032,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) const struct of_device_id *match; dma_cap_mask_t mask; unsigned tx_req, rx_req; - struct pinctrl *pinctrl; const struct omap_mmc_of_data *data; apply_clk_hack(pdev-dev); @@ -2258,11 +2257,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) omap_hsmmc_disable_irq(host); - pinctrl = devm_pinctrl_get_select_default(pdev-dev); - if (IS_ERR(pinctrl)) - dev_warn(pdev-dev, - pins are not configured from the driver\n); - /* * For now, only support SDIO interrupt if we have a separate * wake-up interrupt configured from device tree. This is because @@ -2486,10 +2480,15 @@ static int omap_hsmmc_runtime_suspend(struct device *dev) goto abort; } + pinctrl_pm_select_idle_state(dev); + WARN_ON(host-flags HSMMC_WAKE_IRQ_ENABLED); enable_irq(host-wake_irq); host-flags |= HSMMC_WAKE_IRQ_ENABLED; + } else { + pinctrl_pm_select_idle_state(dev); } + abort: spin_unlock_irqrestore(host-irq_lock, flags); return ret; @@ -2513,9 +2512,14 @@ static int omap_hsmmc_runtime_resume(struct device *dev) host-flags = ~HSMMC_WAKE_IRQ_ENABLED; } + pinctrl_pm_select_default_state(host-dev); + + /* irq lost, if pinmux incorrect */ OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, ISE, CIRQ_EN); OMAP_HSMMC_WRITE(host-base, IE, CIRQ_EN); + } else { + pinctrl_pm_select_default_state(host-dev); } spin_unlock_irqrestore(host-irq_lock, flags); return 0; -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v10 1/5] mmc: omap_hsmmc: Enable SDIO interrupt
Hi Andreas, 2014-04-30 14:23 GMT+02:00 Andreas Müller schnitzelt...@googlemail.com: On Mon, Apr 28, 2014 at 9:40 AM, Andreas Fenkart afenk...@gmail.com wrote: @@ -2201,11 +2346,16 @@ static int omap_hsmmc_suspend(struct device *dev) pm_runtime_get_sync(host-dev); if (!(host-mmc-pm_flags MMC_PM_KEEP_POWER)) { - omap_hsmmc_disable_irq(host); + OMAP_HSMMC_WRITE(host-base, ISE, 0); + OMAP_HSMMC_WRITE(host-base, IE, 0); + OMAP_HSMMC_WRITE(host-base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host-base, HCTL, OMAP_HSMMC_READ(host-base, HCTL) ~SDBP); } + if (host-wake_irq !(host-mmc-pm_flags MMC_PM_WAKE_SDIO_IRQ)) + disable_irq(host-wake_irq); + I think it says, Do you want to wake up from deep power states when an SDIO IRQ is pending Will try to bring this more to the point if (host-dbclk) clk_disable_unprepare(host-dbclk); @@ -2231,6 +2381,9 @@ static int omap_hsmmc_resume(struct device *dev) omap_hsmmc_protect_card(host); + if (host-wake_irq !(host-mmc-pm_flags MMC_PM_WAKE_SDIO_IRQ)) you're right should be '' + enable_irq(host-wake_irq); + pm_runtime_mark_last_busy(host-dev); pm_runtime_put_autosuspend(host-dev); return 0; Maybe I misunderstand something here but shouldn't disable_irq/enable_irq be swapped here? /Andreas -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/5] mmc: omap_hsmmc: Enable SDIO IRQ.
Hi Balaji, Tony, all v10 - bug fix on multi-core, untested - incorporated changes from Balaji - use devres / RAII mechanism to configure wake_up / sdio irq capabilities - drop pinctrl state 'active' rely on driver-model states 'default', 'idle' - add specific 'gpio_dat1' state for am335x SWAKEUP hack - reorganized patches; +1 patch multi-core bugfix / +1 for pinctrl - rebased 455c6fdbd21916 / cherry-picks from mmc-next v9 - extended comment about why wake-irq is needed - drop double '(' ')' around card_detect_irq - drop final '.' in in subject line of patch v8 - rebased on top of Tony Lindgrent...@atomide.com changes - improved changelog describing the earlier work - improved wakeup irq setup - works for am3730 es platform now - my changes on top: - compile tested with #undef CONFIG_OF - disable wake_irq in handler to prevent infinite loop - fixed typo and added comment about wake-irq v7 - rebase on 3.14.0-rc3-49726-g77e15ec - split omap_hsmmc_pin_init due to regression on omap-3730 platform v6 - rebase on Linux 3.13-rc3 - reformatting debugfs v5 - fix compile error introduced by last minute one line fix v4: - switch to interrupts-extended format - drop ti,swakeup-missing flag convert to comaptible section v3: - removed gpio_irq from platform_data v2: - incorparated changes as suggested by reviewers - simplified workaround for am335x, gpio will now only wake the module from runtime suspend, not handle the sdio irq itself Andreas Fenkart (5): mmc: omap_hsmmc: Enable SDIO interrupt mmc: omap_hsmmc: bug: abort runtime suspend if pending sdio irq detected mmc: omap_hsmmc: Extend debugfs by SDIO IRQ handling, runtime state mmc: omap_hsmmc: switch default/idle pinctrl states in runtime hooks mmc: omap_hsmmc: Pin remux workaround to support SDIO interrupt on AM335x .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 51 drivers/mmc/host/omap_hsmmc.c | 285 ++-- include/linux/platform_data/mmc-omap.h |1 + 3 files changed, 316 insertions(+), 21 deletions(-) -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html