MMC updates, plus CuBox-i WiFi support
Subsystems (12)
cover MMC updates, plus CuBox-i WiFi support
All,
This is where I'm at with trying to clean up the SDHCI mess, and sort out issues I've noticed when trying to get UHS support working on CuBoxes. This is my full patch set, but I recommend not applying patch 37 as there appears to be a hardware issue preventing it working reliably.
In any case, patches 0-33 inclusive are the SDHCI clean up, based against v3.15-rc1. Patches 34 and 35 are Olof's Wifi support, 36 is my fix against those, and 38 adds the Broadcom Wifi and BT support for CuBox.
The questions over how to handle these devices were never properly settled, so I recommend against merging patch 34 onwards. As for the rest, I'm not planning on any further work, so it may be a good idea for people to consider testing them with a view to getting them merged.
Documentation/devicetree/bindings/mmc/mmc.txt | 11 + arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 34 +- arch/arm/boot/dts/imx6qdl-microsom.dtsi | 98 ++++ drivers/mmc/core/core.c | 42 ++ drivers/mmc/core/host.c | 68 +++ drivers/mmc/core/sdio_irq.c | 41 +- drivers/mmc/host/Kconfig | 63 +-- drivers/mmc/host/dw_mmc.c | 2 + drivers/mmc/host/sdhci-acpi.c | 8 + drivers/mmc/host/sdhci-bcm-kona.c | 4 + drivers/mmc/host/sdhci-bcm2835.c | 4 + drivers/mmc/host/sdhci-cns3xxx.c | 13 +- drivers/mmc/host/sdhci-dove.c | 4 + drivers/mmc/host/sdhci-esdhc-imx.c | 82 +-- drivers/mmc/host/sdhci-esdhc.h | 4 +- drivers/mmc/host/sdhci-of-arasan.c | 4 + drivers/mmc/host/sdhci-of-esdhc.c | 70 ++- drivers/mmc/host/sdhci-of-hlwd.c | 4 + drivers/mmc/host/sdhci-pci.c | 9 +- drivers/mmc/host/sdhci-pltfm.c | 4 + drivers/mmc/host/sdhci-pxav2.c | 14 +- drivers/mmc/host/sdhci-pxav3.c | 13 +- drivers/mmc/host/sdhci-s3c.c | 36 +- drivers/mmc/host/sdhci-sirf.c | 4 + drivers/mmc/host/sdhci-spear.c | 5 +- drivers/mmc/host/sdhci-tegra.c | 27 +- drivers/mmc/host/sdhci.c | 728 +++++++++++++------------- drivers/mmc/host/sdhci.h | 20 +- include/linux/mmc/host.h | 8 + include/linux/mmc/sdhci.h | 15 +- 30 files changed, 885 insertions(+), 554 deletions(-)
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 1/38 mmc: sdio_irq: rework sdio irq handling
Rather than the SDIO support spawning it's own thread for handling card interrupts, use the generic IRQ infrastructure for this, triggering it from the host interface's interrupt handling directly.
This avoids a race between the parent thread waiting to receive an interrupt response from the card, and the slow startup from the sdio irq thread, which can occur as a result of high system load (eg, while udev is running.)
--- drivers/mmc/core/sdio_irq.c | 41 +++++++++++++++++++++++++++++++---------- include/linux/mmc/host.h | 3 +++ 2 files changed, 34 insertions(+), 10 deletions(-)
drivers/mmc/core/sdio_irq.c +31 -10
@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)return ret; } +void sdio_run_irqs (struct mmc_host *host) +{ +mmc_claim_host (host); + host->sdio_irq_pending = true; +process_sdio_pending_irqs (host); +mmc_release_host (host); +} +EXPORT_SYMBOL_GPL (sdio_run_irqs); +static int sdio_irq_thread (void *_host) {struct mmc_host *host = _host;
@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)WARN_ON (!host->claimed);if (!host->sdio_irqs++) { -atomic_set (&host->sdio_irq_thread_abort,0 ); - host->sdio_irq_thread = -kthread_run (sdio_irq_thread, host,"ksdioirqd/%s" , -mmc_hostname (host)); -if (IS_ERR (host->sdio_irq_thread)) { -int err =PTR_ERR (host->sdio_irq_thread); - host->sdio_irqs--; -return err; +if (!(host->caps2 &MMC_CAP2_SDIO_NOTHREAD )) { +atomic_set (&host->sdio_irq_thread_abort,0 ); + host->sdio_irq_thread = +kthread_run (sdio_irq_thread, host, +"ksdioirqd/%s" ,mmc_hostname (host)); +if (IS_ERR (host->sdio_irq_thread)) { +int err =PTR_ERR (host->sdio_irq_thread); + host->sdio_irqs--; +return err; + } + }else { +mmc_host_clk_hold (host); + host->ops->enable_sdio_irq (host,1 ); +mmc_host_clk_release (host); } }
@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)BUG_ON (host->sdio_irqs <1 );if (!--host->sdio_irqs) { -atomic_set (&host->sdio_irq_thread_abort,1 ); -kthread_stop (host->sdio_irq_thread); +if (!(host->caps2 &MMC_CAP2_SDIO_NOTHREAD )) { +atomic_set (&host->sdio_irq_thread_abort,1 ); +kthread_stop (host->sdio_irq_thread); + }else { +mmc_host_clk_hold (host); + host->ops->enable_sdio_irq (host,0 ); +mmc_host_clk_release (host); + } }return 0 ;
include/linux/mmc/host.h +3 -0
@@ -278,6 +278,7 @@ struct mmc_host {#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR)#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)/* Don't power up before scan */ +#define MMC_CAP2_SDIO_NOTHREAD (1 << 15)mmc_pm_flag_t pm_caps;/* supported pm features */
@@ -391,6 +392,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)wake_up_process (host->sdio_irq_thread); } +void sdio_run_irqs (struct mmc_host *host); +#ifdef CONFIG_REGULATOR int mmc_regulator_get_ocrmask (struct regulator *supply); int mmc_regulator_set_ocr(struct mmc_host *mmc,
Signature · 1 line
1.8.3.1
PATCH 1/38 mmc: sdio_irq: rework sdio irq handling
Quoted 48 lines · Russell King
Rather than the SDIO support spawning it's own thread for handling card interrupts, use the generic IRQ infrastructure for this, triggering it from the host interface's interrupt handling directly.
This avoids a race between the parent thread waiting to receive an interrupt response from the card, and the slow startup from the sdio irq thread, which can occur as a result of high system load (eg, while udev is running.)
Signed-off-by Russell King <[email protected]>--- drivers/mmc/core/sdio_irq.c | 41 +++++++++++++++++++++++++++++++---------- include/linux/mmc/host.h | 3 +++ 2 files changed, 34 insertions(+), 10 deletions(-)drivers/mmc/core/sdio_irq.c +10
-8@@ -90,6 +90,15 @@ static int process_sdio_pending_irqs(struct mmc_host *host)return ret; } +void sdio_run_irqs (struct mmc_host *host) +{ +mmc_claim_host (host); + host->sdio_irq_pending = true; +process_sdio_pending_irqs (host); +mmc_release_host (host); +} +EXPORT_SYMBOL_GPL (sdio_run_irqs); +static int sdio_irq_thread (void *_host) {struct mmc_host *host = _host;@@ -189,14 +198,20 @@ static int sdio_card_irq_get(struct mmc_card *card)WARN_ON (!host->claimed);if (!host->sdio_irqs++) { -atomic_set (&host->sdio_irq_thread_abort,0 ); - host->sdio_irq_thread = -kthread_run (sdio_irq_thread, host,"ksdioirqd/%s" , -mmc_hostname (host)); -if (IS_ERR (host->sdio_irq_thread)) { -int err =PTR_ERR (host->sdio_irq_thread); - host->sdio_irqs--; -return err; +if (!(host->caps2 &MMC_CAP2_SDIO_NOTHREAD )) {
drivers/mmc/core/sdio_irq.c static int sdio_card_irq_get(struct mmc_card *card) · line 211
Quoted 10 lines
drivers/mmc/core/sdio_irq.c +10
-0+atomic_set (&host->sdio_irq_thread_abort,0 ); + host->sdio_irq_thread = +kthread_run (sdio_irq_thread, host, +"ksdioirqd/%s" ,mmc_hostname (host)); +if (IS_ERR (host->sdio_irq_thread)) { +int err =PTR_ERR (host->sdio_irq_thread); + host->sdio_irqs--; +return err; + } + }else {
I suppose you need to check for MMC_CAP_SDIO_IRQ here?
Quoted 7 lines
drivers/mmc/core/sdio_irq.c +3
-0+mmc_host_clk_hold (host); + host->ops->enable_sdio_irq (host,1 ); +mmc_host_clk_release (host); } }
drivers/mmc/core/sdio_irq.c static int sdio_card_irq_put(struct mmc_card *card) · line 232
Quoted 9 lines
drivers/mmc/core/sdio_irq.c +4
-2@@ -211,8 +226,14 @@ static int sdio_card_irq_put(struct mmc_card *card)BUG_ON (host->sdio_irqs <1 );if (!--host->sdio_irqs) { -atomic_set (&host->sdio_irq_thread_abort,1 ); -kthread_stop (host->sdio_irq_thread); +if (!(host->caps2 &MMC_CAP2_SDIO_NOTHREAD )) { +atomic_set (&host->sdio_irq_thread_abort,1 ); +kthread_stop (host->sdio_irq_thread); + }else {
I suppose you need to check for MMC_CAP_SDIO_IRQ here?
Quoted 29 lines
drivers/mmc/core/sdio_irq.c +4
-0+mmc_host_clk_hold (host); + host->ops->enable_sdio_irq (host,0 ); +mmc_host_clk_release (host); + } }return 0 ;include/linux/mmc/host.h +3
-1@@ -278,6 +278,7 @@ struct mmc_host {#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \ MMC_CAP2_PACKED_WR)#define MMC_CAP2_NO_PRESCAN_POWERUP (1 << 14)/* Don't power up before scan */ +#define MMC_CAP2_SDIO_NOTHREAD (1 << 15)mmc_pm_flag_t pm_caps;/* supported pm features */ @@ -391,6 +392,8 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)wake_up_process (host->sdio_irq_thread); } +void sdio_run_irqs (struct mmc_host *host); +#ifdef CONFIG_REGULATOR int mmc_regulator_get_ocrmask (struct regulator *supply); int mmc_regulator_set_ocr(struct mmc_host *mmc, --
Quoted 1 line
1.8.3.1
Kind regards
Ulf Hansson
Quoted 5 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 1/38 mmc: sdio_irq: rework sdio irq handling
Quoted 13 lines · Ulf Hansson
drivers/mmc/core/sdio_irq.c static int sdio_card_irq_get(struct mmc_card *card) · line 211
Quoted 11 lines · Russell King
drivers/mmc/core/sdio_irq.c +11
-0+if (!(host->caps2 &MMC_CAP2_SDIO_NOTHREAD )) { +atomic_set (&host->sdio_irq_thread_abort,0 ); + host->sdio_irq_thread = +kthread_run (sdio_irq_thread, host, +"ksdioirqd/%s" ,mmc_hostname (host)); +if (IS_ERR (host->sdio_irq_thread)) { +int err =PTR_ERR (host->sdio_irq_thread); + host->sdio_irqs--; +return err; + } + }else {
Quoted 1 line
I suppose you need to check for
MMC_CAP_SDIO_IRQhere?
Why would you set MMC_CAP2_SDIO_NOTHREAD if you didn't have MMC_CAP_SDIO_IRQ ?
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 1/38 mmc: sdio_irq: rework sdio irq handling
Quoted 14 lines · Russell King - ARM Linux
Quoted 13 lines · Ulf Hansson
Quoted 11 lines · Russell King
drivers/mmc/core/sdio_irq.c +11
-0+if (!(host->caps2 &MMC_CAP2_SDIO_NOTHREAD )) { +atomic_set (&host->sdio_irq_thread_abort,0 ); + host->sdio_irq_thread = +kthread_run (sdio_irq_thread, host, +"ksdioirqd/%s" ,mmc_hostname (host)); +if (IS_ERR (host->sdio_irq_thread)) { +int err =PTR_ERR (host->sdio_irq_thread); + host->sdio_irqs--; +return err; + } + }else {
Quoted 3 lines
Quoted 1 line
I suppose you need to check for
MMC_CAP_SDIO_IRQhere?Why would you set
MMC_CAP2_SDIO_NOTHREADif you didn't haveMMC_CAP_SDIO_IRQ?
You are right!
Maybe change the name to "MMC_CAP2_SDIO_IRQ_NOTHREAD", unless we think it becomes too long :-). Additionally, there are actually still some bits available in the MMC_CAP_* bits, instead of the MMC_CAP2_*.
No strong opinion though, feel free to keep as is.
Quoted 4 lines
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 2/38 mmc: sdhci: clean up interrupt handling
In reply to Russell King - ARM Linuxsdhci interrupt handling is a mess; there is a lot of code doing very similar things. Let's clean this up a bit:
1. set's clear down cmd, data and bus power interrupts in one go - we're always going to handle these.
2. use a do { } while () loop for looping while there are pending interrupts.
3. group clearing of bits in intmask into one place.
This results in the code becoming simpler and easier to read.
--- drivers/mmc/host/sdhci.c | 124 ++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 66 deletions(-)
drivers/mmc/host/sdhci.c +58 -66
@@ -2426,7 +2426,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) {irqreturn_t result;struct sdhci_host *host = dev_id; -u32 intmask, unexpected =0 ; +u32 intmask, mask, unexpected =0 ;int cardint =0 , max_loops =16 ;spin_lock (&host->lock);
@@ -2437,88 +2437,80 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) } intmask =sdhci_readl (host,SDHCI_INT_STATUS ); -if (!intmask || intmask ==0xffffffff ) { result =IRQ_NONE ; goto out; } -again: -DBG ("*** %s got interrupt: 0x%08x\n" , -mmc_hostname (host->mmc), intmask); - -if (intmask & (SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE )) { -u32 present =sdhci_readl (host,SDHCI_PRESENT_STATE ) & -SDHCI_CARD_PRESENT ; - -/* -* There is a observation on i.mx esdhc. INSERT bit will be -* immediately set again when it gets cleared, if a card is -* inserted. We have to mask the irq to prevent interrupt -* storm which will freeze the system. And the REMOVE gets -* the same situation. -* -* More testing are needed here to ensure it works for other -* platforms though. -*/ -sdhci_mask_irqs (host, present ?SDHCI_INT_CARD_INSERT : -SDHCI_INT_CARD_REMOVE ); -sdhci_unmask_irqs (host, present ?SDHCI_INT_CARD_REMOVE : -SDHCI_INT_CARD_INSERT ); - -sdhci_writel (host, intmask & (SDHCI_INT_CARD_INSERT | -SDHCI_INT_CARD_REMOVE ),SDHCI_INT_STATUS ); - intmask &= ~(SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE ); -tasklet_schedule (&host->card_tasklet); - } +do { +/* Clear selected interrupts. */ + mask = intmask & (SDHCI_INT_CMD_MASK |SDHCI_INT_DATA_MASK | +SDHCI_INT_BUS_POWER ); +sdhci_writel (host, mask,SDHCI_INT_STATUS ); -if (intmask &SDHCI_INT_CMD_MASK ) { -sdhci_writel (host, intmask &SDHCI_INT_CMD_MASK , -SDHCI_INT_STATUS ); -sdhci_cmd_irq (host, intmask &SDHCI_INT_CMD_MASK ); - } +DBG ("*** %s got interrupt: 0x%08x\n" , +mmc_hostname (host->mmc), intmask); -if (intmask &SDHCI_INT_DATA_MASK ) { -sdhci_writel (host, intmask &SDHCI_INT_DATA_MASK , -SDHCI_INT_STATUS ); -sdhci_data_irq (host, intmask &SDHCI_INT_DATA_MASK ); - } +if (intmask & (SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE )) { +u32 present =sdhci_readl (host,SDHCI_PRESENT_STATE ) & +SDHCI_CARD_PRESENT ; - intmask &= ~(SDHCI_INT_CMD_MASK |SDHCI_INT_DATA_MASK ); +/* +* There is a observation on i.mx esdhc. INSERT +* bit will be immediately set again when it gets +* cleared, if a card is inserted. We have to mask +* the irq to prevent interrupt storm which will +* freeze the system. And the REMOVE gets the +* same situation. +* +* More testing are needed here to ensure it works +* for other platforms though. +*/ +sdhci_mask_irqs (host, present ?SDHCI_INT_CARD_INSERT : +SDHCI_INT_CARD_REMOVE ); +sdhci_unmask_irqs (host, present ?SDHCI_INT_CARD_REMOVE : +SDHCI_INT_CARD_INSERT ); + +sdhci_writel (host, intmask & (SDHCI_INT_CARD_INSERT | +SDHCI_INT_CARD_REMOVE ),SDHCI_INT_STATUS ); +tasklet_schedule (&host->card_tasklet); + } - intmask &= ~SDHCI_INT_ERROR ; +if (intmask &SDHCI_INT_CMD_MASK ) +sdhci_cmd_irq (host, intmask &SDHCI_INT_CMD_MASK ); -if (intmask &SDHCI_INT_BUS_POWER ) { -pr_err ("%s: Card is consuming too much power!\n" , -mmc_hostname (host->mmc)); -sdhci_writel (host,SDHCI_INT_BUS_POWER ,SDHCI_INT_STATUS ); - } +if (intmask &SDHCI_INT_DATA_MASK ) +sdhci_data_irq (host, intmask &SDHCI_INT_DATA_MASK ); - intmask &= ~SDHCI_INT_BUS_POWER ; +if (intmask &SDHCI_INT_BUS_POWER ) +pr_err ("%s: Card is consuming too much power!\n" , +mmc_hostname (host->mmc)); -if (intmask &SDHCI_INT_CARD_INT ) - cardint =1 ; +if (intmask &SDHCI_INT_CARD_INT ) + cardint =1 ; - intmask &= ~SDHCI_INT_CARD_INT ; + intmask &= ~(SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE | +SDHCI_INT_CMD_MASK |SDHCI_INT_DATA_MASK | +SDHCI_INT_ERROR |SDHCI_INT_BUS_POWER | +SDHCI_INT_CARD_INT ); -if (intmask) { - unexpected |= intmask; -sdhci_writel (host, intmask,SDHCI_INT_STATUS ); - } +if (intmask) { + unexpected |= intmask; +sdhci_writel (host, intmask,SDHCI_INT_STATUS ); + } - result =IRQ_HANDLED ; + result =IRQ_HANDLED ; - intmask =sdhci_readl (host,SDHCI_INT_STATUS ); + intmask =sdhci_readl (host,SDHCI_INT_STATUS ); -/* -* If we know we'll call the driver to signal SDIO IRQ, disregard -* further indications of Card Interrupt in the status to avoid a -* needless loop. -*/ -if (cardint) - intmask &= ~SDHCI_INT_CARD_INT ; -if (intmask && --max_loops) - goto again; +/* +* If we know we'll call the driver to signal SDIO IRQ, +* disregard further indications of Card Interrupt in +* the status to avoid a needless loop. +*/ +if (cardint) + intmask &= ~SDHCI_INT_CARD_INT ; + }while (intmask && --max_loops); out:spin_unlock (&host->lock);
Signature · 1 line
1.8.3.1
PATCH 3/38 mmc: sdhci: clean up sdio interrupt enable handling
In reply to Russell King - ARM LinuxWe don't need to change the SDHCI_SDIO_IRQ_ENABLED flag when we're merely receiving an interrupt - IRQ handling thread in the MMC core will either re-enable or disable the interrupt via the enable_sdio_irq callback, which will update this status appropriately.
--- drivers/mmc/host/sdhci.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-)
drivers/mmc/host/sdhci.c +17 -18
@@ -1709,24 +1709,14 @@ static int sdhci_get_ro(struct mmc_host *mmc)static void sdhci_enable_sdio_irq_nolock (struct sdhci_host *host,int enable) { -if (host->flags &SDHCI_DEVICE_DEAD ) - goto out; - -if (enable) - host->flags |=SDHCI_SDIO_IRQ_ENABLED ; -else - host->flags &= ~SDHCI_SDIO_IRQ_ENABLED ; -/* SDIO IRQ will be enabled as appropriate in runtime resume */ -if (host->runtime_suspended) - goto out; - -if (enable) -sdhci_unmask_irqs (host,SDHCI_INT_CARD_INT ); -else -sdhci_mask_irqs (host,SDHCI_INT_CARD_INT ); -out: -mmiowb (); +if (!(host->flags &SDHCI_DEVICE_DEAD ) || host->runtime_suspended) { +if (enable) +sdhci_unmask_irqs (host,SDHCI_INT_CARD_INT ); +else +sdhci_mask_irqs (host,SDHCI_INT_CARD_INT ); +mmiowb (); + } }static void sdhci_enable_sdio_irq (struct mmc_host *mmc,int enable)
@@ -1734,9 +1724,18 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)struct sdhci_host *host =mmc_priv (mmc);unsigned long flags; +sdhci_runtime_pm_get (host); +spin_lock_irqsave (&host->lock, flags); +if (enable) + host->flags |=SDHCI_SDIO_IRQ_ENABLED ; +else + host->flags &= ~SDHCI_SDIO_IRQ_ENABLED ; +sdhci_enable_sdio_irq_nolock (host, enable);spin_unlock_irqrestore (&host->lock, flags); + +sdhci_runtime_pm_put (host); } static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
@@ -2721,7 +2720,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host) host->runtime_suspended = false;/* Enable SDIO IRQ */ -if ((host->flags &SDHCI_SDIO_IRQ_ENABLED )) +if (host->flags &SDHCI_SDIO_IRQ_ENABLED )sdhci_enable_sdio_irq_nolock (host, true);/* Enable Card Detection */
Signature · 1 line
1.8.3.1
PATCH 4/38 mmc: sdhci: convert to new SDIO IRQ handling
In reply to Russell King - ARM LinuxUse a generic threaded interrupt handler for SDIO interrupt handling, rather than allowing the SDIO core code to buggily spawn its own thread. This results in host drivers to be more in control of how SDIO interrupts are acknowledged in the hardware, rather than having the internals of the SDIO core placed upon them, possibly resulting in sub-standard handling.
At least one SDHCI implementation specifies a very specific sequence to deal with a card interrupt.
--- drivers/mmc/host/sdhci.c | 62 +++++++++++++++++++++++++++++------------------ include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 41 insertions(+), 23 deletions(-)
drivers/mmc/host/sdhci.c +39 -23
@@ -2423,10 +2423,10 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)static irqreturn_t sdhci_irq (int irq,void *dev_id) { -irqreturn_t result; +irqreturn_t result =IRQ_NONE ;struct sdhci_host *host = dev_id;u32 intmask, mask, unexpected =0 ; -int cardint =0 , max_loops =16 ; +int max_loops =16 ;spin_lock (&host->lock);
@@ -2485,8 +2485,11 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)pr_err ("%s: Card is consuming too much power!\n" ,mmc_hostname (host->mmc)); -if (intmask &SDHCI_INT_CARD_INT ) - cardint =1 ; +if (intmask &SDHCI_INT_CARD_INT ) { +sdhci_enable_sdio_irq_nolock (host, false); + host->thread_isr |=SDHCI_INT_CARD_INT ; + result =IRQ_WAKE_THREAD ; + } intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
@@ -2498,17 +2501,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)sdhci_writel (host, intmask,SDHCI_INT_STATUS ); } - result =IRQ_HANDLED ; +if (result ==IRQ_NONE ) + result =IRQ_HANDLED ; intmask =sdhci_readl (host,SDHCI_INT_STATUS ); - -/* -* If we know we'll call the driver to signal SDIO IRQ, -* disregard further indications of Card Interrupt in -* the status to avoid a needless loop. -*/ -if (cardint) - intmask &= ~SDHCI_INT_CARD_INT ; }while (intmask && --max_loops); out:spin_unlock (&host->lock);
@@ -2518,15 +2514,33 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) mmc_hostname(host->mmc), unexpected);sdhci_dumpregs (host); } -/* -* We have to delay this as it calls back into the driver. -*/ -if (cardint) -mmc_signal_sdio_irq (host->mmc);return result; } +static irqreturn_t sdhci_thread_irq (int irq,void *dev_id) +{ +struct sdhci_host *host = dev_id; +unsigned long flags; +u32 isr; + +spin_lock_irqsave (&host->lock, flags); + isr = host->thread_isr; + host->thread_isr =0 ; +spin_unlock_irqrestore (&host->lock, flags); + +if (isr &SDHCI_INT_CARD_INT ) { +sdio_run_irqs (host->mmc); + +spin_lock_irqsave (&host->lock, flags); +if (host->flags &SDHCI_SDIO_IRQ_ENABLED ) +sdhci_enable_sdio_irq_nolock (host, true); +spin_unlock_irqrestore (&host->lock, flags); + } + +return isr ?IRQ_HANDLED :IRQ_NONE ; +} +/*****************************************************************************\ * * * Suspend/resume *
@@ -2596,8 +2610,9 @@ int sdhci_resume_host(struct sdhci_host *host) }if (!device_may_wakeup (mmc_dev (host->mmc))) { - ret =request_irq (host->irq, sdhci_irq,IRQF_SHARED , -mmc_hostname (host->mmc), host); + ret =request_threaded_irq (host->irq, sdhci_irq, + sdhci_thread_irq,IRQF_SHARED , +mmc_hostname (host->mmc), host);if (ret)return ret; }else {
@@ -2676,7 +2691,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)sdhci_mask_irqs (host,SDHCI_INT_ALL_MASK );spin_unlock_irqrestore (&host->lock, flags); -synchronize_irq (host->irq); +synchronize_hardirq (host->irq);spin_lock_irqsave (&host->lock, flags); host->runtime_suspended = true;
@@ -2932,6 +2947,7 @@ int sdhci_add_host(struct sdhci_host *host) mmc->max_busy_timeout = (1 <<27 ) / host->timeout_clk; mmc->caps |=MMC_CAP_SDIO_IRQ |MMC_CAP_ERASE |MMC_CAP_CMD23 ; + mmc->caps2 |=MMC_CAP2_SDIO_NOTHREAD ;if (host->quirks &SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12 ) host->flags |=SDHCI_AUTO_CMD12 ;
@@ -3221,8 +3237,8 @@ int sdhci_add_host(struct sdhci_host *host)sdhci_init (host,0 ); - ret =request_irq (host->irq, sdhci_irq,IRQF_SHARED , -mmc_hostname (mmc), host); + ret =request_threaded_irq (host->irq, sdhci_irq, sdhci_thread_irq, +IRQF_SHARED ,mmc_hostname (mmc), host);if (ret) {pr_err ("%s: Failed to request IRQ %d: %d\n" ,mmc_hostname (mmc), host->irq, ret);
include/linux/mmc/sdhci.h +2 -0
@@ -177,6 +177,8 @@ struct sdhci_host {unsigned int ocr_avail_mmc;u32 ocr_mask;/* available voltages */ +u32 thread_isr; +wait_queue_head_t buf_ready_int;/* Waitqueue for Buffer Read Ready interrupt */ unsigned int tuning_done;/* Condition flag set when CMD19 succeeds */
Signature · 1 line
1.8.3.1
PATCH 5/38 mmc: sdhci: push card_tasklet into threaded irq handler
In reply to Russell King - ARM LinuxThere's no requirement to have the card tasklet separate now that we have a threaded interrupt handler, so kill this and move the called code into the threaded part of the handler.
--- drivers/mmc/host/sdhci.c | 23 +++++++++-------------- include/linux/mmc/sdhci.h | 3 +-- 2 files changed, 10 insertions(+), 16 deletions(-)
drivers/mmc/host/sdhci.c +9 -14
@@ -2123,15 +2123,6 @@ static const struct mmc_host_ops sdhci_ops = {* * \*****************************************************************************/ -static void sdhci_tasklet_card (unsigned long param) -{ -struct sdhci_host *host = (struct sdhci_host *)param; - -sdhci_card_event (host->mmc); - -mmc_detect_change (host->mmc,msecs_to_jiffies (200 )); -} -static void sdhci_tasklet_finish (unsigned long param) {struct sdhci_host *host;
@@ -2472,7 +2463,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)sdhci_writel (host, intmask & (SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE ),SDHCI_INT_STATUS ); -tasklet_schedule (&host->card_tasklet); + + host->thread_isr |= intmask & (SDHCI_INT_CARD_INSERT | +SDHCI_INT_CARD_REMOVE ); + result =IRQ_WAKE_THREAD ; }if (intmask &SDHCI_INT_CMD_MASK )
@@ -2529,6 +2523,11 @@ static irqreturn_t sdhci_thread_irq(int irq, void *dev_id) host->thread_isr =0 ;spin_unlock_irqrestore (&host->lock, flags); +if (isr & (SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE )) { +sdhci_card_event (host->mmc); +mmc_detect_change (host->mmc,msecs_to_jiffies (200 )); + } +if (isr &SDHCI_INT_CARD_INT ) {sdio_run_irqs (host->mmc);
@@ -3219,8 +3218,6 @@ int sdhci_add_host(struct sdhci_host *host)/* * Init tasklets. */ -tasklet_init (&host->card_tasklet, - sdhci_tasklet_card, (unsigned long )host);tasklet_init (&host->finish_tasklet, sdhci_tasklet_finish, (unsigned long )host);
@@ -3285,7 +3282,6 @@ int sdhci_add_host(struct sdhci_host *host)free_irq (host->irq, host);#endif untasklet: -tasklet_kill (&host->card_tasklet);tasklet_kill (&host->finish_tasklet);return ret;
@@ -3329,7 +3325,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)del_timer_sync (&host->timer); -tasklet_kill (&host->card_tasklet);tasklet_kill (&host->finish_tasklet);if (host->vmmc) {
include/linux/mmc/sdhci.h +1 -2
@@ -164,8 +164,7 @@ struct sdhci_host {dma_addr_t adma_addr;/* Mapped ADMA descr. table */ dma_addr_t align_addr;/* Mapped bounce buffer */ -struct tasklet_struct card_tasklet;/* Tasklet structures */ -struct tasklet_struct finish_tasklet; +struct tasklet_struct finish_tasklet;/* Tasklet structures */ struct timer_list timer;/* Timer for timeouts */
Signature · 1 line
1.8.3.1
PATCH 6/38 mmc: sdhci: allow sdio interrupts while sdhci runtime suspended
In reply to Russell King - ARM LinuxAllow SDIO interrupts to be received while the SDHCI host is runtime suspended. We do this by leaving the AHB clock enabled while the host is runtime suspended so we can access the SDHCI registers, and so read and raise the SDIO card interrupt.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 12 ++++++++---- drivers/mmc/host/sdhci.c | 7 +++---- drivers/mmc/host/sdhci.h | 5 +++++ 3 files changed, 16 insertions(+), 8 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +8 -4
@@ -1170,8 +1170,10 @@ static int sdhci_esdhc_runtime_suspend(struct device *dev) ret =sdhci_runtime_suspend_host (host); -clk_disable_unprepare (imx_data->clk_per); -clk_disable_unprepare (imx_data->clk_ipg); +if (!sdhci_sdio_irq_enabled (host)) { +clk_disable_unprepare (imx_data->clk_per); +clk_disable_unprepare (imx_data->clk_ipg); + }clk_disable_unprepare (imx_data->clk_ahb);return ret;
@@ -1183,8 +1185,10 @@ static int sdhci_esdhc_runtime_resume(struct device *dev)struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);struct pltfm_imx_data *imx_data = pltfm_host->priv; -clk_prepare_enable (imx_data->clk_per); -clk_prepare_enable (imx_data->clk_ipg); +if (!sdhci_sdio_irq_enabled (host)) { +clk_prepare_enable (imx_data->clk_per); +clk_prepare_enable (imx_data->clk_ipg); + }clk_prepare_enable (imx_data->clk_ahb);return sdhci_runtime_resume_host (host);
drivers/mmc/host/sdhci.c +3 -4
@@ -1709,8 +1709,7 @@ static int sdhci_get_ro(struct mmc_host *mmc)static void sdhci_enable_sdio_irq_nolock (struct sdhci_host *host,int enable) { -/* SDIO IRQ will be enabled as appropriate in runtime resume */ -if (!(host->flags &SDHCI_DEVICE_DEAD ) || host->runtime_suspended) { +if (!(host->flags &SDHCI_DEVICE_DEAD )) {if (enable)sdhci_unmask_irqs (host,SDHCI_INT_CARD_INT );else
@@ -2421,7 +2420,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)spin_lock (&host->lock); -if (host->runtime_suspended) { +if (host->runtime_suspended && !sdhci_sdio_irq_enabled (host)) {spin_unlock (&host->lock);return IRQ_NONE ; }
@@ -2687,7 +2686,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) }spin_lock_irqsave (&host->lock, flags); -sdhci_mask_irqs (host,SDHCI_INT_ALL_MASK ); +sdhci_mask_irqs (host,SDHCI_INT_ALL_MASK & ~SDHCI_INT_CARD_INT );spin_unlock_irqrestore (&host->lock, flags);synchronize_hardirq (host->irq);
drivers/mmc/host/sdhci.h +5 -0
@@ -397,6 +397,11 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);extern void sdhci_send_command (struct sdhci_host *host,struct mmc_command *cmd); +static inline bool sdhci_sdio_irq_enabled (struct sdhci_host *host) +{ +return !!(host->flags &SDHCI_SDIO_IRQ_ENABLED ); +} +#ifdef CONFIG_PM extern int sdhci_suspend_host (struct sdhci_host *host);extern int sdhci_resume_host (struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 7/38 mmc: sdhci: more efficient interrupt enable register handling
In reply to Russell King - ARM LinuxRather than wasting cycles read-modify-writing the interrupt enable registers, cache the value locally instead.
--- drivers/mmc/host/sdhci.c | 98 +++++++++++++++++++++++------------------------ include/linux/mmc/sdhci.h | 3 ++ 2 files changed, 50 insertions(+), 51 deletions(-)
drivers/mmc/host/sdhci.c +47 -51
@@ -131,27 +131,6 @@ static void sdhci_dumpregs(struct sdhci_host *host)* * \*****************************************************************************/ -static void sdhci_clear_set_irqs (struct sdhci_host *host,u32 clear,u32 set) -{ -u32 ier; - - ier =sdhci_readl (host,SDHCI_INT_ENABLE ); - ier &= ~clear; - ier |= set; -sdhci_writel (host, ier,SDHCI_INT_ENABLE ); -sdhci_writel (host, ier,SDHCI_SIGNAL_ENABLE ); -} - -static void sdhci_unmask_irqs (struct sdhci_host *host,u32 irqs) -{ -sdhci_clear_set_irqs (host,0 , irqs); -} - -static void sdhci_mask_irqs (struct sdhci_host *host,u32 irqs) -{ -sdhci_clear_set_irqs (host, irqs,0 ); -} -static void sdhci_set_card_detection (struct sdhci_host *host,bool enable) {u32 present, irqs;
@@ -165,9 +144,12 @@ static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) irqs = present ?SDHCI_INT_CARD_REMOVE :SDHCI_INT_CARD_INSERT ;if (enable) -sdhci_unmask_irqs (host, irqs); + host->ier |= irqs;else -sdhci_mask_irqs (host, irqs); + host->ier &= ~irqs; + +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE ); }static void sdhci_enable_card_detection (struct sdhci_host *host)
@@ -183,17 +165,12 @@ static void sdhci_disable_card_detection(struct sdhci_host *host)static void sdhci_reset (struct sdhci_host *host,u8 mask) {unsigned long timeout; -u32 uninitialized_var (ier ); -if (host->quirks &SDHCI_QUIRK_NO_CARD_NO_RESET ) {if (!(sdhci_readl (host,SDHCI_PRESENT_STATE ) &SDHCI_CARD_PRESENT ))return ; } -if (host->quirks &SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET ) - ier =sdhci_readl (host,SDHCI_INT_ENABLE ); -if (host->ops->platform_reset_enter) host->ops->platform_reset_enter (host, mask);
@@ -224,8 +201,10 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)if (host->ops->platform_reset_exit) host->ops->platform_reset_exit (host, mask); -if (host->quirks &SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET ) -sdhci_clear_set_irqs (host,SDHCI_INT_ALL_MASK , ier); +if (host->quirks &SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET ) { +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE ); + }if (host->flags & (SDHCI_USE_SDMA |SDHCI_USE_ADMA )) {if ((host->ops->enable_dma) && (mask &SDHCI_RESET_ALL ))
@@ -242,11 +221,14 @@ static void sdhci_init(struct sdhci_host *host, int soft)else sdhci_reset (host,SDHCI_RESET_ALL ); -sdhci_clear_set_irqs (host,SDHCI_INT_ALL_MASK , -SDHCI_INT_BUS_POWER |SDHCI_INT_DATA_END_BIT | -SDHCI_INT_DATA_CRC |SDHCI_INT_DATA_TIMEOUT |SDHCI_INT_INDEX | -SDHCI_INT_END_BIT |SDHCI_INT_CRC |SDHCI_INT_TIMEOUT | -SDHCI_INT_DATA_END |SDHCI_INT_RESPONSE ); + host->ier =SDHCI_INT_BUS_POWER |SDHCI_INT_DATA_END_BIT | +SDHCI_INT_DATA_CRC |SDHCI_INT_DATA_TIMEOUT | +SDHCI_INT_INDEX |SDHCI_INT_END_BIT |SDHCI_INT_CRC | +SDHCI_INT_TIMEOUT |SDHCI_INT_DATA_END | +SDHCI_INT_RESPONSE ; + +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE );if (soft) {/* force clock reconfiguration */
@@ -721,9 +703,12 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host)u32 dma_irqs =SDHCI_INT_DMA_END |SDHCI_INT_ADMA_ERROR ;if (host->flags &SDHCI_REQ_USE_DMA ) -sdhci_clear_set_irqs (host, pio_irqs, dma_irqs); + host->ier = (host->ier & ~pio_irqs) | dma_irqs;else -sdhci_clear_set_irqs (host, dma_irqs, pio_irqs); + host->ier = (host->ier & ~dma_irqs) | pio_irqs; + +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE ); }static void sdhci_prepare_data (struct sdhci_host *host,struct mmc_command *cmd)
@@ -1711,9 +1696,12 @@ static void sdhci_enable_sdio_irq_nolock(struct sdhci_host *host, int enable) {if (!(host->flags &SDHCI_DEVICE_DEAD )) {if (enable) -sdhci_unmask_irqs (host,SDHCI_INT_CARD_INT ); + host->ier |=SDHCI_INT_CARD_INT ;else -sdhci_mask_irqs (host,SDHCI_INT_CARD_INT ); + host->ier &= ~SDHCI_INT_CARD_INT ; + +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE );mmiowb (); } }
@@ -1855,7 +1843,6 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) {struct sdhci_host *host;u16 ctrl; -u32 ier;int tuning_loop_counter =MAX_TUNING_LOOP ;unsigned long timeout;int err =0 ;
@@ -1909,8 +1896,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)* to make sure we don't hit a controller bug, we _only_ * enable Buffer Read Ready interrupt here. */ - ier =sdhci_readl (host,SDHCI_INT_ENABLE ); -sdhci_clear_set_irqs (host, ier,SDHCI_INT_DATA_AVAIL ); +sdhci_writel (host,SDHCI_INT_DATA_AVAIL ,SDHCI_INT_ENABLE ); +sdhci_writel (host,SDHCI_INT_DATA_AVAIL ,SDHCI_SIGNAL_ENABLE );/* * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number
@@ -2042,7 +2029,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)if (err && (host->flags &SDHCI_USING_RETUNING_TIMER )) err =0 ; -sdhci_clear_set_irqs (host,SDHCI_INT_DATA_AVAIL , ier); +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE );spin_unlock_irqrestore (&host->lock, flags);sdhci_runtime_pm_put (host);
@@ -2455,10 +2443,12 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)* More testing are needed here to ensure it works * for other platforms though. */ -sdhci_mask_irqs (host, present ?SDHCI_INT_CARD_INSERT : -SDHCI_INT_CARD_REMOVE ); -sdhci_unmask_irqs (host, present ?SDHCI_INT_CARD_REMOVE : -SDHCI_INT_CARD_INSERT ); + host->ier &= ~(SDHCI_INT_CARD_INSERT | +SDHCI_INT_CARD_REMOVE ); + host->ier |= present ?SDHCI_INT_CARD_REMOVE : +SDHCI_INT_CARD_INSERT ; +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE );sdhci_writel (host, intmask & (SDHCI_INT_CARD_INSERT |SDHCI_INT_CARD_REMOVE ),SDHCI_INT_STATUS );
@@ -2587,7 +2577,9 @@ int sdhci_suspend_host(struct sdhci_host *host) }if (!device_may_wakeup (mmc_dev (host->mmc))) { -sdhci_mask_irqs (host,SDHCI_INT_ALL_MASK ); + host->ier =0 ; +sdhci_writel (host,0 ,SDHCI_INT_ENABLE ); +sdhci_writel (host,0 ,SDHCI_SIGNAL_ENABLE );free_irq (host->irq, host); }else {sdhci_enable_irq_wakeups (host);
@@ -2686,7 +2678,9 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host) }spin_lock_irqsave (&host->lock, flags); -sdhci_mask_irqs (host,SDHCI_INT_ALL_MASK & ~SDHCI_INT_CARD_INT ); + host->ier &=SDHCI_INT_CARD_INT ; +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE );spin_unlock_irqrestore (&host->lock, flags);synchronize_hardirq (host->irq);
@@ -3277,7 +3271,8 @@ int sdhci_add_host(struct sdhci_host *host)#ifdef SDHCI_USE_LEDS_CLASS reset:sdhci_reset (host,SDHCI_RESET_ALL ); -sdhci_mask_irqs (host,SDHCI_INT_ALL_MASK ); +sdhci_writel (host,0 ,SDHCI_INT_ENABLE ); +sdhci_writel (host,0 ,SDHCI_SIGNAL_ENABLE );free_irq (host->irq, host);#endif untasklet:
@@ -3319,7 +3314,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)if (!dead)sdhci_reset (host,SDHCI_RESET_ALL ); -sdhci_mask_irqs (host,SDHCI_INT_ALL_MASK ); +sdhci_writel (host,0 ,SDHCI_INT_ENABLE ); +sdhci_writel (host,0 ,SDHCI_SIGNAL_ENABLE );free_irq (host->irq, host);del_timer_sync (&host->timer);
include/linux/mmc/sdhci.h +3 -0
@@ -178,6 +178,9 @@ struct sdhci_host {u32 thread_isr; +/* cached registers */ +u32 ier; +wait_queue_head_t buf_ready_int;/* Waitqueue for Buffer Read Ready interrupt */ unsigned int tuning_done;/* Condition flag set when CMD19 succeeds */
Signature · 1 line
1.8.3.1
PATCH 8/38 mmc: sdhci: plug hole in disabling card detection interrupts
In reply to Russell King - ARM LinuxWhen we disable card detection interrupts, we should disable both the insert and remove interrupts irrespective of the current state - this avoids races between the hardware card detect changing state before we've read that updated state and altered the interrupt mask.
--- drivers/mmc/host/sdhci.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-)
drivers/mmc/host/sdhci.c +9 -8
@@ -133,20 +133,21 @@ static void sdhci_dumpregs(struct sdhci_host *host)static void sdhci_set_card_detection (struct sdhci_host *host,bool enable) { -u32 present, irqs; +u32 present;if ((host->quirks &SDHCI_QUIRK_BROKEN_CARD_DETECTION ) || (host->mmc->caps &MMC_CAP_NONREMOVABLE ))return ; - present =sdhci_readl (host,SDHCI_PRESENT_STATE ) & -SDHCI_CARD_PRESENT ; - irqs = present ?SDHCI_INT_CARD_REMOVE :SDHCI_INT_CARD_INSERT ; +if (enable) { + present =sdhci_readl (host,SDHCI_PRESENT_STATE ) & +SDHCI_CARD_PRESENT ; -if (enable) - host->ier |= irqs; -else - host->ier &= ~irqs; + host->ier |= present ?SDHCI_INT_CARD_REMOVE : +SDHCI_INT_CARD_INSERT ; + }else { + host->ier &= ~(SDHCI_INT_CARD_REMOVE |SDHCI_INT_CARD_INSERT ); + }sdhci_writel (host, host->ier,SDHCI_INT_ENABLE );sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE );
Signature · 1 line
1.8.3.1
PATCH 9/38 mmc: sdhci: convert generic bus width setup to library function
In reply to Russell King - ARM Linux--- drivers/mmc/host/sdhci-acpi.c | 2 ++ drivers/mmc/host/sdhci-bcm-kona.c | 1 + drivers/mmc/host/sdhci-bcm2835.c | 1 + drivers/mmc/host/sdhci-cns3xxx.c | 1 + drivers/mmc/host/sdhci-dove.c | 1 + drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++--- drivers/mmc/host/sdhci-of-arasan.c | 1 + drivers/mmc/host/sdhci-of-esdhc.c | 6 ++--- drivers/mmc/host/sdhci-of-hlwd.c | 1 + drivers/mmc/host/sdhci-pci.c | 6 ++--- drivers/mmc/host/sdhci-pltfm.c | 1 + drivers/mmc/host/sdhci-pxav2.c | 6 ++--- drivers/mmc/host/sdhci-pxav3.c | 1 + drivers/mmc/host/sdhci-s3c.c | 8 +++---- drivers/mmc/host/sdhci-sirf.c | 1 + drivers/mmc/host/sdhci-spear.c | 2 +- drivers/mmc/host/sdhci-tegra.c | 5 ++--- drivers/mmc/host/sdhci.c | 45 +++++++++++++++++++------------------- drivers/mmc/host/sdhci.h | 5 +++-- 19 files changed, 50 insertions(+), 50 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
@@ -103,10 +103,12 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)static const struct sdhci_ops sdhci_acpi_ops_dflt = { .enable_dma = sdhci_acpi_enable_dma, + .set_bus_width = sdhci_set_bus_width, };static const struct sdhci_ops sdhci_acpi_ops_int = { .enable_dma = sdhci_acpi_enable_dma, + .set_bus_width = sdhci_set_bus_width, .hw_reset = sdhci_acpi_int_hw_reset, };
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
@@ -209,6 +209,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = { .get_max_clock = sdhci_bcm_kona_get_max_clk, .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, + .set_bus_width = sdhci_set_bus_width, .card_event = sdhci_bcm_kona_card_event, };
drivers/mmc/host/sdhci-bcm2835.c +1 -0
@@ -133,6 +133,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = { .read_b = bcm2835_sdhci_readb, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_min_clock = bcm2835_sdhci_get_min_clock, + .set_bus_width = sdhci_set_bus_width, };static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
@@ -82,6 +82,7 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)static const struct sdhci_ops sdhci_cns3xxx_ops = { .get_max_clock = sdhci_cns3xxx_get_max_clk, .set_clock = sdhci_cns3xxx_set_clock, + .set_bus_width = sdhci_set_bus_width, };static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
@@ -86,6 +86,7 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)static const struct sdhci_ops sdhci_dove_ops = { .read_w = sdhci_dove_readw, .read_l = sdhci_dove_readl, + .set_bus_width = sdhci_set_bus_width, };static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-esdhc-imx.c +2 -4
@@ -668,7 +668,7 @@ static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)return -ENOSYS ; } -static int esdhc_pltfm_bus_width (struct sdhci_host *host,int width) +static void esdhc_pltfm_set_bus_width (struct sdhci_host *host,int width) {u32 ctrl;
@@ -686,8 +686,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)esdhc_clrset_le (host,ESDHC_CTRL_BUSWIDTH_MASK , ctrl,SDHCI_HOST_CONTROL ); - -return 0 ; }static void esdhc_prepare_tuning (struct sdhci_host *host,u32 val)
@@ -888,7 +886,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { .get_max_clock = esdhc_pltfm_get_max_clock, .get_min_clock = esdhc_pltfm_get_min_clock, .get_ro = esdhc_pltfm_get_ro, - .platform_bus_width = esdhc_pltfm_bus_width, + .set_bus_width = esdhc_pltfm_set_bus_width, .set_uhs_signaling = esdhc_set_uhs_signaling, };
drivers/mmc/host/sdhci-of-arasan.c +1 -0
@@ -54,6 +54,7 @@ static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host)static struct sdhci_ops sdhci_arasan_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_timeout_clock = sdhci_arasan_get_timeout_clock, + .set_bus_width = sdhci_set_bus_width, };static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +2 -4
@@ -269,7 +269,7 @@ static void esdhc_of_platform_init(struct sdhci_host *host) host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ ; } -static int esdhc_pltfm_bus_width (struct sdhci_host *host,int width) +static void esdhc_pltfm_set_bus_width (struct sdhci_host *host,int width) {u32 ctrl;
@@ -289,8 +289,6 @@ static int esdhc_pltfm_bus_width(struct sdhci_host *host, int width)clrsetbits_be32 (host->ioaddr +SDHCI_HOST_CONTROL ,ESDHC_CTRL_BUSWIDTH_MASK , ctrl); - -return 0 ; }static const struct sdhci_ops sdhci_esdhc_ops = {
@@ -310,7 +308,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .platform_resume = esdhc_of_resume, #endif .adma_workaround = esdhci_of_adma_workaround, - .platform_bus_width = esdhc_pltfm_bus_width, + .set_bus_width = esdhc_pltfm_set_bus_width, }; static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
@@ -58,6 +58,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = { .write_l = sdhci_hlwd_writel, .write_w = sdhci_hlwd_writew, .write_b = sdhci_hlwd_writeb, + .set_bus_width = sdhci_set_bus_width, };static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +2 -4
@@ -1031,7 +1031,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host)return 0 ; } -static int sdhci_pci_bus_width (struct sdhci_host *host,int width) +static void sdhci_pci_set_bus_width (struct sdhci_host *host,int width) {u8 ctrl;
@@ -1052,8 +1052,6 @@ static int sdhci_pci_bus_width(struct sdhci_host *host, int width) }sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL ); - -return 0 ; }static void sdhci_pci_gpio_hw_reset (struct sdhci_host *host)
@@ -1081,7 +1079,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)static const struct sdhci_ops sdhci_pci_ops = { .enable_dma = sdhci_pci_enable_dma, - .platform_bus_width = sdhci_pci_bus_width, + .set_bus_width = sdhci_pci_set_bus_width, .hw_reset = sdhci_pci_hw_reset, };
drivers/mmc/host/sdhci-pltfm.c +1 -0
@@ -45,6 +45,7 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)EXPORT_SYMBOL_GPL (sdhci_pltfm_clk_get_max_clock);static const struct sdhci_ops sdhci_pltfm_ops = { + .set_bus_width = sdhci_set_bus_width, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +2 -4
@@ -88,7 +88,7 @@ static void pxav2_set_private_registers(struct sdhci_host *host, u8 mask) } } -static int pxav2_mmc_set_width (struct sdhci_host *host,int width) +static void pxav2_mmc_set_bus_width (struct sdhci_host *host,int width) {u8 ctrl;u16 tmp;
@@ -107,14 +107,12 @@ static int pxav2_mmc_set_width(struct sdhci_host *host, int width) }writew (tmp, host->ioaddr +SD_CE_ATA_2 );writeb (ctrl, host->ioaddr +SDHCI_HOST_CONTROL ); - -return 0 ; }static const struct sdhci_ops pxav2_sdhci_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .platform_reset_exit = pxav2_set_private_registers, - .platform_bus_width = pxav2_mmc_set_width, + .set_bus_width = pxav2_mmc_set_bus_width, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +1 -0
@@ -227,6 +227,7 @@ static const struct sdhci_ops pxav3_sdhci_ops = { .set_uhs_signaling = pxav3_set_uhs_signaling, .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .set_bus_width = sdhci_set_bus_width, };static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +3 -5
@@ -329,14 +329,14 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) }/** -* sdhci_s3c_platform_bus_width - support 8bit buswidth +* sdhci_s3c_set_bus_width - support 8bit buswidth * @host: The SDHCI host being queried * @width: MMC_BUS_WIDTH_ macro for the bus width being requested * * We have 8-bit width support but is not a v3 controller. * So we add platform_bus_width() and support 8bit width. */ -static int sdhci_s3c_platform_bus_width (struct sdhci_host *host,int width) +static void sdhci_s3c_set_bus_width (struct sdhci_host *host,int width) {u8 ctrl;
@@ -358,15 +358,13 @@ static int sdhci_s3c_platform_bus_width(struct sdhci_host *host, int width) }sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL ); - -return 0 ; }static struct sdhci_ops sdhci_s3c_ops = { .get_max_clock = sdhci_s3c_get_max_clk, .set_clock = sdhci_s3c_set_clock, .get_min_clock = sdhci_s3c_get_min_clock, - .platform_bus_width = sdhci_s3c_platform_bus_width, + .set_bus_width = sdhci_s3c_set_bus_width, };static void sdhci_s3c_notify_change (struct platform_device *dev,int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
@@ -29,6 +29,7 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)static struct sdhci_ops sdhci_sirf_ops = { .get_max_clock = sdhci_sirf_get_max_clk, + .set_bus_width = sdhci_set_bus_width, };static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -1
@@ -38,7 +38,7 @@ struct spear_sdhci {/* sdhci ops */ static const struct sdhci_ops sdhci_pltfm_ops = { -/* Nothing to do for now. */ + .set_bus_width = sdhci_set_bus_width, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +2 -3
@@ -127,7 +127,7 @@ static void tegra_sdhci_reset_exit(struct sdhci_host *host, u8 mask) } } -static int tegra_sdhci_buswidth (struct sdhci_host *host,int bus_width) +static void tegra_sdhci_set_bus_width (struct sdhci_host *host,int bus_width) {u32 ctrl;
@@ -144,7 +144,6 @@ static int tegra_sdhci_buswidth(struct sdhci_host *host, int bus_width) ctrl &= ~SDHCI_CTRL_4BITBUS ; }sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL ); -return 0 ; }static const struct sdhci_ops tegra_sdhci_ops = {
@@ -152,7 +151,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { .read_l = tegra_sdhci_readl, .read_w = tegra_sdhci_readw, .write_l = tegra_sdhci_writel, - .platform_bus_width = tegra_sdhci_buswidth, + .set_bus_width = tegra_sdhci_set_bus_width, .platform_reset_exit = tegra_sdhci_reset_exit, };
drivers/mmc/host/sdhci.c +22 -23
57 lines not on this page · raw message
drivers/mmc/host/sdhci.h +3 -2
@@ -281,8 +281,7 @@ struct sdhci_ops {unsigned int (*get_max_clock)(struct sdhci_host *host);unsigned int (*get_min_clock)(struct sdhci_host *host);unsigned int (*get_timeout_clock)(struct sdhci_host *host); -int (*platform_bus_width)(struct sdhci_host *host, -int width); +void (*set_bus_width)(struct sdhci_host *host,int width);void (*platform_send_init_74_clocks)(struct sdhci_host *host,u8 power_mode);unsigned int (*get_ro)(struct sdhci_host *host);
@@ -402,6 +401,8 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)return !!(host->flags &SDHCI_SDIO_IRQ_ENABLED ); } +void sdhci_set_bus_width (struct sdhci_host *host,int width); +#ifdef CONFIG_PM extern int sdhci_suspend_host (struct sdhci_host *host);extern int sdhci_resume_host (struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 10/38 mmc: sdhci: convert reset into a library function
In reply to Russell King - ARM LinuxRather than having platform_reset_enter/platform_reset_exit methods, turn the core of the reset handling into a library function which platforms can call at the appropriate moment in their (new) reset method.
--- drivers/mmc/host/sdhci-acpi.c | 2 ++ drivers/mmc/host/sdhci-bcm-kona.c | 1 + drivers/mmc/host/sdhci-bcm2835.c | 1 + drivers/mmc/host/sdhci-cns3xxx.c | 1 + drivers/mmc/host/sdhci-dove.c | 1 + drivers/mmc/host/sdhci-esdhc-imx.c | 1 + drivers/mmc/host/sdhci-of-arasan.c | 1 + drivers/mmc/host/sdhci-of-esdhc.c | 1 + drivers/mmc/host/sdhci-of-hlwd.c | 1 + drivers/mmc/host/sdhci-pci.c | 1 + drivers/mmc/host/sdhci-pltfm.c | 1 + drivers/mmc/host/sdhci-pxav2.c | 6 +++-- drivers/mmc/host/sdhci-pxav3.c | 6 +++-- drivers/mmc/host/sdhci-s3c.c | 1 + drivers/mmc/host/sdhci-sirf.c | 1 + drivers/mmc/host/sdhci-spear.c | 1 + drivers/mmc/host/sdhci-tegra.c | 6 +++-- drivers/mmc/host/sdhci.c | 47 +++++++++++++++++++------------------- drivers/mmc/host/sdhci.h | 4 ++-- 19 files changed, 53 insertions(+), 31 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
@@ -104,11 +104,13 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host)static const struct sdhci_ops sdhci_acpi_ops_dflt = { .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };static const struct sdhci_ops sdhci_acpi_ops_int = { .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, .hw_reset = sdhci_acpi_int_hw_reset, };
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
@@ -210,6 +210,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = { .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, .card_event = sdhci_bcm_kona_card_event, };
drivers/mmc/host/sdhci-bcm2835.c +1 -0
@@ -134,6 +134,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_min_clock = bcm2835_sdhci_get_min_clock, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
@@ -83,6 +83,7 @@ static const struct sdhci_ops sdhci_cns3xxx_ops = { .get_max_clock = sdhci_cns3xxx_get_max_clk, .set_clock = sdhci_cns3xxx_set_clock, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
@@ -87,6 +87,7 @@ static const struct sdhci_ops sdhci_dove_ops = { .read_w = sdhci_dove_readw, .read_l = sdhci_dove_readl, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-esdhc-imx.c +1 -0
@@ -888,6 +888,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { .get_ro = esdhc_pltfm_get_ro, .set_bus_width = esdhc_pltfm_set_bus_width, .set_uhs_signaling = esdhc_set_uhs_signaling, + .reset = sdhci_reset, };static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
drivers/mmc/host/sdhci-of-arasan.c +1 -0
@@ -55,6 +55,7 @@ static struct sdhci_ops sdhci_arasan_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_timeout_clock = sdhci_arasan_get_timeout_clock, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +1 -0
@@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = {#endif .adma_workaround = esdhci_of_adma_workaround, .set_bus_width = esdhc_pltfm_set_bus_width, + .reset = sdhci_reset, };static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
@@ -59,6 +59,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = { .write_w = sdhci_hlwd_writew, .write_b = sdhci_hlwd_writeb, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +1 -0
@@ -1080,6 +1080,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host)static const struct sdhci_ops sdhci_pci_ops = { .enable_dma = sdhci_pci_enable_dma, .set_bus_width = sdhci_pci_set_bus_width, + .reset = sdhci_reset, .hw_reset = sdhci_pci_hw_reset, };
drivers/mmc/host/sdhci-pltfm.c +1 -0
@@ -46,6 +46,7 @@ EXPORT_SYMBOL_GPL(sdhci_pltfm_clk_get_max_clock);static const struct sdhci_ops sdhci_pltfm_ops = { .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +4 -2
@@ -51,11 +51,13 @@#define MMC_CARD 0x1000#define MMC_WIDTH 0x0100 -static void pxav2_set_private_registers (struct sdhci_host *host,u8 mask) +static void pxav2_reset (struct sdhci_host *host,u8 mask) {struct platform_device *pdev =to_platform_device (mmc_dev (host->mmc));struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; +sdhci_reset (host, mask); +if (mask ==SDHCI_RESET_ALL ) {u16 tmp =0 ;
@@ -111,8 +113,8 @@ static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width)static const struct sdhci_ops pxav2_sdhci_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, - .platform_reset_exit = pxav2_set_private_registers, .set_bus_width = pxav2_mmc_set_bus_width, + .reset = pxav2_reset, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +4 -2
@@ -112,11 +112,13 @@ static int mv_conf_mbus_windows(struct platform_device *pdev,return 0 ; } -static void pxav3_set_private_registers (struct sdhci_host *host,u8 mask) +static void pxav3_reset (struct sdhci_host *host,u8 mask) {struct platform_device *pdev =to_platform_device (mmc_dev (host->mmc));struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data; +sdhci_reset (host, mask); +if (mask ==SDHCI_RESET_ALL ) {/* * tune timing of read data/command when crc error happen
@@ -223,11 +225,11 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) }static const struct sdhci_ops pxav3_sdhci_ops = { - .platform_reset_exit = pxav3_set_private_registers, .set_uhs_signaling = pxav3_set_uhs_signaling, .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .set_bus_width = sdhci_set_bus_width, + .reset = pxav3_reset, };static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +1 -0
@@ -365,6 +365,7 @@ static struct sdhci_ops sdhci_s3c_ops = { .set_clock = sdhci_s3c_set_clock, .get_min_clock = sdhci_s3c_get_min_clock, .set_bus_width = sdhci_s3c_set_bus_width, + .reset = sdhci_reset, };static void sdhci_s3c_notify_change (struct platform_device *dev,int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
@@ -30,6 +30,7 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host)static struct sdhci_ops sdhci_sirf_ops = { .get_max_clock = sdhci_sirf_get_max_clk, .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -0
@@ -39,6 +39,7 @@ struct spear_sdhci {/* sdhci ops */ static const struct sdhci_ops sdhci_pltfm_ops = { .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +4 -2
@@ -108,12 +108,14 @@ static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host)return mmc_gpio_get_ro (host->mmc); } -static void tegra_sdhci_reset_exit (struct sdhci_host *host,u8 mask) +static void tegra_sdhci_reset (struct sdhci_host *host,u8 mask) {struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);struct sdhci_tegra *tegra_host = pltfm_host->priv;const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; +sdhci_reset (host, mask); +if (!(mask &SDHCI_RESET_ALL ))return ;
@@ -152,7 +154,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { .read_w = tegra_sdhci_readw, .write_l = tegra_sdhci_writel, .set_bus_width = tegra_sdhci_set_bus_width, - .platform_reset_exit = tegra_sdhci_reset_exit, + .reset = tegra_sdhci_reset, };static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
drivers/mmc/host/sdhci.c +24 -23
111 lines not on this page · raw message
drivers/mmc/host/sdhci.h +2 -2
@@ -285,8 +285,7 @@ struct sdhci_ops {void (*platform_send_init_74_clocks)(struct sdhci_host *host,u8 power_mode);unsigned int (*get_ro)(struct sdhci_host *host); -void (*platform_reset_enter)(struct sdhci_host *host,u8 mask); -void (*platform_reset_exit)(struct sdhci_host *host,u8 mask); +void (*reset)(struct sdhci_host *host,u8 mask);int (*platform_execute_tuning)(struct sdhci_host *host,u32 opcode);int (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs);void (*hw_reset)(struct sdhci_host *host);
@@ -402,6 +401,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host) }void sdhci_set_bus_width (struct sdhci_host *host,int width); +void sdhci_reset (struct sdhci_host *host,u8 mask);#ifdef CONFIG_PM extern int sdhci_suspend_host (struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 11/38 mmc: sdhci: move FSL ESDHC reset handling quirk into esdhc code
In reply to Russell King - ARM LinuxThe Freescale esdhc driver is the only driver which needs the interrupt registers restored after a reset. Move this quirk to be part of the ESDHC driver implementation.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 10 +++++++++- drivers/mmc/host/sdhci-esdhc.h | 3 +-- drivers/mmc/host/sdhci.c | 5 ----- include/linux/mmc/sdhci.h | 2 -- 4 files changed, 10 insertions(+), 10 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +9 -1
@@ -876,6 +876,14 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)return esdhc_change_pinstate (host, uhs); } +static void esdhc_reset (struct sdhci_host *host,u8 mask) +{ +sdhci_reset (host, mask); + +sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); +sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE ); +} +static struct sdhci_ops sdhci_esdhc_ops = { .read_l = esdhc_readl_le, .read_w = esdhc_readw_le,
@@ -888,7 +896,7 @@ static struct sdhci_ops sdhci_esdhc_ops = { .get_ro = esdhc_pltfm_get_ro, .set_bus_width = esdhc_pltfm_set_bus_width, .set_uhs_signaling = esdhc_set_uhs_signaling, - .reset = sdhci_reset, + .reset = esdhc_reset, };static const struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
drivers/mmc/host/sdhci-esdhc.h +1 -2
@@ -22,8 +22,7 @@ SDHCI_QUIRK_NO_BUSY_IRQ | \ SDHCI_QUIRK_NONSTANDARD_CLOCK | \ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ - SDHCI_QUIRK_PIO_NEEDS_DELAY | \ - SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) + SDHCI_QUIRK_PIO_NEEDS_DELAY)#define ESDHC_SYSTEM_CONTROL 0x2c#define ESDHC_CLOCK_MASK 0x0000fff0
drivers/mmc/host/sdhci.c +0 -5
@@ -203,11 +203,6 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) host->ops->reset (host, mask); -if (host->quirks &SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET ) { -sdhci_writel (host, host->ier,SDHCI_INT_ENABLE ); -sdhci_writel (host, host->ier,SDHCI_SIGNAL_ENABLE ); - } -if (host->flags & (SDHCI_USE_SDMA |SDHCI_USE_ADMA )) {if ((host->ops->enable_dma) && (mask &SDHCI_RESET_ALL )) host->ops->enable_dma (host);
include/linux/mmc/sdhci.h +0 -2
@@ -61,8 +61,6 @@ struct sdhci_host {#define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17)/* Controller does not like fast PIO transfers */ #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) -/* Controller losing signal/interrupt enable states after reset */ -#define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19)/* Controller has to be forced to use block size of 2048 bytes */ #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20)/* Controller cannot do multi-block transfers */
Signature · 1 line
1.8.3.1
PATCH 12/38 mmc: sdhci: avoid sync'ing the SG if there's no misalignment
In reply to Russell King - ARM LinuxOn read, we don't need to sync the whole scatterlist and then check whether any segments need copying - if we check first, we avoid potentially expensive cache handling.
--- drivers/mmc/host/sdhci.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/mmc/host/sdhci.c +10 -1
@@ -602,6 +602,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host,u8 *align;char *buffer;unsigned long flags; +bool has_unaligned;if (data->flags &MMC_DATA_READ ) direction =DMA_FROM_DEVICE ;
@@ -614,7 +615,15 @@ static void sdhci_adma_table_post(struct sdhci_host *host,dma_unmap_single (mmc_dev (host->mmc), host->align_addr,128 *4 , direction); -if (data->flags &MMC_DATA_READ ) { +/* Do a quick scan of the SG list for any unaligned mappings */ + has_unaligned = false; +for_each_sg (data->sg, sg, host->sg_count, i) +if (sg_dma_address (sg) &3 ) { + has_unaligned = true; +break ; + } + +if (has_unaligned && data->flags &MMC_DATA_READ ) {dma_sync_sg_for_cpu (mmc_dev (host->mmc), data->sg, data->sg_len, direction);
Signature · 1 line
1.8.3.1
PATCH 13/38 mmc: sdhci: convert ADMA descriptors to a coherent allocation
In reply to Russell King - ARM LinuxRather than using the streaming API, use the coherent allocator to provide this memory, thereby eliminating cache flushing of it each time we map and unmap it. This results in a 7.5% increase in transfer speed with a UHS-1 card operating in 3.3v mode at a clock of 49.5MHz.
--- drivers/mmc/host/sdhci.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-)
drivers/mmc/host/sdhci.c +22 -21
@@ -44,6 +44,8 @@#define MAX_TUNING_LOOP 40 +#define ADMA_SIZE ((128 * 2 + 1) * 4) +static unsigned int debug_quirks =0 ;static unsigned int debug_quirks2;
@@ -481,11 +483,6 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,else direction =DMA_TO_DEVICE ; -/* -* The ADMA descriptor table is mapped further down as we -* need to fill it with data first. -*/ - host->align_addr =dma_map_single (mmc_dev (host->mmc), host->align_buffer,128 *4 , direction);if (dma_mapping_error (mmc_dev (host->mmc), host->align_addr))
@@ -546,7 +543,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,* If this triggers then we have a calculation bug * somewhere. :/ */ -WARN_ON ((desc - host->adma_desc) > (128 *2 +1 ) *4 ); +WARN_ON ((desc - host->adma_desc) >ADMA_SIZE ); }if (host->quirks &SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC ) {
@@ -574,17 +571,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, host->align_addr, 128 * 4, direction); } - host->adma_addr =dma_map_single (mmc_dev (host->mmc), - host->adma_desc, (128 *2 +1 ) *4 ,DMA_TO_DEVICE ); -if (dma_mapping_error (mmc_dev (host->mmc), host->adma_addr)) - goto unmap_entries; -BUG_ON (host->adma_addr &0x3 ); -return 0 ; -unmap_entries: -dma_unmap_sg (mmc_dev (host->mmc), data->sg, - data->sg_len, direction); unmap_align:dma_unmap_single (mmc_dev (host->mmc), host->align_addr,128 *4 , direction);
@@ -609,9 +597,6 @@ static void sdhci_adma_table_post(struct sdhci_host *host,else direction =DMA_TO_DEVICE ; -dma_unmap_single (mmc_dev (host->mmc), host->adma_addr, - (128 *2 +1 ) *4 ,DMA_TO_DEVICE ); -dma_unmap_single (mmc_dev (host->mmc), host->align_addr,128 *4 , direction);
@@ -2851,15 +2836,29 @@ int sdhci_add_host(struct sdhci_host *host)* (128) and potentially one alignment transfer for * each of those entries. */ - host->adma_desc =kmalloc ((128 *2 +1 ) *4 ,GFP_KERNEL ); + host->adma_desc =dma_alloc_coherent (mmc_dev (host->mmc), +ADMA_SIZE , &host->adma_addr, +GFP_KERNEL ); host->align_buffer =kmalloc (128 *4 ,GFP_KERNEL );if (!host->adma_desc || !host->align_buffer) { -kfree (host->adma_desc); +dma_free_coherent (mmc_dev (host->mmc),ADMA_SIZE , + host->adma_desc, host->adma_addr);kfree (host->align_buffer);pr_warning ("%s: Unable to allocate ADMA " "buffers. Falling back to standard DMA.\n" ,mmc_hostname (mmc)); host->flags &= ~SDHCI_USE_ADMA ; + host->adma_desc =NULL ; + host->align_buffer =NULL ; + }else if (host->adma_addr &3 ) { +pr_warning ("%s: unable to allocate aligned ADMA descriptor\n" , +mmc_hostname (mmc)); + host->flags &= ~SDHCI_USE_ADMA ; +dma_free_coherent (mmc_dev (host->mmc),ADMA_SIZE , + host->adma_desc, host->adma_addr); +kfree (host->align_buffer); + host->adma_desc =NULL ; + host->align_buffer =NULL ; } }
@@ -3337,7 +3336,9 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)regulator_put (host->vqmmc); } -kfree (host->adma_desc); +if (host->adma_desc) +dma_free_coherent (mmc_dev (host->mmc),ADMA_SIZE , + host->adma_desc, host->adma_addr);kfree (host->align_buffer); host->adma_desc =NULL ;
Signature · 1 line
1.8.3.1
PATCH 14/38 mmc: sdhci: clean up sdhci_update_clock()/sdhci_set_clock()
In reply to Russell King - ARM LinuxOnly one caller to sdhci_set_clock() needs to check whether the requested clock frequency was the same as the currently set frequency, yet we work around this in several other sites via sdhci_update_clock(). Rather than doing this, move those checks out into sdhci_do_set_ios(), which then allows sdhci_update_clock() to be eliminated.
--- drivers/mmc/host/sdhci-cns3xxx.c | 3 --- drivers/mmc/host/sdhci.c | 21 +++++---------------- 2 files changed, 5 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-cns3xxx.c +0 -3
@@ -30,9 +30,6 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)u16 clk;unsigned long timeout; -if (clock == host->clock) -return ; -sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL );if (clock ==0 )
drivers/mmc/host/sdhci.c +5 -16
@@ -1119,9 +1119,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)u16 clk =0 ;unsigned long timeout; -if (clock && clock == host->clock) -return ; - host->mmc->actual_clock =0 ;if (host->ops->set_clock) {
@@ -1228,15 +1225,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) host->clock = clock; } -static inline void sdhci_update_clock (struct sdhci_host *host) -{ -unsigned int clock; - - clock = host->clock; - host->clock =0 ; -sdhci_set_clock (host, clock); -} -static int sdhci_set_power (struct sdhci_host *host,unsigned short power) {u8 pwr =0 ;
@@ -1453,7 +1441,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))sdhci_enable_preset_value (host, false); -sdhci_set_clock (host, ios->clock); +if (!ios->clock || ios->clock != host->clock) +sdhci_set_clock (host, ios->clock);if (ios->power_mode ==MMC_POWER_OFF ) vdd_bit =sdhci_set_power (host,-1 );
@@ -1521,7 +1510,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );/* Re-enable SD Clock */ -sdhci_update_clock (host); +sdhci_set_clock (host, host->clock); }
@@ -1565,7 +1554,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) }/* Re-enable SD Clock */ -sdhci_update_clock (host); +sdhci_set_clock (host, host->clock); }else sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );
@@ -2136,7 +2125,7 @@ static void sdhci_tasklet_finish(unsigned long param)/* Some controllers need this kick or reset won't work here */ if (host->quirks &SDHCI_QUIRK_CLOCK_BEFORE_RESET )/* This is to force an update */ -sdhci_update_clock (host); +sdhci_set_clock (host, host->clock);/* Spec says we should do both at the same time, but Ricoh controllers do not like that. */
Signature · 1 line
1.8.3.1
PATCH 15/38 mmc: sdhci: move setting host->clock into sdhci_do_set_ios()
In reply to Russell King - ARM LinuxWe don't need implementations to do this, since the only time it's necessary is when we change the clock, and the only place that happens is in sdhci_do_set_ios(). So, move it there, and remove it from the iMX platform backend.
--- drivers/mmc/host/sdhci-cns3xxx.c | 4 +--- drivers/mmc/host/sdhci-esdhc-imx.c | 4 +--- drivers/mmc/host/sdhci-of-esdhc.c | 4 +--- drivers/mmc/host/sdhci-s3c.c | 3 --- drivers/mmc/host/sdhci.c | 9 ++++----- 5 files changed, 7 insertions(+), 17 deletions(-)
drivers/mmc/host/sdhci-cns3xxx.c +1 -3
@@ -33,7 +33,7 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL );if (clock ==0 ) - goto out; +return ;while (host->max_clk / div > clock) {/*
@@ -72,8 +72,6 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock) clk |=SDHCI_CLOCK_CARD_EN ;sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -out: - host->clock = clock; }static const struct sdhci_ops sdhci_cns3xxx_ops = {
drivers/mmc/host/sdhci-esdhc-imx.c +1 -3
@@ -605,7 +605,7 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,writel (val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON , host->ioaddr +ESDHC_VENDOR_SPEC ); } - goto out; +return ; }if (esdhc_is_usdhc (imx_data) && !imx_data->is_ddr)
@@ -645,8 +645,6 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host, }mdelay (1 ); -out: - host->clock = clock; }static unsigned int esdhc_pltfm_get_ro (struct sdhci_host *host)
drivers/mmc/host/sdhci-of-esdhc.c +1 -3
@@ -205,7 +205,7 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)u32 temp;if (clock ==0 ) - goto out; +return ;/* Workaround to reduce the clock frequency for p1010 esdhc */ if (of_find_compatible_node (NULL ,NULL ,"fsl,p1010-esdhc" )) {
@@ -238,8 +238,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock) | (pre_div << ESDHC_PREDIV_SHIFT));sdhci_writel (host, temp,ESDHC_SYSTEM_CONTROL );mdelay (1 ); -out: - host->clock = clock; }#ifdef CONFIG_PM
drivers/mmc/host/sdhci-s3c.c +0 -3
@@ -298,7 +298,6 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)/* If the clock is going off, set to 0 at clock control register */ if (clock ==0 ) {sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL ); - host->clock = clock;return ; }
@@ -306,8 +305,6 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)clk_set_rate (ourhost->clk_bus[ourhost->cur_clk], clock); - host->clock = clock; - clk =SDHCI_CLOCK_INT_EN ;sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL );
drivers/mmc/host/sdhci.c +4 -5
@@ -1130,7 +1130,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL );if (clock ==0 ) - goto out; +return ;if (host->version >=SDHCI_SPEC_300 ) { if (sdhci_readw(host, SDHCI_HOST_CONTROL2) &
@@ -1220,9 +1220,6 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) clk |=SDHCI_CLOCK_CARD_EN ;sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); - -out: - host->clock = clock; }static int sdhci_set_power (struct sdhci_host *host,unsigned short power)
@@ -1441,8 +1438,10 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN))sdhci_enable_preset_value (host, false); -if (!ios->clock || ios->clock != host->clock) +if (!ios->clock || ios->clock != host->clock) {sdhci_set_clock (host, ios->clock); + host->clock = ios->clock; + }if (ios->power_mode ==MMC_POWER_OFF ) vdd_bit =sdhci_set_power (host,-1 );
Signature · 1 line
1.8.3.1
PATCH 16/38 mmc: sdhci: move setting mmc->actual_clock into set_clock handlers
In reply to Russell King - ARM LinuxMove the setting of mmc->actual_clock to zero into the set_clock handlers themselves. This will allow us to clean up the calling logic for the set_clock() method, and turn sdhci_set_clock() into a library function.
--- drivers/mmc/host/sdhci-cns3xxx.c | 2 ++ drivers/mmc/host/sdhci-esdhc-imx.c | 2 ++ drivers/mmc/host/sdhci-of-esdhc.c | 3 ++- drivers/mmc/host/sdhci-s3c.c | 4 ++++ drivers/mmc/host/sdhci.c | 4 ++-- 5 files changed, 12 insertions(+), 3 deletions(-)
drivers/mmc/host/sdhci-cns3xxx.c +2 -0
@@ -30,6 +30,8 @@ static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)u16 clk;unsigned long timeout; + host->mmc->actual_clock =0 ; +sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL );if (clock ==0 )
drivers/mmc/host/sdhci-esdhc-imx.c +2 -0
@@ -600,6 +600,8 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,u32 temp, val;if (clock ==0 ) { + host->mmc->actual_clock =0 ; +if (esdhc_is_usdhc (imx_data)) { val =readl (host->ioaddr +ESDHC_VENDOR_SPEC ); writel(val & ~ESDHC_VENDOR_SPEC_FRC_SDCLK_ON,
drivers/mmc/host/sdhci-of-esdhc.c +2 -1
@@ -199,11 +199,12 @@ static unsigned int esdhc_of_get_min_clock(struct sdhci_host *host)static void esdhc_of_set_clock (struct sdhci_host *host,unsigned int clock) { -int pre_div =2 ;int div =1 ;u32 temp; + host->mmc->actual_clock =0 ; +if (clock ==0 )return ;
drivers/mmc/host/sdhci-s3c.c +4 -0
@@ -161,6 +161,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)int src;u32 ctrl; + host->mmc->actual_clock =0 ; +/* don't bother if the clock is going off. */ if (clock ==0 )return ;
@@ -295,6 +297,8 @@ static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock)unsigned long timeout;u16 clk =0 ; + host->mmc->actual_clock =0 ; +/* If the clock is going off, set to 0 at clock control register */ if (clock ==0 ) {sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL );
drivers/mmc/host/sdhci.c +2 -2
@@ -1119,14 +1119,14 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)u16 clk =0 ;unsigned long timeout; - host->mmc->actual_clock =0 ; -if (host->ops->set_clock) { host->ops->set_clock (host, clock);if (host->quirks &SDHCI_QUIRK_NONSTANDARD_CLOCK )return ; } + host->mmc->actual_clock =0 ; +sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL );if (clock ==0 )
Signature · 1 line
1.8.3.1
PATCH 17/38 mmc: sdhci: convert sdhci_set_clock() into a library function
In reply to Russell King - ARM Linux--- drivers/mmc/host/sdhci-acpi.c | 2 ++ drivers/mmc/host/sdhci-bcm-kona.c | 1 + drivers/mmc/host/sdhci-bcm2835.c | 1 + drivers/mmc/host/sdhci-cns3xxx.c | 3 +-- drivers/mmc/host/sdhci-dove.c | 1 + drivers/mmc/host/sdhci-esdhc.h | 1 - drivers/mmc/host/sdhci-of-arasan.c | 1 + drivers/mmc/host/sdhci-of-hlwd.c | 1 + drivers/mmc/host/sdhci-pci.c | 1 + drivers/mmc/host/sdhci-pltfm.c | 1 + drivers/mmc/host/sdhci-pxav2.c | 1 + drivers/mmc/host/sdhci-pxav3.c | 1 + drivers/mmc/host/sdhci-s3c.c | 19 ++++++++++++++----- drivers/mmc/host/sdhci-sirf.c | 1 + drivers/mmc/host/sdhci-spear.c | 1 + drivers/mmc/host/sdhci-tegra.c | 1 + drivers/mmc/host/sdhci.c | 17 ++++++----------- drivers/mmc/host/sdhci.h | 1 + include/linux/mmc/sdhci.h | 2 -- 19 files changed, 36 insertions(+), 21 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
@@ -102,12 +102,14 @@ static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) }static const struct sdhci_ops sdhci_acpi_ops_dflt = { + .set_clock = sdhci_set_clock, .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, };static const struct sdhci_ops sdhci_acpi_ops_int = { + .set_clock = sdhci_set_clock, .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset,
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
@@ -206,6 +206,7 @@ static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host, }static struct sdhci_ops sdhci_bcm_kona_ops = { + .set_clock = sdhci_set_clock, .get_max_clock = sdhci_bcm_kona_get_max_clk, .get_timeout_clock = sdhci_bcm_kona_get_timeout_clock, .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
drivers/mmc/host/sdhci-bcm2835.c +1 -0
@@ -131,6 +131,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = { .read_l = bcm2835_sdhci_readl, .read_w = bcm2835_sdhci_readw, .read_b = bcm2835_sdhci_readb, + .set_clock = sdhci_set_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_min_clock = bcm2835_sdhci_get_min_clock, .set_bus_width = sdhci_set_bus_width,
drivers/mmc/host/sdhci-cns3xxx.c +1 -2
@@ -89,8 +89,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |SDHCI_QUIRK_INVERTED_WRITE_PROTECT |SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | -SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | - SDHCI_QUIRK_NONSTANDARD_CLOCK, + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, };static int sdhci_cns3xxx_probe (struct platform_device *pdev)
drivers/mmc/host/sdhci-dove.c +1 -0
@@ -86,6 +86,7 @@ static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)static const struct sdhci_ops sdhci_dove_ops = { .read_w = sdhci_dove_readw, .read_l = sdhci_dove_readl, + .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, };
drivers/mmc/host/sdhci-esdhc.h +0 -1
@@ -20,7 +20,6 @@#define ESDHC_DEFAULT_QUIRKS (SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \ SDHCI_QUIRK_NO_BUSY_IRQ | \ - SDHCI_QUIRK_NONSTANDARD_CLOCK | \ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \ SDHCI_QUIRK_PIO_NEEDS_DELAY)
drivers/mmc/host/sdhci-of-arasan.c +1 -0
@@ -52,6 +52,7 @@ static unsigned int sdhci_arasan_get_timeout_clock(struct sdhci_host *host) }static struct sdhci_ops sdhci_arasan_ops = { + .set_clock = sdhci_set_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .get_timeout_clock = sdhci_arasan_get_timeout_clock, .set_bus_width = sdhci_set_bus_width,
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
@@ -58,6 +58,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = { .write_l = sdhci_hlwd_writel, .write_w = sdhci_hlwd_writew, .write_b = sdhci_hlwd_writeb, + .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, };
drivers/mmc/host/sdhci-pci.c +1 -0
@@ -1078,6 +1078,7 @@ static void sdhci_pci_hw_reset(struct sdhci_host *host) }static const struct sdhci_ops sdhci_pci_ops = { + .set_clock = sdhci_set_clock, .enable_dma = sdhci_pci_enable_dma, .set_bus_width = sdhci_pci_set_bus_width, .reset = sdhci_reset,
drivers/mmc/host/sdhci-pltfm.c +1 -0
@@ -45,6 +45,7 @@ unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host)EXPORT_SYMBOL_GPL (sdhci_pltfm_clk_get_max_clock);static const struct sdhci_ops sdhci_pltfm_ops = { + .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, };
drivers/mmc/host/sdhci-pxav2.c +1 -0
@@ -112,6 +112,7 @@ static void pxav2_mmc_set_bus_width(struct sdhci_host *host, int width) }static const struct sdhci_ops pxav2_sdhci_ops = { + .set_clock = sdhci_set_clock, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .set_bus_width = pxav2_mmc_set_bus_width, .reset = pxav2_reset,
drivers/mmc/host/sdhci-pxav3.c +1 -0
@@ -225,6 +225,7 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs) }static const struct sdhci_ops pxav3_sdhci_ops = { + .set_clock = sdhci_set_clock, .set_uhs_signaling = pxav3_set_uhs_signaling, .platform_send_init_74_clocks = pxav3_gen_init_74_clocks, .get_max_clock = sdhci_pltfm_clk_get_max_clock,
drivers/mmc/host/sdhci-s3c.c +14 -5
@@ -58,6 +58,8 @@ struct sdhci_s3c {struct clk *clk_io;struct clk *clk_bus[MAX_BUS_CLK ];unsigned long clk_rates[MAX_BUS_CLK ]; + +bool no_divider; };/**
@@ -70,6 +72,7 @@ struct sdhci_s3c {*/ struct sdhci_s3c_drv_data {unsigned int sdhci_quirks; +bool no_divider; };static inline struct sdhci_s3c *to_s3c (struct sdhci_host *host)
@@ -119,7 +122,7 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,* If controller uses a non-standard clock division, find the best clock * speed possible with selected clock source and skip the division. */ -if (ourhost->host->quirks &SDHCI_QUIRK_NONSTANDARD_CLOCK ) { +if (ourhost->no_divider) { rate =clk_round_rate (clksrc, wanted);return wanted - rate; }
@@ -164,8 +167,10 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock) host->mmc->actual_clock =0 ;/* don't bother if the clock is going off. */ -if (clock ==0 ) +if (clock ==0 ) { +sdhci_set_clock (host, clock);return ; + }for (src =0 ; src <MAX_BUS_CLK ; src++) { delta =sdhci_s3c_consider_clock (ourhost, src, clock);
@@ -217,6 +222,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)if (clock <25 *1000000 ) ctrl |= (S3C_SDHCI_CTRL3_FCSEL3 |S3C_SDHCI_CTRL3_FCSEL2 );writel (ctrl, host->ioaddr +S3C_SDHCI_CONTROL3 ); + +sdhci_set_clock (host, clock); }/**
@@ -606,8 +613,10 @@ static int sdhci_s3c_probe(struct platform_device *pdev)/* Setup quirks for the controller */ host->quirks |=SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC ; host->quirks |=SDHCI_QUIRK_NO_HISPD_BIT ; -if (drv_data) +if (drv_data) { host->quirks |= drv_data->sdhci_quirks; + sc->no_divider = drv_data->no_divider; + }#ifndef CONFIG_MMC_SDHCI_S3C_DMA
@@ -656,7 +665,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev)* If controller does not have internal clock divider, * we can use overriding functions instead of default. */ -if (host->quirks &SDHCI_QUIRK_NONSTANDARD_CLOCK ) { +if (sc->no_divider) { sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock;
@@ -797,7 +806,7 @@ static const struct dev_pm_ops sdhci_s3c_pmops = {#if defined(CONFIG_CPU_EXYNOS4210 ) || defined(CONFIG_SOC_EXYNOS4212 )static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { - .sdhci_quirks =SDHCI_QUIRK_NONSTANDARD_CLOCK , + .no_divider = true, };#define EXYNOS4_SDHCI_DRV_DATA ((kernel_ulong_t)&exynos4_sdhci_drv_data)#else
drivers/mmc/host/sdhci-sirf.c +1 -0
@@ -28,6 +28,7 @@ static unsigned int sdhci_sirf_get_max_clk(struct sdhci_host *host) }static struct sdhci_ops sdhci_sirf_ops = { + .set_clock = sdhci_set_clock, .get_max_clock = sdhci_sirf_get_max_clk, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset,
drivers/mmc/host/sdhci-spear.c +1 -0
@@ -38,6 +38,7 @@ struct spear_sdhci {/* sdhci ops */ static const struct sdhci_ops sdhci_pltfm_ops = { + .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, };
drivers/mmc/host/sdhci-tegra.c +1 -0
@@ -153,6 +153,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { .read_l = tegra_sdhci_readl, .read_w = tegra_sdhci_readw, .write_l = tegra_sdhci_writel, + .set_clock = sdhci_set_clock, .set_bus_width = tegra_sdhci_set_bus_width, .reset = tegra_sdhci_reset, };
drivers/mmc/host/sdhci.c +6 -11
@@ -1112,19 +1112,13 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host)return preset; } -static void sdhci_set_clock (struct sdhci_host *host,unsigned int clock) +void sdhci_set_clock (struct sdhci_host *host,unsigned int clock) {int div =0 ;/* Initialized for compiler warning */ int real_div = div, clk_mul =1 ;u16 clk =0 ;unsigned long timeout; -if (host->ops->set_clock) { - host->ops->set_clock (host, clock); -if (host->quirks &SDHCI_QUIRK_NONSTANDARD_CLOCK ) -return ; - } - host->mmc->actual_clock =0 ;sdhci_writew (host,0 ,SDHCI_CLOCK_CONTROL );
@@ -1221,6 +1215,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) clk |=SDHCI_CLOCK_CARD_EN ;sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); } +EXPORT_SYMBOL_GPL (sdhci_set_clock);static int sdhci_set_power (struct sdhci_host *host,unsigned short power) {
@@ -1439,7 +1434,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)sdhci_enable_preset_value (host, false);if (!ios->clock || ios->clock != host->clock) { -sdhci_set_clock (host, ios->clock); + host->ops->set_clock (host, ios->clock); host->clock = ios->clock; }
@@ -1509,7 +1504,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );/* Re-enable SD Clock */ -sdhci_set_clock (host, host->clock); + host->ops->set_clock (host, host->clock); }
@@ -1553,7 +1548,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) }/* Re-enable SD Clock */ -sdhci_set_clock (host, host->clock); + host->ops->set_clock (host, host->clock); }else sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );
@@ -2124,7 +2119,7 @@ static void sdhci_tasklet_finish(unsigned long param)/* Some controllers need this kick or reset won't work here */ if (host->quirks &SDHCI_QUIRK_CLOCK_BEFORE_RESET )/* This is to force an update */ -sdhci_set_clock (host, host->clock); + host->ops->set_clock (host, host->clock);/* Spec says we should do both at the same time, but Ricoh controllers do not like that. */
drivers/mmc/host/sdhci.h +1 -0
@@ -400,6 +400,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)return !!(host->flags &SDHCI_SDIO_IRQ_ENABLED ); } +void sdhci_set_clock (struct sdhci_host *host,unsigned int clock);void sdhci_set_bus_width (struct sdhci_host *host,int width);void sdhci_reset (struct sdhci_host *host,u8 mask);
include/linux/mmc/sdhci.h +0 -2
@@ -57,8 +57,6 @@ struct sdhci_host {#define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15)/* Controller reports inverted write-protect state */ #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) -/* Controller has nonstandard clock management */ -#define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17)/* Controller does not like fast PIO transfers */ #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18)/* Controller has to be forced to use block size of 2048 bytes */
Signature · 1 line
1.8.3.1
PATCH 18/38 mmc: sdhci-esdhc-imx: avoid DMA to kernel stack
In reply to Russell King - ARM Linuxsdhci-esdhc-imx tries to DMA to the kernel stack when tuning the interface, which causes dma-debug to complain. Fix this by kmallocing a buffer to hold the received tuning pattern.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +16 -9
@@ -711,13 +711,12 @@ static void esdhc_request_done(struct mmc_request *mrq)complete (&mrq->completion); } -static int esdhc_send_tuning_cmd (struct sdhci_host *host,u32 opcode) +static int esdhc_send_tuning_cmd (struct sdhci_host *host,u32 opcode, +struct scatterlist *sg) {struct mmc_command cmd = {0 };struct mmc_request mrq = {NULL };struct mmc_data data = {0 }; -struct scatterlist sg; -char tuning_pattern[ESDHC_TUNING_BLOCK_PATTERN_LEN ]; cmd.opcode = opcode; cmd.arg =0 ;
@@ -726,11 +725,9 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode) data.blksz =ESDHC_TUNING_BLOCK_PATTERN_LEN ; data.blocks =1 ; data.flags =MMC_DATA_READ ; - data.sg = &sg; + data.sg = sg; data.sg_len =1 ; -sg_init_one (&sg, tuning_pattern,sizeof (tuning_pattern)); - mrq.cmd = &cmd; mrq.cmd->mrq = &mrq; mrq.data = &data;
@@ -770,13 +767,21 @@ static void esdhc_post_tuning(struct sdhci_host *host)static int esdhc_executing_tuning (struct sdhci_host *host,u32 opcode) { +struct scatterlist sg; +char *tuning_pattern;int min, max, avg, ret; + tuning_pattern =kmalloc (ESDHC_TUNING_BLOCK_PATTERN_LEN ,GFP_KERNEL ); +if (!tuning_pattern) +return -ENOMEM ; + +sg_init_one (&sg, tuning_pattern,ESDHC_TUNING_BLOCK_PATTERN_LEN ); +/* find the mininum delay first which can pass tuning */ min =ESDHC_TUNE_CTRL_MIN ;while (min <ESDHC_TUNE_CTRL_MAX ) {esdhc_prepare_tuning (host, min); -if (!esdhc_send_tuning_cmd (host, opcode)) +if (!esdhc_send_tuning_cmd (host, opcode, &sg))break ; min +=ESDHC_TUNE_CTRL_STEP ; }
@@ -785,7 +790,7 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode) max = min +ESDHC_TUNE_CTRL_STEP ;while (max <ESDHC_TUNE_CTRL_MAX ) {esdhc_prepare_tuning (host, max); -if (esdhc_send_tuning_cmd (host, opcode)) { +if (esdhc_send_tuning_cmd (host, opcode, &sg)) { max -=ESDHC_TUNE_CTRL_STEP ;break ; }
@@ -795,9 +800,11 @@ static int esdhc_executing_tuning(struct sdhci_host *host, u32 opcode)/* use average delay to get the best timing */ avg = (min + max) /2 ;esdhc_prepare_tuning (host, avg); - ret =esdhc_send_tuning_cmd (host, opcode); + ret =esdhc_send_tuning_cmd (host, opcode, &sg);esdhc_post_tuning (host); +kfree (tuning_pattern); +dev_dbg (mmc_dev (host->mmc),"tunning %s at 0x%x ret %d\n" , ret ?"failed" :"passed" , avg, ret);
Signature · 1 line
1.8.3.1
PATCH 19/38 mmc: sdhci-esdhc-imx: comment runtime_pm_get_sync() in esdhc_prepare_tuning()
In reply to Russell King - ARM LinuxIt is far from obvious what this is doing, and it looks like it's an unbalanced runtime_pm_get() call. However, the put is inside sdhci_tasklet_finish(), so it's not unbalanced at all. This should be documented so people know what's going on here. Do so.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 1 + 1 file changed, 1 insertion(+)
drivers/mmc/host/sdhci-esdhc-imx.c +1 -0
@@ -695,6 +695,7 @@ static void esdhc_prepare_tuning(struct sdhci_host *host, u32 val)/* FIXME: delay a bit for card to be ready for next tuning due to errors */ mdelay (1 ); +/* This is balanced by the runtime put in sdhci_tasklet_finish */ pm_runtime_get_sync (host->mmc->parent); reg =readl (host->ioaddr +ESDHC_MIX_CTRL ); reg |= ESDHC_MIX_CTRL_EXE_TUNE | ESDHC_MIX_CTRL_SMPCLK_SEL |
Signature · 1 line
1.8.3.1
PATCH 20/38 mmc: sdhci-esdhc-imx: fix lockdep splat upon tuning
In reply to Russell King - ARM Linux=================================
[ INFO: inconsistent lock state ]
3.14.0-rc1+ #490 Not tainted
---------------------------------
inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
kworker/u8:0/6 [HC0[0]:SC0[0]:HE1:SE1] takes:
(&(&host->lock)->rlock#2){?.-...}, at: [<c04b57a4>] esdhc_send_tuning_cmd+0x104/0x14c
{IN-HARDIRQ-W} state was registered at:
[<c00652fc>] mark_lock+0x15c/0x6f8 [<c0066354>] __lock_acquire+0xabc/0x1ca0 [<c0067ad8>] lock_acquire+0xa0/0x130 [<c0697a44>] _raw_spin_lock+0x34/0x44 [<c04b0dbc>] sdhci_irq+0x20/0xa40 [<c0071b1c>] handle_irq_event_percpu+0x74/0x284 [<c0071d70>] handle_irq_event+0x44/0x64 [<c0074db8>] handle_fasteoi_irq+0xac/0x140 [<c007147c>] generic_handle_irq+0x28/0x38 [<c000efd4>] handle_IRQ+0x40/0x98 [<c0008584>] gic_handle_irq+0x30/0x64 [<c0013144>] __irq_svc+0x44/0x58 [<c0028fc8>] irq_exit+0xc0/0x120 [<c000efd8>] handle_IRQ+0x44/0x98 [<c0008584>] gic_handle_irq+0x30/0x64 [<c0013144>] __irq_svc+0x44/0x58 [<c068f398>] printk+0x3c/0x44 [<c03191d0>] _regulator_get+0x1b4/0x1e0 [<c031924c>] regulator_get+0x18/0x1c [<c049fbc4>] mmc_add_host+0x30/0x1c0 [<c04b2e10>] sdhci_add_host+0x804/0xbbc [<c04b5318>] sdhci_esdhc_imx_probe+0x380/0x674 [<c036d530>] platform_drv_probe+0x20/0x50 [<c036b948>] driver_probe_device+0x120/0x234 [<c036baf8>] __driver_attach+0x9c/0xa0 [<c036a04c>] bus_for_each_dev+0x5c/0x90 [<c036b418>] driver_attach+0x24/0x28 [<c036b018>] bus_add_driver+0xe4/0x1d8 [<c036c1b0>] driver_register+0x80/0xfc [<c036ce28>] __platform_driver_register+0x50/0x64 [<c093706c>] sdhci_esdhc_imx_driver_init+0x18/0x20 [<c0008834>] do_one_initcall+0x3c/0x164 [<c0901c94>] kernel_init_freeable+0x104/0x1d0 [<c068c45c>] kernel_init+0x10/0x118 [<c000e768>] ret_from_fork+0x14/0x2c irq event stamp: 5933 hardirqs last enabled at (5933): [<c069813c>] _raw_spin_unlock_irqrestore+0x38/0x4c hardirqs last disabled at (5932): [<c0697b04>] _raw_spin_lock_irqsave+0x24/0x60 softirqs last enabled at (5914): [<c0028ba0>] __do_softirq+0x260/0x360 softirqs last disabled at (5909): [<c0028fc8>] irq_exit+0xc0/0x120
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(&(&host->lock)->rlock#2);
<Interrupt>
lock(&(&host->lock)->rlock#2);*** DEADLOCK ***
2 locks held by kworker/u8:0/6:
#0: (kmmcd){.+.+.+}, at: [<c003d890>] process_one_work+0x134/0x4e8
#1: ((&(&host->detect)->work)){+.+.+.}, at: [<c003d890>] process_one_work+0x134/0x4e8
stack backtrace: CPU: 2 PID: 6 Comm: kworker/u8:0 Not tainted 3.14.0-rc1+ #490 Workqueue: kmmcd mmc_rescan Backtrace: [<c00124a0>] (dump_backtrace) from [<c0012640>] (show_stack+0x18/0x1c) [<c0012628>] (show_stack) from [<c069164c>] (dump_stack+0x70/0x8c) [<c06915dc>] (dump_stack) from [<c068f080>] (print_usage_bug+0x274/0x2e4) [<c068ee0c>] (print_usage_bug) from [<c0065774>] (mark_lock+0x5d4/0x6f8) [<c00651a0>] (mark_lock) from [<c0065e6c>] (__lock_acquire+0x5d4/0x1ca0) [<c0065898>] (__lock_acquire) from [<c0067ad8>] (lock_acquire+0xa0/0x130) [<c0067a38>] (lock_acquire) from [<c0697a44>] (_raw_spin_lock+0x34/0x44) [<c0697a10>] (_raw_spin_lock) from [<c04b57a4>] (esdhc_send_tuning_cmd+0x104/0x14c) [<c04b56a0>] (esdhc_send_tuning_cmd) from [<c04b582c>] (esdhc_executing_tuning+0x40/0x100) [<c04b57ec>] (esdhc_executing_tuning) from [<c04afa54>] (sdhci_execute_tuning+0xcc/0x754) [<c04af988>] (sdhci_execute_tuning) from [<c04a4684>] (mmc_sd_init_card+0x65c/0x694) [<c04a4028>] (mmc_sd_init_card) from [<c04a48f0>] (mmc_attach_sd+0xb0/0x184) [<c04a4840>] (mmc_attach_sd) from [<c049eb28>] (mmc_rescan+0x26c/0x2e8) [<c049e8bc>] (mmc_rescan) from [<c003d914>] (process_one_work+0x1b8/0x4e8) [<c003d75c>] (process_one_work) from [<c003e090>] (worker_thread+0x13c/0x3f8) [<c003df54>] (worker_thread) from [<c00449bc>] (kthread+0xcc/0xe8) [<c00448f0>] (kthread) from [<c000e768>] (ret_from_fork+0x14/0x2c)
--- drivers/mmc/host/sdhci-esdhc-imx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +2 -4
@@ -738,14 +738,12 @@ static int esdhc_send_tuning_cmd(struct sdhci_host *host, u32 opcode, mrq.done = esdhc_request_done;init_completion (&(mrq.completion)); -disable_irq (host->irq); -spin_lock (&host->lock); +spin_lock_irq (&host->lock); host->mrq = &mrq;sdhci_send_command (host, mrq.cmd); -spin_unlock (&host->lock); -enable_irq (host->irq); +spin_unlock_irq (&host->lock);wait_for_completion (&mrq.completion);
Signature · 1 line
1.8.3.1
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
In reply to Russell King - ARM LinuxPatch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
--- drivers/mmc/host/sdhci.c | 12 ------------ 1 file changed, 12 deletions(-)
drivers/mmc/host/sdhci.c +0 -12
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -if (host->ops->set_uhs_signaling) host->ops->set_uhs_signaling (host, ios->timing);else {
@@ -1546,9 +1540,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) ios->drv_type = (preset &SDHCI_PRESET_DRV_MASK ) >>SDHCI_PRESET_DRV_SHIFT ; } - -/* Re-enable SD Clock */ - host->ops->set_clock (host, host->clock); }else sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );
@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, ctrl |=SDHCI_CTRL_VDD_180 ;sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); -/* Wait for 5ms */ -usleep_range (5000 ,5500 ); -/* 1.8V regulator output should be stable within 5 ms */ ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 );if (ctrl &SDHCI_CTRL_VDD_180 )
Signature · 1 line
1.8.3.1
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Hi,
Quoted 5 lines · Russell King
Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
Signed-off-by Russell King <[email protected]>
I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:
# dmesg | grep mmc2 mmc2: no vqmmc regulator found mmc2: no vmmc regulator found mmc2: SDHCI controller on 219c000.usdhc [219c000.usdhc] using ADMA mmc2: BKOPS_EN bit is not set mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: error -110 whilst initialising MMC card mmc2: BKOPS_EN bit is not set mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: error -110 whilst initialising MMC card mmc2: BKOPS_EN bit is not set
Any ideas?
Regards,
Markus
Quoted 50 lines
--- drivers/mmc/host/sdhci.c | 12 ------------ 1 file changed, 12 deletions(-)drivers/mmc/host/sdhci.c +0
-12@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -if (host->ops->set_uhs_signaling) host->ops->set_uhs_signaling (host, ios->timing);else {@@ -1546,9 +1540,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) ios->drv_type = (preset &SDHCI_PRESET_DRV_MASK ) >>SDHCI_PRESET_DRV_SHIFT ; } - -/* Re-enable SD Clock */ - host->ops->set_clock (host, host->clock); }else sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, ctrl |=SDHCI_CTRL_VDD_180 ;sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); -/* Wait for 5ms */ -usleep_range (5000 ,5500 ); -/* 1.8V regulator output should be stable within 5 ms */ ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 );if (ctrl &SDHCI_CTRL_VDD_180 )Signature · 7 lines
1.8.3.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel at lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140425/7932e0b9/attachment.sig>
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Quoted 11 lines · Markus Pargmann
Hi,
Quoted 5 lines · Russell King
Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
Signed-off-by Russell King <[email protected]>I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:
Unfortunately, I don't have any emmc sdhci using devices, so this is a combination I can't test myself.
What would be useful is to find out which of the two changes in there is the cause - can you try with just the change to sdhci_do_start_signal_voltage_switch applied, iow just this change:
drivers/mmc/host/sdhci.c +0 -3
@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, ctrl |=SDHCI_CTRL_VDD_180 ;sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); -/* Wait for 5ms */ -usleep_range (5000 ,5500 ); -/* 1.8V regulator output should be stable within 5 ms */ ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 );if (ctrl &SDHCI_CTRL_VDD_180 )
Thanks.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Quoted 13 lines · Russell King - ARM Linux
Quoted 11 lines · Markus Pargmann
Hi,
Quoted 5 lines · Russell King
Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
Signed-off-by Russell King <[email protected]>I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:
Quoted 6 lines
Unfortunately, I don't have any emmc sdhci using devices, so this is a combination I can't test myself.
What would be useful is to find out which of the two changes in there is the cause - can you try with just the change to
sdhci_do_start_signal_voltage_switchapplied, iow just this change:
I just tried the different parts of the patch. Without the following change, emmc works:
drivers/mmc/host/sdhci.c +0 -6
@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -
Regards,
Markus
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140425/41d480c8/attachment.sig>
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Quoted 6 lines · Markus Pargmann
I just tried the different parts of the patch. Without the following change, emmc works:
drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515
Quoted 9 lines
drivers/mmc/host/sdhci.c +0
-6@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -
So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.
Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Quoted 20 lines · Russell King - ARM Linux
Quoted 6 lines · Markus Pargmann
I just tried the different parts of the patch. Without the following change, emmc works:
drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515
Quoted 9 lines
drivers/mmc/host/sdhci.c +0
-6@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.
Quoted 2 lines
Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.
In the mean time, here's the remainder (to patch 33) of the series with this commit omitted.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 21/32 mmc: sdhci: set_uhs_signaling() need not return a value
The set_uhs_signaling() method gives the impression that it can fail, but anything returned from the method is entirely ignored by the sdhci driver. So returning failure has no effect.
So, kill the idea that it's possible for this to return an error by removing the returned value.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++-- drivers/mmc/host/sdhci-pxav3.c | 4 +--- drivers/mmc/host/sdhci.h | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +2 -2
@@ -841,7 +841,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,return pinctrl_select_state (imx_data->pinctrl, pinctrl); } -static int esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) +static void esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) {struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);struct pltfm_imx_data *imx_data = pltfm_host->priv;
@@ -879,7 +879,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)break ; } -return esdhc_change_pinstate (host, uhs); +esdhc_change_pinstate (host, uhs); }static void esdhc_reset (struct sdhci_host *host,u8 mask)
drivers/mmc/host/sdhci-pxav3.c +1 -3
@@ -186,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode) pxa->power_mode = power_mode; } -static int pxav3_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) +static void pxav3_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) {u16 ctrl_2;
@@ -220,8 +220,6 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)dev_dbg (mmc_dev (host->mmc),"%s uhs = %d, ctrl_2 = %04X\n" , __func__, uhs, ctrl_2); - -return 0 ; }static const struct sdhci_ops pxav3_sdhci_ops = {
drivers/mmc/host/sdhci.h +1 -1
@@ -287,7 +287,7 @@ struct sdhci_ops {unsigned int (*get_ro)(struct sdhci_host *host);void (*reset)(struct sdhci_host *host,u8 mask);int (*platform_execute_tuning)(struct sdhci_host *host,u32 opcode); -int (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs); +void (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs);void (*hw_reset)(struct sdhci_host *host);void (*platform_suspend)(struct sdhci_host *host);void (*platform_resume)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 22/32 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
In reply to Russell King - ARM LinuxAdd sdhci_set_uhs_signaling() and always call the set_uhs_signaling method. This avoids quirks being added into sdhci_set_uhs_signaling().
--- drivers/mmc/host/sdhci-acpi.c | 2 ++ drivers/mmc/host/sdhci-bcm-kona.c | 1 + drivers/mmc/host/sdhci-bcm2835.c | 1 + drivers/mmc/host/sdhci-cns3xxx.c | 1 + drivers/mmc/host/sdhci-dove.c | 1 + drivers/mmc/host/sdhci-of-arasan.c | 1 + drivers/mmc/host/sdhci-of-esdhc.c | 1 + drivers/mmc/host/sdhci-of-hlwd.c | 1 + drivers/mmc/host/sdhci-pci.c | 1 + drivers/mmc/host/sdhci-pltfm.c | 1 + drivers/mmc/host/sdhci-pxav2.c | 1 + drivers/mmc/host/sdhci-pxav3.c | 1 + drivers/mmc/host/sdhci-s3c.c | 1 + drivers/mmc/host/sdhci-sirf.c | 1 + drivers/mmc/host/sdhci-spear.c | 1 + drivers/mmc/host/sdhci-tegra.c | 1 + drivers/mmc/host/sdhci.c | 43 ++++++++++++++++++++------------------ drivers/mmc/host/sdhci.h | 1 + 18 files changed, 41 insertions(+), 20 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
@@ -106,6 +106,7 @@ static const struct sdhci_ops sdhci_acpi_ops_dflt = { .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_ops sdhci_acpi_ops_int = {
@@ -113,6 +114,7 @@ static const struct sdhci_ops sdhci_acpi_ops_int = { .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, .hw_reset = sdhci_acpi_int_hw_reset, };
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
@@ -212,6 +212,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = { .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, .card_event = sdhci_bcm_kona_card_event, };
drivers/mmc/host/sdhci-bcm2835.c +1 -0
@@ -136,6 +136,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = { .get_min_clock = bcm2835_sdhci_get_min_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
@@ -81,6 +81,7 @@ static const struct sdhci_ops sdhci_cns3xxx_ops = { .set_clock = sdhci_cns3xxx_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
@@ -89,6 +89,7 @@ static const struct sdhci_ops sdhci_dove_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-of-arasan.c +1 -0
@@ -57,6 +57,7 @@ static struct sdhci_ops sdhci_arasan_ops = { .get_timeout_clock = sdhci_arasan_get_timeout_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +1 -0
@@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .adma_workaround = esdhci_of_adma_workaround, .set_bus_width = esdhc_pltfm_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
@@ -61,6 +61,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +1 -0
@@ -1082,6 +1082,7 @@ static const struct sdhci_ops sdhci_pci_ops = { .enable_dma = sdhci_pci_enable_dma, .set_bus_width = sdhci_pci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, .hw_reset = sdhci_pci_hw_reset, };
drivers/mmc/host/sdhci-pltfm.c +1 -0
@@ -48,6 +48,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +1 -0
@@ -116,6 +116,7 @@ static const struct sdhci_ops pxav2_sdhci_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .set_bus_width = pxav2_mmc_set_bus_width, .reset = pxav2_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +1 -0
@@ -229,6 +229,7 @@ static const struct sdhci_ops pxav3_sdhci_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .set_bus_width = sdhci_set_bus_width, .reset = pxav3_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +1 -0
@@ -374,6 +374,7 @@ static struct sdhci_ops sdhci_s3c_ops = { .get_min_clock = sdhci_s3c_get_min_clock, .set_bus_width = sdhci_s3c_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static void sdhci_s3c_notify_change (struct platform_device *dev,int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
@@ -32,6 +32,7 @@ static struct sdhci_ops sdhci_sirf_ops = { .get_max_clock = sdhci_sirf_get_max_clk, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -0
@@ -41,6 +41,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +1 -0
@@ -156,6 +156,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { .set_clock = sdhci_set_clock, .set_bus_width = tegra_sdhci_set_bus_width, .reset = tegra_sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
drivers/mmc/host/sdhci.c +23 -20
60 lines not on this page · raw message
drivers/mmc/host/sdhci.h +1 -0
@@ -403,6 +403,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)void sdhci_set_clock (struct sdhci_host *host,unsigned int clock);void sdhci_set_bus_width (struct sdhci_host *host,int width);void sdhci_reset (struct sdhci_host *host,u8 mask); +void sdhci_set_uhs_signaling (struct sdhci_host *host,unsigned timing);#ifdef CONFIG_PM extern int sdhci_suspend_host (struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 23/32 mmc: sdhci: cache timing information locally
In reply to Russell King - ARM LinuxRather than reading back the timing information from the registers, cache it locally. This allows implementations to translate the UHS timing by overriding the set_uhs_signaling() method as required without also having to emulate the SDHCI_HOST_CONTROL2 register.
--- drivers/mmc/host/sdhci.c | 23 ++++++++++++----------- include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 14 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci.c +12 -11
@@ -1083,24 +1083,23 @@ static void sdhci_finish_command(struct sdhci_host *host)static u16 sdhci_get_preset_value (struct sdhci_host *host) { -u16 ctrl, preset =0 ; +u16 preset =0 ; - ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); - -switch (ctrl &SDHCI_CTRL_UHS_MASK ) { -case SDHCI_CTRL_UHS_SDR12 : +switch (host->timing) { +case MMC_TIMING_UHS_SDR12 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR12 );break ; -case SDHCI_CTRL_UHS_SDR25 : +case MMC_TIMING_UHS_SDR25 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR25 );break ; -case SDHCI_CTRL_UHS_SDR50 : +case MMC_TIMING_UHS_SDR50 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR50 );break ; -case SDHCI_CTRL_UHS_SDR104 : +case MMC_TIMING_UHS_SDR104 : +case MMC_TIMING_MMC_HS200 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR104 );break ; -case SDHCI_CTRL_UHS_DDR50 : +case MMC_TIMING_UHS_DDR50 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_DDR50 );break ;default :
@@ -1535,6 +1534,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); host->ops->set_uhs_signaling (host, ios->timing); + host->timing = ios->timing; if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ((ios->timing == MMC_TIMING_UHS_SDR12) ||
@@ -1839,12 +1839,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)* If the Host Controller supports the HS200 mode then the * tuning function has to be executed. */ -if (((ctrl &SDHCI_CTRL_UHS_MASK ) ==SDHCI_CTRL_UHS_SDR50 ) && +if (host->timing ==MMC_TIMING_UHS_SDR50 && (host->flags &SDHCI_SDR50_NEEDS_TUNING || host->flags &SDHCI_SDR104_NEEDS_TUNING )) requires_tuning_nonuhs = true; -if (((ctrl &SDHCI_CTRL_UHS_MASK ) ==SDHCI_CTRL_UHS_SDR104 ) || +if (host->timing ==MMC_TIMING_MMC_HS200 || + host->timing ==MMC_TIMING_UHS_SDR104 || requires_tuning_nonuhs) ctrl |=SDHCI_CTRL_EXEC_TUNING ;else {
include/linux/mmc/sdhci.h +2 -0
@@ -172,6 +172,8 @@ struct sdhci_host {unsigned int ocr_avail_mmc;u32 ocr_mask;/* available voltages */ +unsigned timing;/* Current timing */ +u32 thread_isr;/* cached registers */
Signature · 1 line
1.8.3.1
PATCH 24/32 mmc: sdhci: clean up sdhci_execute_tuning() decision
In reply to Russell King - ARM LinuxClean up the code in sdhci_execute_tuning() so the decision whether to execute tuning is clearer - and despite this reflecting what the original code was doing, it shows that it may not be what the author actually intended.
--- drivers/mmc/host/sdhci.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
drivers/mmc/host/sdhci.c +15 -16
@@ -1817,21 +1817,16 @@ static int sdhci_card_busy(struct mmc_host *mmc)static int sdhci_execute_tuning (struct mmc_host *mmc,u32 opcode) { -struct sdhci_host *host; +struct sdhci_host *host =mmc_priv (mmc);u16 ctrl;int tuning_loop_counter =MAX_TUNING_LOOP ;unsigned long timeout;int err =0 ; -bool requires_tuning_nonuhs = false;unsigned long flags; - host =mmc_priv (mmc); -sdhci_runtime_pm_get (host);spin_lock_irqsave (&host->lock, flags); - ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* * The Host Controller needs tuning only in case of SDR104 mode * and for SDR50 mode when Use Tuning for SDR50 is set in the
@@ -1839,16 +1834,18 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)* If the Host Controller supports the HS200 mode then the * tuning function has to be executed. */ -if (host->timing ==MMC_TIMING_UHS_SDR50 && - (host->flags &SDHCI_SDR50_NEEDS_TUNING || - host->flags &SDHCI_SDR104_NEEDS_TUNING )) - requires_tuning_nonuhs = true; - -if (host->timing ==MMC_TIMING_MMC_HS200 || - host->timing ==MMC_TIMING_UHS_SDR104 || - requires_tuning_nonuhs) - ctrl |=SDHCI_CTRL_EXEC_TUNING ; -else { +switch (host->timing) { +case MMC_TIMING_MMC_HS200 : +case MMC_TIMING_UHS_SDR104 : +break ; + +case MMC_TIMING_UHS_SDR50 : +if (host->flags &SDHCI_SDR50_NEEDS_TUNING || + host->flags &SDHCI_SDR104_NEEDS_TUNING ) +break ; +/* FALLTHROUGH */ + +default :spin_unlock_irqrestore (&host->lock, flags);sdhci_runtime_pm_put (host);return 0 ;
@@ -1861,6 +1858,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)return err; } + ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); + ctrl |=SDHCI_CTRL_EXEC_TUNING ;sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 );/*
Signature · 1 line
1.8.3.1
PATCH 25/32 mmc: sdhci-esdhc-imx: remove emulation of uhs_mode
In reply to Russell King - ARM LinuxWe no longer need to emulate the uhs_mode field of the host control2 register - the main sdhci driver never reads this back to evaluate the current mode as it caches the current mode instead.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +3 -14
@@ -160,7 +160,6 @@ struct pltfm_imx_data {MULTIBLK_IN_PROCESS ,/* exact multiblock cmd in process */ WAIT_FOR_INT ,/* sent CMD12, waiting for response INT */ } multiblock_status; -u32 uhs_mode;u32 is_ddr; };
@@ -382,7 +381,6 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)if (val &ESDHC_MIX_CTRL_SMPCLK_SEL ) ret |=SDHCI_CTRL_TUNED_CLK ; - ret |= (imx_data->uhs_mode &SDHCI_CTRL_UHS_MASK ); ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE ;return ret;
@@ -429,7 +427,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)else new_val &= ~ESDHC_VENDOR_SPEC_VSELECT ;writel (new_val, host->ioaddr +ESDHC_VENDOR_SPEC ); - imx_data->uhs_mode = val &SDHCI_CTRL_UHS_MASK ;if (imx_data->socdata->flags &ESDHC_FLAG_MAN_TUNING ) { new_val =readl (host->ioaddr +ESDHC_MIX_CTRL );if (val &SDHCI_CTRL_TUNED_CLK )
@@ -841,28 +838,20 @@ static int esdhc_change_pinstate(struct sdhci_host *host,return pinctrl_select_state (imx_data->pinctrl, pinctrl); } -static void esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) +static void esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned timing) {struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);struct pltfm_imx_data *imx_data = pltfm_host->priv;struct esdhc_platform_data *boarddata = &imx_data->boarddata; -switch (uhs) { +switch (timing) {case MMC_TIMING_UHS_SDR12 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR12 ; -break ;case MMC_TIMING_UHS_SDR25 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR25 ; -break ;case MMC_TIMING_UHS_SDR50 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR50 ; -break ;case MMC_TIMING_UHS_SDR104 :case MMC_TIMING_MMC_HS200 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR104 ;break ;case MMC_TIMING_UHS_DDR50 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_DDR50 ;writel (readl (host->ioaddr +ESDHC_MIX_CTRL ) |ESDHC_MIX_CTRL_DDREN , host->ioaddr +ESDHC_MIX_CTRL );
@@ -879,7 +868,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)break ; } -esdhc_change_pinstate (host, uhs); +esdhc_change_pinstate (host, timing); }static void esdhc_reset (struct sdhci_host *host,u8 mask)
Signature · 1 line
1.8.3.1
PATCH 26/32 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks
In reply to Russell King - ARM LinuxWe don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.
--- drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-of-esdhc.c +36 -19
@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)mdelay (1 ); } -#ifdef CONFIG_PM -static u32 esdhc_proctl; -static void esdhc_of_suspend (struct sdhci_host *host) -{ - esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); -} - -static void esdhc_of_resume (struct sdhci_host *host) -{ -esdhc_of_enable_dma (host); -sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); -} -#endif -static void esdhc_of_platform_init (struct sdhci_host *host) {u32 vvn;
@@ -302,16 +288,47 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .get_max_clock = esdhc_of_get_max_clock, .get_min_clock = esdhc_of_get_min_clock, .platform_init = esdhc_of_platform_init, -#ifdef CONFIG_PM - .platform_suspend = esdhc_of_suspend, - .platform_resume = esdhc_of_resume, -#endif .adma_workaround = esdhci_of_adma_workaround, .set_bus_width = esdhc_pltfm_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, }; +#ifdef CONFIG_PM + +static u32 esdhc_proctl; +static int esdhc_of_suspend (struct device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); + + esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); + +return sdhci_suspend_host (host); +} + +static void esdhc_of_resume (device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); +int ret =sdhci_resume_host (host); + +if (ret ==0 ) { +/* Isn't this already done by sdhci_resume_host() ? --rmk */ +esdhc_of_enable_dma (host); +sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); + } + +return ret; +} + +static const struct dev_pm_ops esdhc_pmops = { + .suspend = esdhci_of_suspend, + .resume = esdhci_of_resume, +}; +#define ESDHC_PMOPS (&esdhc_pmops) +#else +#define ESDHC_PMOPS NULL +#endif +static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {/* * card detection could be handled via GPIO
@@ -373,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = { .name = "sdhci-esdhc", .owner = THIS_MODULE, .of_match_table = sdhci_esdhc_of_match, - .pm = SDHCI_PLTFM_PMOPS, + .pm = ESDHC_PMOPS, }, .probe = sdhci_esdhc_probe, .remove = sdhci_esdhc_remove,
Signature · 1 line
1.8.3.1
PATCH 27/32 mmc: sdhci: remove platform_suspend/platform_resume callbacks
In reply to Russell King - ARM LinuxThe only user (sdhci-of-esdhc) no longer uses these callbacks, so lets remove them to discourage any further use.
--- drivers/mmc/host/sdhci.c | 6 ------ drivers/mmc/host/sdhci.h | 2 -- 2 files changed, 8 deletions(-)
drivers/mmc/host/sdhci.c +0 -6
@@ -2541,9 +2541,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);int sdhci_suspend_host (struct sdhci_host *host) { -if (host->ops->platform_suspend) - host->ops->platform_suspend (host); -sdhci_disable_card_detection (host);/* Disable tuning since we are suspending */
@@ -2600,9 +2597,6 @@ int sdhci_resume_host(struct sdhci_host *host)sdhci_enable_card_detection (host); -if (host->ops->platform_resume) - host->ops->platform_resume (host); -/* Set the re-tuning expiration flag */ if (host->flags &SDHCI_USING_RETUNING_TIMER ) host->flags |=SDHCI_NEEDS_RETUNING ;
drivers/mmc/host/sdhci.h +0 -2
@@ -289,8 +289,6 @@ struct sdhci_ops {int (*platform_execute_tuning)(struct sdhci_host *host,u32 opcode);void (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs);void (*hw_reset)(struct sdhci_host *host); -void (*platform_suspend)(struct sdhci_host *host); -void (*platform_resume)(struct sdhci_host *host);void (*adma_workaround)(struct sdhci_host *host,u32 intmask);void (*platform_init)(struct sdhci_host *host);void (*card_event)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 28/32 mmc: sdhci-tegra: get rid of special PRESENT_STATE register handling
In reply to Russell King - ARM Linuxsdhci-tegra provides a get_ro method, which overrides the checking of the write protect bit in the PRESENT_STATE register in sdhci.c:
if (host->flags & SDHCI_DEVICE_DEAD)
is_readonly = 0;
else if (host->ops->get_ro)
is_readonly = host->ops->get_ro(host);
else
is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
& SDHCI_WRITE_PROTECT);This means it's pointless detecting accesses to this register and manually setting the SDHCI_WRITE_PROTECT as it has no effect.
This means that the whole of tegra_sdhci_readl() can be removed and we can use the builtin sdhci readl functionality here.
--- drivers/mmc/host/sdhci-tegra.c | 14 -------------- 1 file changed, 14 deletions(-)
drivers/mmc/host/sdhci-tegra.c +0 -14
@@ -48,19 +48,6 @@ struct sdhci_tegra {int power_gpio; }; -static u32 tegra_sdhci_readl (struct sdhci_host *host,int reg) -{ -u32 val; - -if (unlikely (reg ==SDHCI_PRESENT_STATE )) { -/* Use wp_gpio here instead? */ - val =readl (host->ioaddr + reg); -return val |SDHCI_WRITE_PROTECT ; - } - -return readl (host->ioaddr + reg); -} -static u16 tegra_sdhci_readw (struct sdhci_host *host,int reg) {struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);
@@ -150,7 +137,6 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)static const struct sdhci_ops tegra_sdhci_ops = { .get_ro = tegra_sdhci_get_ro, - .read_l = tegra_sdhci_readl, .read_w = tegra_sdhci_readw, .write_l = tegra_sdhci_writel, .set_clock = sdhci_set_clock,
Signature · 1 line
1.8.3.1
PATCH 29/32 mmc: sdhci: move regulator handling into sdhci_set_power()
In reply to Russell King - ARM LinuxMove the regulator handling into sdhci_set_power() rather than being in sdhci_do_set_ios(). This wraps all power control up into this function.
--- drivers/mmc/host/sdhci.c | 72 +++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 37 deletions(-)
drivers/mmc/host/sdhci.c +35 -37
@@ -1216,7 +1216,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) }EXPORT_SYMBOL_GPL (sdhci_set_clock); -static int sdhci_set_power (struct sdhci_host *host,unsigned short power) +static void sdhci_set_power (struct sdhci_host *host,unsigned short power) {u8 pwr =0 ;
@@ -1239,7 +1239,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) }if (host->pwr == pwr) -return -1 ; +return ; host->pwr = pwr;
@@ -1247,38 +1247,43 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL );if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON )sdhci_runtime_pm_bus_off (host); -return 0 ; - } - -/* -* Spec says that we should clear the power reg before setting -* a new value. Some controllers don't seem to like this though. -*/ -if (!(host->quirks &SDHCI_QUIRK_SINGLE_POWER_WRITE )) -sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL ); + power =0 ; + }else { +/* +* Spec says that we should clear the power reg before setting +* a new value. Some controllers don't seem to like this though. +*/ +if (!(host->quirks &SDHCI_QUIRK_SINGLE_POWER_WRITE )) +sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL ); -/* -* At least the Marvell CaFe chip gets confused if we set the voltage -* and set turn on power at the same time, so set the voltage first. -*/ -if (host->quirks &SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER ) -sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); +/* +* At least the Marvell CaFe chip gets confused if we set the +* voltage and set turn on power at the same time, so set the +* voltage first. +*/ +if (host->quirks &SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER ) +sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); - pwr |=SDHCI_POWER_ON ; + pwr |=SDHCI_POWER_ON ; -sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); +sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); -if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON ) -sdhci_runtime_pm_bus_on (host); +if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON ) +sdhci_runtime_pm_bus_on (host); -/* -* Some controllers need an extra 10ms delay of 10ms before they -* can apply clock after applying power -*/ -if (host->quirks &SDHCI_QUIRK_DELAY_AFTER_POWER ) -mdelay (10 ); +/* +* Some controllers need an extra 10ms delay of 10ms before +* they can apply clock after applying power +*/ +if (host->quirks &SDHCI_QUIRK_DELAY_AFTER_POWER ) +mdelay (10 ); + } -return power; +if (host->vmmc) { +spin_unlock_irq (&host->lock); +mmc_regulator_set_ocr (host->mmc, host->vmmc, power); +spin_lock_irq (&host->lock); + } }/*****************************************************************************\
@@ -1428,7 +1433,6 @@ EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);static void sdhci_do_set_ios (struct sdhci_host *host,struct mmc_ios *ios) {unsigned long flags; -int vdd_bit =-1 ;u8 ctrl;spin_lock_irqsave (&host->lock, flags);
@@ -1460,15 +1464,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) }if (ios->power_mode ==MMC_POWER_OFF ) - vdd_bit =sdhci_set_power (host,-1 ); +sdhci_set_power (host,-1 );else - vdd_bit =sdhci_set_power (host, ios->vdd); - -if (host->vmmc && vdd_bit !=-1 ) { -spin_unlock_irqrestore (&host->lock, flags); -mmc_regulator_set_ocr (host->mmc, host->vmmc, vdd_bit); -spin_lock_irqsave (&host->lock, flags); - } +sdhci_set_power (host, ios->vdd);if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks (host, ios->power_mode);
Signature · 1 line
1.8.3.1
PATCH 30/32 mmc: sdhci: move remaining power handling into sdhci_set_power()
In reply to Russell King - ARM LinuxMove the remaining parts of the power handling in sdhci_do_set_ios() into sdhci_set_power().
--- drivers/mmc/host/sdhci.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci.c +7 -9
@@ -1216,12 +1216,13 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) }EXPORT_SYMBOL_GPL (sdhci_set_clock); -static void sdhci_set_power (struct sdhci_host *host,unsigned short power) +static void sdhci_set_power (struct sdhci_host *host,unsigned char mode, +unsigned short vdd) {u8 pwr =0 ; -if (power != (unsigned short )-1 ) { -switch (1 << power) { +if (mode !=MMC_POWER_OFF ) { +switch (1 << vdd) {case MMC_VDD_165_195 : pwr =SDHCI_POWER_180 ;break ;
@@ -1247,7 +1248,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL );if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON )sdhci_runtime_pm_bus_off (host); - power =0 ; + vdd =0 ; }else {/* * Spec says that we should clear the power reg before setting
@@ -1281,7 +1282,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)if (host->vmmc) {spin_unlock_irq (&host->lock); -mmc_regulator_set_ocr (host->mmc, host->vmmc, power); +mmc_regulator_set_ocr (host->mmc, host->vmmc, vdd);spin_lock_irq (&host->lock); } }
@@ -1463,10 +1464,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->clock = ios->clock; } -if (ios->power_mode ==MMC_POWER_OFF ) -sdhci_set_power (host,-1 ); -else -sdhci_set_power (host, ios->vdd); +sdhci_set_power (host, ios->power_mode, ios->vdd);if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks (host, ios->power_mode);
Signature · 1 line
1.8.3.1
PATCH 31/32 mmc: sdhci: track whether preset mode is currently enabled in hardware
In reply to Russell King - ARM LinuxTrack whether preset mode is currently enabled in hardware, and use that when making decisions elsewhere in the code rather than reading the register and checking the bit.
--- drivers/mmc/host/sdhci.c | 44 ++++++++++++++++++++++++++------------------ include/linux/mmc/sdhci.h | 1 + 2 files changed, 27 insertions(+), 18 deletions(-)
drivers/mmc/host/sdhci.c +26 -18
@@ -205,9 +205,14 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) host->ops->reset (host, mask); -if (host->flags & (SDHCI_USE_SDMA |SDHCI_USE_ADMA )) { -if ((host->ops->enable_dma) && (mask &SDHCI_RESET_ALL )) - host->ops->enable_dma (host); +if (mask &SDHCI_RESET_ALL ) { +if (host->flags & (SDHCI_USE_SDMA |SDHCI_USE_ADMA )) { +if (host->ops->enable_dma) + host->ops->enable_dma (host); + } + +/* Resetting the controller clears many */ + host->preset_enabled = false; } }
@@ -1126,8 +1131,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)return ;if (host->version >=SDHCI_SPEC_300 ) { -if (sdhci_readw (host,SDHCI_HOST_CONTROL2 ) & -SDHCI_CTRL_PRESET_VAL_ENABLE ) { +if (host->preset_enabled) {u16 pre_val; clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL );
@@ -1491,13 +1495,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) (ios->timing == MMC_TIMING_UHS_SDR25)) ctrl |=SDHCI_CTRL_HISPD ; - ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -if (!(ctrl_2 &SDHCI_CTRL_PRESET_VAL_ENABLE )) { +if (!host->preset_enabled) {sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );/* * We only need to set Driver Strength if the * preset value enable is not set. */ + ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK ;if (ios->drv_type ==MMC_SET_DRIVER_TYPE_A ) ctrl_2 |=SDHCI_CTRL_DRV_TYPE_A ;
@@ -2012,26 +2016,30 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)static void sdhci_enable_preset_value (struct sdhci_host *host,bool enable) { -u16 ctrl; -/* Host Controller v3.00 defines preset value registers */ if (host->version <SDHCI_SPEC_300 )return ; - ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* * We only enable or disable Preset Value if they are not already * enabled or disabled respectively. Otherwise, we bail out. */ -if (enable && !(ctrl &SDHCI_CTRL_PRESET_VAL_ENABLE )) { - ctrl |=SDHCI_CTRL_PRESET_VAL_ENABLE ; -sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); - host->flags |=SDHCI_PV_ENABLED ; - }else if (!enable && (ctrl &SDHCI_CTRL_PRESET_VAL_ENABLE )) { - ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE ; +if (host->preset_enabled != enable) { +u16 ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); + +if (enable) + ctrl |=SDHCI_CTRL_PRESET_VAL_ENABLE ; +else + ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE ; +sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); - host->flags &= ~SDHCI_PV_ENABLED ; + +if (enable) + host->flags |=SDHCI_PV_ENABLED ; +else + host->flags &= ~SDHCI_PV_ENABLED ; + + host->preset_enabled = enable; } }
include/linux/mmc/sdhci.h +1 -0
@@ -143,6 +143,7 @@ struct sdhci_host {bool runtime_suspended;/* Host is runtime suspended */ bool bus_on;/* Bus power prevents runtime suspend */ +bool preset_enabled;/* Preset is enabled */ struct mmc_request *mrq;/* Current request */ struct mmc_command *cmd;/* Current command */
Signature · 1 line
1.8.3.1
PATCH 32/32 mmc: sdhci: fix SDHCI dependencies
In reply to Russell King - ARM Linux--- drivers/mmc/host/Kconfig | 63 ++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 31 deletions(-)
drivers/mmc/host/Kconfig +32 -31
@@ -25,8 +25,7 @@ config MMC_PXA If unsure, say N. config MMC_SDHCI - tristate "Secure Digital Host Controller Interface support" - depends on HAS_DMA + tristate help This selects the generic Secure Digital Host Controller Interface. It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@@ -59,7 +58,8 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER config MMC_SDHCI_PCI tristate "SDHCI support on PCI bus" - depends on MMC_SDHCI && PCI + depends on PCI && HAS_DMA + select MMC_SDHCI help This selects the PCI Secure Digital Host Controller Interface. Most controllers found today are PCI devices.
@@ -83,7 +83,8 @@ config MMC_RICOH_MMC config MMC_SDHCI_ACPI tristate "SDHCI support for ACPI enumerated SDHCI controllers" - depends on MMC_SDHCI && ACPI + depends on ACPI && HAS_DMA + select MMC_SDHCI help This selects support for ACPI enumerated SDHCI controllers, identified by ACPI Compatibility ID PNP0D40 or specific
@@ -94,8 +95,8 @@ config MMC_SDHCI_ACPI If unsure, say N. config MMC_SDHCI_PLTFM - tristate "SDHCI platform and OF driver helper" - depends on MMC_SDHCI + tristate + select MMC_SDHCI help This selects the common helper functions support for Secure Digital Host Controller Interface based platform and OF drivers.
@@ -106,8 +107,8 @@ config MMC_SDHCI_PLTFM config MMC_SDHCI_OF_ARASAN tristate "SDHCI OF support for the Arasan SDHCI controllers" - depends on MMC_SDHCI_PLTFM - depends on OF + depends on OF && HAS_DMA + select MMC_SDHCI_PLTFM help This selects the Arasan Secure Digital Host Controller Interface (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
@@ -118,9 +119,9 @@ config MMC_SDHCI_OF_ARASAN config MMC_SDHCI_OF_ESDHC tristate "SDHCI OF support for the Freescale eSDHC controller" - depends on MMC_SDHCI_PLTFM - depends on PPC_OF + depends on PPC_OF && HAS_DMA select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER + select MMC_SDHCI_PLTFM help This selects the Freescale eSDHC controller support.
@@ -130,9 +131,9 @@ config MMC_SDHCI_OF_ESDHC config MMC_SDHCI_OF_HLWD tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers" - depends on MMC_SDHCI_PLTFM - depends on PPC_OF + depends on PPC_OF && HAS_DMA select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER + select MMC_SDHCI_PLTFM help This selects the Secure Digital Host Controller Interface (SDHCI) found in the "Hollywood" chipset of the Nintendo Wii video game
@@ -144,8 +145,8 @@ config MMC_SDHCI_OF_HLWD config MMC_SDHCI_CNS3XXX tristate "SDHCI support on the Cavium Networks CNS3xxx SoC" - depends on ARCH_CNS3XXX - depends on MMC_SDHCI_PLTFM + depends on ARCH_CNS3XXX && HAS_DMA + select MMC_SDHCI_PLTFM help This selects the SDHCI support for CNS3xxx System-on-Chip devices.
@@ -155,9 +156,9 @@ config MMC_SDHCI_CNS3XXX config MMC_SDHCI_ESDHC_IMX tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller" - depends on ARCH_MXC - depends on MMC_SDHCI_PLTFM + depends on ARCH_MXC && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the Freescale eSDHC/uSDHC controller support found on i.MX25, i.MX35 i.MX5x and i.MX6x.
@@ -168,9 +169,9 @@ config MMC_SDHCI_ESDHC_IMX config MMC_SDHCI_DOVE tristate "SDHCI support on Marvell's Dove SoC" - depends on ARCH_DOVE - depends on MMC_SDHCI_PLTFM + depends on ARCH_DOVE && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the Secure Digital Host Controller Interface in Marvell's Dove SoC.
@@ -181,9 +182,9 @@ config MMC_SDHCI_DOVE config MMC_SDHCI_TEGRA tristate "SDHCI platform support for the Tegra SD/MMC Controller" - depends on ARCH_TEGRA - depends on MMC_SDHCI_PLTFM + depends on ARCH_TEGRA && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the Tegra SD/MMC controller. If you have a Tegra platform with SD or MMC devices, say Y or M here.
@@ -192,7 +193,8 @@ config MMC_SDHCI_TEGRA config MMC_SDHCI_S3C tristate "SDHCI support on Samsung S3C SoC" - depends on MMC_SDHCI && PLAT_SAMSUNG + depends on PLAT_SAMSUNG && HAS_DMA + select MMC_SDHCI help This selects the Secure Digital Host Controller Interface (SDHCI) often referrered to as the HSMMC block in some of the Samsung S3C
@@ -204,8 +206,8 @@ config MMC_SDHCI_S3C config MMC_SDHCI_SIRF tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs" - depends on ARCH_SIRF - depends on MMC_SDHCI_PLTFM + depends on ARCH_SIRF && HAS_DMA + select MMC_SDHCI_PLTFM help This selects the SDHCI support for SiRF System-on-Chip devices.
@@ -215,8 +217,7 @@ config MMC_SDHCI_SIRF config MMC_SDHCI_PXAV3 tristate "Marvell MMP2 SD Host Controller support (PXAV3)" - depends on CLKDEV_LOOKUP - select MMC_SDHCI + depends on CLKDEV_LOOKUP && HAS_DMA select MMC_SDHCI_PLTFM default CPU_MMP2 help
@@ -228,8 +229,7 @@ config MMC_SDHCI_PXAV3 config MMC_SDHCI_PXAV2 tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" - depends on CLKDEV_LOOKUP - select MMC_SDHCI + depends on CLKDEV_LOOKUP && HAS_DMA select MMC_SDHCI_PLTFM default CPU_PXA910 help
@@ -241,7 +241,8 @@ config MMC_SDHCI_PXAV2 config MMC_SDHCI_SPEAR tristate "SDHCI support on ST SPEAr platform" - depends on MMC_SDHCI && PLAT_SPEAR + depends on PLAT_SPEAR && HAS_DMA + select MMC_SDHCI help This selects the Secure Digital Host Controller Interface (SDHCI) often referrered to as the HSMMC block in some of the ST SPEAR range
@@ -263,7 +264,7 @@ config MMC_SDHCI_S3C_DMA config MMC_SDHCI_BCM_KONA tristate "SDHCI support on Broadcom KONA platform" - depends on ARCH_BCM_MOBILE + depends on ARCH_BCM_MOBILE && HAS_DMA select MMC_SDHCI_PLTFM help This selects the Broadcom Kona Secure Digital Host Controller
@@ -274,9 +275,9 @@ config MMC_SDHCI_BCM_KONA config MMC_SDHCI_BCM2835 tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" - depends on ARCH_BCM2835 - depends on MMC_SDHCI_PLTFM + depends on ARCH_BCM2835 && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the BCM2835 SD/MMC controller. If you have a BCM2835 platform with SD or MMC devices, say Y or M here.
Signature · 1 line
1.8.3.1
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
In reply to Russell King - ARM LinuxHi,
Quoted 21 lines · Russell King - ARM Linux
Quoted 20 lines · Russell King - ARM Linux
Quoted 6 lines · Markus Pargmann
I just tried the different parts of the patch. Without the following change, emmc works:
drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515
Quoted 9 lines
drivers/mmc/host/sdhci.c +0
-6@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.
Quoted 5 lines
Quoted 2 lines
Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.
In the mean time, here's the remainder (to patch 33) of the series with this commit omitted.
I tested the whole series again, from 1 to patch 32 and it is working correctly now on the RIoT board (imx6s) with emmc and sd-card. You can add my tested-by tag for all core and imx related patches if you want to.
Regards,
Markus
Signature · 11 lines
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140428/67e1f8c6/attachment.sig>
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
In reply to Russell King - ARM LinuxQuoted 20 lines · Russell King - ARM Linux
Quoted 6 lines · Markus Pargmann
I just tried the different parts of the patch. Without the following change, emmc works:
drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1515
Quoted 9 lines
drivers/mmc/host/sdhci.c +0
-6@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -So the bit which stops us violating the SD spec stops eMMC from working... that's... just great.
Quoted 2 lines
Okay, I'll look deeper at this and see what can be done, but I suspect it will turn out to require more patches and be more invasive.
Well, I've given up trying to work out how to clean that mess up - sdhci will attempt to do all the high speed switching bollocks every time a set_ios call is made, turning the clock on and off multiple times in the process.
I've since replaced it with a patch covering just the last hunk of this patch and killed the other two changes there (and rewritten the description.)
I'm afraid that it looks like we're going to be stuck with turning the clock on and off multiple times during the transition to 1.8V signalling, which is technically against the SD spec. The spec'd procedure is:
- send command
- check card reports busy
- clock off
- switch to 1.8v signalling
- wait 5ms
- clock on
- wait 1ms
- check card reports non-busy
whereas what we end up doing is:
- send command
- check card reports busy
- clock off
- switch to 1.8v signalling, waiting 5 to 5.5ms
- wait 5ms
- clock on
- clock off
- tweak other settings
- clock on again
- wait 1ms
- check card reports non-busy
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
In reply to Markus PargmannQuoted 11 lines · Markus Pargmann
Hi,
Quoted 5 lines · Russell King
Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
Signed-off-by Russell King <[email protected]>I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:
Hi Markus,
Thanks for helping out testing!
Does that mean patch 1->20 works fine for you? May I add your tested-by tag?
Kind regards
Ulf Hansson
Quoted 81 lines
# dmesg | grep mmc2 mmc2: no vqmmc regulator found mmc2: no vmmc regulator found mmc2: SDHCI controller on 219c000.usdhc [219c000.usdhc] using ADMA mmc2: BKOPS_EN bit is not set mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: error -110 whilst initialising MMC card mmc2: BKOPS_EN bit is not set mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: Timeout waiting for hardware interrupt. mmc2: error -110 whilst initialising MMC card mmc2: BKOPS_EN bit is not setAny ideas?
Regards,
Markus
Quoted 45 lines
--- drivers/mmc/host/sdhci.c | 12 ------------ 1 file changed, 12 deletions(-)drivers/mmc/host/sdhci.c +0
-13@@ -1507,12 +1507,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } - -/* Reset SD Clock Enable */ - clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); - clk &= ~SDHCI_CLOCK_CARD_EN ; -sdhci_writew (host, clk,SDHCI_CLOCK_CONTROL ); -if (host->ops->set_uhs_signaling) host->ops->set_uhs_signaling (host, ios->timing);else {@@ -1546,9 +1540,6 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) ios->drv_type = (preset &SDHCI_PRESET_DRV_MASK ) >>SDHCI_PRESET_DRV_SHIFT ; } - -/* Re-enable SD Clock */ - host->ops->set_clock (host, host->clock); }else sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );@@ -1757,9 +1748,6 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host, ctrl |=SDHCI_CTRL_VDD_180 ;sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); -/* Wait for 5ms */ -usleep_range (5000 ,5500 ); -/* 1.8V regulator output should be stable within 5 ms */ ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 );if (ctrl &SDHCI_CTRL_VDD_180 ) --1.8.3.1
Quoted 5 lines
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel--
Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Quoted 10 lines · Ulf Hansson
Quoted 9 lines · Markus Pargmann
Hi,
Quoted 5 lines · Russell King
Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
Signed-off-by Russell King <[email protected]>
Quoted 8 lines
Quoted 2 lines
I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:
Hi Markus,
Thanks for helping out testing!
Does that mean patch 1->20 works fine for you? May I add your tested-by tag?
Why should _you_ add someone elses tested-by tag to _my_ patches?
I still wonder whether you understood anything that I've already said to you about the handling of this patch set.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Quoted 16 lines · Russell King - ARM Linux
Quoted 15 lines · Ulf Hansson
Quoted 11 lines · Markus Pargmann
Hi,
Quoted 5 lines · Russell King
Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
Signed-off-by Russell King <[email protected]>I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:
Hi Markus,
Quoted 8 lines
Quoted 3 lines
Thanks for helping out testing!
Does that mean patch 1->20 works fine for you? May I add your tested-by tag?
Why should _you_ add someone elses tested-by tag to _my_ patches?
I still wonder whether you understood anything that I've already said to you about the handling of this patch set.
That was based upon that _I_ would help out in creating the pull request to Chris, to minimize his effort in resolving conflicts.
All-right, I back off - I was just trying to help here. Please send the pull request to Chris directly instead.
Kind regards
Ulf Hansson
Quoted 4 lines
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 21/38 mmc: sdhci: hack up driver to make it more compliant with UHS-1
Quoted 23 lines · Ulf Hansson
Quoted 22 lines · Russell King - ARM Linux
Quoted 10 lines · Ulf Hansson
Quoted 9 lines · Markus Pargmann
Hi,
Quoted 5 lines · Russell King
Patch suggested by Dong Aisheng <[email protected]>, this avoids additional clock start/stop cycles during the transition to 1.8V signalling mode.
Signed-off-by Russell King <[email protected]>Quoted 8 lines
Quoted 2 lines
I tested the series on imx6s with a RIoT board. With this patch applied the RIoT board emmc does not work. Here is the output of the board:
Hi Markus,
Thanks for helping out testing!
Does that mean patch 1->20 works fine for you? May I add your tested-by tag?
Why should _you_ add someone elses tested-by tag to _my_ patches?
Quoted 8 lines
Quoted 2 lines
I still wonder whether you understood anything that I've already said to you about the handling of this patch set.
That was based upon that _I_ would help out in creating the pull request to Chris, to minimize his effort in resolving conflicts.
All-right, I back off - I was just trying to help here. Please send the pull request to Chris directly instead.
I thought I clearly explained the logistics in a previous mail:
| I /could/ rebase it but then I wouldn't be able to produce the patch | sets/patches for others [*] (such as the Novena project) to derive | their kernel tree from my iMX6 patch set. | | What I'd prefer is to keep the patch set intact, and provide Chris | with a pull request for it up to patch 33, which would need a | conflict fixed - and this would mean that I can be sure that what | I'm testing, and what I'm distributing is what Chris will also be | submitting.
One of the problems with your approaches is that the commit IDs for the patches I'm carrying become different from the commit IDs which will end up being merged, which then means I have to either silently drop _my_ commits and hope that they've been merged intact, or I have to manually diff each patch and compare it with what's merged, or I have to rebase my patch set on top of what's merged and hope that git spots that the patches are already applied (which it won't do if there's other changes on top of them which make it non-obvious to git that they're applied.)
To put it another way, recommitting these changes makes /more/ work for me in the long run because of how git works.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 22/38 mmc: sdhci: set_uhs_signaling() need not return a value
In reply to Russell King - ARM LinuxThe set_uhs_signaling() method gives the impression that it can fail, but anything returned from the method is entirely ignored by the sdhci driver. So returning failure has no effect.
So, kill the idea that it's possible for this to return an error by removing the returned value.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++-- drivers/mmc/host/sdhci-pxav3.c | 4 +--- drivers/mmc/host/sdhci.h | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +2 -2
@@ -841,7 +841,7 @@ static int esdhc_change_pinstate(struct sdhci_host *host,return pinctrl_select_state (imx_data->pinctrl, pinctrl); } -static int esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) +static void esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) {struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);struct pltfm_imx_data *imx_data = pltfm_host->priv;
@@ -879,7 +879,7 @@ static int esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)break ; } -return esdhc_change_pinstate (host, uhs); +esdhc_change_pinstate (host, uhs); }static void esdhc_reset (struct sdhci_host *host,u8 mask)
drivers/mmc/host/sdhci-pxav3.c +1 -3
@@ -186,7 +186,7 @@ static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode) pxa->power_mode = power_mode; } -static int pxav3_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) +static void pxav3_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) {u16 ctrl_2;
@@ -220,8 +220,6 @@ static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)dev_dbg (mmc_dev (host->mmc),"%s uhs = %d, ctrl_2 = %04X\n" , __func__, uhs, ctrl_2); - -return 0 ; }static const struct sdhci_ops pxav3_sdhci_ops = {
drivers/mmc/host/sdhci.h +1 -1
@@ -287,7 +287,7 @@ struct sdhci_ops {unsigned int (*get_ro)(struct sdhci_host *host);void (*reset)(struct sdhci_host *host,u8 mask);int (*platform_execute_tuning)(struct sdhci_host *host,u32 opcode); -int (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs); +void (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs);void (*hw_reset)(struct sdhci_host *host);void (*platform_suspend)(struct sdhci_host *host);void (*platform_resume)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
In reply to Russell King - ARM LinuxAdd sdhci_set_uhs_signaling() and always call the set_uhs_signaling method. This avoids quirks being added into sdhci_set_uhs_signaling().
--- drivers/mmc/host/sdhci-acpi.c | 2 ++ drivers/mmc/host/sdhci-bcm-kona.c | 1 + drivers/mmc/host/sdhci-bcm2835.c | 1 + drivers/mmc/host/sdhci-cns3xxx.c | 1 + drivers/mmc/host/sdhci-dove.c | 1 + drivers/mmc/host/sdhci-of-arasan.c | 1 + drivers/mmc/host/sdhci-of-esdhc.c | 1 + drivers/mmc/host/sdhci-of-hlwd.c | 1 + drivers/mmc/host/sdhci-pci.c | 1 + drivers/mmc/host/sdhci-pltfm.c | 1 + drivers/mmc/host/sdhci-pxav2.c | 1 + drivers/mmc/host/sdhci-pxav3.c | 1 + drivers/mmc/host/sdhci-s3c.c | 1 + drivers/mmc/host/sdhci-sirf.c | 1 + drivers/mmc/host/sdhci-spear.c | 1 + drivers/mmc/host/sdhci-tegra.c | 1 + drivers/mmc/host/sdhci.c | 42 +++++++++++++++++++++----------------- drivers/mmc/host/sdhci.h | 1 + 18 files changed, 41 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-acpi.c +2 -0
@@ -106,6 +106,7 @@ static const struct sdhci_ops sdhci_acpi_ops_dflt = { .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_ops sdhci_acpi_ops_int = {
@@ -113,6 +114,7 @@ static const struct sdhci_ops sdhci_acpi_ops_int = { .enable_dma = sdhci_acpi_enable_dma, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, .hw_reset = sdhci_acpi_int_hw_reset, };
drivers/mmc/host/sdhci-bcm-kona.c +1 -0
@@ -212,6 +212,7 @@ static struct sdhci_ops sdhci_bcm_kona_ops = { .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, .card_event = sdhci_bcm_kona_card_event, };
drivers/mmc/host/sdhci-bcm2835.c +1 -0
@@ -136,6 +136,7 @@ static const struct sdhci_ops bcm2835_sdhci_ops = { .get_min_clock = bcm2835_sdhci_get_min_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data bcm2835_sdhci_pdata = {
drivers/mmc/host/sdhci-cns3xxx.c +1 -0
@@ -81,6 +81,7 @@ static const struct sdhci_ops sdhci_cns3xxx_ops = { .set_clock = sdhci_cns3xxx_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
drivers/mmc/host/sdhci-dove.c +1 -0
@@ -89,6 +89,7 @@ static const struct sdhci_ops sdhci_dove_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_dove_pdata = {
drivers/mmc/host/sdhci-of-arasan.c +1 -0
@@ -57,6 +57,7 @@ static struct sdhci_ops sdhci_arasan_ops = { .get_timeout_clock = sdhci_arasan_get_timeout_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static struct sdhci_pltfm_data sdhci_arasan_pdata = {
drivers/mmc/host/sdhci-of-esdhc.c +1 -0
@@ -309,6 +309,7 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .adma_workaround = esdhci_of_adma_workaround, .set_bus_width = esdhc_pltfm_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
drivers/mmc/host/sdhci-of-hlwd.c +1 -0
@@ -61,6 +61,7 @@ static const struct sdhci_ops sdhci_hlwd_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
drivers/mmc/host/sdhci-pci.c +1 -0
@@ -1082,6 +1082,7 @@ static const struct sdhci_ops sdhci_pci_ops = { .enable_dma = sdhci_pci_enable_dma, .set_bus_width = sdhci_pci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, .hw_reset = sdhci_pci_hw_reset, };
drivers/mmc/host/sdhci-pltfm.c +1 -0
@@ -48,6 +48,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav2.c +1 -0
@@ -116,6 +116,7 @@ static const struct sdhci_ops pxav2_sdhci_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .set_bus_width = pxav2_mmc_set_bus_width, .reset = pxav2_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-pxav3.c +1 -0
@@ -229,6 +229,7 @@ static const struct sdhci_ops pxav3_sdhci_ops = { .get_max_clock = sdhci_pltfm_clk_get_max_clock, .set_bus_width = sdhci_set_bus_width, .reset = pxav3_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
drivers/mmc/host/sdhci-s3c.c +1 -0
@@ -374,6 +374,7 @@ static struct sdhci_ops sdhci_s3c_ops = { .get_min_clock = sdhci_s3c_get_min_clock, .set_bus_width = sdhci_s3c_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static void sdhci_s3c_notify_change (struct platform_device *dev,int state)
drivers/mmc/host/sdhci-sirf.c +1 -0
@@ -32,6 +32,7 @@ static struct sdhci_ops sdhci_sirf_ops = { .get_max_clock = sdhci_sirf_get_max_clk, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static struct sdhci_pltfm_data sdhci_sirf_pdata = {
drivers/mmc/host/sdhci-spear.c +1 -0
@@ -41,6 +41,7 @@ static const struct sdhci_ops sdhci_pltfm_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };#ifdef CONFIG_OF
drivers/mmc/host/sdhci-tegra.c +1 -0
@@ -156,6 +156,7 @@ static const struct sdhci_ops tegra_sdhci_ops = { .set_clock = sdhci_set_clock, .set_bus_width = tegra_sdhci_set_bus_width, .reset = tegra_sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, };static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
drivers/mmc/host/sdhci.c +23 -19
54 lines not on this page · raw message
drivers/mmc/host/sdhci.h +1 -0
@@ -403,6 +403,7 @@ static inline bool sdhci_sdio_irq_enabled(struct sdhci_host *host)void sdhci_set_clock (struct sdhci_host *host,unsigned int clock);void sdhci_set_bus_width (struct sdhci_host *host,int width);void sdhci_reset (struct sdhci_host *host,u8 mask); +void sdhci_set_uhs_signaling (struct sdhci_host *host,unsigned timing);#ifdef CONFIG_PM extern int sdhci_suspend_host (struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
Quoted 17 lines · Russell King
drivers/mmc/host/sdhci.c +0
-13@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } -if (host->ops->set_uhs_signaling) - host->ops->set_uhs_signaling (host, ios->timing); -else { - ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* Select Bus Speed Mode for host */ - ctrl_2 &= ~SDHCI_CTRL_UHS_MASK ; -if ((ios->timing ==MMC_TIMING_MMC_HS200 ) || - (ios->timing ==MMC_TIMING_UHS_SDR104 )) - ctrl_2 |=SDHCI_CTRL_UHS_SDR104 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR12 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR12 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR25 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR25 ;
drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535
Quoted 10 lines
drivers/mmc/host/sdhci.c +1
-6-else if (ios->timing ==MMC_TIMING_UHS_SDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR50 ; -else if (ios->timing ==MMC_TIMING_UHS_DDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_DDR50 ; -sdhci_writew (host, ctrl_2,SDHCI_HOST_CONTROL2 ); - } + host->ops->set_uhs_signaling (host, ios->timing); if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ((ios->timing == MMC_TIMING_UHS_SDR12) ||
Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.
The other thing I'd ask is that the MMC people learn C precedence rules, and realise that it's not necessary (and actively harmful) to add additional parenthesis around simple if() conditions. Testing for timing being one of two values does not need anything more than one set of parenthesis - it does not need if ((a == b) || (a == c)) - if (a == b || a == c) does just fine, and is less confusing when encountering more complex statements, such as:
if ((((a == b) || (a == c)) && ((d > a) || (d < c))) || (z == f))
compared with:
if (((a == b || a == c) && (d > a || d < c)) || z == f)
With the former "style", I normally end up having to pull the file into the editor, and rewrite the damned statement to work out what the grouping is, because the excessive use of parenthesis is detrimental to readability. Don't do it. Learn the C precedence rules and keep code readable.
Signature · 2 lines
FTTC broadband for 0.8mile line: [email protected] down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
Quoted 26 lines · Russell King - ARM Linux
Quoted 25 lines · Russell King
drivers/mmc/host/sdhci.c +1
-19@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } -if (host->ops->set_uhs_signaling) - host->ops->set_uhs_signaling (host, ios->timing); -else { - ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* Select Bus Speed Mode for host */ - ctrl_2 &= ~SDHCI_CTRL_UHS_MASK ; -if ((ios->timing ==MMC_TIMING_MMC_HS200 ) || - (ios->timing ==MMC_TIMING_UHS_SDR104 )) - ctrl_2 |=SDHCI_CTRL_UHS_SDR104 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR12 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR12 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR25 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR25 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR50 ; -else if (ios->timing ==MMC_TIMING_UHS_DDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_DDR50 ; -sdhci_writew (host, ctrl_2,SDHCI_HOST_CONTROL2 ); - } + host->ops->set_uhs_signaling (host, ios->timing);
Quoted 7 lines
drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535
Quoted 2 lines
drivers/mmc/host/sdhci.c +0
-0if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ((ios->timing == MMC_TIMING_UHS_SDR12) ||Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.
Hi Russell,
We kindly pinged you several times asking for your state and for the PR, but I suppose you were just too busy. Your PR were kind of blocking patches for sdhci, if you remember.
Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.
The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.
Quoted 13 lines
The other thing I'd ask is that the MMC people learn C precedence rules, and realise that it's not necessary (and actively harmful) to add additional parenthesis around simple
if()conditions. Testing for timing being one of two values does not need anything more than one set of parenthesis - it does not need if ((a == b) || (a == c)) - if (a == b || a == c) does just fine, and is less confusing when encountering more complex statements, such as:if ((((a == b) || (a == c)) && ((d > a) || (d < c))) || (z == f))compared with:
Quoted 7 lines
if (((a == b || a == c) && (d > a || d < c)) || z == f)With the former "style", I normally end up having to pull the file into the editor, and rewrite the damned statement to work out what the grouping is, because the excessive use of parenthesis is detrimental to readability. Don't do it. Learn the C precedence rules and keep code readable.
Sure, we will adopt.
Please, feel free to send a patch to fixup my misstake. I will happily apply it.
Kind regards
Ulf Hansson
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
Quoted 35 lines · Ulf Hansson
Quoted 33 lines · Russell King - ARM Linux
Quoted 17 lines · Russell King
drivers/mmc/host/sdhci.c +0
-13@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } -if (host->ops->set_uhs_signaling) - host->ops->set_uhs_signaling (host, ios->timing); -else { - ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* Select Bus Speed Mode for host */ - ctrl_2 &= ~SDHCI_CTRL_UHS_MASK ; -if ((ios->timing ==MMC_TIMING_MMC_HS200 ) || - (ios->timing ==MMC_TIMING_UHS_SDR104 )) - ctrl_2 |=SDHCI_CTRL_UHS_SDR104 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR12 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR12 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR25 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR25 ;drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535
Quoted 10 lines
drivers/mmc/host/sdhci.c +1
-6-else if (ios->timing ==MMC_TIMING_UHS_SDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR50 ; -else if (ios->timing ==MMC_TIMING_UHS_DDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_DDR50 ; -sdhci_writew (host, ctrl_2,SDHCI_HOST_CONTROL2 ); - } + host->ops->set_uhs_signaling (host, ios->timing); if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ((ios->timing == MMC_TIMING_UHS_SDR12) ||Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.
[snip]
Quoted 1 line
Please, feel free to send a patch to fixup my misstake. I will happily apply it.
I had a second look to fix it up myself, but I just can't find that your patch was different than the one I applied (beside the conflict I resolved).
If you do find any other issue regarding the patches in this patchset
- please let me know and I will try to help.
Kind regards
Uffe
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
In reply to Ulf HanssonQuoted 35 lines · Ulf Hansson
Quoted 26 lines · Russell King - ARM Linux
Quoted 25 lines · Russell King
drivers/mmc/host/sdhci.c +1
-19@@ -1507,25 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->ops->set_clock (host, host->clock); } -if (host->ops->set_uhs_signaling) - host->ops->set_uhs_signaling (host, ios->timing); -else { - ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* Select Bus Speed Mode for host */ - ctrl_2 &= ~SDHCI_CTRL_UHS_MASK ; -if ((ios->timing ==MMC_TIMING_MMC_HS200 ) || - (ios->timing ==MMC_TIMING_UHS_SDR104 )) - ctrl_2 |=SDHCI_CTRL_UHS_SDR104 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR12 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR12 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR25 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR25 ; -else if (ios->timing ==MMC_TIMING_UHS_SDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_SDR50 ; -else if (ios->timing ==MMC_TIMING_UHS_DDR50 ) - ctrl_2 |=SDHCI_CTRL_UHS_DDR50 ; -sdhci_writew (host, ctrl_2,SDHCI_HOST_CONTROL2 ); - } + host->ops->set_uhs_signaling (host, ios->timing);Quoted 7 lines
drivers/mmc/host/sdhci.c static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) · line 1535
Quoted 2 lines
drivers/mmc/host/sdhci.c +0
-0if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ((ios->timing == MMC_TIMING_UHS_SDR12) ||Whoever decided to poorly pick these patches up against my will has slightly messed this patch up - whereas my original patch left the code correctly formatted, when whoever applied this patch did so, they left an additional blank line in the above.
Quoted 5 lines
Hi Russell,
We kindly pinged you several times asking for your state and for the PR, but I suppose you were just too busy. Your PR were kind of blocking patches for sdhci, if you remember.
I wasn't "too busy". I had walked away from all kernel maintanence in disgust at the way many in the ARM community ignores questions, and ignores patches which need testing - I'm talking there about the L2C patch series which was extremely poorly tested, and still, to this day, has questions outstanding. Yes, the code now produces warnings. It produces warnings /because/ people were not willing to help.
Those warnings serve as a reminder that there's still problems which need solving there, and they're not going to go away until those problems are solved.
While I don't like pushing unfinished code into mainline, in this case, others deemed the patch set too important _not_ to go into mainline even with these problems.
Now, it's been /soo/ long since I worked on that patch set that my knowledge has now diminished... so it's now going to be _much_ harder to resolve those issues than it would have been three months ago.
And I'm also holding a grudge, and I bear grudges for a long time, so expect me to be "difficult" towards Linux stuff for a while yet.
Quoted 3 lines
The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.
The formatting problem I refer to above is line 1532/1533 in sdhci.c - there's an additional blank line which somehow got left behind, caused presumably by insufficient attention paid to cleaning up a conflict between my original patches and the state of the tree they were applied to.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
In reply to Ulf HanssonQuoted 9 lines · Ulf Hansson
Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.
The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.
I tend to look through slightly less rose-tinted glasses.
The fact is... there's loads of ARM platforms which now fail in Olof's build/boot testing, and they all seem to have a very similar pattern:
hummingboard:
[ 1.149688] sdhci: Secure Digital Host Controller Interface driver [ 1.155901] sdhci: Copyright(c) Pierre Ossman ... [ 1.253630] Waiting for root device /dev/mmcblk0p2... [ 60.325469] imx-sdma 20ec000.sdma: firmware not found
~$off
# PYBOOT: Exception: timeout
jetson:
[ 2.261355] Waiting for root device /dev/mmcblk0p1...
wandboard:
[ 1.186870] sdhci: Secure Digital Host Controller Interface driver [ 1.193075] sdhci: Copyright(c) Pierre Ossman ... [ 1.291064] Waiting for root device /dev/mmcblk0p2...
Whether these are caused by the patch set or not is anyone's guess, because we (a) don't know what's causing these failures, and (b) my patch series was never tested on anything but iMX6.
I'm pretty certain that the hummingboard failure is not related to my series as that's one of the platforms I did test my series on.
There's more failures which look like possibly something in core MMC is rather screwed, as OMAP5 (which doesn't use SDHCI) is also failing at a similar point.
What these failures /do/ mean is that when I'm pushing my ARM for-next branch out, Olof's builder picks it up and runs a build across it, and the report returns a whole load of failures. A whole load of failures means that those platforms haven't tested my changes, which means the quality of testing is much lower than it should be.
With 26 passing and 15 failing, that's over 1/3 of platforms failing, which means 1/3 aren't getting tested.
This level of failure has been going on for quite a while now, and (afaik) it remains uninvestigated and undiagnosed. (This is one of the complaints I have about Olof's build/boot test system, much of the information about the build and boot is hidden away and unpublished, which makes it almost impossible for third parties to diagnose any problem there. I've given up looking at most of Olof's build/boot mails because of this - it's just not interesting to see the same abbreviated boot failure logs which give no useful information time and time again.)
We need to get on top of these failures and get them sorted.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
Quoted 25 lines · Russell King - ARM Linux
Quoted 9 lines · Ulf Hansson
Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.
The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.
I tend to look through slightly less rose-tinted glasses.
The fact is... there's loads of ARM platforms which now fail in Olof's build/boot testing, and they all seem to have a very similar pattern:
hummingboard:
[ 1.149688] sdhci: Secure Digital Host Controller Interface driver [ 1.155901] sdhci: Copyright(c) Pierre Ossman ... [ 1.253630] Waiting for root device /dev/mmcblk0p2... [ 60.325469] imx-sdma 20ec000.sdma: firmware not found~$off
# PYBOOT: Exception: timeout
Quoted 8 lines
jetson:
[ 2.261355] Waiting for root device /dev/mmcblk0p1...wandboard:
[ 1.186870] sdhci: Secure Digital Host Controller Interface driver [ 1.193075] sdhci: Copyright(c) Pierre Ossman ... [ 1.291064] Waiting for root device /dev/mmcblk0p2...
Any SDHCI failures in Linus' tree (but not linux-next) that occur only in multi_v7_defconfig are likely solved by:
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-June/264012.html
[PATCH] ARM: multi_v7_defconfig: re-enable SDHCI drivers
Quoted 3 lines
Whether these are caused by the patch set or not is anyone's guess, because we (a) don't know what's causing these failures, and (b) my patch series was never tested on anything but iMX6.
I thought that I'd tested at least some of it on Tegra.
PATCH 23/38 mmc: sdhci: convert sdhci_set_uhs_signaling() into a library function
In reply to Russell King - ARM LinuxQuoted 54 lines · Russell King - ARM Linux
Quoted 9 lines · Ulf Hansson
Anyway, we did get some folks to test the patches and was thus fairly confident that we could merge them. Chris asked me to try to collect them in a PR for him, so I did. Sorry if I managed to screw some things up, there were several conflicts and actual regressions, which I tried to take care of.
The mmc people were also very helping in sending patches to fixup related regressions, immediately after we merged your patchset. Thus together I think we managed to pull it off.
I tend to look through slightly less rose-tinted glasses.
The fact is... there's loads of ARM platforms which now fail in Olof's build/boot testing, and they all seem to have a very similar pattern:
hummingboard:
[ 1.149688] sdhci: Secure Digital Host Controller Interface driver [ 1.155901] sdhci: Copyright(c) Pierre Ossman ... [ 1.253630] Waiting for root device /dev/mmcblk0p2... [ 60.325469] imx-sdma 20ec000.sdma: firmware not found~$off
# PYBOOT: Exception: timeoutjetson:
[ 2.261355] Waiting for root device /dev/mmcblk0p1...wandboard:
[ 1.186870] sdhci: Secure Digital Host Controller Interface driver [ 1.193075] sdhci: Copyright(c) Pierre Ossman ... [ 1.291064] Waiting for root device /dev/mmcblk0p2...Whether these are caused by the patch set or not is anyone's guess, because we (a) don't know what's causing these failures, and (b) my patch series was never tested on anything but iMX6.
I'm pretty certain that the hummingboard failure is not related to my series as that's one of the platforms I did test my series on.
There's more failures which look like possibly something in core MMC is rather screwed, as OMAP5 (which doesn't use SDHCI) is also failing at a similar point.
What these failures /do/ mean is that when I'm pushing my ARM for-next branch out, Olof's builder picks it up and runs a build across it, and the report returns a whole load of failures. A whole load of failures means that those platforms haven't tested my changes, which means the quality of testing is much lower than it should be.
With 26 passing and 15 failing, that's over 1/3 of platforms failing, which means 1/3 aren't getting tested.
Quoted 8 lines
This level of failure has been going on for quite a while now, and (afaik) it remains uninvestigated and undiagnosed. (This is one of the complaints I have about Olof's build/boot test system, much of the information about the build and boot is hidden away and unpublished, which makes it almost impossible for third parties to diagnose any problem there. I've given up looking at most of Olof's build/boot mails because of this - it's just not interesting to see the same abbreviated boot failure logs which give no useful information time and time again.)
Most of this is because I want to avoid sending huuuge emails out with the failures. I'll add a push of the full log to arm-soc.lixom.net and include a link to it in the emails, similar to how I do the build logs. I'll let you know when I've made that change.
-Olof
PATCH 24/38 mmc: sdhci: cache timing information locally
In reply to Russell King - ARM LinuxRather than reading back the timing information from the registers, cache it locally. This allows implementations to translate the UHS timing by overriding the set_uhs_signaling() method as required without also having to emulate the SDHCI_HOST_CONTROL2 register.
--- drivers/mmc/host/sdhci.c | 23 ++++++++++++----------- include/linux/mmc/sdhci.h | 2 ++ 2 files changed, 14 insertions(+), 11 deletions(-)
drivers/mmc/host/sdhci.c +12 -11
@@ -1083,24 +1083,23 @@ static void sdhci_finish_command(struct sdhci_host *host)static u16 sdhci_get_preset_value (struct sdhci_host *host) { -u16 ctrl, preset =0 ; +u16 preset =0 ; - ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); - -switch (ctrl &SDHCI_CTRL_UHS_MASK ) { -case SDHCI_CTRL_UHS_SDR12 : +switch (host->timing) { +case MMC_TIMING_UHS_SDR12 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR12 );break ; -case SDHCI_CTRL_UHS_SDR25 : +case MMC_TIMING_UHS_SDR25 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR25 );break ; -case SDHCI_CTRL_UHS_SDR50 : +case MMC_TIMING_UHS_SDR50 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR50 );break ; -case SDHCI_CTRL_UHS_SDR104 : +case MMC_TIMING_UHS_SDR104 : +case MMC_TIMING_MMC_HS200 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_SDR104 );break ; -case SDHCI_CTRL_UHS_DDR50 : +case MMC_TIMING_UHS_DDR50 : preset =sdhci_readw (host,SDHCI_PRESET_FOR_DDR50 );break ;default :
@@ -1530,6 +1529,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) } host->ops->set_uhs_signaling (host, ios->timing); + host->timing = ios->timing; if (!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN) && ((ios->timing == MMC_TIMING_UHS_SDR12) ||
@@ -1828,12 +1828,13 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)* If the Host Controller supports the HS200 mode then the * tuning function has to be executed. */ -if (((ctrl &SDHCI_CTRL_UHS_MASK ) ==SDHCI_CTRL_UHS_SDR50 ) && +if (host->timing ==MMC_TIMING_UHS_SDR50 && (host->flags &SDHCI_SDR50_NEEDS_TUNING || host->flags &SDHCI_SDR104_NEEDS_TUNING )) requires_tuning_nonuhs = true; -if (((ctrl &SDHCI_CTRL_UHS_MASK ) ==SDHCI_CTRL_UHS_SDR104 ) || +if (host->timing ==MMC_TIMING_MMC_HS200 || + host->timing ==MMC_TIMING_UHS_SDR104 || requires_tuning_nonuhs) ctrl |=SDHCI_CTRL_EXEC_TUNING ;else {
include/linux/mmc/sdhci.h +2 -0
@@ -172,6 +172,8 @@ struct sdhci_host {unsigned int ocr_avail_mmc;u32 ocr_mask;/* available voltages */ +unsigned timing;/* Current timing */ +u32 thread_isr;/* cached registers */
Signature · 1 line
1.8.3.1
PATCH 25/38 mmc: sdhci: clean up sdhci_execute_tuning() decision
In reply to Russell King - ARM LinuxClean up the code in sdhci_execute_tuning() so the decision whether to execute tuning is clearer - and despite this reflecting what the original code was doing, it shows that it may not be what the author actually intended.
--- drivers/mmc/host/sdhci.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
drivers/mmc/host/sdhci.c +15 -16
@@ -1806,21 +1806,16 @@ static int sdhci_card_busy(struct mmc_host *mmc)static int sdhci_execute_tuning (struct mmc_host *mmc,u32 opcode) { -struct sdhci_host *host; +struct sdhci_host *host =mmc_priv (mmc);u16 ctrl;int tuning_loop_counter =MAX_TUNING_LOOP ;unsigned long timeout;int err =0 ; -bool requires_tuning_nonuhs = false;unsigned long flags; - host =mmc_priv (mmc); -sdhci_runtime_pm_get (host);spin_lock_irqsave (&host->lock, flags); - ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* * The Host Controller needs tuning only in case of SDR104 mode * and for SDR50 mode when Use Tuning for SDR50 is set in the
@@ -1828,16 +1823,18 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)* If the Host Controller supports the HS200 mode then the * tuning function has to be executed. */ -if (host->timing ==MMC_TIMING_UHS_SDR50 && - (host->flags &SDHCI_SDR50_NEEDS_TUNING || - host->flags &SDHCI_SDR104_NEEDS_TUNING )) - requires_tuning_nonuhs = true; - -if (host->timing ==MMC_TIMING_MMC_HS200 || - host->timing ==MMC_TIMING_UHS_SDR104 || - requires_tuning_nonuhs) - ctrl |=SDHCI_CTRL_EXEC_TUNING ; -else { +switch (host->timing) { +case MMC_TIMING_MMC_HS200 : +case MMC_TIMING_UHS_SDR104 : +break ; + +case MMC_TIMING_UHS_SDR50 : +if (host->flags &SDHCI_SDR50_NEEDS_TUNING || + host->flags &SDHCI_SDR104_NEEDS_TUNING ) +break ; +/* FALLTHROUGH */ + +default :spin_unlock_irqrestore (&host->lock, flags);sdhci_runtime_pm_put (host);return 0 ;
@@ -1850,6 +1847,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)return err; } + ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); + ctrl |=SDHCI_CTRL_EXEC_TUNING ;sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 );/*
Signature · 1 line
1.8.3.1
PATCH 26/38 mmc: sdhci-esdhc-imx: remove emulation of uhs_mode
In reply to Russell King - ARM LinuxWe no longer need to emulate the uhs_mode field of the host control2 register - the main sdhci driver never reads this back to evaluate the current mode as it caches the current mode instead.
--- drivers/mmc/host/sdhci-esdhc-imx.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-)
drivers/mmc/host/sdhci-esdhc-imx.c +3 -14
@@ -160,7 +160,6 @@ struct pltfm_imx_data {MULTIBLK_IN_PROCESS ,/* exact multiblock cmd in process */ WAIT_FOR_INT ,/* sent CMD12, waiting for response INT */ } multiblock_status; -u32 uhs_mode;u32 is_ddr; };
@@ -382,7 +381,6 @@ static u16 esdhc_readw_le(struct sdhci_host *host, int reg)if (val &ESDHC_MIX_CTRL_SMPCLK_SEL ) ret |=SDHCI_CTRL_TUNED_CLK ; - ret |= (imx_data->uhs_mode &SDHCI_CTRL_UHS_MASK ); ret &= ~SDHCI_CTRL_PRESET_VAL_ENABLE ;return ret;
@@ -429,7 +427,6 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)else new_val &= ~ESDHC_VENDOR_SPEC_VSELECT ;writel (new_val, host->ioaddr +ESDHC_VENDOR_SPEC ); - imx_data->uhs_mode = val &SDHCI_CTRL_UHS_MASK ;if (imx_data->socdata->flags &ESDHC_FLAG_MAN_TUNING ) { new_val =readl (host->ioaddr +ESDHC_MIX_CTRL );if (val &SDHCI_CTRL_TUNED_CLK )
@@ -841,28 +838,20 @@ static int esdhc_change_pinstate(struct sdhci_host *host,return pinctrl_select_state (imx_data->pinctrl, pinctrl); } -static void esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned int uhs) +static void esdhc_set_uhs_signaling (struct sdhci_host *host,unsigned timing) {struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);struct pltfm_imx_data *imx_data = pltfm_host->priv;struct esdhc_platform_data *boarddata = &imx_data->boarddata; -switch (uhs) { +switch (timing) {case MMC_TIMING_UHS_SDR12 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR12 ; -break ;case MMC_TIMING_UHS_SDR25 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR25 ; -break ;case MMC_TIMING_UHS_SDR50 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR50 ; -break ;case MMC_TIMING_UHS_SDR104 :case MMC_TIMING_MMC_HS200 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_SDR104 ;break ;case MMC_TIMING_UHS_DDR50 : - imx_data->uhs_mode =SDHCI_CTRL_UHS_DDR50 ;writel (readl (host->ioaddr +ESDHC_MIX_CTRL ) |ESDHC_MIX_CTRL_DDREN , host->ioaddr +ESDHC_MIX_CTRL );
@@ -879,7 +868,7 @@ static void esdhc_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)break ; } -esdhc_change_pinstate (host, uhs); +esdhc_change_pinstate (host, timing); }static void esdhc_reset (struct sdhci_host *host,u8 mask)
Signature · 1 line
1.8.3.1
PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks
In reply to Russell King - ARM LinuxWe don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.
--- drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-)
drivers/mmc/host/sdhci-of-esdhc.c +36 -19
@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)mdelay (1 ); } -#ifdef CONFIG_PM -static u32 esdhc_proctl; -static void esdhc_of_suspend (struct sdhci_host *host) -{ - esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); -} - -static void esdhc_of_resume (struct sdhci_host *host) -{ -esdhc_of_enable_dma (host); -sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); -} -#endif -static void esdhc_of_platform_init (struct sdhci_host *host) {u32 vvn;
@@ -302,16 +288,47 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .get_max_clock = esdhc_of_get_max_clock, .get_min_clock = esdhc_of_get_min_clock, .platform_init = esdhc_of_platform_init, -#ifdef CONFIG_PM - .platform_suspend = esdhc_of_suspend, - .platform_resume = esdhc_of_resume, -#endif .adma_workaround = esdhci_of_adma_workaround, .set_bus_width = esdhc_pltfm_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, }; +#ifdef CONFIG_PM + +static u32 esdhc_proctl; +static int esdhc_of_suspend (struct device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); + + esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); + +return sdhci_suspend_host (host); +} + +static void esdhc_of_resume (device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); +int ret =sdhci_resume_host (host); + +if (ret ==0 ) { +/* Isn't this already done by sdhci_resume_host() ? --rmk */ +esdhc_of_enable_dma (host); +sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); + } + +return ret; +} + +static const struct dev_pm_ops esdhc_pmops = { + .suspend = esdhci_of_suspend, + .resume = esdhci_of_resume, +}; +#define ESDHC_PMOPS (&esdhc_pmops) +#else +#define ESDHC_PMOPS NULL +#endif +static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {/* * card detection could be handled via GPIO
@@ -373,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = { .name = "sdhci-esdhc", .owner = THIS_MODULE, .of_match_table = sdhci_esdhc_of_match, - .pm = SDHCI_PLTFM_PMOPS, + .pm = ESDHC_PMOPS, }, .probe = sdhci_esdhc_probe, .remove = sdhci_esdhc_remove,
Signature · 1 line
1.8.3.1
PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks
Quoted 39 lines · Russell King
We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.
Signed-off-by Russell King <[email protected]>--- drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-)drivers/mmc/host/sdhci-of-esdhc.c +0
-15@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)mdelay (1 ); } -#ifdef CONFIG_PM -static u32 esdhc_proctl; -static void esdhc_of_suspend (struct sdhci_host *host) -{ - esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); -} - -static void esdhc_of_resume (struct sdhci_host *host) -{ -esdhc_of_enable_dma (host); -sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); -} -#endif -static void esdhc_of_platform_init (struct sdhci_host *host) {u32 vvn;@@ -302,16 +288,47 @@ static const struct sdhci_ops sdhci_esdhc_ops = { .get_max_clock = esdhc_of_get_max_clock, .get_min_clock = esdhc_of_get_min_clock, .platform_init = esdhc_of_platform_init, -#ifdef CONFIG_PM
drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 297
Quoted 10 lines
drivers/mmc/host/sdhci-of-esdhc.c +1
-3- .platform_suspend = esdhc_of_suspend, - .platform_resume = esdhc_of_resume, -#endif .adma_workaround = esdhci_of_adma_workaround, .set_bus_width = esdhc_pltfm_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, }; +#ifdef CONFIG_PM
This should be CONFIG_PM_SLEEP
Quoted 24 lines
drivers/mmc/host/sdhci-of-esdhc.c +24
-0+ +static u32 esdhc_proctl; +static int esdhc_of_suspend (struct device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); + + esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); + +return sdhci_suspend_host (host); +} + +static void esdhc_of_resume (device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); +int ret =sdhci_resume_host (host); + +if (ret ==0 ) { +/* Isn't this already done by sdhci_resume_host() ? --rmk */ +esdhc_of_enable_dma (host); +sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); + } + +return ret; +}
drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 331
Quoted 10 lines
drivers/mmc/host/sdhci-of-esdhc.c +10
-0+ +static const struct dev_pm_ops esdhc_pmops = { + .suspend = esdhci_of_suspend, + .resume = esdhci_of_resume, +}; +#define ESDHC_PMOPS (&esdhc_pmops) +#else +#define ESDHC_PMOPS NULL +#endif +
I would suggest to use the SIMPLE_DEV_PM_OPS macro to simplify code a bit.
Quoted 15 lines
drivers/mmc/host/sdhci-of-esdhc.c +1
-2static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {/* * card detection could be handled via GPIO @@ -373,7 +390,7 @@ static struct platform_driver sdhci_esdhc_driver = { .name = "sdhci-esdhc", .owner = THIS_MODULE, .of_match_table = sdhci_esdhc_of_match, - .pm = SDHCI_PLTFM_PMOPS, + .pm = ESDHC_PMOPS, }, .probe = sdhci_esdhc_probe, .remove = sdhci_esdhc_remove, --1.8.3.1
Quoted 4 lines
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Kind regards
Ulf Hansson
PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks
Quoted 19 lines · Ulf Hansson
Quoted 18 lines · Russell King
We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.
Signed-off-by Russell King <[email protected]>--- drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-)drivers/mmc/host/sdhci-of-esdhc.c +0
-1@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)mdelay (1 ); } -#ifdef CONFIG_PM
...
Quoted 3 lines
Quoted 1 line
+#ifdef
CONFIG_PMThis should be
CONFIG_PM_SLEEP
That may be the case, but that would be an additional modification, and so should be a separate patch.
Quoted 29 lines
Quoted 29 lines
drivers/mmc/host/sdhci-of-esdhc.c +28
-0+ +static u32 esdhc_proctl; +static int esdhc_of_suspend (struct device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); + + esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); + +return sdhci_suspend_host (host); +} + +static void esdhc_of_resume (device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); +int ret =sdhci_resume_host (host); + +if (ret ==0 ) { +/* Isn't this already done by sdhci_resume_host() ? --rmk */ +esdhc_of_enable_dma (host); +sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); + } + +return ret; +} + +static const struct dev_pm_ops esdhc_pmops = { + .suspend = esdhci_of_suspend, + .resume = esdhci_of_resume,
Quoted 8 lines
drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 331
Quoted 6 lines
drivers/mmc/host/sdhci-of-esdhc.c +6
-0+}; +#define ESDHC_PMOPS (&esdhc_pmops) +#else +#define ESDHC_PMOPS NULL +#endif +I would suggest to use the
SIMPLE_DEV_PM_OPSmacro to simplify code a bit.
That is dependent on changing the ifdef. As I say, that should be a separate patch - possibly one which comes before this one.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks
Quoted 19 lines · Russell King - ARM Linux
Quoted 18 lines · Ulf Hansson
Quoted 17 lines · Russell King
We don't need these hooks in order to insert code in these paths, we can just provide our own handlers and call the main sdhci handlers as appropriate.
Signed-off-by Russell King <[email protected]>--- drivers/mmc/host/sdhci-of-esdhc.c | 55 +++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 19 deletions(-)drivers/mmc/host/sdhci-of-esdhc.c +0
-0@@ -241,20 +241,6 @@ static void esdhc_of_set_clock(struct sdhci_host *host, unsigned int clock)mdelay (1 ); }
Quoted 8 lines
Quoted 1 line
Quoted 1 line
drivers/mmc/host/sdhci-of-esdhc.c +0
-1-#ifdef CONFIG_PM ...
Quoted 3 lines
Quoted 1 line
+#ifdef
CONFIG_PMThis should be
CONFIG_PM_SLEEPThat may be the case, but that would be an additional modification, and so should be a separate patch.
I just thought it make sense to include it here - it's really a simple fix, touching the same code as this patch.
Additionally, it would simplify this patch since you would be able to use the PM macro.
Quoted 38 lines
Quoted 29 lines
Quoted 29 lines
drivers/mmc/host/sdhci-of-esdhc.c +28
-0+ +static u32 esdhc_proctl; +static int esdhc_of_suspend (struct device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); + + esdhc_proctl =sdhci_be32bs_readl (host,SDHCI_HOST_CONTROL ); + +return sdhci_suspend_host (host); +} + +static void esdhc_of_resume (device *dev) +{ +struct sdhci_host *host =dev_get_drvdata (dev); +int ret =sdhci_resume_host (host); + +if (ret ==0 ) { +/* Isn't this already done by sdhci_resume_host() ? --rmk */ +esdhc_of_enable_dma (host); +sdhci_be32bs_writel (host, esdhc_proctl,SDHCI_HOST_CONTROL ); + } + +return ret; +} + +static const struct dev_pm_ops esdhc_pmops = { + .suspend = esdhci_of_suspend, + .resume = esdhci_of_resume,Quoted 8 lines
drivers/mmc/host/sdhci-of-esdhc.c static const struct sdhci_ops sdhci_esdhc_ops = { · line 331
Quoted 6 lines
drivers/mmc/host/sdhci-of-esdhc.c +6
-0+}; +#define ESDHC_PMOPS (&esdhc_pmops) +#else +#define ESDHC_PMOPS NULL +#endif +I would suggest to use the
SIMPLE_DEV_PM_OPSmacro to simplify code a bit.
Quoted 2 lines
That is dependent on changing the ifdef. As I say, that should be a separate patch - possibly one which comes before this one.
So, choose whatever option you prefer, if you would like another patch going before this one, I am fine with that. As long as we convert to use the macro, I am happy. :-)
Quoted 4 lines
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks
Quoted 9 lines · Ulf Hansson
Quoted 2 lines · Russell King - ARM Linux
That may be the case, but that would be an additional modification, and so should be a separate patch.
I just thought it make sense to include it here - it's really a simple fix, touching the same code as this patch.
Additionally, it would simplify this patch since you would be able to use the PM macro.
No, I'm not going to make this change after looking deeper at the existing code.
The existing code does this:
sdhci-pltfm.c:
#ifdef CONFIG_PM
int sdhci_pltfm_suspend(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
return sdhci_suspend_host(host);
}EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);
int sdhci_pltfm_resume(struct device *dev)
{
struct sdhci_host *host = dev_get_drvdata(dev);
return sdhci_resume_host(host);
}EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);
const struct dev_pm_ops sdhci_pltfm_pmops = {
.suspend = sdhci_pltfm_suspend,
.resume = sdhci_pltfm_resume,
};EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
#endif /* CONFIG_PM */
sdhci-pltfm.h:
#ifdef CONFIG_PM
extern int sdhci_pltfm_suspend(struct device *dev); extern int sdhci_pltfm_resume(struct device *dev); extern const struct dev_pm_ops sdhci_pltfm_pmops; #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops) #else
#define SDHCI_PLTFM_PMOPS NULL
#endif
sdhci-of-esdhc.c:
static struct platform_driver sdhci_esdhc_driver = {
.driver = {
.pm = SDHCI_PLTFM_PMOPS,
Changing this to use SIMPLE_DEV_PM_OPS changes the behaviour of this by placing the callbacks into the other methods.
Is that change correct?
Who's going to test that that change doesn't break anything (I don't have the hardware, and it's not a transformational change like the rest of the patch set, but a functional change)?
Should this change be made for other SDHCI platforms as well?
Frankly, I'm not happy to make such a change in a series which is supposed to be mainly about cleaning up and _not_ introducing functional changes.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 27/38 mmc: sdhci-of-esdhc: remove platform_suspend/platform_resume callbacks
Quoted 59 lines · Russell King - ARM Linux
Quoted 9 lines · Ulf Hansson
Quoted 2 lines · Russell King - ARM Linux
That may be the case, but that would be an additional modification, and so should be a separate patch.
I just thought it make sense to include it here - it's really a simple fix, touching the same code as this patch.
Additionally, it would simplify this patch since you would be able to use the PM macro.
No, I'm not going to make this change after looking deeper at the existing code.
The existing code does this:
sdhci-pltfm.c:
#ifdefCONFIG_PM
intsdhci_pltfm_suspend(struct device *dev){ struct sdhci_host *host = dev_get_drvdata(dev); return sdhci_suspend_host(host); }
EXPORT_SYMBOL_GPL(sdhci_pltfm_suspend);int
sdhci_pltfm_resume(struct device *dev){ struct sdhci_host *host = dev_get_drvdata(dev); return sdhci_resume_host(host); }
EXPORT_SYMBOL_GPL(sdhci_pltfm_resume);const struct
dev_pm_opssdhci_pltfm_pmops= {
.suspend =sdhci_pltfm_suspend,
.resume =sdhci_pltfm_resume,
};EXPORT_SYMBOL_GPL(sdhci_pltfm_pmops);
#endif /*CONFIG_PM*/
sdhci-pltfm.h:
#ifdefCONFIG_PM
extern intsdhci_pltfm_suspend(struct device *dev); extern intsdhci_pltfm_resume(struct device *dev); extern const structdev_pm_opssdhci_pltfm_pmops; #defineSDHCI_PLTFM_PMOPS(&sdhci_pltfm_pmops) #else
#defineSDHCI_PLTFM_PMOPSNULL
#endif
sdhci-of-esdhc.c:
static structplatform_driversdhci_esdhc_driver= {
.driver = {
.pm =SDHCI_PLTFM_PMOPS,Changing this to use
SIMPLE_DEV_PM_OPSchanges the behaviour of this by placing the callbacks into the other methods.
Quoted 8 lines
Is that change correct?
Who's going to test that that change doesn't break anything (I don't have the hardware, and it's not a transformational change like the rest of the patch set, but a functional change)?
Should this change be made for other SDHCI platforms as well?Frankly, I'm not happy to make such a change in a series which is supposed to be mainly about cleaning up and _not_ introducing functional changes.
Fair enough, let's keep it as is then and let's handle functional changes separate.
Quoted 4 lines
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 28/38 mmc: sdhci: remove platform_suspend/platform_resume callbacks
In reply to Russell King - ARM LinuxThe only user (sdhci-of-esdhc) no longer uses these callbacks, so lets remove them to discourage any further use.
--- drivers/mmc/host/sdhci.c | 6 ------ drivers/mmc/host/sdhci.h | 2 -- 2 files changed, 8 deletions(-)
drivers/mmc/host/sdhci.c +0 -6
@@ -2530,9 +2530,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);int sdhci_suspend_host (struct sdhci_host *host) { -if (host->ops->platform_suspend) - host->ops->platform_suspend (host); -sdhci_disable_card_detection (host);/* Disable tuning since we are suspending */
@@ -2589,9 +2586,6 @@ int sdhci_resume_host(struct sdhci_host *host)sdhci_enable_card_detection (host); -if (host->ops->platform_resume) - host->ops->platform_resume (host); -/* Set the re-tuning expiration flag */ if (host->flags &SDHCI_USING_RETUNING_TIMER ) host->flags |=SDHCI_NEEDS_RETUNING ;
drivers/mmc/host/sdhci.h +0 -2
@@ -289,8 +289,6 @@ struct sdhci_ops {int (*platform_execute_tuning)(struct sdhci_host *host,u32 opcode);void (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs);void (*hw_reset)(struct sdhci_host *host); -void (*platform_suspend)(struct sdhci_host *host); -void (*platform_resume)(struct sdhci_host *host);void (*adma_workaround)(struct sdhci_host *host,u32 intmask);void (*platform_init)(struct sdhci_host *host);void (*card_event)(struct sdhci_host *host);
Signature · 1 line
1.8.3.1
PATCH 28/38 mmc: sdhci: remove platform_suspend/platform_resume callbacks
Quoted 4 lines · Russell King
The only user (sdhci-of-esdhc) no longer uses these callbacks, so lets remove them to discourage any further use.
Signed-off-by Russell King <[email protected]>
Quoted 49 lines
--- drivers/mmc/host/sdhci.c | 6 ------ drivers/mmc/host/sdhci.h | 2 -- 2 files changed, 8 deletions(-)drivers/mmc/host/sdhci.c +0
-6@@ -2530,9 +2530,6 @@ EXPORT_SYMBOL_GPL(sdhci_disable_irq_wakeups);int sdhci_suspend_host (struct sdhci_host *host) { -if (host->ops->platform_suspend) - host->ops->platform_suspend (host); -sdhci_disable_card_detection (host);/* Disable tuning since we are suspending */ @@ -2589,9 +2586,6 @@ int sdhci_resume_host(struct sdhci_host *host)sdhci_enable_card_detection (host); -if (host->ops->platform_resume) - host->ops->platform_resume (host); -/* Set the re-tuning expiration flag */ if (host->flags &SDHCI_USING_RETUNING_TIMER ) host->flags |=SDHCI_NEEDS_RETUNING ;drivers/mmc/host/sdhci.h +0
-3@@ -289,8 +289,6 @@ struct sdhci_ops {int (*platform_execute_tuning)(struct sdhci_host *host,u32 opcode);void (*set_uhs_signaling)(struct sdhci_host *host,unsigned int uhs);void (*hw_reset)(struct sdhci_host *host); -void (*platform_suspend)(struct sdhci_host *host); -void (*platform_resume)(struct sdhci_host *host);void (*adma_workaround)(struct sdhci_host *host,u32 intmask);void (*platform_init)(struct sdhci_host *host);void (*card_event)(struct sdhci_host *host); --1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 29/38 mmc: sdhci-tegra: get rid of special PRESENT_STATE register handling
In reply to Russell King - ARM Linuxsdhci-tegra provides a get_ro method, which overrides the checking of the write protect bit in the PRESENT_STATE register in sdhci.c:
if (host->flags & SDHCI_DEVICE_DEAD)
is_readonly = 0;
else if (host->ops->get_ro)
is_readonly = host->ops->get_ro(host);
else
is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
& SDHCI_WRITE_PROTECT);This means it's pointless detecting accesses to this register and manually setting the SDHCI_WRITE_PROTECT as it has no effect.
This means that the whole of tegra_sdhci_readl() can be removed and we can use the builtin sdhci readl functionality here.
--- drivers/mmc/host/sdhci-tegra.c | 14 -------------- 1 file changed, 14 deletions(-)
drivers/mmc/host/sdhci-tegra.c +0 -14
@@ -48,19 +48,6 @@ struct sdhci_tegra {int power_gpio; }; -static u32 tegra_sdhci_readl (struct sdhci_host *host,int reg) -{ -u32 val; - -if (unlikely (reg ==SDHCI_PRESENT_STATE )) { -/* Use wp_gpio here instead? */ - val =readl (host->ioaddr + reg); -return val |SDHCI_WRITE_PROTECT ; - } - -return readl (host->ioaddr + reg); -} -static u16 tegra_sdhci_readw (struct sdhci_host *host,int reg) {struct sdhci_pltfm_host *pltfm_host =sdhci_priv (host);
@@ -150,7 +137,6 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)static const struct sdhci_ops tegra_sdhci_ops = { .get_ro = tegra_sdhci_get_ro, - .read_l = tegra_sdhci_readl, .read_w = tegra_sdhci_readw, .write_l = tegra_sdhci_writel, .set_clock = sdhci_set_clock,
Signature · 1 line
1.8.3.1
PATCH 30/38 mmc: sdhci: move regulator handling into sdhci_set_power()
In reply to Russell King - ARM LinuxMove the regulator handling into sdhci_set_power() rather than being in sdhci_do_set_ios(). This wraps all power control up into this function.
--- drivers/mmc/host/sdhci.c | 72 +++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 37 deletions(-)
drivers/mmc/host/sdhci.c +35 -37
@@ -1216,7 +1216,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) }EXPORT_SYMBOL_GPL (sdhci_set_clock); -static int sdhci_set_power (struct sdhci_host *host,unsigned short power) +static void sdhci_set_power (struct sdhci_host *host,unsigned short power) {u8 pwr =0 ;
@@ -1239,7 +1239,7 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power) }if (host->pwr == pwr) -return -1 ; +return ; host->pwr = pwr;
@@ -1247,38 +1247,43 @@ static int sdhci_set_power(struct sdhci_host *host, unsigned short power)sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL );if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON )sdhci_runtime_pm_bus_off (host); -return 0 ; - } - -/* -* Spec says that we should clear the power reg before setting -* a new value. Some controllers don't seem to like this though. -*/ -if (!(host->quirks &SDHCI_QUIRK_SINGLE_POWER_WRITE )) -sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL ); + power =0 ; + }else { +/* +* Spec says that we should clear the power reg before setting +* a new value. Some controllers don't seem to like this though. +*/ +if (!(host->quirks &SDHCI_QUIRK_SINGLE_POWER_WRITE )) +sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL ); -/* -* At least the Marvell CaFe chip gets confused if we set the voltage -* and set turn on power at the same time, so set the voltage first. -*/ -if (host->quirks &SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER ) -sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); +/* +* At least the Marvell CaFe chip gets confused if we set the +* voltage and set turn on power at the same time, so set the +* voltage first. +*/ +if (host->quirks &SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER ) +sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); - pwr |=SDHCI_POWER_ON ; + pwr |=SDHCI_POWER_ON ; -sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); +sdhci_writeb (host, pwr,SDHCI_POWER_CONTROL ); -if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON ) -sdhci_runtime_pm_bus_on (host); +if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON ) +sdhci_runtime_pm_bus_on (host); -/* -* Some controllers need an extra 10ms delay of 10ms before they -* can apply clock after applying power -*/ -if (host->quirks &SDHCI_QUIRK_DELAY_AFTER_POWER ) -mdelay (10 ); +/* +* Some controllers need an extra 10ms delay of 10ms before +* they can apply clock after applying power +*/ +if (host->quirks &SDHCI_QUIRK_DELAY_AFTER_POWER ) +mdelay (10 ); + } -return power; +if (host->vmmc) { +spin_unlock_irq (&host->lock); +mmc_regulator_set_ocr (host->mmc, host->vmmc, power); +spin_lock_irq (&host->lock); + } }/*****************************************************************************\
@@ -1428,7 +1433,6 @@ EXPORT_SYMBOL_GPL(sdhci_set_uhs_signaling);static void sdhci_do_set_ios (struct sdhci_host *host,struct mmc_ios *ios) {unsigned long flags; -int vdd_bit =-1 ;u8 ctrl;spin_lock_irqsave (&host->lock, flags);
@@ -1460,15 +1464,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) }if (ios->power_mode ==MMC_POWER_OFF ) - vdd_bit =sdhci_set_power (host,-1 ); +sdhci_set_power (host,-1 );else - vdd_bit =sdhci_set_power (host, ios->vdd); - -if (host->vmmc && vdd_bit !=-1 ) { -spin_unlock_irqrestore (&host->lock, flags); -mmc_regulator_set_ocr (host->mmc, host->vmmc, vdd_bit); -spin_lock_irqsave (&host->lock, flags); - } +sdhci_set_power (host, ios->vdd);if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks (host, ios->power_mode);
Signature · 1 line
1.8.3.1
PATCH 31/38 mmc: sdhci: move remaining power handling into sdhci_set_power()
In reply to Russell King - ARM LinuxMove the remaining parts of the power handling in sdhci_do_set_ios() into sdhci_set_power().
--- drivers/mmc/host/sdhci.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
drivers/mmc/host/sdhci.c +7 -9
@@ -1216,12 +1216,13 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) }EXPORT_SYMBOL_GPL (sdhci_set_clock); -static void sdhci_set_power (struct sdhci_host *host,unsigned short power) +static void sdhci_set_power (struct sdhci_host *host,unsigned char mode, +unsigned short vdd) {u8 pwr =0 ; -if (power != (unsigned short )-1 ) { -switch (1 << power) { +if (mode !=MMC_POWER_OFF ) { +switch (1 << vdd) {case MMC_VDD_165_195 : pwr =SDHCI_POWER_180 ;break ;
@@ -1247,7 +1248,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)sdhci_writeb (host,0 ,SDHCI_POWER_CONTROL );if (host->quirks2 &SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON )sdhci_runtime_pm_bus_off (host); - power =0 ; + vdd =0 ; }else {/* * Spec says that we should clear the power reg before setting
@@ -1281,7 +1282,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)if (host->vmmc) {spin_unlock_irq (&host->lock); -mmc_regulator_set_ocr (host->mmc, host->vmmc, power); +mmc_regulator_set_ocr (host->mmc, host->vmmc, vdd);spin_lock_irq (&host->lock); } }
@@ -1463,10 +1464,7 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) host->clock = ios->clock; } -if (ios->power_mode ==MMC_POWER_OFF ) -sdhci_set_power (host,-1 ); -else -sdhci_set_power (host, ios->vdd); +sdhci_set_power (host, ios->power_mode, ios->vdd);if (host->ops->platform_send_init_74_clocks) host->ops->platform_send_init_74_clocks (host, ios->power_mode);
Signature · 1 line
1.8.3.1
PATCH 32/38 mmc: sdhci: track whether preset mode is currently enabled in hardware
In reply to Russell King - ARM LinuxTrack whether preset mode is currently enabled in hardware, and use that when making decisions elsewhere in the code rather than reading the register and checking the bit.
--- drivers/mmc/host/sdhci.c | 44 ++++++++++++++++++++++++++------------------ include/linux/mmc/sdhci.h | 1 + 2 files changed, 27 insertions(+), 18 deletions(-)
drivers/mmc/host/sdhci.c +26 -18
@@ -205,9 +205,14 @@ static void sdhci_do_reset(struct sdhci_host *host, u8 mask) host->ops->reset (host, mask); -if (host->flags & (SDHCI_USE_SDMA |SDHCI_USE_ADMA )) { -if ((host->ops->enable_dma) && (mask &SDHCI_RESET_ALL )) - host->ops->enable_dma (host); +if (mask &SDHCI_RESET_ALL ) { +if (host->flags & (SDHCI_USE_SDMA |SDHCI_USE_ADMA )) { +if (host->ops->enable_dma) + host->ops->enable_dma (host); + } + +/* Resetting the controller clears many */ + host->preset_enabled = false; } }
@@ -1126,8 +1131,7 @@ void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)return ;if (host->version >=SDHCI_SPEC_300 ) { -if (sdhci_readw (host,SDHCI_HOST_CONTROL2 ) & -SDHCI_CTRL_PRESET_VAL_ENABLE ) { +if (host->preset_enabled) {u16 pre_val; clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL );
@@ -1491,13 +1495,13 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) (ios->timing == MMC_TIMING_UHS_SDR25)) ctrl |=SDHCI_CTRL_HISPD ; - ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -if (!(ctrl_2 &SDHCI_CTRL_PRESET_VAL_ENABLE )) { +if (!host->preset_enabled) {sdhci_writeb (host, ctrl,SDHCI_HOST_CONTROL );/* * We only need to set Driver Strength if the * preset value enable is not set. */ + ctrl_2 =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); ctrl_2 &= ~SDHCI_CTRL_DRV_TYPE_MASK ;if (ios->drv_type ==MMC_SET_DRIVER_TYPE_A ) ctrl_2 |=SDHCI_CTRL_DRV_TYPE_A ;
@@ -2001,26 +2005,30 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)static void sdhci_enable_preset_value (struct sdhci_host *host,bool enable) { -u16 ctrl; -/* Host Controller v3.00 defines preset value registers */ if (host->version <SDHCI_SPEC_300 )return ; - ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); -/* * We only enable or disable Preset Value if they are not already * enabled or disabled respectively. Otherwise, we bail out. */ -if (enable && !(ctrl &SDHCI_CTRL_PRESET_VAL_ENABLE )) { - ctrl |=SDHCI_CTRL_PRESET_VAL_ENABLE ; -sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); - host->flags |=SDHCI_PV_ENABLED ; - }else if (!enable && (ctrl &SDHCI_CTRL_PRESET_VAL_ENABLE )) { - ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE ; +if (host->preset_enabled != enable) { +u16 ctrl =sdhci_readw (host,SDHCI_HOST_CONTROL2 ); + +if (enable) + ctrl |=SDHCI_CTRL_PRESET_VAL_ENABLE ; +else + ctrl &= ~SDHCI_CTRL_PRESET_VAL_ENABLE ; +sdhci_writew (host, ctrl,SDHCI_HOST_CONTROL2 ); - host->flags &= ~SDHCI_PV_ENABLED ; + +if (enable) + host->flags |=SDHCI_PV_ENABLED ; +else + host->flags &= ~SDHCI_PV_ENABLED ; + + host->preset_enabled = enable; } }
include/linux/mmc/sdhci.h +1 -0
@@ -143,6 +143,7 @@ struct sdhci_host {bool runtime_suspended;/* Host is runtime suspended */ bool bus_on;/* Bus power prevents runtime suspend */ +bool preset_enabled;/* Preset is enabled */ struct mmc_request *mrq;/* Current request */ struct mmc_command *cmd;/* Current command */
Signature · 1 line
1.8.3.1
PATCH 33/38 mmc: sdhci: fix SDHCI dependencies
In reply to Russell King - ARM Linux--- drivers/mmc/host/Kconfig | 63 ++++++++++++++++++++++++------------------------ 1 file changed, 32 insertions(+), 31 deletions(-)
drivers/mmc/host/Kconfig +32 -31
@@ -25,8 +25,7 @@ config MMC_PXA If unsure, say N. config MMC_SDHCI - tristate "Secure Digital Host Controller Interface support" - depends on HAS_DMA + tristate help This selects the generic Secure Digital Host Controller Interface. It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
@@ -59,7 +58,8 @@ config MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER config MMC_SDHCI_PCI tristate "SDHCI support on PCI bus" - depends on MMC_SDHCI && PCI + depends on PCI && HAS_DMA + select MMC_SDHCI help This selects the PCI Secure Digital Host Controller Interface. Most controllers found today are PCI devices.
@@ -83,7 +83,8 @@ config MMC_RICOH_MMC config MMC_SDHCI_ACPI tristate "SDHCI support for ACPI enumerated SDHCI controllers" - depends on MMC_SDHCI && ACPI + depends on ACPI && HAS_DMA + select MMC_SDHCI help This selects support for ACPI enumerated SDHCI controllers, identified by ACPI Compatibility ID PNP0D40 or specific
@@ -94,8 +95,8 @@ config MMC_SDHCI_ACPI If unsure, say N. config MMC_SDHCI_PLTFM - tristate "SDHCI platform and OF driver helper" - depends on MMC_SDHCI + tristate + select MMC_SDHCI help This selects the common helper functions support for Secure Digital Host Controller Interface based platform and OF drivers.
@@ -106,8 +107,8 @@ config MMC_SDHCI_PLTFM config MMC_SDHCI_OF_ARASAN tristate "SDHCI OF support for the Arasan SDHCI controllers" - depends on MMC_SDHCI_PLTFM - depends on OF + depends on OF && HAS_DMA + select MMC_SDHCI_PLTFM help This selects the Arasan Secure Digital Host Controller Interface (SDHCI). This hardware is found e.g. in Xilinx' Zynq SoC.
@@ -118,9 +119,9 @@ config MMC_SDHCI_OF_ARASAN config MMC_SDHCI_OF_ESDHC tristate "SDHCI OF support for the Freescale eSDHC controller" - depends on MMC_SDHCI_PLTFM - depends on PPC_OF + depends on PPC_OF && HAS_DMA select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER + select MMC_SDHCI_PLTFM help This selects the Freescale eSDHC controller support.
@@ -130,9 +131,9 @@ config MMC_SDHCI_OF_ESDHC config MMC_SDHCI_OF_HLWD tristate "SDHCI OF support for the Nintendo Wii SDHCI controllers" - depends on MMC_SDHCI_PLTFM - depends on PPC_OF + depends on PPC_OF && HAS_DMA select MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER + select MMC_SDHCI_PLTFM help This selects the Secure Digital Host Controller Interface (SDHCI) found in the "Hollywood" chipset of the Nintendo Wii video game
@@ -144,8 +145,8 @@ config MMC_SDHCI_OF_HLWD config MMC_SDHCI_CNS3XXX tristate "SDHCI support on the Cavium Networks CNS3xxx SoC" - depends on ARCH_CNS3XXX - depends on MMC_SDHCI_PLTFM + depends on ARCH_CNS3XXX && HAS_DMA + select MMC_SDHCI_PLTFM help This selects the SDHCI support for CNS3xxx System-on-Chip devices.
@@ -155,9 +156,9 @@ config MMC_SDHCI_CNS3XXX config MMC_SDHCI_ESDHC_IMX tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller" - depends on ARCH_MXC - depends on MMC_SDHCI_PLTFM + depends on ARCH_MXC && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the Freescale eSDHC/uSDHC controller support found on i.MX25, i.MX35 i.MX5x and i.MX6x.
@@ -168,9 +169,9 @@ config MMC_SDHCI_ESDHC_IMX config MMC_SDHCI_DOVE tristate "SDHCI support on Marvell's Dove SoC" - depends on ARCH_DOVE - depends on MMC_SDHCI_PLTFM + depends on ARCH_DOVE && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the Secure Digital Host Controller Interface in Marvell's Dove SoC.
@@ -181,9 +182,9 @@ config MMC_SDHCI_DOVE config MMC_SDHCI_TEGRA tristate "SDHCI platform support for the Tegra SD/MMC Controller" - depends on ARCH_TEGRA - depends on MMC_SDHCI_PLTFM + depends on ARCH_TEGRA && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the Tegra SD/MMC controller. If you have a Tegra platform with SD or MMC devices, say Y or M here.
@@ -192,7 +193,8 @@ config MMC_SDHCI_TEGRA config MMC_SDHCI_S3C tristate "SDHCI support on Samsung S3C SoC" - depends on MMC_SDHCI && PLAT_SAMSUNG + depends on PLAT_SAMSUNG && HAS_DMA + select MMC_SDHCI help This selects the Secure Digital Host Controller Interface (SDHCI) often referrered to as the HSMMC block in some of the Samsung S3C
@@ -204,8 +206,8 @@ config MMC_SDHCI_S3C config MMC_SDHCI_SIRF tristate "SDHCI support on CSR SiRFprimaII and SiRFmarco SoCs" - depends on ARCH_SIRF - depends on MMC_SDHCI_PLTFM + depends on ARCH_SIRF && HAS_DMA + select MMC_SDHCI_PLTFM help This selects the SDHCI support for SiRF System-on-Chip devices.
@@ -215,8 +217,7 @@ config MMC_SDHCI_SIRF config MMC_SDHCI_PXAV3 tristate "Marvell MMP2 SD Host Controller support (PXAV3)" - depends on CLKDEV_LOOKUP - select MMC_SDHCI + depends on CLKDEV_LOOKUP && HAS_DMA select MMC_SDHCI_PLTFM default CPU_MMP2 help
@@ -228,8 +229,7 @@ config MMC_SDHCI_PXAV3 config MMC_SDHCI_PXAV2 tristate "Marvell PXA9XX SD Host Controller support (PXAV2)" - depends on CLKDEV_LOOKUP - select MMC_SDHCI + depends on CLKDEV_LOOKUP && HAS_DMA select MMC_SDHCI_PLTFM default CPU_PXA910 help
@@ -241,7 +241,8 @@ config MMC_SDHCI_PXAV2 config MMC_SDHCI_SPEAR tristate "SDHCI support on ST SPEAr platform" - depends on MMC_SDHCI && PLAT_SPEAR + depends on PLAT_SPEAR && HAS_DMA + select MMC_SDHCI help This selects the Secure Digital Host Controller Interface (SDHCI) often referrered to as the HSMMC block in some of the ST SPEAR range
@@ -263,7 +264,7 @@ config MMC_SDHCI_S3C_DMA config MMC_SDHCI_BCM_KONA tristate "SDHCI support on Broadcom KONA platform" - depends on ARCH_BCM_MOBILE + depends on ARCH_BCM_MOBILE && HAS_DMA select MMC_SDHCI_PLTFM help This selects the Broadcom Kona Secure Digital Host Controller
@@ -274,9 +275,9 @@ config MMC_SDHCI_BCM_KONA config MMC_SDHCI_BCM2835 tristate "SDHCI platform support for the BCM2835 SD/MMC Controller" - depends on ARCH_BCM2835 - depends on MMC_SDHCI_PLTFM + depends on ARCH_BCM2835 && HAS_DMA select MMC_SDHCI_IO_ACCESSORS + select MMC_SDHCI_PLTFM help This selects the BCM2835 SD/MMC controller. If you have a BCM2835 platform with SD or MMC devices, say Y or M here.
Signature · 1 line
1.8.3.1
PATCH 33/38 mmc: sdhci: fix SDHCI dependencies
Quoted 1 line · Russell King
Signed-off-by Russell King <[email protected]>
A patch description would be useful so I can work out why...
drivers/mmc/host/Kconfig config MMC_PXA · line 31
Quoted 9 lines
drivers/mmc/host/Kconfig +1
-2config MMC_SDHCI - tristate "Secure Digital Host Controller Interface support" - depends on HAS_DMA + tristate help This selects the generic Secure Digital Host Controller Interface. It is used by manufacturers such as Texas Instruments(R), Ricoh(R)
... it's useful to remove that depends from here and ...
drivers/mmc/host/Kconfig config MMC_SDHCI_DOVE · line 185
Quoted 5 lines
config
MMC_SDHCI_TEGRAdrivers/mmc/host/Kconfig +1
-2tristate "SDHCI platform support for the Tegra SD/MMC Controller" - depends on ARCH_TEGRA - depends on MMC_SDHCI_PLTFM + depends on ARCH_TEGRA && HAS_DMA
... duplicate it in all the HW-specific drivers.
On Tegra (and I believe at least any ARM system), I think HAS_DMA is always true, so is there a need for "&& HAS_DMA" at all, now that this statement is pushed into arch-/HW-specific options?
PATCH 34/38 mmc: add support for power-on sequencing through DT
In reply to Russell King - ARM LinuxFrom: Olof Johansson <[email protected]>
This patch enables support for power-on sequencing of SDIO peripherals through DT.
In general, it's quite common that wifi modules and other similar peripherals have several signals in addition to the SDIO interface that needs wiggling before the module will power on. It's common to have a reference clock, one or several power rails and one or several lines for reset/enable type functions.
The binding as written today introduces a number of reset gpios, a regulator and a clock specifier. The code will handle up to 2 gpio reset lines, but it's trivial to increase to more than that if needed at some point.
Implementation-wise, the MMC core has been changed to handle this during host power up, before the host interface is powered on. I have not yet implemented the power-down side, I wanted people to have a chance for reporting back w.r.t. issues (or comments on the bindings) first.
I have not tested the regulator portion, since the system and module I'm working on doesn't need one (Samsung Chromebook with Marvell 8797-based wifi). Testing of those portions (and reporting back) would be appreciated.
--- Documentation/devicetree/bindings/mmc/mmc.txt | 11 +++++++ drivers/mmc/core/core.c | 42 +++++++++++++++++++++++++++ drivers/mmc/core/host.c | 30 ++++++++++++++++++- include/linux/mmc/host.h | 5 ++++ 4 files changed, 87 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/mmc/mmc.txt +11 -0
@@ -5,6 +5,8 @@ these definitions. Interpreted by the OF core: - reg: Registers location and length. - interrupts: Interrupts used by the MMC controller. +- clocks: Clocks needed for the host controller, if any. +- clock-names: Goes with clocks above. Card detection: If no property below is supplied, host native card detect is used.
@@ -39,6 +41,15 @@ If no property below is supplied, host native card detect is used. - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported +Card power and reset control: +The following properties can be specified for cases where the MMC +peripheral needs additional reset, regulator and clock lines. It is for +example common for WiFi/BT adapters to have these separate from the main +MMC bus: + - card-reset-gpios: Specify GPIOs for card reset (reset active low) + - card-external-vcc-supply: Regulator to drive (independent) card VCC + - clock with name "card_ext_clock": External clock provided to the card + *NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line polarity properties, we have to fix the meaning of the "normal" and "inverted" line levels. We choose to follow the SDHCI standard, which specifies both those
drivers/mmc/core/core.c +42 -0
65 lines not on this page · raw message
drivers/mmc/core/host.c +29 -1
@@ -12,14 +12,18 @@* MMC host class device management */ +#include <linux/kernel.h> +#include <linux/clk.h> #include <linux/device.h> #include <linux/err.h> +#include <linux/gpio/consumer.h> #include <linux/idr.h> #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/pagemap.h> #include <linux/export.h> #include <linux/leds.h> +#include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/suspend.h>
@@ -312,7 +316,7 @@ int mmc_of_parse(struct mmc_host *host)u32 bus_width;bool explicit_inv_wp, gpio_inv_wp = false;enum of_gpio_flags flags; -int len, ret, gpio; +int i, len, ret, gpio;if (!host->parent || !host->parent->of_node)return 0 ;
@@ -415,6 +419,30 @@ int mmc_of_parse(struct mmc_host *host)if (explicit_inv_wp ^ gpio_inv_wp) host->caps2 |=MMC_CAP2_RO_ACTIVE_HIGH ; +/* Parse card power/reset/clock control */ +if (of_find_property (np,"card-reset-gpios" ,NULL )) { +struct gpio_desc *gpd; +for (i =0 ; i <ARRAY_SIZE (host->card_reset_gpios); i++) { + gpd =devm_gpiod_get_index (host->parent,"card-reset" , i); +if (IS_ERR (gpd)) +break ; +gpiod_direction_output (gpd,0 ); + host->card_reset_gpios[i] = gpd; + } + + gpd =devm_gpiod_get_index (host->parent,"card-reset" ,ARRAY_SIZE (host->card_reset_gpios)); +if (!IS_ERR (gpd)) { +dev_warn (host->parent,"More reset gpios than we can handle" ); +gpiod_put (gpd); + } + } + + host->card_clk =of_clk_get_by_name (np,"card_ext_clock" ); +if (IS_ERR (host->card_clk)) + host->card_clk =NULL ; + + host->card_regulator =regulator_get (host->parent,"card-external-vcc" ); +if (of_find_property (np,"cap-sd-highspeed" , &len)) host->caps |=MMC_CAP_SD_HIGHSPEED ;if (of_find_property (np,"cap-mmc-highspeed" , &len))
include/linux/mmc/host.h +5 -0
@@ -294,6 +294,11 @@ struct mmc_host {unsigned long clkgate_delay;#endif +/* card specific properties to deal with power and reset */ +struct regulator *card_regulator;/* External VCC needed by the card */ +struct gpio_desc *card_reset_gpios[2 ];/* External resets, active low */ +struct clk *card_clk;/* External clock needed by the card */ +/* host specific block data */ unsigned int max_seg_size;/* see blk_queue_max_segment_size */ unsigned short max_segs;/* see blk_queue_max_segments */
Signature · 1 line
1.8.3.1
PATCH 34/38 mmc: add support for power-on sequencing through DT
Hi Russell,
Quoted 48 lines · Russell King
From: Olof Johansson <[email protected]>
This patch enables support for power-on sequencing of SDIO peripherals through DT.
In general, it's quite common that wifi modules and other similar peripherals have several signals in addition to the SDIO interface that needs wiggling before the module will power on. It's common to have a reference clock, one or several power rails and one or several lines for reset/enable type functions.
The binding as written today introduces a number of reset gpios, a regulator and a clock specifier. The code will handle up to 2 gpio reset lines, but it's trivial to increase to more than that if needed at some point.
Implementation-wise, the MMC core has been changed to handle this during host power up, before the host interface is powered on. I have not yet implemented the power-down side, I wanted people to have a chance for reporting back w.r.t. issues (or comments on the bindings) first.
I have not tested the regulator portion, since the system and module I'm working on doesn't need one (Samsung Chromebook with Marvell 8797-based wifi). Testing of those portions (and reporting back) would be appreciated.
Signed-off-by Olof Johansson <[email protected]>Signed-off-by Russell King <[email protected]>--- Documentation/devicetree/bindings/mmc/mmc.txt | 11 +++++++ drivers/mmc/core/core.c | 42 +++++++++++++++++++++++++++ drivers/mmc/core/host.c | 30 ++++++++++++++++++- include/linux/mmc/host.h | 5 ++++ 4 files changed, 87 insertions(+), 1 deletion(-)Documentation/devicetree/bindings/mmc/mmc.txt +2
-0@@ -5,6 +5,8 @@ these definitions. Interpreted by the OF core: - reg: Registers location and length. - interrupts: Interrupts used by the MMC controller. +- clocks: Clocks needed for the host controller, if any. +- clock-names: Goes with clocks above. Card detection: If no property below is supplied, host native card detect is used.
Documentation/devicetree/bindings/mmc/mmc.txt If no property below is supplied, host native card detect is used. · line 49
Quoted 9 lines
Documentation/devicetree/bindings/mmc/mmc.txt +6
-0@@ -39,6 +41,15 @@ If no property below is supplied, host native card detect is used. - mmc-hs200-1_8v: eMMC HS200 mode(1.8V I/O) is supported - mmc-hs200-1_2v: eMMC HS200 mode(1.2V I/O) is supported +Card power and reset control: +The following properties can be specified for cases where the MMC +peripheral needs additional reset, regulator and clock lines. It is for +example common for WiFi/BT adapters to have these separate from the main +MMC bus: + - card-reset-gpios: Specify GPIOs for card reset (reset active low)
That probably can use the reset frameworks bindings and the reset-gpio driver Philipp Zabel has been working on.
Documentation/devicetree/bindings/mmc/mmc.txt If no property below is supplied, host native card detect is used. · line 51
Quoted 2 lines
Documentation/devicetree/bindings/mmc/mmc.txt +2
-0+ - card-external-vcc-supply: Regulator to drive (independent) card VCC + - clock with name "card_ext_clock": External clock provided to the card
I'm not sure this is the right path.
This looks pretty harmless for now, but I'm pretty concerned that it's just going to be an ever-increasing list of properties to deal with the various corner-cases everyone has, like for example how to enforce a given frequency for that card_ext_clock, or the fact that it has several SDIO cards connected to them, each with different clocks/reset/regulator lines.
While all of this would easily be solved by representing all this as a bus, like it should, with subdevices grabbing their own clocks and having whatever property they need.
Maxime
Signature · 10 lines
Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: Digital signature URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140424/d03ee267/attachment.sig>
PATCH 35/38 mmc: dw_mmc: call mmc_of_parse to fill in common options
In reply to Russell King - ARM LinuxFrom: Olof Johansson <[email protected]>
The shared of parse function fills in common options for capabilities, etc, but it needs to be called from each driver that wants to make use of it. dw_mmc was missing the call.
--- drivers/mmc/host/dw_mmc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/mmc/host/dw_mmc.c +2 -0
@@ -2140,6 +2140,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)if (!mmc)return -ENOMEM ; +mmc_of_parse (mmc); + slot =mmc_priv (mmc); slot->id = id; slot->mmc = mmc;
Signature · 1 line
1.8.3.1
Jaehoon Chung
maintainerPATCH 35/38 mmc: dw_mmc: call mmc_of_parse to fill in common options
Dear, Russell.
I didn't know which version you have checked.
But I have known that mmc_of_parse() have already included at mmc-next repository.
commit 6ca5c60605dde3420ce7fee6f93ec4a7c7924848
Author: Jaehoon Chung <[email protected]> Date: Mon Mar 3 11:36:41 2014 +0900
mmc: dw_mmc: use the mmc_of_parse() instead of local parser
mmc_of_parse() have been already parsed the general capability. Didn't need to use the local parser.
Could you check it, plz?
Best Regards,
Jaehoon Chung
Quoted 26 lines · Russell King
From: Olof Johansson <[email protected]>
The shared of parse function fills in common options for capabilities, etc, but it needs to be called from each driver that wants to make use of it.
dw_mmcwas missing the call.Signed-off-by Olof Johansson <[email protected]>Signed-off-by Russell King <[email protected]>--- drivers/mmc/host/dw_mmc.c | 2 ++ 1 file changed, 2 insertions(+)drivers/mmc/host/dw_mmc.c +2
-0@@ -2140,6 +2140,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)if (!mmc)return -ENOMEM ; +mmc_of_parse (mmc); + slot =mmc_priv (mmc); slot->id = id; slot->mmc = mmc;
PATCH 35/38 mmc: dw_mmc: call mmc_of_parse to fill in common options
Quoted 3 lines · Jaehoon Chung
Dear, Russell.
I didn't know which version you have checked.
As I said in the cover, this series is based on v3.15-rc1. It's based there because it's part of a much larger set of patches that need to be based on a common point in order to generate a series of around 230 patches against a mainline kernel version.
Quoted 2 lines
But I have known that
mmc_of_parse()have already included at mmc-next repository.
That's partly good news, but only partly because I raised issues with Olof's patches which were silently ignored - you'll notice that patch 36 reworks Olof's patch (my patch 34) in such a way that other hosts (eg, sdhci) can make use of it.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
PATCH 36/38 mmc: fix power-on sequencing for esdhc-imx driver
In reply to Russell King - ARM LinuxThere's no reason that this can't be applied to all MMC interfaces as it's all core code, so tie this into the core rather than it being optional for each host.
--- drivers/mmc/core/host.c | 90 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 25 deletions(-)
drivers/mmc/core/host.c +65 -25
@@ -316,7 +316,7 @@ int mmc_of_parse(struct mmc_host *host)u32 bus_width;bool explicit_inv_wp, gpio_inv_wp = false;enum of_gpio_flags flags; -int i, len, ret, gpio; +int len, ret, gpio;if (!host->parent || !host->parent->of_node)return 0 ;
@@ -419,30 +419,6 @@ int mmc_of_parse(struct mmc_host *host)if (explicit_inv_wp ^ gpio_inv_wp) host->caps2 |=MMC_CAP2_RO_ACTIVE_HIGH ; -/* Parse card power/reset/clock control */ -if (of_find_property (np,"card-reset-gpios" ,NULL )) { -struct gpio_desc *gpd; -for (i =0 ; i <ARRAY_SIZE (host->card_reset_gpios); i++) { - gpd =devm_gpiod_get_index (host->parent,"card-reset" , i); -if (IS_ERR (gpd)) -break ; -gpiod_direction_output (gpd,0 ); - host->card_reset_gpios[i] = gpd; - } - - gpd =devm_gpiod_get_index (host->parent,"card-reset" ,ARRAY_SIZE (host->card_reset_gpios)); -if (!IS_ERR (gpd)) { -dev_warn (host->parent,"More reset gpios than we can handle" ); -gpiod_put (gpd); - } - } - - host->card_clk =of_clk_get_by_name (np,"card_ext_clock" ); -if (IS_ERR (host->card_clk)) - host->card_clk =NULL ; - - host->card_regulator =regulator_get (host->parent,"card-external-vcc" ); -if (of_find_property (np,"cap-sd-highspeed" , &len)) host->caps |=MMC_CAP_SD_HIGHSPEED ;if (of_find_property (np,"cap-mmc-highspeed" , &len))
@@ -485,6 +461,66 @@ int mmc_of_parse(struct mmc_host *host)EXPORT_SYMBOL (mmc_of_parse); +static int mmc_of_parse_child (struct mmc_host *host) +{ +struct device_node *np; +struct clk *clk; +int i; + +if (!host->parent || !host->parent->of_node) +return 0 ; + + np = host->parent->of_node; + + host->card_regulator =regulator_get (host->parent,"card-external-vcc" ); +if (IS_ERR (host->card_regulator)) { +if (PTR_ERR (host->card_regulator) == -EPROBE_DEFER ) +return PTR_ERR (host->card_regulator); + host->card_regulator =NULL ; + } + +/* Parse card power/reset/clock control */ +if (of_find_property (np,"card-reset-gpios" ,NULL )) { +struct gpio_desc *gpd; +int level =0 ; + +/* +* If the regulator is enabled, then we can hold the +* card in reset with an active high resets. Otherwise, +* hold the resets low. +*/ +if (host->card_regulator &®ulator_is_enabled (host->card_regulator)) + level =1 ; + +for (i =0 ; i <ARRAY_SIZE (host->card_reset_gpios); i++) { + gpd =devm_gpiod_get_index (host->parent,"card-reset" , i); +if (IS_ERR (gpd)) { +if (PTR_ERR (gpd) == -EPROBE_DEFER ) +return PTR_ERR (gpd); +break ; + } +gpiod_direction_output (gpd,gpiod_is_active_low (gpd) | level); + host->card_reset_gpios[i] = gpd; + } + + gpd =devm_gpiod_get_index (host->parent,"card-reset" ,ARRAY_SIZE (host->card_reset_gpios)); +if (!IS_ERR (gpd)) { +dev_warn (host->parent,"More reset gpios than we can handle" ); +gpiod_put (gpd); + } + } + + clk =of_clk_get_by_name (np,"card_ext_clock" ); +if (IS_ERR (clk)) { +if (PTR_ERR (clk) == -EPROBE_DEFER ) +return PTR_ERR (clk); + clk =NULL ; + } + host->card_clk = clk; + +return 0 ; +} +/** * mmc_alloc_host - initialise the per-host structure. * @extra: sizeof private data structure
@@ -564,6 +600,10 @@ int mmc_add_host(struct mmc_host *host) {int err; + err =mmc_of_parse_child (host); +if (err) +return err; +WARN_ON ((host->caps &MMC_CAP_SDIO_IRQ ) && !host->ops->enable_sdio_irq);
Signature · 1 line
1.8.3.1
PATCH 37/38 ARM: cubox-i: add support for SD UHS-1 cards
In reply to Russell King - ARM Linux--- arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +25 -1
@@ -111,6 +111,28 @@ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x13059 >; }; + + pinctrl_cubox_i_usdhc2_100mhz: cubox-i-usdhc2-100mhz { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170b9 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100b9 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170b9 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170b9 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170b9 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130b9 + >; + }; + + pinctrl_cubox_i_usdhc2_200mhz: cubox-i-usdhc2-200mhz { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x170f9 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x100f9 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x170f9 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x170f9 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x170f9 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x130f9 + >; + }; }; };
@@ -131,8 +153,10 @@ }; &usdhc2 { - pinctrl-names = "default"; + pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>; + pinctrl-1 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_100mhz>; + pinctrl-2 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2_200mhz>; vmmc-supply = <®_3p3v>; cd-gpios = <&gpio1 4 0>; status = "okay";
Signature · 1 line
1.8.3.1
PATCH 38/38 ARM: cubox-i: add support for Wifi/BT
In reply to Russell King - ARM Linux--- arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 8 +++ arch/arm/boot/dts/imx6qdl-microsom.dtsi | 98 +++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+)
arch/arm/boot/dts/imx6qdl-cubox-i.dtsi +8 -0
@@ -152,6 +152,14 @@ status = "okay"; }; +&uart4 { + status = "okay"; +}; + +&usdhc1 { + status = "okay"; +}; + &usdhc2 { pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
arch/arm/boot/dts/imx6qdl-microsom.dtsi +98 -0
126 lines not on this page · raw message
Signature · 1 line
1.8.3.1
cover MMC updates, plus CuBox-i WiFi support
In reply to Russell King - ARM LinuxQuoted 7 lines · Russell King - ARM Linux
All,
This is where I'm at with trying to clean up the SDHCI mess, and sort out issues I've noticed when trying to get UHS support working on CuBoxes. This is my full patch set, but I recommend not applying patch 37 as there appears to be a hardware issue preventing it working reliably.
Quoted 9 lines
In any case, patches 0-33 inclusive are the SDHCI clean up, based against v3.15-rc1. Patches 34 and 35 are Olof's Wifi support, 36 is my fix against those, and 38 adds the Broadcom Wifi and BT support for CuBox.
The questions over how to handle these devices were never properly settled, so I recommend against merging patch 34 onwards. As for the rest, I'm not planning on any further work, so it may be a good idea for people to consider testing them with a view to getting them merged.
I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.
I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.
Kind regards
Ulf Hansson
Quoted 40 lines
Documentation/devicetree/bindings/mmc/mmc.txt | 11 + arch/arm/boot/dts/imx6qdl-cubox-i.dtsi | 34 +- arch/arm/boot/dts/imx6qdl-microsom.dtsi | 98 ++++ drivers/mmc/core/core.c | 42 ++ drivers/mmc/core/host.c | 68 +++ drivers/mmc/core/sdio_irq.c | 41 +- drivers/mmc/host/Kconfig | 63 +-- drivers/mmc/host/dw_mmc.c | 2 + drivers/mmc/host/sdhci-acpi.c | 8 + drivers/mmc/host/sdhci-bcm-kona.c | 4 + drivers/mmc/host/sdhci-bcm2835.c | 4 + drivers/mmc/host/sdhci-cns3xxx.c | 13 +- drivers/mmc/host/sdhci-dove.c | 4 + drivers/mmc/host/sdhci-esdhc-imx.c | 82 +-- drivers/mmc/host/sdhci-esdhc.h | 4 +- drivers/mmc/host/sdhci-of-arasan.c | 4 + drivers/mmc/host/sdhci-of-esdhc.c | 70 ++- drivers/mmc/host/sdhci-of-hlwd.c | 4 + drivers/mmc/host/sdhci-pci.c | 9 +- drivers/mmc/host/sdhci-pltfm.c | 4 + drivers/mmc/host/sdhci-pxav2.c | 14 +- drivers/mmc/host/sdhci-pxav3.c | 13 +- drivers/mmc/host/sdhci-s3c.c | 36 +- drivers/mmc/host/sdhci-sirf.c | 4 + drivers/mmc/host/sdhci-spear.c | 5 +- drivers/mmc/host/sdhci-tegra.c | 27 +- drivers/mmc/host/sdhci.c | 728 +++++++++++++------------- drivers/mmc/host/sdhci.h | 20 +- include/linux/mmc/host.h | 8 + include/linux/mmc/sdhci.h | 15 +- 30 files changed, 885 insertions(+), 554 deletions(-)--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
cover MMC updates, plus CuBox-i WiFi support
Quoted 8 lines · Ulf Hansson
I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.
I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.
I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.
What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.
* - this currently stands at 230 patches in all - mmc + l2c + fec + imx-drm + other iMX6 changes.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
cover MMC updates, plus CuBox-i WiFi support
Quoted 14 lines · Russell King - ARM Linux
Quoted 8 lines · Ulf Hansson
I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.
I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.
I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.
Quoted 5 lines
What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.
Whether there are more than one conflict, I don't know. I just stopped at patch 23.
Moreover, there are other patches for sdhci that have been posted and being discussed. In principle, we then need to put all these on hold to prevent further conflicts. I guess that doable, as long as we don't to that for too long. Maybe Chris have some more thoughts how to handle this!?
Kind regards
Ulf Hansson
Quoted 11 lines
* - this currently stands at 230 patches in all - mmc + l2c + fec + imx-drm + other iMX6 changes.
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
cover MMC updates, plus CuBox-i WiFi support
Quoted 21 lines · Ulf Hansson
Quoted 14 lines · Russell King - ARM Linux
Quoted 8 lines · Ulf Hansson
I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.
I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.
I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.
Quoted 5 lines
What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.
Quoted 8 lines
Whether there are more than one conflict, I don't know. I just stopped at patch 23.
Moreover, there are other patches for sdhci that have been posted and being discussed. In principle, we then need to put all these on hold to prevent further conflicts. I guess that doable, as long as we don't to that for too long. Maybe Chris have some more thoughts how to handle this!?
This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.
Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
cover MMC updates, plus CuBox-i WiFi support
Quoted 35 lines · Russell King - ARM Linux
Quoted 21 lines · Ulf Hansson
Quoted 14 lines · Russell King - ARM Linux
Quoted 8 lines · Ulf Hansson
I have looked though the patches up until patch 33 and this is clearly a nice piece of clean-up /fixes work for sdhci. Besides my minor comments per patch, I don't have any objections code-review wise to proceed merging them.
I have also tried to applied them on Chris' mmc-next branch, unfortunate it fails at patch 23, so it would be nice to get a re-based patchset for the mmc-next branch.
I /could/ rebase it but then I wouldn't be able to produce the patch sets/patches for others [*] (such as the Novena project) to derive their kernel tree from my iMX6 patch set.
Quoted 5 lines
What I'd prefer is to keep the patch set intact, and provide Chris with a pull request for it up to patch 33, which would need a conflict fixed - and this would mean that I can be sure that what I'm testing, and what I'm distributing is what Chris will also be submitting.
Quoted 8 lines
Whether there are more than one conflict, I don't know. I just stopped at patch 23.
Moreover, there are other patches for sdhci that have been posted and being discussed. In principle, we then need to put all these on hold to prevent further conflicts. I guess that doable, as long as we don't to that for too long. Maybe Chris have some more thoughts how to handle this!?
This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.
Quoted 6 lines
Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.
Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.
How about if I resolve the conflicts and send the pull request to Chris? I suppose it makes life a bit easier for Chris.
Kind regards
Ulf Hansson
Quoted 8 lines
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
cover MMC updates, plus CuBox-i WiFi support
Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux
This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.
Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.
Quoted 2 lines
Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.
Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is sdhci-esdhc-imx.c.
They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
cover MMC updates, plus CuBox-i WiFi support
Quoted 16 lines · Russell King - ARM Linux
Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux
This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.
Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.
Quoted 2 lines
Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.
Quoted 7 lines
Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is
sdhci-esdhc-imx.c.They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?
I was hoping people could start doing tests, before Chris actually decided to pull them in. Now, if that doesn't happen, we could just merge them, as you say, and thus we have to fix potential problems afterwards. I would expect you to help out if problem occurs.
If we decide to not merge in a while, I am not sure how long we could prevent other sdhci patches from being merged. I guess Chris will have to take the final call.
Quoted 8 lines
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
cover MMC updates, plus CuBox-i WiFi support
Quoted 25 lines · Ulf Hansson
Quoted 16 lines · Russell King - ARM Linux
Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux
This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.
Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.
Quoted 2 lines
Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.
Quoted 7 lines
Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is
sdhci-esdhc-imx.c.They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?
Quoted 8 lines
I was hoping people could start doing tests, before Chris actually decided to pull them in. Now, if that doesn't happen, we could just merge them, as you say, and thus we have to fix potential problems afterwards. I would expect you to help out if problem occurs.
If we decide to not merge in a while, I am not sure how long we could prevent other sdhci patches from being merged. I guess Chris will have to take the final call.
Or we just drop them for yet another cycle and show how mainline kernel development sucks, why getting stuff into mainline is utterly painful, and why using vendor kernels is /soo/ much better than this crap.
Signature · 2 lines
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
cover MMC updates, plus CuBox-i WiFi support
Quoted 31 lines · Russell King - ARM Linux
Quoted 30 lines · Ulf Hansson
Quoted 16 lines · Russell King - ARM Linux
Quoted 12 lines · Ulf Hansson
Quoted 10 lines · Russell King - ARM Linux
This is nothing new or unexpected - it was last posted back in February, and I elected that it should be held off until after the last merge window.
Unfortunately, I didn't have time to post it immediately after the merge window closed, partly because it needed to be rebased on top of tglx's IRQ changes on which it depends. I was carrying those as separate commits to the ones Thomas was carrying in his tree - and in the event, Thomas had modified his patches slightly between sending me copies of them and the versions he sent during the merge window.
Quoted 2 lines
Okay, so let's keep up the frequency here then. I only had some minor comments, please fix them and send a v2.
Quoted 7 lines
Right, so I've updated the patches, and added one ack to one patch. That seems insufficient to me - the only platform these have been tested on is iMX6, which is
sdhci-esdhc-imx.c.They _really_ need testing elsewhere too. Or is the plan to merge them and then see about getting people to test them and fix them up afterwards?
I was hoping people could start doing tests, before Chris actually decided to pull them in. Now, if that doesn't happen, we could just merge them, as you say, and thus we have to fix potential problems afterwards. I would expect you to help out if problem occurs.
Quoted 7 lines
Quoted 3 lines
If we decide to not merge in a while, I am not sure how long we could prevent other sdhci patches from being merged. I guess Chris will have to take the final call.
Or we just drop them for yet another cycle and show how mainline kernel development sucks, why getting stuff into mainline is utterly painful, and why using vendor kernels is /soo/ much better than this crap.
Dropping them is too me a bad option and I really don't think that should be needed.
I would like to encourage people to help out with testing and I suppose we have to give this at least some time.
Anyway, post your new version. I will create the pull request based on that.
Quoted 4 lines
--
FTTC broadband for 0.8mile line: now at 9.7Mbps down 460kbps up... slowly improving, and getting towards what was expected from it.
cover MMC updates, plus CuBox-i WiFi support
In reply to Russell King - ARM LinuxQuoted 7 lines · Russell King - ARM Linux
All,
This is where I'm at with trying to clean up the SDHCI mess, and sort out issues I've noticed when trying to get UHS support working on CuBoxes. This is my full patch set, but I recommend not applying patch 37 as there appears to be a hardware issue preventing it working reliably.
Quoted 8 lines
In any case, patches 0-33 inclusive are the SDHCI clean up, based against v3.15-rc1. Patches 34 and 35 are Olof's Wifi support, 36 is my fix against those, and 38 adds the Broadcom Wifi and BT support for CuBox.
The questions over how to handle these devices were never properly settled, so I recommend against merging patch 34 onwards. As for the rest, I'm not planning on any further work, so it may be a good idea for people to consider testing them with a view to getting them merged.
The series,
(On an NVIDIA Tegra "Jetson TK1" board, with the patches applied on top of next-20140428, also with Andrew Bresticker's Tegra SDHCI patches "mmc: tegra: disable UHS modes" and "mmc: tegra: fix reporting of base clock frequency" applied)
cover MMC updates, plus CuBox-i WiFi support
Hi,
Quoted 7 lines · Stephen Warren
The series,
Tested-by Stephen Warren <[email protected]>(On an NVIDIA Tegra "Jetson TK1" board, with the patches applied on top of next-20140428, also with Andrew Bresticker's Tegra SDHCI patches "mmc: tegra: disable UHS modes" and "mmc: tegra: fix reporting of base clock frequency" applied)
Thanks very much Stephen, Russell for the series, and Ulf.
This seems like a good time to merge to mmc-next and call for testing in linux-next -- I'm happy to merge a v2 PR when ready.
- Chris.
Signature · 1 line
Chris Ball <http://printf.net/>
cover MMC updates, plus CuBox-i WiFi support
Quoted 11 lines · Chris Ball
Hi,
Quoted 7 lines · Stephen Warren
The series,
Tested-by Stephen Warren <[email protected]>(On an NVIDIA Tegra "Jetson TK1" board, with the patches applied on top of next-20140428, also with Andrew Bresticker's Tegra SDHCI patches "mmc: tegra: disable UHS modes" and "mmc: tegra: fix reporting of base clock frequency" applied)
Quoted 6 lines
Thanks very much Stephen, Russell for the series, and Ulf.
This seems like a good time to merge to mmc-next and call for testing in linux-next -- I'm happy to merge a v2 PR when ready.
- Chris.
Hi Russell,
Do you have a rough idea about when you will post your v2 pull request?
I have a pending sdhci patch that I would like to rebase on top of your latest work once it is available.
Thanks,
Tim Kryger