Re: [PATCH 2/3] eSDHC: Fix errors when booting kernel with fsl esdhc
On Tue, Jul 5, 2011 at 9:49 AM, Roy Zang tie-fei.z...@freescale.com wrote: From: Xu lei b33...@freescale.com When esdhc module was enabled in p5020, there were following errors: mmc0: Timeout waiting for hardware interrupt. mmc0: error -110 whilst initialising SD card mmc0: Unexpected interrupt 0x0200. mmc0: Timeout waiting for hardware interrupt. mmc0: error -110 whilst initialising SD card mmc0: Unexpected interrupt 0x0200. It is because ESDHC controller has different bit setting for PROCTL register, when kernel sets Power Control Register by method for standard SD Host Specification, it would overwritten FSL ESDHC PROCTL[DMAS]; when it set Host Control Registers[DMAS], it sets PROCTL[EMODE] and PROCTL[D3CD]. These operations will set bad bits for PROCTL Register on FSL ESDHC Controller and cause errors, so this patch will make esdhc driver access FSL PROCTL Register according to block guide instead of standard SD Host Specification. For some FSL chips, such as MPC8536/P2020, PROCTL[VOLT_SEL] and PROCTL[DMAS] bits are reserved and even if they are set to wrong bits there is no error. But considering that all FSL ESDHC Controller register map is not fully compliant to standard SD Host Specification, we put the patch to all of FSL ESDHC Controllers. Signed-off-by: Lei Xu b33...@freescale.com Signed-off-by: Roy Zang tie-fei.z...@freescale.com Signed-off-by: Kumar Gala ga...@kernel.crashing.org --- drivers/mmc/host/sdhci-of-core.c | 3 ++ drivers/mmc/host/sdhci.c | 62 ++--- include/linux/mmc/sdhci.h | 6 ++- 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c index 60e4186..fede43d 100644 --- a/drivers/mmc/host/sdhci-of-core.c +++ b/drivers/mmc/host/sdhci-of-core.c @@ -179,6 +179,9 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev) if (sdhci_of_wp_inverted(np)) host-quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; + if (of_device_is_compatible(np, fsl,esdhc)) + host-quirks |= SDHCI_QUIRK_QORIQ_PROCTL_WEIRD; + clk = of_get_property(np, clock-frequency, size); if (clk size == sizeof(*clk) *clk) of_host-clock = be32_to_cpup(clk); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 58d5436..77174e5 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -674,7 +674,7 @@ static void sdhci_set_transfer_irqs(struct sdhci_host *host) static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) { u8 count; - u8 ctrl; + u32 ctrl; struct mmc_data *data = cmd-data; int ret; @@ -807,14 +807,28 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd) * is ADMA. */ if (host-version = SDHCI_SPEC_200) { - ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); - ctrl = ~SDHCI_CTRL_DMA_MASK; - if ((host-flags SDHCI_REQ_USE_DMA) - (host-flags SDHCI_USE_ADMA)) - ctrl |= SDHCI_CTRL_ADMA32; - else - ctrl |= SDHCI_CTRL_SDMA; - sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + if (host-quirks SDHCI_QUIRK_QORIQ_PROCTL_WEIRD) { +#define ESDHCI_PROCTL_DMAS_MASK 0x0300 +#define ESDHCI_PROCTL_ADMA32 0x0200 +#define ESDHCI_PROCTL_SDMA 0x Breaks the code flow / readability. Can be moved to top of the file ? + ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL); + ctrl = ~ESDHCI_PROCTL_DMAS_MASK; + if ((host-flags SDHCI_REQ_USE_DMA) + (host-flags SDHCI_USE_ADMA)) + ctrl |= ESDHCI_PROCTL_ADMA32; + else + ctrl |= ESDHCI_PROCTL_SDMA; + sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL); + } else { + ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); + ctrl = ~SDHCI_CTRL_DMA_MASK; + if ((host-flags SDHCI_REQ_USE_DMA) + (host-flags SDHCI_USE_ADMA)) + ctrl |= SDHCI_CTRL_ADMA32; + else + ctrl |= SDHCI_CTRL_SDMA; + sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); + } } if (!(host-flags SDHCI_REQ_USE_DMA)) { @@ -1138,19 +1152,32 @@ out: static void sdhci_set_power(struct sdhci_host *host, unsigned short power) { u8 pwr = 0; + u8 volt = 0; if (power != (unsigned short)-1) { switch (1 power) { +#define
Re: [PATCH v2] arm: mach-mmp: brownstone.c support multiple sd slots
On Fri, Apr 29, 2011 at 4:45 AM, Philip Rakity prak...@marvell.com wrote: Support multiple sd/eMMC interfaces. enable mmc1, 2, and 3. mmc2 is used eMMC and slot is marked PERMANENT and 8 bit device. mmc1 is used for Wifi and slot is marked PERMANENT Note: eMMC (mmc2) is set to initialize first to workaround a problem where booting in logical order requires mmc create work queue to be multi-threaded otherwise boot process hangs. BUG report send to linux-mmc and linux-kernel mailing list. Wifi (mmc1) requires we enable power on the device by toggling the gpio lines for power and reset. Signed-off-by: Philip Rakity prak...@marvell.com Applied. Though the email client was fiddling the spaces/CR-LF a bit. --- arch/arm/mach-mmp/brownstone.c | 52 +++- 1 files changed, 51 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index 7bb78fd..577e8de 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -19,6 +19,7 @@ #include linux/regulator/max8649.h #include linux/regulator/fixed.h #include linux/mfd/max8925.h +#include linux/delay.h #include asm/mach-types.h #include asm/mach/arch.h @@ -177,9 +178,56 @@ static struct i2c_board_info brownstone_twsi1_info[] = { }; static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = { - .max_speed = 2500, + .adjust_clocks = 1, + .clk_select = 1, + .clk_delay = 31, }; +static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc1 = { + .adjust_clocks = 1, + .clk_select = 1, + .clk_delay = 15, + .flags = PXA_FLAG_CARD_PERMANENT, +}; + +static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc2 = { + .adjust_clocks = 1, + .clk_select = 1, + .clk_delay = 31, + .flags = PXA_FLAG_CARD_PERMANENT | + PXA_FLAG_SD_8_BIT_CAPABLE_SLOT, +}; + +static void __init mmc_sdio_wifi(void) +{ + int poweron; + int reset; + + poweron = mfp_to_gpio(GPIO57_GPIO); + reset = mfp_to_gpio(GPIO58_GPIO); + + if (gpio_request(reset, sd8xxx reset)) { + printk(KERN_INFO gpio %d request failed\n, reset); + return; + } + + if (gpio_request(poweron, sd8xxx PDn)) { + gpio_free(reset); + printk(KERN_INFO gpio %d request failed\n, poweron); + return; + } + + gpio_direction_output(poweron, 1); + msleep(1); + gpio_direction_output(reset, 0); + msleep(1); + gpio_direction_output(reset, 1); + gpio_free(reset); + gpio_free(poweron); + + mmp2_add_sdhost(1, mmp2_sdh_platdata_mmc1); /* Wifi */ +} + static void __init brownstone_init(void) { mfp_config(ARRAY_AND_SIZE(brownstone_pin_config)); @@ -188,7 +236,9 @@ static void __init brownstone_init(void) mmp2_add_uart(1); mmp2_add_uart(3); mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info)); + mmp2_add_sdhost(2, mmp2_sdh_platdata_mmc2); /* eMMC */ mmp2_add_sdhost(0, mmp2_sdh_platdata_mmc0); /* SD/MMC */ + mmc_sdio_wifi(); /* enable 5v regulator */ platform_device_register(brownstone_v_5vp_device); -- 1.7.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] arm: mach-mmp: brownstone.c support multiple sd slots
On Tue, Jul 5, 2011 at 2:52 PM, Eric Miao eric.y.m...@gmail.com wrote: On Fri, Apr 29, 2011 at 4:45 AM, Philip Rakity prak...@marvell.com wrote: Support multiple sd/eMMC interfaces. enable mmc1, 2, and 3. mmc2 is used eMMC and slot is marked PERMANENT and 8 bit device. mmc1 is used for Wifi and slot is marked PERMANENT Note: eMMC (mmc2) is set to initialize first to workaround a problem where booting in logical order requires mmc create work queue to be multi-threaded otherwise boot process hangs. BUG report send to linux-mmc and linux-kernel mailing list. Wifi (mmc1) requires we enable power on the device by toggling the gpio lines for power and reset. Signed-off-by: Philip Rakity prak...@marvell.com Applied. Though the email client was fiddling the spaces/CR-LF a bit. --- arch/arm/mach-mmp/brownstone.c | 52 +++- 1 files changed, 51 insertions(+), 1 deletions(-) Hi, Eric arch/arm/mach-mmp/brownstone.c has already been modified from mmc-next, here will have conflict. Sorry for inconvenience. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] arm: mach-mmp: brownstone.c support multiple sd slots
On Tue, Jul 5, 2011 at 3:05 PM, zhangfei gao zhangfei@gmail.com wrote: On Tue, Jul 5, 2011 at 2:52 PM, Eric Miao eric.y.m...@gmail.com wrote: On Fri, Apr 29, 2011 at 4:45 AM, Philip Rakity prak...@marvell.com wrote: Support multiple sd/eMMC interfaces. enable mmc1, 2, and 3. mmc2 is used eMMC and slot is marked PERMANENT and 8 bit device. mmc1 is used for Wifi and slot is marked PERMANENT Note: eMMC (mmc2) is set to initialize first to workaround a problem where booting in logical order requires mmc create work queue to be multi-threaded otherwise boot process hangs. BUG report send to linux-mmc and linux-kernel mailing list. Wifi (mmc1) requires we enable power on the device by toggling the gpio lines for power and reset. Signed-off-by: Philip Rakity prak...@marvell.com Applied. Though the email client was fiddling the spaces/CR-LF a bit. --- arch/arm/mach-mmp/brownstone.c | 52 +++- 1 files changed, 51 insertions(+), 1 deletions(-) Hi, Eric arch/arm/mach-mmp/brownstone.c has already been modified from mmc-next, here will have conflict. Sorry for inconvenience. 'K, I'll drop it then. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: irq flood with mmc boot partitions on s3c2416 with 3.0rc1
Hi again, sorry for having taken so long, but university-work called :-) Am Montag 20 Juni 2011, 21:34:53 schrieb Andrei Warkentin: On Sun, Jun 19, 2011 at 9:23 AM, Heiko Stübner he...@sntech.de wrote: Am Samstag 18 Juni 2011, 22:56:11 schrieb Daniel Mack: The log you sent out seems a bit short (it's covers 1s of boot time - usb0: no IPv6 routers present is the last line ). Can you send - 1) A full log with errors without any of my patches. 2) A full log with just the first patch. 3) A full log with just the second patch. I have attached a log with mmc-debugging enabled. The relevant parts start around line 2634 (waiting for /dev to be fully populated - the udev start). The culprit (Hynix-nand) is mmc1. Switching the patches on and off will have to wait until the weekend. But I can say the error (irq message and register dump [and them looping endlessly]) has not not changed from before your patches. I'm curious, is mmc_blk_resume (which is modified by your second patch) called at other times than when waking up from system suspend? [i.e. during system startup] I'm interested in knowing what the pattern of access to boot0 and boot1 is that causes these failures - does it only report I/O errors for for certain blocks (say, above some number) or for all of them. it doesn't report io-errors at all. It send endless loops of CMD13 calls with the same argument and receives interrupts it does not expect :-) Thanks again for your time Heiko dmesg-debug_20110629.txt.gz Description: GNU Zip compressed data
Re: [PATCH 3/3] eSDHC: fix incorrect default value of the capabilities register on P4080
On Tue, Jul 05, 2011 at 12:19:03PM +0800, Roy Zang wrote: P4080 eSDHC errata 12 describes incorrect default value of the the host controller capabilities register. The default value of the VS18 and VS30 fields in the host controller capabilities register (HOSTCAPBLT) are incorrect. The default of these bits should be zero instead of one in the eSDHC logic. This patch adds the workaround for these errata. Signed-off-by: Roy Zang tie-fei.z...@freescale.com --- drivers/mmc/host/sdhci-of-core.c |3 +++ drivers/mmc/host/sdhci.c |6 ++ include/linux/mmc/sdhci.h|4 3 files changed, 13 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c index fede43d..9bdd30d 100644 --- a/drivers/mmc/host/sdhci-of-core.c +++ b/drivers/mmc/host/sdhci-of-core.c @@ -182,6 +182,9 @@ static int __devinit sdhci_of_probe(struct platform_device *ofdev) if (of_device_is_compatible(np, fsl,esdhc)) host-quirks |= SDHCI_QUIRK_QORIQ_PROCTL_WEIRD; + if (of_device_is_compatible(np, fsl,p4080-esdhc)) + host-quirks |= SDHCI_QUIRK_QORIQ_HOSTCAPBLT_ONLY_VS33; Should really use voltage-ranges, not quirks. http://www.spinics.net/lists/linux-mmc/msg02785.html Thanks, -- Anton Vorontsov Email: cbouatmai...@gmail.com -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] mmci: use StartBitErr to detect bad connections
On Tue, Jun 28, 2011 at 09:57:25AM +0200, Linus Walleij wrote: Stresstesting insert/remove of SD-cards can trigger a StartBitErr. This made the driver to hang in forever waiting for a non ocurring data timeout. This bit and interrupt is documented in the original PL180 TRM, just never implemented until now. Signed-off-by: Ulf Hansson ulf.hans...@stericsson.com Reviewed-by: Linus Walleij linus.wall...@stericsson.com Reviewed-by: Jonas Aberg jonas.ab...@stericsson.com Signed-off-by: Linus Walleij linus.wall...@linaro.org Acked-by: Russell King rmk+ker...@arm.linux.org.uk -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] mmci: adjust calculation of f_min
On Tue, Jun 28, 2011 at 09:57:33AM +0200, Linus Walleij wrote: From: Ulf Hansson ulf.hans...@stericsson.com For the st_clkdiv variant f_min is too low for practical cases, there is a heuristic calculation that appear to set the min frequency to mclk rounded up with 512, for our practical use cases dividing by 257 gives a reasonable floor value on the ST Micro version of the clock divider. The only requirement with f_min is that the hardware is capable of producing a clock at that rate. Having it smaller than 'practical' is not a problem, and may help some cards be detected. The core tries clocks at 400kHz, 300, 200 and 100kHz during probe, and that's the lowest frequency that will be attempted (provided the card doesn't actualy say it wants something slower.) So unless there is a reason not to (eg, divisors above 257 are invalid) its better to leave it as is. -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] mmci: sync DATAEND irq with dma|pio transfer done
On Tue, Jun 28, 2011 at 09:57:40AM +0200, Linus Walleij wrote: From: Ulf Hansson ulf.hans...@stericsson.com The end of a dma|pio data transfer is synced with the DATAEND irq. This will prevent the mmci driver from ending the request before the dma|pio job is completely done. For dma we use DMA_PREP_INTERRUPT to register a callback function which is called when dma driver is done with job. To also make sure we prevent hanging forever, waiting for DATAEND irq or a dma|pio transfer to be done, we setup a timer when either a DATAEND or dma|pio job is done. Once both conditions have occured, the timer is cancelled and the data transfer is completed. If a timeout occurs, the data transfer is terminated in a controlled manner and EAGAIN is returned to the framework. A timeout value of 50 ms has been found to work well for our usecases. What is the framework supposed to do with that error code? Magic the driver into disabling DMA by some non-existant callback? Please, stop introducing magic new error codes which have no meaning to the upper levels unless you're also going to add some handling of those error conditions as well. -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mmc: enable background operations for emmc4.41 with HPI support
Background operations is an optional feature defined in eMMC4.41 spec. The need for BKOPS will be checked after servicing each user request in R1 response. If need for BKOPS flag is set, then start BKOPS when request queue is idle. Once bkops is started and meanwhile any user read/write request comes then the bkops will be interrupted by issuing HPI, otherwise bkops keep going until it gets finished. This patch is based on the four patches submitted by Chuanxiao Dong to linux-mmc. Signed-off-by: Hanumath Prasad hanumath.pra...@stericsson.com --- drivers/mmc/card/block.c | 14 +++- drivers/mmc/card/queue.c |1 + drivers/mmc/core/core.c| 75 drivers/mmc/core/mmc.c | 52 +- drivers/mmc/core/mmc_ops.c | 33 +++ drivers/mmc/core/mmc_ops.h |1 + include/linux/mmc/card.h | 14 include/linux/mmc/core.h |3 +- include/linux/mmc/mmc.h|6 +++ 9 files changed, 195 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 71da564..26a87ca 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -799,6 +799,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) mmc_queue_bounce_pre(mq); + if (mmc_card_doing_bkops(card)) { + if (mmc_interrupt_bkops(card)) + goto cmd_err; + } + mmc_wait_for_req(card-host, brq.mrq); mmc_queue_bounce_post(mq); @@ -897,10 +902,17 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) goto cmd_err; } + spin_lock_irq(md-lock); + /* +* Check BKOPS urgency from each R1 response +*/ + if (mmc_card_mmc(card) + (brq.cmd.resp[0] R1_URGENT_BKOPS)) + mmc_card_set_need_bkops(card); + /* * A block was successfully transferred. */ - spin_lock_irq(md-lock); ret = __blk_end_request(req, 0, brq.data.bytes_xfered); spin_unlock_irq(md-lock); } while (ret); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index c07322c..c491edd 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -64,6 +64,7 @@ static int mmc_queue_thread(void *d) set_current_state(TASK_RUNNING); break; } + mmc_start_bkops(mq-card); up(mq-thread_sem); schedule(); down(mq-thread_sem); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 68091dd..e5e1d7c 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -196,6 +196,48 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) host-ops-request(host, mrq); } +/** + * mmc_start_bkops - start BKOPS for supported cards + * @card: MMC card to start BKOPS + * + * Start background operations whenever requested. + * when the urgent BKOPS bit is set in a R1 command response + * then background operations should be started immediately. + */ +void mmc_start_bkops(struct mmc_card *card) +{ + int err; + unsigned long flags; + + if (!card || !card-ext_csd.bkops_en) + return; + /* +* If card is already doing bkops or need for +* bkops flag is not set, then do nothing just +* return +*/ + if (mmc_card_doing_bkops(card) + || !mmc_card_need_bkops(card)) + return; + + mmc_claim_host(card-host); + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_BKOPS_START, 1, 0); + if (err) { + printk(KERN_ERR error %d starting bkops\n, + err); + mmc_card_clr_need_bkops(card); + goto out; + } + spin_lock_irqsave(card-host-lock, flags); + mmc_card_clr_need_bkops(card); + mmc_card_set_doing_bkops(card); + spin_unlock_irqrestore(card-host-lock, flags); +out: + mmc_release_host(card-host); +} +EXPORT_SYMBOL(mmc_start_bkops); + static void mmc_wait_done(struct mmc_request *mrq) { complete(mrq-done_data); @@ -254,6 +296,39 @@ int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries EXPORT_SYMBOL(mmc_wait_for_cmd); /** + * mmc_interrupt_bkops - interrupt ongoing BKOPS + * @card: MMC card to check BKOPS + * + * Send HPI command to interrupt ongoing background operations, + * to allow rapid servicing of foreground operations,e.g. read/ + * writes. Wait until the card comes out of
OMAP HS-MMC: convert to dev_pm_ops broke hibernation
Hi, commit a791daa15305e7e549a418ef0ae6bc4b4580066e converted PM operations to use dev_pm_ops. But this broke hibernation/suspend to disk : - now there no state argument - but there is one call back per state : -- suspend/resume for s2ram -- freeze/thaw poweroff/restore for s2disk look like most of the mmc driver using dev_pm_ops got the same problem (only jz4740_mmc define poweroff/restore) Matthieu -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mmc: documentation of mmc non-blocking request usage and design.
Documentation about the background and the design of mmc non-blocking. Host driver guide lines to minimize request preparation over head. Signed-off-by: Per Forlin per.for...@linaro.org --- Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 85 +++ 2 files changed, 87 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX index 93dd7a7..11bc2cf 100644 --- a/Documentation/mmc/00-INDEX +++ b/Documentation/mmc/00-INDEX @@ -4,3 +4,5 @@ mmc-dev-attrs.txt - info on SD and MMC device attributes mmc-dev-parts.txt - info on SD and MMC device partitions +mmc-async-req.txt +- info on mmc asynchronous request diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt new file mode 100644 index 000..d139a51 --- /dev/null +++ b/Documentation/mmc/mmc-async-req.txt @@ -0,0 +1,85 @@ +Rationale += + +How significant is the cache maintenance over head? +It depends, fast eMMC and multiple cache levels with speculative cache pre-fetch +makes the cache overhead relatively significant. If the DMA preparations +for the next request is done in parallel to the current transfer +the DMA preparation overhead would not affect the MMC performance. +The intention of non-blocking (asynchronous) mmc requests is to minimize the +time between a mmc request ends and another mmc request begins. +Using mmc_wait_for_req() the MMC controller is idle when dma_map_sg and +dma_unmap_sg is processing. Using non-blocking mmc request makes it +possible to prepare the caches for next job in parallel to an active +mmc request. + +MMC block driver + + +The issue_rw_rq() in the mmc block driver is made non-blocking. +The increase in throughput is proportional to the time it takes to +prepare (major part of preparations is dma_map_sg and dma_unmap_sg) +a request and how fast the memory is. The faster the MMC/SD is +the more significant the prepare request time becomes. Roughly the expected +performance gain is 5% for large writes and 10% on large reads on a L2 cache +platform. In power save mode, when clocks run on a lower frequency, the DMA +preparation may cost even more. As long as these slower preparations are run +in parallel to the transfer performance wont be affected. + +Details on measurements from IOZone and mmc_test + + +https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req + +MMC core API extension +== + +There is one new public function mmc_start_req() +Is starts a new MMC command request for a host. The function isn't +truely non-blocking. If there is on ongoing async request it waits +for completion of that request and starts the new one and return. It +Doesn't wait for the new request to complete. If there is no ongoing +request it starts the new request and returns immediately. + +MMC host extensions +=== + +There are two optional hooks pre_req() and post_req() that the host driver +may implement in order to move work to before and after the actual mmc_request +function is called. In the DMA case pre_req() may do dma_map_sg() and prepare +the dma descriptor, and post_req runs the dma_unmap_sg. + +Optimize for the first request +== + +The first request in a series of requests can't be prepared in parallel to the +previous transfer, since there is no previous request. +The argument is_first_req in pre_req() indicates that there is no previous +request. The host driver may optimize for this scenario to minimize +the performance loss. A way to optimize for this is to split the current +request in two chunks, prepare the first chunk and start the request, +and finally prepare the second chunk and start the transfer. + +Pseudocode to handle is_first_req scenario with minimal prepare over head: +if (is_first_req req-size threshold) + /* start MMC transfer for the complete transfer size */ + mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE) + + /* +* Begin to prepare DMA while cmd is being processed by MMC. +* The first chunk of the request should take the same time +* to prepare as the MMC process command time. +* If prepare time exceeds MMC cmd time +* the transfer is delayed, guesstimate max 4k as first chunk size. +*/ +prepare_1st_chunk_for_dma(req) +/* flush pending desc to the DMAC (dmaengine.h) */ +dma_issue_pending(req-dma_desc); + +prepare_2st_chunk_for_dma(req) +/* + * The second issue_pending should be called before MMC runs out + * of the first chunk. If the MMC runs out of the first data chunk before + * this call, the transfer is delayed. + */ +dma_issue_pending(req-dma_desc); -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message
[PATCH v2 0/3] Add device tree probe for sdhci-esdhc-imx
The first patch removes the uses of cpu_is_mx(), the second one makes a dt related fix on sdhci-pltfm.c, and the third one adds device tree probe for sdhci-esdhc-imx driver. Changes since v1: * Address review comments given by Grant Shawn Guo (3): mmc: sdhci-esdhc-imx: get rid of the uses of cpu_is_mx() mmc: sdhci-pltfm: dt device does not pass parent to sdhci_alloc_host mmc: sdhci-esdhc-imx: add device tree probe support .../devicetree/bindings/mmc/fsl-imx-esdhc.txt | 40 ++ arch/arm/mach-imx/clock-imx25.c|4 +- arch/arm/mach-imx/clock-imx35.c|6 +- arch/arm/mach-mx5/clock-mx51-mx53.c| 16 +- arch/arm/mach-mx5/mx51_efika.c |4 +- .../plat-mxc/devices/platform-sdhci-esdhc-imx.c| 17 ++- arch/arm/plat-mxc/include/mach/devices-common.h|1 + drivers/mmc/host/sdhci-esdhc-imx.c | 144 ++-- drivers/mmc/host/sdhci-pltfm.c |3 +- 9 files changed, 202 insertions(+), 33 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/3] mmc: sdhci-esdhc-imx: get rid of the uses of cpu_is_mx()
The patch removes all the uses of cpu_is_mx(). Instead, it utilizes platform_device_id to distinguish the esdhc differences among SoCs. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org --- arch/arm/mach-imx/clock-imx25.c|4 +- arch/arm/mach-imx/clock-imx35.c|6 +- arch/arm/mach-mx5/clock-mx51-mx53.c| 16 +++--- arch/arm/mach-mx5/mx51_efika.c |4 +- .../plat-mxc/devices/platform-sdhci-esdhc-imx.c| 17 +++--- arch/arm/plat-mxc/include/mach/devices-common.h|1 + drivers/mmc/host/sdhci-esdhc-imx.c | 60 ++- 7 files changed, 81 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c index a65838f..2955afa 100644 --- a/arch/arm/mach-imx/clock-imx25.c +++ b/arch/arm/mach-imx/clock-imx25.c @@ -300,8 +300,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(imx2-wdt.0, NULL, wdt_clk) _REGISTER_CLOCK(imx-ssi.0, NULL, ssi1_clk) _REGISTER_CLOCK(imx-ssi.1, NULL, ssi2_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx25.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx25.1, NULL, esdhc2_clk) _REGISTER_CLOCK(mx2-camera.0, NULL, csi_clk) _REGISTER_CLOCK(NULL, audmux, audmux_clk) _REGISTER_CLOCK(flexcan.0, NULL, can1_clk) diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c index 5a4cc1e..2f80f14 100644 --- a/arch/arm/mach-imx/clock-imx35.c +++ b/arch/arm/mach-imx/clock-imx35.c @@ -458,9 +458,9 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(imx-epit.0, NULL, epit1_clk) _REGISTER_CLOCK(imx-epit.1, NULL, epit2_clk) _REGISTER_CLOCK(NULL, esai, esai_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.2, NULL, esdhc3_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx35.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx35.1, NULL, esdhc2_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx35.2, NULL, esdhc3_clk) _REGISTER_CLOCK(fec.0, NULL, fec_clk) _REGISTER_CLOCK(NULL, gpio, gpio1_clk) _REGISTER_CLOCK(NULL, gpio, gpio2_clk) diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c index 699b0d2..fd60e2c 100644 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c @@ -1453,10 +1453,10 @@ static struct clk_lookup mx51_lookups[] = { _REGISTER_CLOCK(imx51-ecspi.0, NULL, ecspi1_clk) _REGISTER_CLOCK(imx51-ecspi.1, NULL, ecspi2_clk) _REGISTER_CLOCK(imx51-cspi.0, NULL, cspi_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.2, NULL, esdhc3_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.3, NULL, esdhc4_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.1, NULL, esdhc2_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.2, NULL, esdhc3_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.3, NULL, esdhc4_clk) _REGISTER_CLOCK(NULL, cpu_clk, cpu_clk) _REGISTER_CLOCK(NULL, iim_clk, iim_clk) _REGISTER_CLOCK(imx2-wdt.0, NULL, dummy_clk) @@ -1480,10 +1480,10 @@ static struct clk_lookup mx53_lookups[] = { _REGISTER_CLOCK(imx-i2c.0, NULL, i2c1_clk) _REGISTER_CLOCK(imx-i2c.1, NULL, i2c2_clk) _REGISTER_CLOCK(imx-i2c.2, NULL, i2c3_mx53_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_mx53_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.2, NULL, esdhc3_mx53_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.3, NULL, esdhc4_mx53_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.1, NULL, esdhc2_mx53_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.2, NULL, esdhc3_mx53_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.3, NULL, esdhc4_mx53_clk) _REGISTER_CLOCK(imx53-ecspi.0, NULL, ecspi1_clk) _REGISTER_CLOCK(imx53-ecspi.1, NULL, ecspi2_clk) _REGISTER_CLOCK(imx53-cspi.0, NULL, cspi_clk) diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c index 56739c2..4435e03 100644 --- a/arch/arm/mach-mx5/mx51_efika.c +++ b/arch/arm/mach-mx5/mx51_efika.c @@ -260,8 +260,8 @@ static struct regulator_consumer_supply vvideo_consumers[] = { }; static struct regulator_consumer_supply vsd_consumers[] = { - REGULATOR_SUPPLY(vmmc, sdhci-esdhc-imx.0), - REGULATOR_SUPPLY(vmmc, sdhci-esdhc-imx.1), + REGULATOR_SUPPLY(vmmc, sdhci-esdhc-imx51.0), + REGULATOR_SUPPLY(vmmc,
[PATCH v2 2/3] mmc: sdhci-pltfm: dt device does not pass parent to sdhci_alloc_host
Neither platform based nor dt based device needs to pass the parent to sdhci_alloc_host. There is no difference between platform and dt on this point. The patch makes the change to pass device itself than its parent to sdhci_alloc_host for dt case too. Otherwise the probe function of sdhci based drivers which is shared between platform and dt will fail on dt case. Signed-off-by: Shawn Guo shawn@linaro.org Acked-by: Grant Likely grant.lik...@secretlab.ca Cc: Chris Ball c...@laptop.org --- drivers/mmc/host/sdhci-pltfm.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 71c0ce1..6414efe 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c @@ -85,6 +85,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, { struct sdhci_host *host; struct sdhci_pltfm_host *pltfm_host; + struct device_node *np = pdev-dev.of_node; struct resource *iomem; int ret; @@ -98,7 +99,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev, dev_err(pdev-dev, Invalid iomem size!\n); /* Some PCI-based MFD need the parent here */ - if (pdev-dev.parent != platform_bus) + if (pdev-dev.parent != platform_bus !np) host = sdhci_alloc_host(pdev-dev.parent, sizeof(*pltfm_host)); else host = sdhci_alloc_host(pdev-dev, sizeof(*pltfm_host)); -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/3] mmc: sdhci-esdhc-imx: add device tree probe support
The patch adds device tree probe support for sdhci-esdhc-imx driver. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org Cc: Grant Likely grant.lik...@secretlab.ca --- .../devicetree/bindings/mmc/fsl-imx-esdhc.txt | 40 drivers/mmc/host/sdhci-esdhc-imx.c | 102 +++- 2 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt new file mode 100644 index 000..351d239 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -0,0 +1,40 @@ +* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX + +The Enhanced Secure Digital Host Controller on Freescale i.MX family +provides an interface for MMC, SD, and SDIO types of memory cards. + +Required properties: +- compatible : Should be fsl,chip-esdhc +- reg : Should contain eSDHC registers location and length +- interrupts : Should contain eSDHC interrupt +- cd-type : String, card detection (CD) method. Supported values are: +none : No CD +controller : Uses eSDHC controller internal CD signal +gpio : Uses GPIO pin for CD +permanent : No CD because card is permanently wired to host +- wp-type : String, write protection (WP) method. Supported values are: +none : No WP +controller : Uses eSDHC controller internal WP signal +gpio : Uses GPIO pin for WP +- gpios : Should specify GPIOs in this order: CD GPIO, WP GPIO, if + properties cd-type and wp-type are gpio. + +Examples: + +esdhc@70004000 { + compatible = fsl,imx51-esdhc; + reg = 0x70004000 0x4000; + interrupts = 1; + fsl,cd-type = controller; + fsl,wp-type = controller; +}; + +esdhc@70008000 { + compatible = fsl,imx51-esdhc; + reg = 0x70008000 0x4000; + interrupts = 2; + fsl,cd-type = gpio; + fsl,wp-type = gpio; + cd-gpios = gpio0 6 0; /* GPIO1_6 */ + wp-gpios = gpio0 5 0; /* GPIO1_5 */ +}; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1edda29..593d6b9 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -20,6 +20,9 @@ #include linux/mmc/host.h #include linux/mmc/mmc.h #include linux/mmc/sdio.h +#include linux/of.h +#include linux/of_device.h +#include linux/of_gpio.h #include mach/esdhc.h #include sdhci-pltfm.h #include sdhci-esdhc.h @@ -72,6 +75,14 @@ static struct platform_device_id imx_esdhc_devtype[] = { } }; +static const struct of_device_id imx_esdhc_dt_ids[] = { + { .compatible = fsl,imx25-esdhc, .data = imx_esdhc_devtype[IMX25_ESDHC], }, + { .compatible = fsl,imx35-esdhc, .data = imx_esdhc_devtype[IMX35_ESDHC], }, + { .compatible = fsl,imx51-esdhc, .data = imx_esdhc_devtype[IMX51_ESDHC], }, + { .compatible = fsl,imx53-esdhc, .data = imx_esdhc_devtype[IMX53_ESDHC], }, + { /* sentinel */ } +}; + static inline int is_imx25_esdhc(struct pltfm_imx_data *data) { return data-devtype == IMX25_ESDHC; @@ -305,24 +316,96 @@ static irqreturn_t cd_irq(int irq, void *data) return IRQ_HANDLED; }; +#ifdef CONFIG_OF +static const char *cd_types[] = { + [ESDHC_CD_NONE] = none, + [ESDHC_CD_CONTROLLER] = controller, + [ESDHC_CD_GPIO] = gpio, + [ESDHC_CD_PERMANENT]= permanent, +}; + +static const char *wp_types[] = { + [ESDHC_WP_NONE] = none, + [ESDHC_WP_CONTROLLER] = controller, + [ESDHC_WP_GPIO] = gpio, +}; + +static int __devinit sdhci_esdhc_imx_probe_dt(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(imx_esdhc_dt_ids, pdev-dev); + struct device_node *np = pdev-dev.of_node; + struct esdhc_platform_data *boarddata; + int err, i; + const char *cd, *wp; + + if (!np) + return -ENODEV; + + boarddata = kzalloc(sizeof(*boarddata), GFP_KERNEL); + if (!boarddata) + return -ENOMEM; + pdev-dev.platform_data = boarddata; + + err = of_property_read_string(np, fsl,cd-type, cd); + if (err) + return err; + for (i = 0; i ARRAY_SIZE(cd_types); i++) + if (!strcasecmp(cd, cd_types[i])) { + boarddata-cd_type = i; + break; + } + + err = of_property_read_string(np, fsl,wp-type, wp); + if (err) + return err; + for (i = 0; i ARRAY_SIZE(wp_types); i++) + if (!strcasecmp(wp, wp_types[i])) { + boarddata-wp_type = i; + break; + } + + boarddata-cd_gpio = of_get_gpio(np, 0); + boarddata-wp_gpio = of_get_gpio(np, 1);
Re: [PATCH] mmc: documentation of mmc non-blocking request usage and design.
Hi Per, minor proofreading, On Tue, Jul 05 2011, Per Forlin wrote: Documentation about the background and the design of mmc non-blocking. Host driver guide lines to minimize request preparation over head. guidelines, overhead Signed-off-by: Per Forlin per.for...@linaro.org --- Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 85 +++ 2 files changed, 87 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX index 93dd7a7..11bc2cf 100644 --- a/Documentation/mmc/00-INDEX +++ b/Documentation/mmc/00-INDEX @@ -4,3 +4,5 @@ mmc-dev-attrs.txt - info on SD and MMC device attributes mmc-dev-parts.txt - info on SD and MMC device partitions +mmc-async-req.txt +- info on mmc asynchronous request diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt new file mode 100644 index 000..d139a51 --- /dev/null +++ b/Documentation/mmc/mmc-async-req.txt @@ -0,0 +1,85 @@ +Rationale += + +How significant is the cache maintenance over head? overhead +It depends, fast eMMC and multiple cache levels with speculative cache pre-fetch This line is over 80 cols. Please wrap at around 76 cols. +makes the cache overhead relatively significant. If the DMA preparations +for the next request is done in parallel to the current transfer are done +the DMA preparation overhead would not affect the MMC performance. +The intention of non-blocking (asynchronous) mmc requests is to minimize the +time between a mmc request ends and another mmc request begins. between when an +Using mmc_wait_for_req() the MMC controller is idle when dma_map_sg and s/when/while/ +dma_unmap_sg is processing. Using non-blocking mmc request makes it requests +possible to prepare the caches for next job in parallel to an active +mmc request. + +MMC block driver + + +The issue_rw_rq() in the mmc block driver is made non-blocking. +The increase in throughput is proportional to the time it takes to +prepare (major part of preparations is dma_map_sg and dma_unmap_sg) +a request and how fast the memory is. The faster the MMC/SD is +the more significant the prepare request time becomes. Roughly the expected +performance gain is 5% for large writes and 10% on large reads on a L2 cache +platform. In power save mode, when clocks run on a lower frequency, the DMA +preparation may cost even more. As long as these slower preparations are run +in parallel to the transfer performance wont be affected. + +Details on measurements from IOZone and mmc_test + + +https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req + +MMC core API extension +== + +There is one new public function mmc_start_req() +Is starts a new MMC command request for a host. The function isn't s/Is/It/ +truely non-blocking. If there is on ongoing async request it waits truly +for completion of that request and starts the new one and return. It start +Doesn't wait for the new request to complete. If there is no ongoing s/Doesn't/doesn't/ +request it starts the new request and returns immediately. + +MMC host extensions +=== + +There are two optional hooks pre_req() and post_req() that the host driver +may implement in order to move work to before and after the actual mmc_request +function is called. In the DMA case pre_req() may do dma_map_sg() and prepare +the dma descriptor, and post_req runs the dma_unmap_sg. + +Optimize for the first request +== + +The first request in a series of requests can't be prepared in parallel to the +previous transfer, since there is no previous request. +The argument is_first_req in pre_req() indicates that there is no previous +request. The host driver may optimize for this scenario to minimize +the performance loss. A way to optimize for this is to split the current +request in two chunks, prepare the first chunk and start the request, +and finally prepare the second chunk and start the transfer. + +Pseudocode to handle is_first_req scenario with minimal prepare over head: overhead +if (is_first_req req-size threshold) + /* start MMC transfer for the complete transfer size */ + mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE) + + /* +* Begin to prepare DMA while cmd is being processed by MMC. +* The first chunk of the request should take the same time +* to prepare as the MMC process command time. +* If prepare time exceeds MMC cmd time +* the transfer is delayed, guesstimate max 4k as first chunk size. +*/ +prepare_1st_chunk_for_dma(req) +/* flush pending desc to the DMAC (dmaengine.h) */ +dma_issue_pending(req-dma_desc); + +
Re: [PATCH 3/3] mmc: sdhci-esdhc-imx: add device tree probe support
On Mon, Jul 04, 2011 at 12:25:48AM -0600, Grant Likely wrote: On Sun, Jul 03, 2011 at 04:30:51PM +0800, Shawn Guo wrote: The patch adds device tree probe support for sdhci-esdhc-imx driver. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org Cc: Grant Likely grant.lik...@secretlab.ca --- .../devicetree/bindings/mmc/fsl-imx-esdhc.txt | 40 drivers/mmc/host/sdhci-esdhc-imx.c | 99 +++- 2 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt new file mode 100644 index 000..e182e7c --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -0,0 +1,40 @@ +* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX + +The Enhanced Secure Digital Host Controller on Freescale i.MX family +provides an interface for MMC, SD, and SDIO types of memory cards. + +Required properties: +- compatible : Should be fsl,chip-esdhc +- reg : Should contain eSDHC registers location and length +- interrupts : Should contain eSDHC interrupt +- cd-type : String, card detection (CD) method. Supported values are: Similar to previous comments, use the fsl, prefix to this property name. I did not know even property name could be written like this. I tried it and found it works :) +none : No CD +controller : Uses eSDHC controller internal CD signal +gpio : Uses GPIO pin for CD I would say the presence of a cd-gpios property would implicitly mean gpio is to be used for the CD pin. Yes, you are right. But I would say this is a direct translation of the existing platform_data. After all, we are sharing most of code path between platform and dt. -- Regards, Shawn -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/3] mmc: sdhci-esdhc-imx: add device tree probe support
On Tue, Jul 5, 2011 at 9:35 AM, Shawn Guo shawn@freescale.com wrote: On Mon, Jul 04, 2011 at 12:25:48AM -0600, Grant Likely wrote: + none : No CD + controller : Uses eSDHC controller internal CD signal + gpio : Uses GPIO pin for CD I would say the presence of a cd-gpios property would implicitly mean gpio is to be used for the CD pin. Yes, you are right. But I would say this is a direct translation of the existing platform_data. After all, we are sharing most of code path between platform and dt. Meh, that's just implementation detail and the DT bindings should *not* be focused on what Linux happens to currently do. Define a binding that makes sense first and foremost, and then make the driver use it. g. -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv4 0/3] OMAP: HSMMC: cleanup and runtime pm
S, Venkatraman svenk...@ti.com writes: From: Kevin Hilman khil...@ti.com Date: Fri, Jul 1, 2011 at 11:24 PM Subject: Re: [PATCHv4 0/3] OMAP: HSMMC: cleanup and runtime pm To: c...@laptop.org Cc: Balaji T K balaj...@ti.com, linux-o...@vger.kernel.org, linux-mmc@vger.kernel.org, t...@atomide.com, madhu...@ti.com, b-cous...@ti.com, p...@pwsan.com, kishore.kadiy...@ti.com Chris, Balaji T K balaj...@ti.com writes: Removing the custom state machine - lazy disable framework in omap_hsmmc to make way for runtime pm to handle host controller power states. This allows mmc_host_enable/mmc_host_disable to be replaced by runtime get_sync and put_sync at host controller driver. Enable runtime PM in omap_hsmmc Rebased to MMC tree : mmc-next branch Tested on OMAP4430SDP, OMAP3430SDP, OMAP2430SDP Reviewed-by: Kevin Hilman khil...@ti.com Tested-by: Kevin Hilman khil...@ti.com Could you queue this series for the v3.1 merge window? Or, with your ack, we are happy to take this through the OMAP tree along with the other dependecies mentioned below. I've also tested this on OMAP4430/Blaze, OMAP3630/Zoom3 and OMAP3430/n900. We have OMAP PM core code changes queued for v3.1 which require the MMC driver to correctly use runtime PM or we can get hangs if MMC is used during boot. Kevin Kevin, Another series from Per Forlin [1] is also modifying the same file, and might result in merge conflict if this series is queued under OMAP and the other is queued by Chris. OK, then Chris should take this series through his tree. Thanks, Kevin Chris, If you intend to queue [1] into mmc-next, Balaji / myself can repost this series on top of it or you'd like to practice some git merge ? Let me know if there is anything that I can do to help. [1] https://lkml.org/lkml/2011/7/1/303 MMC runtime patch has dependency on [PATCH 0/6] OMAP2+: hwmod framework fixes [1] for MMC1/MMC2 clock to get ungated after idle in OMAP4. Without [1] patches, MMC1/MMC2 fails to get detected on OMAP4. [1] http://www.mail-archive.com/linux-omap@vger.kernel.org/msg51457.html Balaji T K (3): MMC: OMAP: HSMMC: Remove lazy_disable MMC: OMAP: HSMMC: add runtime pm support MMC: OMAP: HSMMC: Remove unused iclk drivers/mmc/host/omap_hsmmc.c | 365 +++-- 1 files changed, 57 insertions(+), 308 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 1/3] mmc: sdhci-esdhc-imx: get rid of the uses of cpu_is_mx()
On Tue, Jul 5, 2011 at 9:26 AM, Shawn Guo shawn@linaro.org wrote: The patch removes all the uses of cpu_is_mx(). Instead, it utilizes platform_device_id to distinguish the esdhc differences among SoCs. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org Acked-by: Grant Likely grant.lik...@secretlab.ca --- arch/arm/mach-imx/clock-imx25.c | 4 +- arch/arm/mach-imx/clock-imx35.c | 6 +- arch/arm/mach-mx5/clock-mx51-mx53.c | 16 +++--- arch/arm/mach-mx5/mx51_efika.c | 4 +- .../plat-mxc/devices/platform-sdhci-esdhc-imx.c | 17 +++--- arch/arm/plat-mxc/include/mach/devices-common.h | 1 + drivers/mmc/host/sdhci-esdhc-imx.c | 60 ++- 7 files changed, 81 insertions(+), 27 deletions(-) diff --git a/arch/arm/mach-imx/clock-imx25.c b/arch/arm/mach-imx/clock-imx25.c index a65838f..2955afa 100644 --- a/arch/arm/mach-imx/clock-imx25.c +++ b/arch/arm/mach-imx/clock-imx25.c @@ -300,8 +300,8 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(imx2-wdt.0, NULL, wdt_clk) _REGISTER_CLOCK(imx-ssi.0, NULL, ssi1_clk) _REGISTER_CLOCK(imx-ssi.1, NULL, ssi2_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx25.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx25.1, NULL, esdhc2_clk) _REGISTER_CLOCK(mx2-camera.0, NULL, csi_clk) _REGISTER_CLOCK(NULL, audmux, audmux_clk) _REGISTER_CLOCK(flexcan.0, NULL, can1_clk) diff --git a/arch/arm/mach-imx/clock-imx35.c b/arch/arm/mach-imx/clock-imx35.c index 5a4cc1e..2f80f14 100644 --- a/arch/arm/mach-imx/clock-imx35.c +++ b/arch/arm/mach-imx/clock-imx35.c @@ -458,9 +458,9 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK(imx-epit.0, NULL, epit1_clk) _REGISTER_CLOCK(imx-epit.1, NULL, epit2_clk) _REGISTER_CLOCK(NULL, esai, esai_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.2, NULL, esdhc3_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx35.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx35.1, NULL, esdhc2_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx35.2, NULL, esdhc3_clk) _REGISTER_CLOCK(fec.0, NULL, fec_clk) _REGISTER_CLOCK(NULL, gpio, gpio1_clk) _REGISTER_CLOCK(NULL, gpio, gpio2_clk) diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c index 699b0d2..fd60e2c 100644 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c @@ -1453,10 +1453,10 @@ static struct clk_lookup mx51_lookups[] = { _REGISTER_CLOCK(imx51-ecspi.0, NULL, ecspi1_clk) _REGISTER_CLOCK(imx51-ecspi.1, NULL, ecspi2_clk) _REGISTER_CLOCK(imx51-cspi.0, NULL, cspi_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.2, NULL, esdhc3_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.3, NULL, esdhc4_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.1, NULL, esdhc2_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.2, NULL, esdhc3_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx51.3, NULL, esdhc4_clk) _REGISTER_CLOCK(NULL, cpu_clk, cpu_clk) _REGISTER_CLOCK(NULL, iim_clk, iim_clk) _REGISTER_CLOCK(imx2-wdt.0, NULL, dummy_clk) @@ -1480,10 +1480,10 @@ static struct clk_lookup mx53_lookups[] = { _REGISTER_CLOCK(imx-i2c.0, NULL, i2c1_clk) _REGISTER_CLOCK(imx-i2c.1, NULL, i2c2_clk) _REGISTER_CLOCK(imx-i2c.2, NULL, i2c3_mx53_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.0, NULL, esdhc1_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.1, NULL, esdhc2_mx53_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.2, NULL, esdhc3_mx53_clk) - _REGISTER_CLOCK(sdhci-esdhc-imx.3, NULL, esdhc4_mx53_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.0, NULL, esdhc1_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.1, NULL, esdhc2_mx53_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.2, NULL, esdhc3_mx53_clk) + _REGISTER_CLOCK(sdhci-esdhc-imx53.3, NULL, esdhc4_mx53_clk) _REGISTER_CLOCK(imx53-ecspi.0, NULL, ecspi1_clk) _REGISTER_CLOCK(imx53-ecspi.1, NULL, ecspi2_clk) _REGISTER_CLOCK(imx53-cspi.0, NULL, cspi_clk) diff --git a/arch/arm/mach-mx5/mx51_efika.c b/arch/arm/mach-mx5/mx51_efika.c index 56739c2..4435e03 100644 --- a/arch/arm/mach-mx5/mx51_efika.c +++ b/arch/arm/mach-mx5/mx51_efika.c @@ -260,8 +260,8 @@ static struct regulator_consumer_supply vvideo_consumers[] = { }; static struct regulator_consumer_supply vsd_consumers[] = { -
Re: [PATCH v2 3/3] mmc: sdhci-esdhc-imx: add device tree probe support
On Tue, Jul 5, 2011 at 9:26 AM, Shawn Guo shawn@linaro.org wrote: The patch adds device tree probe support for sdhci-esdhc-imx driver. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org Cc: Grant Likely grant.lik...@secretlab.ca --- .../devicetree/bindings/mmc/fsl-imx-esdhc.txt | 40 drivers/mmc/host/sdhci-esdhc-imx.c | 102 +++- 2 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt new file mode 100644 index 000..351d239 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -0,0 +1,40 @@ +* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX + +The Enhanced Secure Digital Host Controller on Freescale i.MX family +provides an interface for MMC, SD, and SDIO types of memory cards. + +Required properties: +- compatible : Should be fsl,chip-esdhc +- reg : Should contain eSDHC registers location and length +- interrupts : Should contain eSDHC interrupt +- cd-type : String, card detection (CD) method. Supported values are: + none : No CD + controller : Uses eSDHC controller internal CD signal + gpio : Uses GPIO pin for CD + permanent : No CD because card is permanently wired to host +- wp-type : String, write protection (WP) method. Supported values are: + none : No WP + controller : Uses eSDHC controller internal WP signal + gpio : Uses GPIO pin for WP +- gpios : Should specify GPIOs in this order: CD GPIO, WP GPIO, if + properties cd-type and wp-type are gpio. Again, be explicit in your gpios property names. Create a different property for each gpio: cd-gpios and wp-gpios. As for wp-type and cd-type, I think you can drop them. Default to internal controller CD and WP pins. Use gpio if cd-gpios or wp-gpios is present, and define specific properties for the no-wp, no-cd and fixed-card cases. (can you tell that I'm not a fan of the *-type binding for this driver?) :-) + +Examples: + +esdhc@70004000 { + compatible = fsl,imx51-esdhc; + reg = 0x70004000 0x4000; + interrupts = 1; + fsl,cd-type = controller; + fsl,wp-type = controller; +}; + +esdhc@70008000 { + compatible = fsl,imx51-esdhc; + reg = 0x70008000 0x4000; + interrupts = 2; + fsl,cd-type = gpio; + fsl,wp-type = gpio; + cd-gpios = gpio0 6 0; /* GPIO1_6 */ + wp-gpios = gpio0 5 0; /* GPIO1_5 */ +}; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1edda29..593d6b9 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -20,6 +20,9 @@ #include linux/mmc/host.h #include linux/mmc/mmc.h #include linux/mmc/sdio.h +#include linux/of.h +#include linux/of_device.h +#include linux/of_gpio.h #include mach/esdhc.h #include sdhci-pltfm.h #include sdhci-esdhc.h @@ -72,6 +75,14 @@ static struct platform_device_id imx_esdhc_devtype[] = { } }; +static const struct of_device_id imx_esdhc_dt_ids[] = { + { .compatible = fsl,imx25-esdhc, .data = imx_esdhc_devtype[IMX25_ESDHC], }, + { .compatible = fsl,imx35-esdhc, .data = imx_esdhc_devtype[IMX35_ESDHC], }, + { .compatible = fsl,imx51-esdhc, .data = imx_esdhc_devtype[IMX51_ESDHC], }, + { .compatible = fsl,imx53-esdhc, .data = imx_esdhc_devtype[IMX53_ESDHC], }, + { /* sentinel */ } +}; + static inline int is_imx25_esdhc(struct pltfm_imx_data *data) { return data-devtype == IMX25_ESDHC; @@ -305,24 +316,96 @@ static irqreturn_t cd_irq(int irq, void *data) return IRQ_HANDLED; }; +#ifdef CONFIG_OF +static const char *cd_types[] = { + [ESDHC_CD_NONE] = none, + [ESDHC_CD_CONTROLLER] = controller, + [ESDHC_CD_GPIO] = gpio, + [ESDHC_CD_PERMANENT] = permanent, +}; + +static const char *wp_types[] = { + [ESDHC_WP_NONE] = none, + [ESDHC_WP_CONTROLLER] = controller, + [ESDHC_WP_GPIO] = gpio, +}; + +static int __devinit sdhci_esdhc_imx_probe_dt(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(imx_esdhc_dt_ids, pdev-dev); + struct device_node *np = pdev-dev.of_node; + struct esdhc_platform_data *boarddata; + int err, i; + const char *cd, *wp; + + if (!np) + return -ENODEV; + + boarddata = kzalloc(sizeof(*boarddata), GFP_KERNEL); + if (!boarddata) + return -ENOMEM; + pdev-dev.platform_data = boarddata; This is illegal. As far as device drivers are concerned, pdev-dev.platform_data is immutable
Re: [PATCH] mmc: documentation of mmc non-blocking request usage and design.
On 5 July 2011 17:24, Chris Ball c...@laptop.org wrote: Hi Per, minor proofreading, Hi Chris, Thanks for all your comments. I'll update and send out a v2. Thanks, Per -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] documentation of mmc non-blocking request
changes since v1: * Minor updates after proofreading comments from Chris Per Forlin (1): mmc: documentation of mmc non-blocking request usage and design. Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 86 +++ 2 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] mmc: documentation of mmc non-blocking request usage and design.
Documentation about the background and the design of mmc non-blocking. Host driver guidelines to minimize request preparation overhead. Signed-off-by: Per Forlin per.for...@linaro.org --- Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 86 +++ 2 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX index 93dd7a7..11bc2cf 100644 --- a/Documentation/mmc/00-INDEX +++ b/Documentation/mmc/00-INDEX @@ -4,3 +4,5 @@ mmc-dev-attrs.txt - info on SD and MMC device attributes mmc-dev-parts.txt - info on SD and MMC device partitions +mmc-async-req.txt +- info on mmc asynchronous request diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt new file mode 100644 index 000..ff1e66f --- /dev/null +++ b/Documentation/mmc/mmc-async-req.txt @@ -0,0 +1,86 @@ +Rationale += + +How significant is the cache maintenance overhead? +It depends, fast eMMC and multiple cache levels with speculative cache +pre-fetch makes the cache overhead relatively significant. If the DMA +preparations for the next request are done in parallel to the current +transfer the DMA preparation overhead would not affect the MMC performance. +The intention of non-blocking (asynchronous) mmc requests is to minimize the +time between when an mmc request ends and another mmc request begins. +Using mmc_wait_for_req() the MMC controller is idle while dma_map_sg and +dma_unmap_sg is processing. Using non-blocking mmc requests makes it +possible to prepare the caches for next job in parallel to an active +mmc request. + +MMC block driver + + +The issue_rw_rq() in the mmc block driver is made non-blocking. +The increase in throughput is proportional to the time it takes to +prepare (major part of preparations is dma_map_sg and dma_unmap_sg) +a request and how fast the memory is. The faster the MMC/SD is +the more significant the prepare request time becomes. Roughly the expected +performance gain is 5% for large writes and 10% on large reads on a L2 cache +platform. In power save mode, when clocks run on a lower frequency, the DMA +preparation may cost even more. As long as these slower preparations are run +in parallel to the transfer performance wont be affected. + +Details on measurements from IOZone and mmc_test + + +https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req + +MMC core API extension +== + +There is one new public function mmc_start_req() +It starts a new MMC command request for a host. The function isn't +truly non-blocking. If there is on ongoing async request it waits +for completion of that request and start the new one and return. It +doesn't wait for the new request to complete. If there is no ongoing +request it starts the new request and returns immediately. + +MMC host extensions +=== + +There are two optional hooks pre_req() and post_req() that the host driver +may implement in order to move work to before and after the actual +mmc_request function is called. In the DMA case pre_req() may do +dma_map_sg() and prepare the dma descriptor, and post_req runs +the dma_unmap_sg. + +Optimize for the first request +== + +The first request in a series of requests can't be prepared in parallel to +the previous transfer, since there is no previous request. +The argument is_first_req in pre_req() indicates that there is no previous +request. The host driver may optimize for this scenario to minimize +the performance loss. A way to optimize for this is to split the current +request in two chunks, prepare the first chunk and start the request, +and finally prepare the second chunk and start the transfer. + +Pseudocode to handle is_first_req scenario with minimal prepare overhead: +if (is_first_req req-size threshold) + /* start MMC transfer for the complete transfer size */ + mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE) + + /* +* Begin to prepare DMA while cmd is being processed by MMC. +* The first chunk of the request should take the same time +* to prepare as the MMC process command time. +* If prepare time exceeds MMC cmd time +* the transfer is delayed, guesstimate max 4k as first chunk size. +*/ +prepare_1st_chunk_for_dma(req) +/* flush pending desc to the DMAC (dmaengine.h) */ +dma_issue_pending(req-dma_desc); + +prepare_2nd_chunk_for_dma(req) +/* + * The second issue_pending should be called before MMC runs out + * of the first chunk. If the MMC runs out of the first data chunk + * before this call, the transfer is delayed. + */ +dma_issue_pending(req-dma_desc); -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a
[PATCH v3] documentation of mmc non-blocking request
changes since v2: * Minor updates after more comments from Chris Per Forlin (1): mmc: documentation of mmc non-blocking request usage and design. Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 86 +++ 2 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] mmc: documentation of mmc non-blocking request usage and design.
Documentation about the background and the design of mmc non-blocking. Host driver guidelines to minimize request preparation overhead. Signed-off-by: Per Forlin per.for...@linaro.org --- Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 86 +++ 2 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX index 93dd7a7..11bc2cf 100644 --- a/Documentation/mmc/00-INDEX +++ b/Documentation/mmc/00-INDEX @@ -4,3 +4,5 @@ mmc-dev-attrs.txt - info on SD and MMC device attributes mmc-dev-parts.txt - info on SD and MMC device partitions +mmc-async-req.txt +- info on mmc asynchronous request diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt new file mode 100644 index 000..d7e7698 --- /dev/null +++ b/Documentation/mmc/mmc-async-req.txt @@ -0,0 +1,86 @@ +Rationale += + +How significant is the cache maintenance overhead? +It depends, fast eMMC and multiple cache levels with speculative cache +pre-fetch makes the cache overhead relatively significant. If the DMA +preparations for the next request are done in parallel to the current +transfer the DMA preparation overhead would not affect the MMC performance. +The intention of non-blocking (asynchronous) mmc requests is to minimize the +time between when an mmc request ends and another mmc request begins. +Using mmc_wait_for_req() the MMC controller is idle while dma_map_sg and +dma_unmap_sg is processing. Using non-blocking mmc requests makes it +possible to prepare the caches for next job in parallel to an active +mmc request. + +MMC block driver + + +The issue_rw_rq() in the mmc block driver is made non-blocking. +The increase in throughput is proportional to the time it takes to +prepare (major part of preparations is dma_map_sg and dma_unmap_sg) +a request and how fast the memory is. The faster the MMC/SD is +the more significant the prepare request time becomes. Roughly the expected +performance gain is 5% for large writes and 10% on large reads on a L2 cache +platform. In power save mode, when clocks run on a lower frequency, the DMA +preparation may cost even more. As long as these slower preparations are run +in parallel to the transfer performance wont be affected. + +Details on measurements from IOZone and mmc_test + + +https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req + +MMC core API extension +== + +There is one new public function mmc_start_req() +It starts a new MMC command request for a host. The function isn't +truly non-blocking. If there is on ongoing async request it waits +for completion of that request and starts the new one and returns. It +doesn't wait for the new request to complete. If there is no ongoing +request it starts the new request and returns immediately. + +MMC host extensions +=== + +There are two optional hooks pre_req() and post_req() that the host driver +may implement in order to move work to before and after the actual +mmc_request function is called. In the DMA case pre_req() may do +dma_map_sg() and prepare the dma descriptor, and post_req runs +the dma_unmap_sg. + +Optimize for the first request +== + +The first request in a series of requests can't be prepared in parallel to +the previous transfer, since there is no previous request. +The argument is_first_req in pre_req() indicates that there is no previous +request. The host driver may optimize for this scenario to minimize +the performance loss. A way to optimize for this is to split the current +request in two chunks, prepare the first chunk and start the request, +and finally prepare the second chunk and start the transfer. + +Pseudocode to handle is_first_req scenario with minimal prepare overhead: +if (is_first_req req-size threshold) + /* start MMC transfer for the complete transfer size */ + mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE) + + /* +* Begin to prepare DMA while cmd is being processed by MMC. +* The first chunk of the request should take the same time +* to prepare as the MMC process command time. +* If prepare time exceeds MMC cmd time +* the transfer is delayed, guesstimate max 4k as first chunk size. +*/ +prepare_1st_chunk_for_dma(req) +/* flush pending desc to the DMAC (dmaengine.h) */ +dma_issue_pending(req-dma_desc) + +prepare_2nd_chunk_for_dma(req) +/* + * The second issue_pending should be called before MMC runs out + * of the first chunk. If the MMC runs out of the first data chunk + * before this call, the transfer is delayed. + */ +dma_issue_pending(req-dma_desc) -- 1.7.4.1 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a
[PATCH v3] arm: mach-mmp: brownstone.c support multiple sd slots
Subject: [PATCH V3] arm: mach-mmp: brownstone.c support multiple sd slots V3 == Change since V2 -- delete mmc3 since it was committed to linux next. enable mmc1 used for wifi (8688) and marked PERMANENT. Wifi requires enabling of power on the device by toggling the gpio lines for power and reset. Enable eMMC first to work around problem in booting order due to workqueue bug. Signed-off-by: Philip Rakity prak...@marvell.com --- arch/arm/mach-mmp/brownstone.c | 41 +++- 1 files changed, 40 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index c79162a..940982c 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -19,6 +19,7 @@ #include linux/regulator/max8649.h #include linux/regulator/fixed.h #include linux/mfd/max8925.h +#include linux/delay.h #include asm/mach-types.h #include asm/mach/arch.h @@ -180,6 +181,11 @@ static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc0 = { .clk_delay_cycles = 0x1f, }; +static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc1 = { + .clk_delay_cycles = 0x1f, + .flags = PXA_FLAG_CARD_PERMANENT, +}; + static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc2 = { .clk_delay_cycles = 0x1f, .flags = PXA_FLAG_CARD_PERMANENT @@ -187,6 +193,38 @@ static struct sdhci_pxa_platdata mmp2_sdh_platdata_mmc2 = { }; +static void __init mmc_sdio_wifi(void) +{ + int poweron; + int reset; + + poweron = mfp_to_gpio(GPIO57_GPIO); + reset = mfp_to_gpio(GPIO58_GPIO); + + if (gpio_request(reset, sd8xxx reset)) { + printk(KERN_INFO gpio %d request failed\n, reset); + return; + } + + if (gpio_request(poweron, sd8xxx PDn)) { + gpio_free(reset); + printk(KERN_INFO gpio %d request failed\n, poweron); + return; + } + + gpio_direction_output(poweron, 0); + msleep(1); + gpio_direction_output(poweron, 1); + msleep(1); + gpio_direction_output(reset, 0); + msleep(1); + gpio_direction_output(reset, 1); + gpio_free(reset); + gpio_free(poweron); + + mmp2_add_sdhost(1, mmp2_sdh_platdata_mmc1); /* Wifi */ +} + static void __init brownstone_init(void) { mfp_config(ARRAY_AND_SIZE(brownstone_pin_config)); @@ -195,8 +233,9 @@ static void __init brownstone_init(void) mmp2_add_uart(1); mmp2_add_uart(3); mmp2_add_twsi(1, NULL, ARRAY_AND_SIZE(brownstone_twsi1_info)); - mmp2_add_sdhost(0, mmp2_sdh_platdata_mmc0); /* SD/MMC */ mmp2_add_sdhost(2, mmp2_sdh_platdata_mmc2); /* eMMC */ + mmp2_add_sdhost(0, mmp2_sdh_platdata_mmc0); /* SD/MMC */ + mmc_sdio_wifi(); /* enable 5v regulator */ platform_device_register(brownstone_v_5vp_device); -- 1.7.0.4 On Jul 5, 2011, at 12:20 AM, Eric Miao wrote: On Tue, Jul 5, 2011 at 3:05 PM, zhangfei gao zhangfei@gmail.com wrote: On Tue, Jul 5, 2011 at 2:52 PM, Eric Miao eric.y.m...@gmail.com wrote: On Fri, Apr 29, 2011 at 4:45 AM, Philip Rakity prak...@marvell.com wrote: Support multiple sd/eMMC interfaces. enable mmc1, 2, and 3. mmc2 is used eMMC and slot is marked PERMANENT and 8 bit device. mmc1 is used for Wifi and slot is marked PERMANENT Note: eMMC (mmc2) is set to initialize first to workaround a problem where booting in logical order requires mmc create work queue to be multi-threaded otherwise boot process hangs. BUG report send to linux-mmc and linux-kernel mailing list. Wifi (mmc1) requires we enable power on the device by toggling the gpio lines for power and reset. Signed-off-by: Philip Rakity prak...@marvell.com Applied. Though the email client was fiddling the spaces/CR-LF a bit. --- arch/arm/mach-mmp/brownstone.c | 52 +++- 1 files changed, 51 insertions(+), 1 deletions(-) Hi, Eric arch/arm/mach-mmp/brownstone.c has already been modified from mmc-next, here will have conflict. Sorry for inconvenience. 'K, I'll drop it then. Thanks -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] mmc: documentation of mmc non-blocking request usage and design.
On Tue, 5 Jul 2011 21:43:28 +0200 Per Forlin wrote: Documentation about the background and the design of mmc non-blocking. Host driver guidelines to minimize request preparation overhead. Signed-off-by: Per Forlin per.for...@linaro.org --- It would be better to omit the introductory email and put all of its comments in this one [PATCH] email. Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 86 +++ 2 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX index 93dd7a7..11bc2cf 100644 --- a/Documentation/mmc/00-INDEX +++ b/Documentation/mmc/00-INDEX @@ -4,3 +4,5 @@ mmc-dev-attrs.txt - info on SD and MMC device attributes mmc-dev-parts.txt - info on SD and MMC device partitions +mmc-async-req.txt +- info on mmc asynchronous request requests diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt new file mode 100644 index 000..d7e7698 --- /dev/null +++ b/Documentation/mmc/mmc-async-req.txt @@ -0,0 +1,86 @@ +Rationale += + +How significant is the cache maintenance overhead? +It depends, fast eMMC and multiple cache levels with speculative cache It depends: or It depends. Fast +pre-fetch makes the cache overhead relatively significant. If the DMA +preparations for the next request are done in parallel to the current with the current +transfer the DMA preparation overhead would not affect the MMC performance. transfer, +The intention of non-blocking (asynchronous) mmc requests is to minimize the +time between when an mmc request ends and another mmc request begins. +Using mmc_wait_for_req() the MMC controller is idle while dma_map_sg and mmc_wait_for_req(), +dma_unmap_sg is processing. Using non-blocking mmc requests makes it are processing. +possible to prepare the caches for next job in parallel to an active with an active +mmc request. + +MMC block driver + + +The issue_rw_rq() in the mmc block driver is made non-blocking. preferably: MMC throughout the file (when not a function or data name, etc.) +The increase in throughput is proportional to the time it takes to +prepare (major part of preparations is dma_map_sg and dma_unmap_sg) are +a request and how fast the memory is. The faster the MMC/SD is +the more significant the prepare request time becomes. Roughly the expected +performance gain is 5% for large writes and 10% on large reads on a L2 cache +platform. In power save mode, when clocks run on a lower frequency, the DMA +preparation may cost even more. As long as these slower preparations are run +in parallel to the transfer performance wont be affected. withwon't + +Details on measurements from IOZone and mmc_test + + +https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req + +MMC core API extension +== + +There is one new public function mmc_start_req() mmc_start_req(). +It starts a new MMC command request for a host. The function isn't +truly non-blocking. If there is on ongoing async request it waits +for completion of that request and starts the new one and returns. It +doesn't wait for the new request to complete. If there is no ongoing +request it starts the new request and returns immediately. + +MMC host extensions +=== + +There are two optional hooks pre_req() and post_req() that the host driver hooks -- pre_req() and post_req() -- that +may implement in order to move work to before and after the actual +mmc_request function is called. In the DMA case pre_req() may do +dma_map_sg() and prepare the dma descriptor, and post_req runs DMA +the dma_unmap_sg. + +Optimize for the first request +== + +The first request in a series of requests can't be prepared in parallel to with +the previous transfer, since there is no previous request. +The argument is_first_req in pre_req() indicates that there is no previous +request. The host driver may optimize for this scenario to minimize +the performance loss. A way to optimize for this is to split the current +request in two chunks, prepare the first chunk and start the request, +and finally prepare the second chunk and start the transfer. + +Pseudocode to handle is_first_req scenario
Re: [PATCH v3] mmc: documentation of mmc non-blocking request usage and design.
On 5 July 2011 22:27, Randy Dunlap rdun...@xenotime.net wrote: On Tue, 5 Jul 2011 21:43:28 +0200 Per Forlin wrote: Documentation about the background and the design of mmc non-blocking. Host driver guidelines to minimize request preparation overhead. Signed-off-by: Per Forlin per.for...@linaro.org --- It would be better to omit the introductory email and put all of its comments in this one [PATCH] email. I agree. I'll put the changelog after -- to exclude it from the commit message. All of your comments will be updated in v4. Thanks for your comments, Per -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4] mmc: documentation of mmc non-blocking request usage and design.
Documentation about the background and the design of mmc non-blocking. Host driver guidelines to minimize request preparation overhead. Signed-off-by: Per Forlin per.for...@linaro.org --- ChangeLog: v2: - Minor updates after proofreading comments from Chris v3: - Minor updates after more comments from Chris v4: - Minor updates after comments from Randy Documentation/mmc/00-INDEX |2 + Documentation/mmc/mmc-async-req.txt | 86 +++ 2 files changed, 88 insertions(+), 0 deletions(-) create mode 100644 Documentation/mmc/mmc-async-req.txt diff --git a/Documentation/mmc/00-INDEX b/Documentation/mmc/00-INDEX index 93dd7a7..a9ba672 100644 --- a/Documentation/mmc/00-INDEX +++ b/Documentation/mmc/00-INDEX @@ -4,3 +4,5 @@ mmc-dev-attrs.txt - info on SD and MMC device attributes mmc-dev-parts.txt - info on SD and MMC device partitions +mmc-async-req.txt +- info on mmc asynchronous requests diff --git a/Documentation/mmc/mmc-async-req.txt b/Documentation/mmc/mmc-async-req.txt new file mode 100644 index 000..4877f29 --- /dev/null +++ b/Documentation/mmc/mmc-async-req.txt @@ -0,0 +1,86 @@ +Rationale += + +How significant is the cache maintenance overhead? +It depends. Fast eMMC and multiple cache levels with speculative cache +pre-fetch makes the cache overhead relatively significant. If the DMA +preparations for the next request are done in parallel with the current +transfer, the DMA preparation overhead would not affect the MMC performance. +The intention of non-blocking (asynchronous) MMC requests is to minimize the +time between when an MMC request ends and another MMC request begins. +Using mmc_wait_for_req(), the MMC controller is idle while dma_map_sg and +dma_unmap_sg are processing. Using non-blocking MMC requests makes it +possible to prepare the caches for next job in parallel with an active +MMC request. + +MMC block driver + + +The issue_rw_rq() in the MMC block driver is made non-blocking. +The increase in throughput is proportional to the time it takes to +prepare (major part of preparations are dma_map_sg and dma_unmap_sg) +a request and how fast the memory is. The faster the MMC/SD is +the more significant the prepare request time becomes. Roughly the expected +performance gain is 5% for large writes and 10% on large reads on a L2 cache +platform. In power save mode, when clocks run on a lower frequency, the DMA +preparation may cost even more. As long as these slower preparations are run +in parallel with the transfer performance wont be affected. + +Details on measurements from IOZone and mmc_test + + +https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req + +MMC core API extension +== + +There is one new public function mmc_start_req(). +It starts a new MMC command request for a host. The function isn't +truly non-blocking. If there is on ongoing async request it waits +for completion of that request and starts the new one and returns. It +doesn't wait for the new request to complete. If there is no ongoing +request it starts the new request and returns immediately. + +MMC host extensions +=== + +There are two optional hooks -- pre_req() and post_req() -- that the host +driver may implement in order to move work to before and after the actual +mmc_request function is called. In the DMA case pre_req() may do +dma_map_sg() and prepare the DMA descriptor, and post_req runs +the dma_unmap_sg. + +Optimize for the first request +== + +The first request in a series of requests can't be prepared in parallel with +the previous transfer, since there is no previous request. +The argument is_first_req in pre_req() indicates that there is no previous +request. The host driver may optimize for this scenario to minimize +the performance loss. A way to optimize for this is to split the current +request in two chunks, prepare the first chunk and start the request, +and finally prepare the second chunk and start the transfer. + +Pseudocode to handle is_first_req scenario with minimal prepare overhead: +if (is_first_req req-size threshold) + /* start MMC transfer for the complete transfer size */ + mmc_start_command(MMC_CMD_TRANSFER_FULL_SIZE); + + /* +* Begin to prepare DMA while cmd is being processed by MMC. +* The first chunk of the request should take the same time +* to prepare as the MMC process command time. +* If prepare time exceeds MMC cmd time +* the transfer is delayed, guesstimate max 4k as first chunk size. +*/ +prepare_1st_chunk_for_dma(req); +/* flush pending desc to the DMAC (dmaengine.h) */ +dma_issue_pending(req-dma_desc); + +prepare_2nd_chunk_for_dma(req); +/* + * The second issue_pending should be called before MMC runs out + * of the first chunk. If the MMC runs out of the first data chunk + *
Re: [PATCH v4] mmc: documentation of mmc non-blocking request usage and design.
On Tue, 5 Jul 2011 23:35:32 +0200 Per Forlin wrote: +MMC block driver + + +The issue_rw_rq() in the MMC block driver is made non-blocking. +The increase in throughput is proportional to the time it takes to +prepare (major part of preparations are dma_map_sg and dma_unmap_sg) +a request and how fast the memory is. The faster the MMC/SD is +the more significant the prepare request time becomes. Roughly the expected +performance gain is 5% for large writes and 10% on large reads on a L2 cache +platform. In power save mode, when clocks run on a lower frequency, the DMA +preparation may cost even more. As long as these slower preparations are run +in parallel with the transfer performance wont be affected. won't Acked-by: Randy Dunlap rdun...@xenotime.net thanks. --- ~Randy *** Remember to use Documentation/SubmitChecklist when testing your code *** -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] mmc: sd.c Set Non Default Drive Strength via platform
Non default Drive Strength cannot be set automatically. It is a function of the board design and only if there is a specific platform handler can it to set. The platform handler needs to take into account the board design. Pass to the platform code the necessary information. For example: The card and host controller may indicate they support HIGH and LOW drive strength. There is no way to know what should be chosen without specific board knowledge. There is not mechanism (like ethernet duplex or speed pulses) to determine what should be done. If no platform handler is defined -- use the default value. Signed-off-by: Philip Rakity prak...@marvell.com --- drivers/mmc/core/sd.c | 68 - 1 files changed, 39 insertions(+), 29 deletions(-) diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index ff27741..633975f 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -409,52 +409,62 @@ out: static int sd_select_driver_type(struct mmc_card *card, u8 *status) { - int host_drv_type = 0, card_drv_type = 0; + int host_drv_type = SD_DRIVER_TYPE_B; + int card_drv_type = SD_DRIVER_TYPE_B; + int drive_strength; int err; /* * If the host doesn't support any of the Driver Types A,C or D, -* default Driver Type B is used. +* or there is no board specific handler then default Driver +* Type B is used. */ if (!(card-host-caps (MMC_CAP_DRIVER_TYPE_A | MMC_CAP_DRIVER_TYPE_C | MMC_CAP_DRIVER_TYPE_D))) return 0; - if (card-host-caps MMC_CAP_DRIVER_TYPE_A) { - host_drv_type = MMC_SET_DRIVER_TYPE_A; - if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_A) - card_drv_type = MMC_SET_DRIVER_TYPE_A; - else if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_B) - card_drv_type = MMC_SET_DRIVER_TYPE_B; - else if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_C) - card_drv_type = MMC_SET_DRIVER_TYPE_C; - } else if (card-host-caps MMC_CAP_DRIVER_TYPE_C) { - host_drv_type = MMC_SET_DRIVER_TYPE_C; - if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_C) - card_drv_type = MMC_SET_DRIVER_TYPE_C; - } else if (!(card-host-caps MMC_CAP_DRIVER_TYPE_D)) { - /* -* If we are here, that means only the default driver type -* B is supported by the host. -*/ - host_drv_type = MMC_SET_DRIVER_TYPE_B; - if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_B) - card_drv_type = MMC_SET_DRIVER_TYPE_B; - else if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_C) - card_drv_type = MMC_SET_DRIVER_TYPE_C; - } + if (!card-host-ops-select_drive_strength) + return 0; + + if (card-host-caps MMC_CAP_DRIVER_TYPE_A) + host_drv_type |= SD_DRIVER_TYPE_A; + + if (card-host-caps MMC_CAP_DRIVER_TYPE_C) + host_drv_type |= SD_DRIVER_TYPE_C; + + if (card-host-caps MMC_CAP_DRIVER_TYPE_D) + host_drv_type |= SD_DRIVER_TYPE_D; + + if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_A) + card_drv_type |= SD_DRIVER_TYPE_A; + + if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_C) + card_drv_type |= SD_DRIVER_TYPE_C; + + if (card-sw_caps.sd3_drv_type SD_DRIVER_TYPE_D) + card_drv_type |= SD_DRIVER_TYPE_D; + + /* +* The drive strength that the hardware can support +* depends on the board design. Pass the appropriate +* information and let the hardware specific code +* return what is possible given the options +*/ + drive_strength = card-host-ops-select_drive_strength( + card-sw_caps.uhs_max_dtr, + host_drv_type, card_drv_type); - err = mmc_sd_switch(card, 1, 2, card_drv_type, status); + err = mmc_sd_switch(card, 1, 2, drive_strength, status); if (err) return err; - if ((status[15] 0xF) != card_drv_type) { - printk(KERN_WARNING %s: Problem setting driver strength!\n, + if ((status[15] 0xF) != drive_strength) { + printk(KERN_WARNING %s: Problem setting drive strength!\n, mmc_hostname(card-host)); return 0; } - mmc_set_driver_type(card-host, host_drv_type); + mmc_set_driver_type(card-host, drive_strength); return 0; } -- 1.7.0.4 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] mmc: enable background operations for emmc4.41 with HPI support
Hi Hanumath, First thank you for working this tasks, HPI BKOPS is required for eMMC performance and latency. But before implement these features. we should define what's addressed by these features. HPI is a feature to handle a higher or urgent request then pre-ongoing request and it's only possible when some conditions are met. BKOPS is a feature to give a chance to optimize the internal for next operation. Current implementation is HPI is used for BKOPS but I think HPI is used for Write operation to reduce the latency. There are some reasons. 1. I wonder BKOPS is really required to perform frequently? Yes I know it's helpful to use but no need to call it frequently. 2. Previous time only one request is handled at mmc block. so it can't implement the HPI for user request. but as Per Forlin implement the double buffering concept. it can possible to implement the HPI, interrupt the current write operation and do urgent read request. Related with this, you can find a HPI background and one of possible solutions in the mmc Spec. 3. real use scenario, realtime class read request has too much latency since previous write request, (when merge operation is happened eMMC internally) With these reason, I hope implement the write HPI first and continue to work BKOPS support. Thank you, Kyungmin Park On Tue, Jul 5, 2011 at 9:27 PM, Hanumath Prasad hanumath.pra...@stericsson.com wrote: Background operations is an optional feature defined in eMMC4.41 spec. The need for BKOPS will be checked after servicing each user request in R1 response. If need for BKOPS flag is set, then start BKOPS when request queue is idle. Once bkops is started and meanwhile any user read/write request comes then the bkops will be interrupted by issuing HPI, otherwise bkops keep going until it gets finished. This patch is based on the four patches submitted by Chuanxiao Dong to linux-mmc. Signed-off-by: Hanumath Prasad hanumath.pra...@stericsson.com --- drivers/mmc/card/block.c | 14 +++- drivers/mmc/card/queue.c | 1 + drivers/mmc/core/core.c | 75 drivers/mmc/core/mmc.c | 52 +- drivers/mmc/core/mmc_ops.c | 33 +++ drivers/mmc/core/mmc_ops.h | 1 + include/linux/mmc/card.h | 14 include/linux/mmc/core.h | 3 +- include/linux/mmc/mmc.h | 6 +++ 9 files changed, 195 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 71da564..26a87ca 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -799,6 +799,11 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) mmc_queue_bounce_pre(mq); + if (mmc_card_doing_bkops(card)) { + if (mmc_interrupt_bkops(card)) + goto cmd_err; + } + mmc_wait_for_req(card-host, brq.mrq); mmc_queue_bounce_post(mq); @@ -897,10 +902,17 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req) goto cmd_err; } + spin_lock_irq(md-lock); + /* + * Check BKOPS urgency from each R1 response + */ + if (mmc_card_mmc(card) + (brq.cmd.resp[0] R1_URGENT_BKOPS)) + mmc_card_set_need_bkops(card); + /* * A block was successfully transferred. */ - spin_lock_irq(md-lock); ret = __blk_end_request(req, 0, brq.data.bytes_xfered); spin_unlock_irq(md-lock); } while (ret); diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index c07322c..c491edd 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -64,6 +64,7 @@ static int mmc_queue_thread(void *d) set_current_state(TASK_RUNNING); break; } + mmc_start_bkops(mq-card); up(mq-thread_sem); schedule(); down(mq-thread_sem); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 68091dd..e5e1d7c 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -196,6 +196,48 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) host-ops-request(host, mrq); } +/** + * mmc_start_bkops - start BKOPS for supported cards + * @card: MMC card to start BKOPS + * + * Start background operations whenever requested. + * when the urgent BKOPS bit is set in a R1 command response + * then background operations should be started immediately. + */ +void mmc_start_bkops(struct mmc_card *card) +{ + int err; + unsigned long
Re: [PATCH v2 3/3] mmc: sdhci-esdhc-imx: add device tree probe support
On Tue, Jul 05, 2011 at 11:54:34AM -0600, Grant Likely wrote: On Tue, Jul 5, 2011 at 9:26 AM, Shawn Guo shawn@linaro.org wrote: The patch adds device tree probe support for sdhci-esdhc-imx driver. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org Cc: Grant Likely grant.lik...@secretlab.ca --- .../devicetree/bindings/mmc/fsl-imx-esdhc.txt | 40 drivers/mmc/host/sdhci-esdhc-imx.c | 102 +++- 2 files changed, 137 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt new file mode 100644 index 000..351d239 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -0,0 +1,40 @@ +* Freescale Enhanced Secure Digital Host Controller (eSDHC) for i.MX + +The Enhanced Secure Digital Host Controller on Freescale i.MX family +provides an interface for MMC, SD, and SDIO types of memory cards. + +Required properties: +- compatible : Should be fsl,chip-esdhc +- reg : Should contain eSDHC registers location and length +- interrupts : Should contain eSDHC interrupt +- cd-type : String, card detection (CD) method. Supported values are: + none : No CD + controller : Uses eSDHC controller internal CD signal + gpio : Uses GPIO pin for CD + permanent : No CD because card is permanently wired to host +- wp-type : String, write protection (WP) method. Supported values are: + none : No WP + controller : Uses eSDHC controller internal WP signal + gpio : Uses GPIO pin for WP +- gpios : Should specify GPIOs in this order: CD GPIO, WP GPIO, if + properties cd-type and wp-type are gpio. Again, be explicit in your gpios property names. Create a different property for each gpio: cd-gpios and wp-gpios. Sorry. I fixed the example below. But this one got missed. As for wp-type and cd-type, I think you can drop them. Default to internal controller CD and WP pins. Use gpio if cd-gpios or wp-gpios is present, and define specific properties for the no-wp, no-cd and fixed-card cases. (can you tell that I'm not a fan of the *-type binding for this driver?) :-) Ok, I'm getting to know you. + +Examples: + +esdhc@70004000 { + compatible = fsl,imx51-esdhc; + reg = 0x70004000 0x4000; + interrupts = 1; + fsl,cd-type = controller; + fsl,wp-type = controller; +}; + +esdhc@70008000 { + compatible = fsl,imx51-esdhc; + reg = 0x70008000 0x4000; + interrupts = 2; + fsl,cd-type = gpio; + fsl,wp-type = gpio; + cd-gpios = gpio0 6 0; /* GPIO1_6 */ + wp-gpios = gpio0 5 0; /* GPIO1_5 */ +}; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 1edda29..593d6b9 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -20,6 +20,9 @@ #include linux/mmc/host.h #include linux/mmc/mmc.h #include linux/mmc/sdio.h +#include linux/of.h +#include linux/of_device.h +#include linux/of_gpio.h #include mach/esdhc.h #include sdhci-pltfm.h #include sdhci-esdhc.h @@ -72,6 +75,14 @@ static struct platform_device_id imx_esdhc_devtype[] = { } }; +static const struct of_device_id imx_esdhc_dt_ids[] = { + { .compatible = fsl,imx25-esdhc, .data = imx_esdhc_devtype[IMX25_ESDHC], }, + { .compatible = fsl,imx35-esdhc, .data = imx_esdhc_devtype[IMX35_ESDHC], }, + { .compatible = fsl,imx51-esdhc, .data = imx_esdhc_devtype[IMX51_ESDHC], }, + { .compatible = fsl,imx53-esdhc, .data = imx_esdhc_devtype[IMX53_ESDHC], }, + { /* sentinel */ } +}; + static inline int is_imx25_esdhc(struct pltfm_imx_data *data) { return data-devtype == IMX25_ESDHC; @@ -305,24 +316,96 @@ static irqreturn_t cd_irq(int irq, void *data) return IRQ_HANDLED; }; +#ifdef CONFIG_OF +static const char *cd_types[] = { + [ESDHC_CD_NONE] = none, + [ESDHC_CD_CONTROLLER] = controller, + [ESDHC_CD_GPIO] = gpio, + [ESDHC_CD_PERMANENT] = permanent, +}; + +static const char *wp_types[] = { + [ESDHC_WP_NONE] = none, + [ESDHC_WP_CONTROLLER] = controller, + [ESDHC_WP_GPIO] = gpio, +}; + +static int __devinit sdhci_esdhc_imx_probe_dt(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(imx_esdhc_dt_ids, pdev-dev); + struct device_node *np = pdev-dev.of_node; + struct esdhc_platform_data *boarddata; + int err, i; + const char *cd, *wp; + + if (!np) +