[PATCH v5] 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 Acked-by: Randy Dunlap rdun...@xenotime.net --- ChangeLog: v2: - Minor updates after proofreading comments from Chris v3: - Minor updates after more comments from Chris v4: - Minor updates after comments from Randy v5: - Fixed one more comment and Acked-by 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..b7a52ea --- /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 won't 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
Re: [PATCH v3] arm: mach-mmp: brownstone.c support multiple sd slots
On Wed, Jul 6, 2011 at 4:20 AM, Philip Rakity prak...@marvell.com wrote: 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 */ +} + The method keeps power on wifi chip, without dynamically enable/disable wifi power, which is not final solution. How about pushing later with dynamically control power, which is in debugging here. 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 -- 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: PM: add suspend/resume in atmel-mci
Take care of slots while going to suspend state. Signed-off-by: Nicolas Ferre nicolas.fe...@atmel.com --- V4: make CONFIG_PM logic work even if not selected V3: take care of each slot SUSPENDED state (adding a status bit in the slot flags) V2: move to pm_ops drivers/mmc/host/atmel-mci.c | 63 ++ 1 files changed, 63 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index aa8039f..fa8cae1 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -203,6 +203,7 @@ struct atmel_mci_slot { #define ATMCI_CARD_PRESENT 0 #define ATMCI_CARD_NEED_INIT 1 #define ATMCI_SHUTDOWN 2 +#define ATMCI_SUSPENDED3 int detect_pin; int wp_pin; @@ -1878,10 +1879,72 @@ static int __exit atmci_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int atmci_suspend(struct device *dev) +{ + struct atmel_mci *host = dev_get_drvdata(dev); + int i; + +for (i = 0; i ATMEL_MCI_MAX_NR_SLOTS; i++) { + struct atmel_mci_slot *slot = host-slot[i]; + int ret; + + if (!slot) + continue; + ret = mmc_suspend_host(slot-mmc); + if (ret 0) { + while (--i = 0) { + slot = host-slot[i]; + if (slot +test_bit(ATMCI_SUSPENDED, slot-flags)) { + mmc_resume_host(host-slot[i]-mmc); + clear_bit(ATMCI_SUSPENDED, slot-flags); + } + } + return ret; + } else { + set_bit(ATMCI_SUSPENDED, slot-flags); + } + } + + return 0; +} + +static int atmci_resume(struct device *dev) +{ + struct atmel_mci *host = dev_get_drvdata(dev); + int i; + int ret = 0; + + for (i = 0; i ATMEL_MCI_MAX_NR_SLOTS; i++) { + struct atmel_mci_slot *slot = host-slot[i]; + int err; + + slot = host-slot[i]; + if (!slot) + continue; + if (!test_bit(ATMCI_SUSPENDED, slot-flags)) + continue; + err = mmc_resume_host(slot-mmc); + if (err 0) + ret = err; + else + clear_bit(ATMCI_SUSPENDED, slot-flags); + } + + return ret; +} +static SIMPLE_DEV_PM_OPS(atmci_pm, atmci_suspend, atmci_resume); +#define ATMCI_PM_OPS (atmci_pm) +#else +#define ATMCI_PM_OPS NULL +#endif + static struct platform_driver atmci_driver = { .remove = __exit_p(atmci_remove), .driver = { .name = atmel_mci, + .pm = ATMCI_PM_OPS, }, }; -- 1.7.3 -- 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 V4] MMC: PM: add suspend/resume in atmel-mci
Hi, On Wed, Jul 06, 2011 at 11:31:36AM +0200, Nicolas Ferre wrote: Take care of slots while going to suspend state. Signed-off-by: Nicolas Ferre nicolas.fe...@atmel.com FWIW: Reviewed-by: Felipe Balbi ba...@ti.com @@ -1878,10 +1879,72 @@ static int __exit atmci_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int atmci_suspend(struct device *dev) +{ + struct atmel_mci *host = dev_get_drvdata(dev); + int i; + + for (i = 0; i ATMEL_MCI_MAX_NR_SLOTS; i++) { + struct atmel_mci_slot *slot = host-slot[i]; + int ret; + + if (!slot) + continue; + ret = mmc_suspend_host(slot-mmc); + if (ret 0) { + while (--i = 0) { + slot = host-slot[i]; + if (slot + test_bit(ATMCI_SUSPENDED, slot-flags)) { + mmc_resume_host(host-slot[i]-mmc); + clear_bit(ATMCI_SUSPENDED, slot-flags); + } + } + return ret; + } else { + set_bit(ATMCI_SUSPENDED, slot-flags); + } just one small nitpicking which you can ignore if you like, but you don't really need the else branch here. If you fall into if (ret 0) you will return early anyway, so you can save two lines and an indentation level :-p -- balbi signature.asc Description: Digital signature
[PATCH] ARM i.MX dma: Fix burstsize settings
dmaengine expects the maxburst parameter in words, not bytes. The imxdma driver and its users do this wrong. Fix this. As a side note the imx-pcm-dma-mx2 driver was 'fixed' to work with imx-dma. This broke the driver with imx-sdma support which correctly takes the maxburst parameter in words. This patch puts the sdma based sound back to work. Signed-off-by: Sascha Hauer s.ha...@pengutronix.de --- I made this as a cross subsystem patch to maintain bisectability. I suggest to push it either via my tree or the dmaengine tree. drivers/dma/imx-dma.c |3 ++- drivers/mmc/host/mxcmmc.c |8 sound/soc/imx/imx-pcm-dma-mx2.c |4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index e18eaab..d99f71c 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -135,7 +135,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, if (ret) return ret; - imx_dma_config_burstlen(imxdmac-imxdma_channel, imxdmac-watermark_level); + imx_dma_config_burstlen(imxdmac-imxdma_channel, + imxdmac-watermark_level * imxdmac-word_size); return 0; default: diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index cc20e02..14aa213 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -715,13 +715,13 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) int burstlen, ret; /* -* use burstlen of 64 in 4 bit mode (-- reg value 0) -* use burstlen of 16 in 1 bit mode (-- reg value 16) +* use burstlen of 64 (16 words) in 4 bit mode (-- reg value 0) +* use burstlen of 16 (4 words) in 1 bit mode (-- reg value 16) */ if (ios-bus_width == MMC_BUS_WIDTH_4) - burstlen = 64; - else burstlen = 16; + else + burstlen = 4; if (mxcmci_use_dma(host) burstlen != host-burstlen) { host-burstlen = burstlen; diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c index 4173b3d..43fdc24f 100644 --- a/sound/soc/imx/imx-pcm-dma-mx2.c +++ b/sound/soc/imx/imx-pcm-dma-mx2.c @@ -110,12 +110,12 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream, slave_config.direction = DMA_TO_DEVICE; slave_config.dst_addr = dma_params-dma_addr; slave_config.dst_addr_width = buswidth; - slave_config.dst_maxburst = dma_params-burstsize * buswidth; + slave_config.dst_maxburst = dma_params-burstsize; } else { slave_config.direction = DMA_FROM_DEVICE; slave_config.src_addr = dma_params-dma_addr; slave_config.src_addr_width = buswidth; - slave_config.src_maxburst = dma_params-burstsize * buswidth; + slave_config.src_maxburst = dma_params-burstsize; } ret = dmaengine_slave_config(iprtd-dma_chan, slave_config); -- 1.7.5.3 -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0| Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917- | -- 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] mxs-mmc: fix clock rate setting
About the patch itself: I didn't verify the formulas, but it does solve one special problem here. Thanks a lot! So: Does it solve any other special problem except for the wrong clock rate setting? Nope, but that it does :) -- Pengutronix e.K. | Wolfram Sang| Industrial Linux Solutions | http://www.pengutronix.de/ | signature.asc Description: Digital signature
[PATCH v2 0/4] mmc: dw_mmc: mmc_test related fixes
No changes since v1 except acked-by and tested-by More improvements and fixes for the Synopsys DesignWare MCI driver so that it passes the mmc_test suite: [PATCH 1/4] mmc: dw_mmc: fix stop when fallen back to PIO Fixes a hang after an error/timeout in PIO mode. [PATCH 2/4] mmc: dw_mmc: remove unnecessary error messages Removes some dev_err's since an errno is sufficient. [PATCH 3/4] mmc: dw_mmc: handle no CRC status error Fixes Correct xfer_size at write tests. [PATCH 4/4] mmc: dw_mmc: reset FIFO after an error Fixes modified Correct xfer_size at write tests (3 blocks instead of 2). drivers/mmc/host/dw_mmc.c | 41 +++-- include/linux/mmc/dw_mmc.h |2 ++ 2 files changed, 33 insertions(+), 10 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/4] mmc: dw_mmc: fix stop when fallen back to PIO
There are several situations when dw_mci_submit_data_dma() decides to fall back to PIO mode instead of using DMA, due to a short (to avoid overhead) or complex (e.g. with unaligned buffers) transaction, even though host-use_dma is set. However dw_mci_stop_dma() decides whether to stop DMA or set the EVENT_XFER_COMPLETE event based on host-use_dma. When falling back to PIO mode this results in data timeout errors getting missed and the driver locking up. Therefore add host-using_dma to indicate whether the current transaction is using dma or not, and adjust dw_mci_stop_dma() to use that instead. Signed-off-by: James Hogan james.ho...@imgtec.com Acked-by: Will Newton will.new...@imgtec.com Tested-by: Jaehoon Chung jh80.ch...@samsung.com --- drivers/mmc/host/dw_mmc.c |6 +- include/linux/mmc/dw_mmc.h |2 ++ 2 files changed, 7 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 10b6979..fcff3c0 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -287,7 +287,7 @@ static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data) /* DMA interface functions */ static void dw_mci_stop_dma(struct dw_mci *host) { - if (host-use_dma) { + if (host-using_dma) { host-dma_ops-stop(host); host-dma_ops-cleanup(host); } else { @@ -435,6 +435,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) unsigned int i, direction, sg_len; u32 temp; + host-using_dma = 0; + /* If we don't have a channel, we can't do DMA */ if (!host-use_dma) return -ENODEV; @@ -454,6 +456,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) return -EINVAL; } + host-using_dma = 1; + if (data-flags MMC_DATA_READ) direction = DMA_FROM_DEVICE; else diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index f3f68ee..6b46819 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -48,6 +48,7 @@ struct mmc_data; * @data: The data currently being transferred, or NULL if no data * transfer is in progress. * @use_dma: Whether DMA channel is initialized or not. + * @using_dma: Whether DMA is in use for the current transfer. * @sg_dma: Bus address of DMA buffer. * @sg_cpu: Virtual address of DMA buffer. * @dma_ops: Pointer to platform-specific DMA callbacks. @@ -121,6 +122,7 @@ struct dw_mci { /* DMA interface members*/ int use_dma; + int using_dma; dma_addr_t sg_dma; void*sg_cpu; -- 1.7.2.3 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] mmc: dw_mmc: remove unnecessary error messages
Remove error messages for timeout and CRC failure, since the error code already indicates the problem. Signed-off-by: James Hogan james.ho...@imgtec.com Acked-by: Will Newton will.new...@imgtec.com Tested-by: Jaehoon Chung jh80.ch...@samsung.com --- drivers/mmc/host/dw_mmc.c |4 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index fcff3c0..bf2157a 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -908,12 +908,8 @@ static void dw_mci_tasklet_func(unsigned long priv) if (status DW_MCI_DATA_ERROR_FLAGS) { if (status SDMMC_INT_DTO) { - dev_err(host-pdev-dev, - data timeout error\n); data-error = -ETIMEDOUT; } else if (status SDMMC_INT_DCRC) { - dev_err(host-pdev-dev, - data CRC error\n); data-error = -EILSEQ; } else { dev_err(host-pdev-dev, -- 1.7.2.3 -- 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] mxs-mmc: fix clock rate setting
On Mon, Jul 04, 2011 at 12:59:29PM +0200, Koen Beel wrote: On Mon, Jul 4, 2011 at 12:34 PM, Wolfram Sang w.s...@pengutronix.de wrote: Well, maybe not. My colleague complained and I think he is right that we are mapping div2 from the range 0 to 256 (inclusive!) to an 8-bit range. This must be wrong for one value per se. If you look at the context of the patch, you will find it's 'div2 - 1' than 'div2' gets written into register. Exactly. The '- 1' is why Koen changed the upper limit from 256 to = 256. The lower limit fix is currently 'if (div2 == 0) div2 == 1', which is a 2:1 mapping. Not good, or? So you are saying the patch is a right fix but not the most optimal one? In that case, it does not concern me. I acked it as an valid fix. The patches fixes a few things, but for div2, it is curing the symptoms, not the cause, I think. If you look at the formula in the datasheet: rate = ssp / (clock_divide * (1 + clock_rate)); In the code, the calculation of div2 is equal to '1 + clock_rate' (the 1 gets subtracted when the value is written to the register which is a bit unfortunate; doing it earlier would reduce confusion IMO). So that can never be 0, it is a divisor. We should really use DIV_ROUND_UP here. Even when not dealing with 0, this seems needed. Assume: ssp = 5760, wanted_rate = 2500, div1 = 2 will give div2 = int(1.152) = 1 (meaning 0 + 1, because div2 - 1 will be written) The rate will thus be: actual_rate = 5760 / 2 * (0 + 1) = 2880 - too fast! Or did I get something wrong? Regards, Wolfram Well, right now the clock freq. is set to the minimum clock value reaching the requested rate. Sorry, it gets a bit confusing: what do you mean with right now? In current implementation, the rate will be higher in lot's of cases (all cases where the requested clock freq. cannot exactly be made). Yes. But the thing is, the driver now enters dev_err, and returns without changing anything when the clock cannot be made as low as requested. In that case you will almost certainly end up with a clock being even higher then the lowest possible. So that not good I think. I might be better to set the clock as low as possible not matter what you to after that. Yes, might be a bit academic (who would want 4kHz ;)), but still correct. Shawn, do you agree? About the rounding. I don't think rounding is good. I think it would We do rounding already (int conversion). Just in the wrong direction. be better to choose between having at least the requested rate (as it is now; will result is somewhat higher clock then requested in many cases) You want a rate faster than what the card could do? , or having at maximum the requested clock rate. Both have there problems. If I understood you correctly, this is my DIV_ROUND_UP suggestion. Which problems does it have? Regards, Wolfram signature.asc Description: Digital signature
[PATCH v2 3/4] mmc: dw_mmc: handle no CRC status error
When a data write isn't acknowledged by the card (so no CRC status token is detected after the data), the error -EIO is returned instead of the -ETIMEDOUT expected by mmc_test 15 - Correct xfer_size at write (start failure) and 17 Correct xfer_size at write (midway failure). In PIO mode the reported number of bytes transferred is also exaggerated since the last block actually failed. Handle the Write no CRC error specially, setting the error to -ETIMEDOUT and setting the bytes_xferred to 0. Signed-off-by: James Hogan james.ho...@imgtec.com Acked-by: Will Newton will.new...@imgtec.com Tested-by: Jaehoon Chung jh80.ch...@samsung.com --- drivers/mmc/host/dw_mmc.c | 19 +++ 1 files changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index bf2157a..0dac397 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -496,15 +496,16 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) host-sg = NULL; host-data = data; + if (data-flags MMC_DATA_READ) + host-dir_status = DW_MCI_RECV_STATUS; + else + host-dir_status = DW_MCI_SEND_STATUS; + if (dw_mci_submit_data_dma(host, data)) { host-sg = data-sg; host-pio_offset = 0; host-part_buf_start = 0; host-part_buf_count = 0; - if (data-flags MMC_DATA_READ) - host-dir_status = DW_MCI_RECV_STATUS; - else - host-dir_status = DW_MCI_SEND_STATUS; mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR); temp = mci_readl(host, INTMASK); @@ -911,6 +912,16 @@ static void dw_mci_tasklet_func(unsigned long priv) data-error = -ETIMEDOUT; } else if (status SDMMC_INT_DCRC) { data-error = -EILSEQ; + } else if (status SDMMC_INT_EBE + host-dir_status == + DW_MCI_SEND_STATUS) { + /* +* No data CRC status was returned. +* The number of bytes transferred will +* be exaggerated in PIO mode. +*/ + data-bytes_xfered = 0; + data-error = -ETIMEDOUT; } else { dev_err(host-pdev-dev, data FIFO error -- 1.7.2.3 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/4] mmc: dw_mmc: reset FIFO after an error
If an error occurs mid way through a transaction (such as a missing CRC status response after the 2nd block written out of 3), then the FIFO may still contain data which will interfere with the next transaction. Therefore after an error has been detected, reset the fifo using the CTRL register. Signed-off-by: James Hogan james.ho...@imgtec.com Acked-by: Will Newton will.new...@imgtec.com Tested-by: Jaehoon Chung jh80.ch...@samsung.com --- drivers/mmc/host/dw_mmc.c | 12 +++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0dac397..0c839d3 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -849,7 +849,7 @@ static void dw_mci_tasklet_func(unsigned long priv) struct mmc_command *cmd; enum dw_mci_state state; enum dw_mci_state prev_state; - u32 status; + u32 status, ctrl; spin_lock(host-lock); @@ -929,6 +929,16 @@ static void dw_mci_tasklet_func(unsigned long priv) status); data-error = -EIO; } + /* +* After an error, there may be data lingering +* in the FIFO, so reset it - doing so +* generates a block interrupt, hence setting +* the scatter-gather pointer to NULL. +*/ + host-sg = NULL; + ctrl = mci_readl(host, CTRL); + ctrl |= SDMMC_CTRL_FIFO_RESET; + mci_writel(host, CTRL, ctrl); } else { data-bytes_xfered = data-blocks * data-blksz; data-error = 0; -- 1.7.2.3 -- 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] mxs-mmc: fix clock rate setting
On Wed, Jul 6, 2011 at 11:38 AM, Wolfram Sang w.s...@pengutronix.de wrote: On Mon, Jul 04, 2011 at 12:59:29PM +0200, Koen Beel wrote: On Mon, Jul 4, 2011 at 12:34 PM, Wolfram Sang w.s...@pengutronix.de wrote: Well, maybe not. My colleague complained and I think he is right that we are mapping div2 from the range 0 to 256 (inclusive!) to an 8-bit range. This must be wrong for one value per se. If you look at the context of the patch, you will find it's 'div2 - 1' than 'div2' gets written into register. Exactly. The '- 1' is why Koen changed the upper limit from 256 to = 256. The lower limit fix is currently 'if (div2 == 0) div2 == 1', which is a 2:1 mapping. Not good, or? So you are saying the patch is a right fix but not the most optimal one? In that case, it does not concern me. I acked it as an valid fix. The patches fixes a few things, but for div2, it is curing the symptoms, not the cause, I think. If you look at the formula in the datasheet: rate = ssp / (clock_divide * (1 + clock_rate)); In the code, the calculation of div2 is equal to '1 + clock_rate' (the 1 gets subtracted when the value is written to the register which is a bit unfortunate; doing it earlier would reduce confusion IMO). So that can never be 0, it is a divisor. We should really use DIV_ROUND_UP here. Even when not dealing with 0, this seems needed. Assume: ssp = 5760, wanted_rate = 2500, div1 = 2 will give div2 = int(1.152) = 1 (meaning 0 + 1, because div2 - 1 will be written) The rate will thus be: actual_rate = 5760 / 2 * (0 + 1) = 2880 - too fast! Or did I get something wrong? Regards, Wolfram Well, right now the clock freq. is set to the minimum clock value reaching the requested rate. Sorry, it gets a bit confusing: what do you mean with right now? I mean: in current mainline the actual clock is set to be at least the requested clock rate. In current implementation, the rate will be higher in lot's of cases (all cases where the requested clock freq. cannot exactly be made). Yes. This is just the consequence of the fact that the actual clock is set to be at least the requested clock rate. But the thing is, the driver now enters dev_err, and returns without changing anything when the clock cannot be made as low as requested. In that case you will almost certainly end up with a clock being even higher then the lowest possible. So that not good I think. I might be better to set the clock as low as possible not matter what you to after that. Yes, might be a bit academic (who would want 4kHz ;)), but still correct. Shawn, do you agree? About the rounding. I don't think rounding is good. I think it would We do rounding already (int conversion). Just in the wrong direction. be better to choose between having at least the requested rate (as it is now; will result is somewhat higher clock then requested in many cases) You want a rate faster than what the card could do? Correct, you don't want the clock to be faster then the requested clock. So the rounding is indeed in the wrong direction now. , or having at maximum the requested clock rate. Both have there problems. If I understood you correctly, this is my DIV_ROUND_UP suggestion. Which problems does it have? I think I misunderstood this suggestion previously. Using DIV_ROUND_UP would do the rounding in the correct direction. This should result in: the actual clock is as high as possible without being higher then the requested clock. Regards, Wolfram -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.10 (GNU/Linux) iEYEARECAAYFAk4ULSgACgkQD27XaX1/VRsorQCfVRVm9Vpv4YSsfiMqIFctTKG9 7qkAnicSrjSzwObzBjyISDnXz6+Sze2s =5LIq -END PGP SIGNATURE- -- 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] mxs-mmc: fix clock rate setting
I think I misunderstood this suggestion previously. Using DIV_ROUND_UP would do the rounding in the correct direction. This should result in: the actual clock is as high as possible without being higher then the requested clock. Yes, that should be done in V2. And if you could also put the '- 1' to the line calculating div2, that would be an extra plus. I think it is a lot more readable to have the whole formula in one place, and not split up. Regards, Wolfram -- Pengutronix e.K. | Wolfram Sang| Industrial Linux Solutions | http://www.pengutronix.de/ | signature.asc Description: Digital signature
Lavagna luminosa a LED con telecomando e lampada per ombrelloni
Led Technology srl vi presenta questo fantastico prodotto per presentare il vostro Menù in un modo più tecnologico, oppure la lampada a led per illuminare i vostri tavoli sotto gli ombrelloni. Vedi la brochure della lavagna cliccando su questo link: http://www.led-technology.it/files/lavagna_luminosa.jpg Vedi la brochure della lampada per ombrelloni clickando su questo link: http://www.led-shop.it/luci_per_ombrelloni.jpg oppure visitate il nostro negozio online per visionare tutti i nostri prodotti a LED per illuminazione stradale, illuminazione architetturale, illuminazione per campi sportivi, illuminazione industriale etc. www.led-shop.it Per acquistare la lavagna luminosa online clicca su questo link: http://www.led-shop.it/negozio/cat066.php?n=1#1 Per acquistare la lampada per ombrelloni clicca su questo link: http://www.led-shop.it/negozio/cat061.php?n=1#1 Contatto commerciale diretto: PIAZZALUNGA ROBERTO CELL. 345 2412480 Se non vi è gradita questa mail scrivete a unsubscr...@led-shop.it , non sarete più disturbati. Grazie. -- 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! 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. Agreed, as I read the spec this would writes, erases and BKOPS (eMMC spec 4.41 7.6.20 (table 20) and the 3rd paragraph in 7.6.19). BKOPS is a feature to give a chance to optimize the internal for next operation. Yes, I believe the main reasons would be when blocks are either replaced or a ERASE or TRIM operation has been issued. The BKOPS feature would allow the eMMC device to clean up its internal state and pre-erase any internal flash devices so that the next write operation would have better performance. I believe this to be the intent at least. Current implementation is HPI is used for BKOPS but I think HPI is used for Write operation to reduce the latency. True, the focus of HPI is for Write operations, however in eMMC spec 4.41 chapter 7.6.19 on background operations it does state that a host may interrupt any ongoing background operations by using HPI. So to me it seems as if the intent from Jedec has been that it may be used in case of BKOPS taking too long and so may be blocking pending requests..? 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. According to the spec it is advised to start bkops whenever the eMMC device itself indicates an urgent need for it. In what way do you think the proposed patch issues bkops too often? I believe that the patch properly checks for R1_URGENT_BKOPS, which seems correct..? 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. Yes, absolutely. Interrupting ongoing write or erase/trim operations would be the other use for BKOPS. How do you feel that the addition of BKOPS (and thus HPI) interferes with this? Is it just a matter of in what order these two features are integrated into the kernel? Related with this, you can find a HPI background and one of possible solutions in the mmc Spec. What part of the spec are you referring to? 3. real use scenario, realtime class read request has too much latency since previous write request, (when merge operation is happened eMMC internally) I'm not sure what you are explaining here. Would you care to describe it further/differently? / Sebastian PS. Sorry for possibly breaking the mail-thread but I was not subscribed when the original reply was posted. N�r��yb�X��ǧv�^�){.n�+{��g��^n�r���z���h����G���h�(�階�ݢj���m��z�ޖ���f���h���~�m�
Re: [PATCH] ARM i.MX dma: Fix burstsize settings
On Wed, Jul 06, 2011 at 11:18:33AM +0200, Sascha Hauer wrote: dmaengine expects the maxburst parameter in words, not bytes. The imxdma driver and its users do this wrong. Fix this. As a side note the imx-pcm-dma-mx2 driver was 'fixed' to work with imx-dma. This broke the driver with imx-sdma support which correctly takes the maxburst parameter in words. This patch puts the sdma based sound back to work. Acked-by: Mark Brown broo...@opensource.wolfsonmicro.com Probably makes sense to send via the ARM tree unless there's merge issues? -- 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
On Wed, Jul 6, 2011 at 11:40 PM, Sebastian RASMUSSEN sebastian.rasmus...@stericsson.com wrote: Hi! 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. Agreed, as I read the spec this would writes, erases and BKOPS (eMMC spec 4.41 7.6.20 (table 20) and the 3rd paragraph in 7.6.19). BKOPS is a feature to give a chance to optimize the internal for next operation. Yes, I believe the main reasons would be when blocks are either replaced or a ERASE or TRIM operation has been issued. The BKOPS feature would allow the eMMC device to clean up its internal state and pre-erase any internal flash devices so that the next write operation would have better performance. I believe this to be the intent at least. Current implementation is HPI is used for BKOPS but I think HPI is used for Write operation to reduce the latency. True, the focus of HPI is for Write operations, however in eMMC spec 4.41 chapter 7.6.19 on background operations it does state that a host may interrupt any ongoing background operations by using HPI. So to me it seems as if the intent from Jedec has been that it may be used in case of BKOPS taking too long and so may be blocking pending requests..? Yes right, there are some operations which doesn't have timeout. BKOPS is one of them. it have to be interrupted when user request. in that case it should use the HPI. 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. According to the spec it is advised to start bkops whenever the eMMC device itself indicates an urgent need for it. In what way do you think the proposed patch issues bkops too often? I believe that the patch properly checks for R1_URGENT_BKOPS, which seems correct..? Right, it checks the R1_URGENT_BKOPS, I mean it called every user request is finished. 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. Yes, absolutely. Interrupting ongoing write or erase/trim operations would be the other use for BKOPS. How do you feel that the addition of BKOPS (and thus HPI) interferes with this? Is it just a matter of in what order these two features are integrated into the kernel? Related with this, you can find a HPI background and one of possible solutions in the mmc Spec. What part of the spec are you referring to? I refers the JDEDC v4.41 and v4.5 draft version. 3. real use scenario, realtime class read request has too much latency since previous write request, (when merge operation is happened eMMC internally) I'm not sure what you are explaining here. Would you care to describe it further/differently? Actually there's no big issue without HPI. but some case (as above) has read latency problem esp. when play movie at foreground, but some background heavy write case. Thank you, Kyungmin Park -- 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] arm: mach-mmp: brownstone.c support multiple sd slots
On Jul 6, 2011, at 12:19 AM, zhangfei gao wrote: On Wed, Jul 6, 2011 at 4:20 AM, Philip Rakity prak...@marvell.com wrote: 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 */ +} + The method keeps power on wifi chip, without dynamically enable/disable wifi power, which is not final solution. How about pushing later with dynamically control power, which is in debugging here. Good Point -- Will do. What is the correct method to handle this ? 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 -- 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 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. 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?) :-) I would let default be no CD/WP, and define properties for controller internal CD/WP and wired case, if you do not see a problem with it. -- 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 v2 3/3] mmc: sdhci-esdhc-imx: add device tree probe support
On Wed, Jul 06, 2011 at 11:43:15PM +0800, Shawn Guo wrote: 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. 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?) :-) I would let default be no CD/WP, and define properties for controller internal CD/WP and wired case, if you do not see a problem with it. Okay. 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
[PATCH V2] mmc: sd.c Set Non Default Drive Strength via platform
V2 -- Include host.h change for callback to select_drive_strength V1 -- 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 be 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. Setting HIGH may lead to reflections and setting LOW may not be sufficient. There is no mechanism (like ethernet duplex or speed pulses) to determine what should be done automatically. If no platform handler is defined -- use the default value. Signed-off-by: Philip Rakity prak...@marvell.com --- drivers/mmc/core/sd.c| 68 ++--- include/linux/mmc/host.h |1 + 2 files changed, 40 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; } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index ac3fbac..4913f6c 100644 ---
Re: -ENOSYS suspend-powerdown regression
On 28 June 2011 23:04, Ohad Ben-Cohen o...@wizery.com wrote: On Wed, Jun 29, 2011 at 12:54 AM, Daniel Drake d...@laptop.org wrote: Too many patches floating around, just trying to be sure of what I'm doing! Ok, let's start from fresh :) Let's take 3.0-rc5, it already includes our work: 297c7f2 mmc: sdio: fix runtime PM path during driver removal c6e633a mmc: sdio: reset card during power_restore Then apply these hunks: Thanks, done. Sorry for the delay in getting to this. Unfortunately something is still weird, this is possibly a case that we missed before. Even if I just do the simplistic test of booting, and then suspending (without loading the libertas driver), things go wrong: http://dev.laptop.org/~dsd/20110706/dmesg.txt I added printk's in mmc_power_save_host and mmc_power_restore_host. The strange thing is that it tries to resume mmc1 even though it is powered down and there is no available driver, and also that it then tries to power it down again (but it is already off). Daniel -- 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] arm: mach-mmp: brownstone.c support multiple sd slots
Eric, Not sure what to suggest. If it makes more sense to take V3 which powers on the wifi card but does not do power handling per new spec take that. At least wifi card works and then wait for power code. New code could delete power code as part of the mod. If it makes more sense to wait for power code -- take V4. Philip V4 == remove code to enable power for wifi. Coming in separate patch (by others) that conforms to new power architecture. 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. Signed-off-by: Philip Rakity prak...@marvell.com --- arch/arm/mach-mmp/brownstone.c |8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index c79162a..7634b2f 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -180,6 +180,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 @@ -195,8 +200,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 */ + mmp2_add_sdhost(1, mmp2_sdh_platdata_mmc1); /* 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 v4] arm: mach-mmp: brownstone.c support multiple sd slots
On Thu, Jul 7, 2011 at 12:08 AM, Philip Rakity prak...@marvell.com wrote: Eric, Not sure what to suggest. If it makes more sense to take V3 which powers on the wifi card but does not do power handling per new spec take that. At least wifi card works and then wait for power code. New code could delete power code as part of the mod. If it makes more sense to wait for power code -- take V4. No worries. I'll wait for v4. Philip V4 == remove code to enable power for wifi. Coming in separate patch (by others) that conforms to new power architecture. 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. Signed-off-by: Philip Rakity prak...@marvell.com --- arch/arm/mach-mmp/brownstone.c | 8 +++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c index c79162a..7634b2f 100644 --- a/arch/arm/mach-mmp/brownstone.c +++ b/arch/arm/mach-mmp/brownstone.c @@ -180,6 +180,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 @@ -195,8 +200,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 */ + mmp2_add_sdhost(1, mmp2_sdh_platdata_mmc1); /* 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] mmc: enable background operations for emmc4.41 with HPI support
Hi! 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. I believe that the patch properly checks for R1_URGENT_BKOPS, which seems correct..? Right, it checks the R1_URGENT_BKOPS, I mean it called every user request is finished. Aha, are you referring to the mmc_start_bkops() called from mmc_queue_thread()? If so, I should point to the check for whether BKOPS are _really_ needed, mmc_card_need_bkops(), at the beginning of mmc_start_bkops(). That flag is only set if R1_URGET_BKOPS is asserted by the eMMC device. So even if mmc_start_bkops() is called after every user request that function would just do an early return. One could argue that the call to mmc_card_need_bkops() should be in queue.c, before the call to mmc_start_bkops(). Maybe that is preferable and would have improved readability..? Related with this, you can find a HPI background and one of possible solutions in the mmc Spec. What part of the spec are you referring to? I refers the JDEDC v4.41 and v4.5 draft version. Ok, then I'm not sure I understand what you are getting at. I tried to look through the chapters for BKOPS but I'm not seeing any descriptive list of solutions concerning HPI BKOPS? (BTW, it seems as if 4.5 draft is now final -- http://www.jedec.org/sites/default/files/docs/jesd84-B45.pdf) Actually there's no big issue without HPI. but some case (as above) has read latency problem esp. when play movie at foreground, but some background heavy write case. Ok, so what you are looking for is to have BKOPS and HPI in separate patches along with measurements to backup that the HPI really _does_ improve request latency when HPI is used? / Sebastian
[PATCH v3 1/4] mmc: sdhci-esdhc-imx: do not reference platform data after probe
The patch copies platform data into pltfm_imx_data and reference the data there than platform data after probe. This work is inspired by Grant Likely and Troy Kisky. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Troy Kisky troy.ki...@boundarydevices.com Cc: Grant Likely grant.lik...@secretlab.ca Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org --- drivers/mmc/host/sdhci-esdhc-imx.c | 22 +- 1 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 3cc6f61..0b0e62e 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -45,6 +45,7 @@ struct pltfm_imx_data { int flags; u32 scratchpad; + struct esdhc_platform_data boarddata; }; static unsigned int esdhc_pltfm_get_max_blk_size(struct sdhci_host *host) @@ -69,8 +70,9 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i static u32 esdhc_readl_le(struct sdhci_host *host, int reg) { - struct esdhc_platform_data *boarddata = - host-mmc-parent-platform_data; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host-priv; + struct esdhc_platform_data *boarddata = imx_data-boarddata; /* fake CARD_PRESENT flag */ u32 val = readl(host-ioaddr + reg); @@ -92,8 +94,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = pltfm_host-priv; - struct esdhc_platform_data *boarddata = - host-mmc-parent-platform_data; + struct esdhc_platform_data *boarddata = imx_data-boarddata; if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE) (boarddata-cd_type == ESDHC_CD_GPIO))) @@ -210,8 +211,9 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) { - struct esdhc_platform_data *boarddata = - host-mmc-parent-platform_data; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host-priv; + struct esdhc_platform_data *boarddata = imx_data-boarddata; switch (boarddata-wp_type) { case ESDHC_WP_GPIO: @@ -291,12 +293,14 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51())) imx_data-flags |= ESDHC_FLAG_MULTIBLK_NO_INT; - boarddata = host-mmc-parent-platform_data; - if (!boarddata) { + if (!host-mmc-parent-platform_data) { dev_err(mmc_dev(host-mmc), no board data!\n); err = -EINVAL; goto no_board_data; } + imx_data-boarddata = *((struct esdhc_platform_data *) + host-mmc-parent-platform_data); + boarddata = imx_data-boarddata; /* write_protect */ if (boarddata-wp_type == ESDHC_WP_GPIO) { @@ -373,8 +377,8 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct esdhc_platform_data *boarddata = host-mmc-parent-platform_data; struct pltfm_imx_data *imx_data = pltfm_host-priv; + struct esdhc_platform_data *boarddata = imx_data-boarddata; int dead = (readl(host-ioaddr + SDHCI_INT_STATUS) == 0x); sdhci_remove_host(host, dead); -- 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 2/4] 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 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 42ef76a..9bb9062 100644 --- a/arch/arm/mach-imx/clock-imx25.c +++ b/arch/arm/mach-imx/clock-imx25.c @@ -301,8 +301,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 b44cb06..2d0b4c8 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 6634f6c..0e1aa03 100644 --- a/arch/arm/mach-mx5/clock-mx51-mx53.c +++ b/arch/arm/mach-mx5/clock-mx51-mx53.c @@ -1454,10 +1454,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) @@ -1482,10 +1482,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,
[PATCH v3 3/4] 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 v3 0/4] Add device tree probe for sdhci-esdhc-imx
The first patch copies platform data into driver private data, and do not reference platform data after probe. The second one removes the uses of cpu_is_mx(). The third one makes a dt related fix on sdhci-pltfm.c, and the last one adds actual device tree probe for sdhci-esdhc-imx driver. Changes since v2: * Add patch #1 * Do not use Linux details of cd-type and wp-type for binding Changes since v1: * Address review comments given by Grant Shawn Guo (4): mmc: sdhci-esdhc-imx: do not reference platform data after probe 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 | 34 + 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 | 151 +--- drivers/mmc/host/sdhci-pltfm.c |3 +- 9 files changed, 194 insertions(+), 42 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 v3 4/4] 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 | 34 + drivers/mmc/host/sdhci-esdhc-imx.c | 77 +--- 2 files changed, 102 insertions(+), 9 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..ab22fe6 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -0,0 +1,34 @@ +* 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 + +Optional properties: +- fsl,card-wired : Indicate the card is wired to host permanently +- fsl,cd-internal : Indicate to use controller internal card detection +- fsl,wp-internal : Indicate to use controller internal write protection +- cd-gpios : Specify GPIOs for card detection +- wp-gpios : Specify GPIOs for write protection + +Examples: + +esdhc@70004000 { + compatible = fsl,imx51-esdhc; + reg = 0x70004000 0x4000; + interrupts = 1; + fsl,cd-internal; + fsl,wp-internal; +}; + +esdhc@70008000 { + compatible = fsl,imx51-esdhc; + reg = 0x70008000 0x4000; + interrupts = 2; + 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 f3efb3b..cbdd91f 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 @@ -73,6 +76,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; @@ -307,8 +318,48 @@ static irqreturn_t cd_irq(int irq, void *data) return IRQ_HANDLED; }; +#ifdef CONFIG_OF +static int __devinit +sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, +struct esdhc_platform_data *boarddata) +{ + struct device_node *np = pdev-dev.of_node; + + if (!np) + return -ENODEV; + + if (of_get_property(np, fsl,card-wired, NULL)) + boarddata-cd_type = ESDHC_CD_PERMANENT; + + if (of_get_property(np, fsl,cd-controller, NULL)) + boarddata-cd_type = ESDHC_CD_CONTROLLER; + + if (of_get_property(np, fsl,wp-controller, NULL)) + boarddata-wp_type = ESDHC_WP_CONTROLLER; + + boarddata-cd_gpio = of_get_named_gpio(np, cd-gpios, 0); + if (gpio_is_valid(boarddata-cd_gpio)) + boarddata-cd_type = ESDHC_CD_GPIO; + + boarddata-wp_gpio = of_get_named_gpio(np, wp-gpios, 0); + if (gpio_is_valid(boarddata-wp_gpio)) + boarddata-wp_type = ESDHC_WP_GPIO; + + return 0; +} +#else +static inline int +sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, +struct esdhc_platform_data *boarddata) +{ + return -ENODEV; +} +#endif + static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = + of_match_device(imx_esdhc_dt_ids, pdev-dev); struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; struct esdhc_platform_data *boarddata; @@ -323,9 +374,13 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) pltfm_host = sdhci_priv(host); imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL); - if (!imx_data) - return -ENOMEM; + if (!imx_data) { + err = -ENOMEM; + goto err_imx_data; + } + if (of_id) + pdev-id_entry = of_id-data; imx_data-devtype = pdev-id_entry-driver_data;
RE: [PATCH V2] mmc: sd.c Set Non Default Drive Strength via platform
Hi Philip, -Original Message- From: Philip Rakity [mailto:prak...@marvell.com] Sent: Wednesday, July 06, 2011 9:22 PM To: linux-mmc@vger.kernel.org Cc: Nath, Arindam Subject: [PATCH V2] mmc: sd.c Set Non Default Drive Strength via platform V2 -- Include host.h change for callback to select_drive_strength V1 -- 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 be 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. Setting HIGH may lead to reflections and setting LOW may not be sufficient. There is no mechanism (like ethernet duplex or speed pulses) to determine what should be done automatically. If no platform handler is defined -- use the default value. Signed-off-by: Philip Rakity prak...@marvell.com --- drivers/mmc/core/sd.c| 68 ++ --- include/linux/mmc/host.h |1 + 2 files changed, 40 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; } -
Re: [PATCH] mmc: enable background operations for emmc4.41 with HPI support
On Tue, Jul 5, 2011 at 5:57 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 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 + *
Re: [PATCH 1/4] mmci: use StartBitErr to detect bad connections
On Tue, Jul 05, 2011 at 12:16:11PM +0100, Russell King - ARM Linux wrote: 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 Ok, I've taken this into my fixes branch. -- 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 1/4] mmc: sdhci-esdhc-imx: do not reference platform data after probe
On Thu, Jul 07, 2011 at 12:47:47AM +0800, Shawn Guo wrote: The patch copies platform data into pltfm_imx_data and reference the data there than platform data after probe. This work is inspired by Grant Likely and Troy Kisky. Signed-off-by: Shawn Guo shawn@linaro.org Cc: Troy Kisky troy.ki...@boundarydevices.com Cc: Grant Likely grant.lik...@secretlab.ca Cc: Wolfram Sang w.s...@pengutronix.de Cc: Chris Ball c...@laptop.org Acked-by: Grant Likely grant.lik...@secretlab.ca --- drivers/mmc/host/sdhci-esdhc-imx.c | 22 +- 1 files changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 3cc6f61..0b0e62e 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -45,6 +45,7 @@ struct pltfm_imx_data { int flags; u32 scratchpad; + struct esdhc_platform_data boarddata; }; static unsigned int esdhc_pltfm_get_max_blk_size(struct sdhci_host *host) @@ -69,8 +70,9 @@ static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, i static u32 esdhc_readl_le(struct sdhci_host *host, int reg) { - struct esdhc_platform_data *boarddata = - host-mmc-parent-platform_data; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host-priv; + struct esdhc_platform_data *boarddata = imx_data-boarddata; /* fake CARD_PRESENT flag */ u32 val = readl(host-ioaddr + reg); @@ -92,8 +94,7 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) { struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct pltfm_imx_data *imx_data = pltfm_host-priv; - struct esdhc_platform_data *boarddata = - host-mmc-parent-platform_data; + struct esdhc_platform_data *boarddata = imx_data-boarddata; if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE) (boarddata-cd_type == ESDHC_CD_GPIO))) @@ -210,8 +211,9 @@ static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host) static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host) { - struct esdhc_platform_data *boarddata = - host-mmc-parent-platform_data; + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host-priv; + struct esdhc_platform_data *boarddata = imx_data-boarddata; switch (boarddata-wp_type) { case ESDHC_WP_GPIO: @@ -291,12 +293,14 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51())) imx_data-flags |= ESDHC_FLAG_MULTIBLK_NO_INT; - boarddata = host-mmc-parent-platform_data; - if (!boarddata) { + if (!host-mmc-parent-platform_data) { dev_err(mmc_dev(host-mmc), no board data!\n); err = -EINVAL; goto no_board_data; } + imx_data-boarddata = *((struct esdhc_platform_data *) + host-mmc-parent-platform_data); + boarddata = imx_data-boarddata; /* write_protect */ if (boarddata-wp_type == ESDHC_WP_GPIO) { @@ -373,8 +377,8 @@ static int __devexit sdhci_esdhc_imx_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); - struct esdhc_platform_data *boarddata = host-mmc-parent-platform_data; struct pltfm_imx_data *imx_data = pltfm_host-priv; + struct esdhc_platform_data *boarddata = imx_data-boarddata; int dead = (readl(host-ioaddr + SDHCI_INT_STATUS) == 0x); sdhci_remove_host(host, dead); -- 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
Re: [PATCH v3 4/4] mmc: sdhci-esdhc-imx: add device tree probe support
On Thu, Jul 07, 2011 at 12:47:50AM +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 Acked-by: Grant Likely grant.lik...@secretlab.ca --- .../devicetree/bindings/mmc/fsl-imx-esdhc.txt | 34 + drivers/mmc/host/sdhci-esdhc-imx.c | 77 +--- 2 files changed, 102 insertions(+), 9 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..ab22fe6 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt @@ -0,0 +1,34 @@ +* 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 + +Optional properties: +- fsl,card-wired : Indicate the card is wired to host permanently +- fsl,cd-internal : Indicate to use controller internal card detection +- fsl,wp-internal : Indicate to use controller internal write protection +- cd-gpios : Specify GPIOs for card detection +- wp-gpios : Specify GPIOs for write protection + +Examples: + +esdhc@70004000 { + compatible = fsl,imx51-esdhc; + reg = 0x70004000 0x4000; + interrupts = 1; + fsl,cd-internal; + fsl,wp-internal; +}; + +esdhc@70008000 { + compatible = fsl,imx51-esdhc; + reg = 0x70008000 0x4000; + interrupts = 2; + 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 f3efb3b..cbdd91f 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 @@ -73,6 +76,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; @@ -307,8 +318,48 @@ static irqreturn_t cd_irq(int irq, void *data) return IRQ_HANDLED; }; +#ifdef CONFIG_OF +static int __devinit +sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, + struct esdhc_platform_data *boarddata) +{ + struct device_node *np = pdev-dev.of_node; + + if (!np) + return -ENODEV; + + if (of_get_property(np, fsl,card-wired, NULL)) + boarddata-cd_type = ESDHC_CD_PERMANENT; + + if (of_get_property(np, fsl,cd-controller, NULL)) + boarddata-cd_type = ESDHC_CD_CONTROLLER; + + if (of_get_property(np, fsl,wp-controller, NULL)) + boarddata-wp_type = ESDHC_WP_CONTROLLER; + + boarddata-cd_gpio = of_get_named_gpio(np, cd-gpios, 0); + if (gpio_is_valid(boarddata-cd_gpio)) + boarddata-cd_type = ESDHC_CD_GPIO; + + boarddata-wp_gpio = of_get_named_gpio(np, wp-gpios, 0); + if (gpio_is_valid(boarddata-wp_gpio)) + boarddata-wp_type = ESDHC_WP_GPIO; + + return 0; +} +#else +static inline int +sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, + struct esdhc_platform_data *boarddata) +{ + return -ENODEV; +} +#endif + static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = + of_match_device(imx_esdhc_dt_ids, pdev-dev); struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; struct esdhc_platform_data *boarddata; @@ -323,9 +374,13 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) pltfm_host = sdhci_priv(host); imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL); - if (!imx_data) - return -ENOMEM; + if (!imx_data) { + err = -ENOMEM; +
Re: [PATCH] ARM i.MX dma: Fix burstsize settings
On Wed, 2011-07-06 at 08:03 -0700, Mark Brown wrote: On Wed, Jul 06, 2011 at 11:18:33AM +0200, Sascha Hauer wrote: dmaengine expects the maxburst parameter in words, not bytes. The imxdma driver and its users do this wrong. Fix this. As a side note the imx-pcm-dma-mx2 driver was 'fixed' to work with imx-dma. This broke the driver with imx-sdma support which correctly takes the maxburst parameter in words. This patch puts the sdma based sound back to work. Acked-by: Mark Brown broo...@opensource.wolfsonmicro.com Acked-by: Vinod Koul vinod.k...@intel.com Probably makes sense to send via the ARM tree unless there's merge issues? Sure, I dont have naything on this driver in my next and previous updates for Sascha went thru imx tree, so would make sense for these to go that way as well ~Vinod Koul Intel Corp. -- 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