Re: [PATCH 1/4] mmc: dw_mmc: fix the transmission handling in IDMAC
On Sun, May 20, 2012 at 5:27 AM, Seungwon Jeon tgih@samsung.com wrote: DTO interrupt can be later than transmit interrupt(IDMAC) in case of write. Current handling of IDMAC interrupt sets EVENT_DATA_COMPLETE as well as EVENT_XFER_COMPLETE regardless DTO rising. This makes the current request be finished in tasklet and permits the next request even though current data transfer is still in progress. As a result, sequence is broken and lock-up happens. Setting EVENT_DATA_COMPLETE is not proper after IDMAC interrupt. It should be taken after DTO interrupt is generated. Reported-by: Dmitry Shmidt dimitr...@android.com Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) This looks ok, although I don't have any IDMAC hardware to test with. Acked-by: Will Newton will.new...@imgtec.com -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] mmc: dw_mmc: fix the IDMAC sw reset
On Sun, May 20, 2012 at 5:27 AM, Seungwon Jeon tgih@samsung.com wrote: IDMAC may not be cleaned in driver probe if it has been already used in boot time. So IDMAC needs sw reset newly. And DMA interface reset precedes the internal DMAC reset. Additionally SDMMC_IDMAC_SWRESET is replaced with magic code. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 18 ++ 1 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index b46faf0..44aa292 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -418,6 +418,8 @@ static int dw_mci_idmac_init(struct dw_mci *host) p-des3 = host-sg_dma; p-des0 = IDMAC_DES0_ER; + mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET); + /* Mask out interrupts - get Tx Rx complete only */ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI); @@ -1724,7 +1726,8 @@ static void dw_mci_work_routine_card(struct work_struct *work) #ifdef CONFIG_MMC_DW_IDMAC ctrl = mci_readl(host, BMOD); - ctrl |= 0x01; /* Software reset of DMA */ + /* Software reset of DMA */ + ctrl |= SDMMC_IDMAC_SWRESET; mci_writel(host, BMOD, ctrl); #endif @@ -1949,10 +1952,6 @@ int dw_mci_probe(struct dw_mci *host) spin_lock_init(host-lock); INIT_LIST_HEAD(host-queue); - - host-dma_ops = host-pdata-dma_ops; - dw_mci_init_dma(host); - /* * Get the host data width - this assumes that HCON has been set with * the correct values. @@ -1985,6 +1984,9 @@ int dw_mci_probe(struct dw_mci *host) goto err_dmaunmap; } + host-dma_ops = host-pdata-dma_ops; + dw_mci_init_dma(host); + I think this change may break the error handling. The error label err_dmaunmap jumped to above expects that host-dma_ops is non-NULL. Please check that the error handling is ok. -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] mmc: dw_mmc: fix the wrong sequence
On Sun, May 20, 2012 at 5:27 AM, Seungwon Jeon tgih@samsung.com wrote: Setting host-data to NULL is incorrect sequence in dw_mci_command_complete. This early setting makes the skip of dma_unmap_sg in dw_mci_dma_cleanup. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) Acked-by: Will Newton will.new...@imgtec.com -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] ARM: at91: add atmel-mci support for chips and boards which can use it
On 05/16/2012 05:51 PM, ludovic.desroc...@atmel.com : From: Ludovic Desroches ludovic.desroc...@atmel.com Since atmel-mci driver supports all atmel mci version excepted the rm9200 one, use it instead of at91_mci driver. Signed-off-by: Ludovic Desroches ludovic.desroc...@atmel.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- arch/arm/mach-at91/at91rm9200_devices.c | 99 ++ arch/arm/mach-at91/at91sam9261_devices.c | 67 arch/arm/mach-at91/at91sam9263.c |2 + arch/arm/mach-at91/at91sam9263_devices.c | 164 ++ arch/arm/mach-at91/at91sam9rl_devices.c | 70 + arch/arm/mach-at91/board-foxg20.c| 16 +++- arch/arm/mach-at91/board-rm9200ek.c | 14 +++ arch/arm/mach-at91/board-sam9-l9260.c| 16 +++- arch/arm/mach-at91/board-sam9260ek.c | 16 +++- arch/arm/mach-at91/board-sam9261ek.c | 14 +++ arch/arm/mach-at91/board-sam9263ek.c | 14 +++ arch/arm/mach-at91/board-sam9rlek.c | 14 +++ arch/arm/mach-at91/board-usb-a926x.c |2 +- 13 files changed, 504 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 05774e5..2c13783 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -374,6 +374,105 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} /* + * MMC / SD + * */ + +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) +static u64 mmc_dmamask = DMA_BIT_MASK(32); +static struct mci_platform_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91RM9200_BASE_MCI, + .end= AT91RM9200_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_MCI, + .end= AT91RM9200_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_mmc_device = { + .name = atmel_mci, + .id = -1, + .dev= { + .dma_mask = mmc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) +{ + unsigned int i; + unsigned int slot_count = 0; + + if (!data) + return; + + for (i = 0; i ATMCI_MAX_NR_SLOTS; i++) { + + if (!data-slot[i].bus_width) + continue; + + /* input/irq */ + if (gpio_is_valid(data-slot[i].detect_pin)) { + at91_set_gpio_input(data-slot[i].detect_pin, 1); + at91_set_deglitch(data-slot[i].detect_pin, 1); + } + if (gpio_is_valid(data-slot[i].wp_pin)) + at91_set_gpio_input(data-slot[i].wp_pin, 1); + + switch (i) { + case 0: /* slot A */ + /* CMD */ + at91_set_A_periph(AT91_PIN_PA28, 1); + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA29, 1); + if (data-slot[i].bus_width == 4) { + at91_set_B_periph(AT91_PIN_PB3, 1); + at91_set_B_periph(AT91_PIN_PB4, 1); + at91_set_B_periph(AT91_PIN_PB5, 1); + } + slot_count++; + break; + case 1: /* slot B */ + /* CMD */ + at91_set_B_periph(AT91_PIN_PA8, 1); + /* DAT0, maybe DAT1..DAT3 */ + at91_set_B_periph(AT91_PIN_PA9, 1); + if (data-slot[i].bus_width == 4) { + at91_set_B_periph(AT91_PIN_PA10, 1); + at91_set_B_periph(AT91_PIN_PA11, 1); + at91_set_B_periph(AT91_PIN_PA12, 1); + } + slot_count++; + break; + default: + printk(KERN_ERR +AT91: SD/MMC slot %d not available\n, i); + break; + } + if (slot_count) { + /* CLK */ + at91_set_A_periph(AT91_PIN_PA27, 0); + +
[PATCH v2] ARM: at91: add atmel-mci support for chips and boards which can use it
From: Ludovic Desroches ludovic.desroc...@atmel.com Since atmel-mci driver supports all atmel mci version excepted the rm9200 one, use it instead of at91_mci driver. Signed-off-by: Ludovic Desroches ludovic.desroc...@atmel.com --- V2: add several boards I missed arch/arm/mach-at91/at91rm9200_devices.c | 99 ++ arch/arm/mach-at91/at91sam9261_devices.c | 67 arch/arm/mach-at91/at91sam9263.c |2 + arch/arm/mach-at91/at91sam9263_devices.c | 164 ++ arch/arm/mach-at91/at91sam9rl_devices.c | 70 + arch/arm/mach-at91/board-afeb-9260v1.c | 14 +++ arch/arm/mach-at91/board-carmeva.c | 14 +++ arch/arm/mach-at91/board-cpu9krea.c | 14 +++ arch/arm/mach-at91/board-cpuat91.c | 14 +++ arch/arm/mach-at91/board-csb337.c| 14 +++ arch/arm/mach-at91/board-eb9200.c| 14 +++ arch/arm/mach-at91/board-ecbat91.c | 14 +++ arch/arm/mach-at91/board-eco920.c| 14 +++ arch/arm/mach-at91/board-flexibity.c | 14 +++ arch/arm/mach-at91/board-foxg20.c| 16 +++- arch/arm/mach-at91/board-kb9202.c| 14 +++ arch/arm/mach-at91/board-neocore926.c| 14 +++ arch/arm/mach-at91/board-picotux200.c| 14 +++ arch/arm/mach-at91/board-qil-a9260.c | 14 +++ arch/arm/mach-at91/board-rm9200dk.c | 14 +++ arch/arm/mach-at91/board-rm9200ek.c | 14 +++ arch/arm/mach-at91/board-rsi-ews.c | 14 +++ arch/arm/mach-at91/board-sam9-l9260.c| 16 +++- arch/arm/mach-at91/board-sam9260ek.c | 16 +++- arch/arm/mach-at91/board-sam9261ek.c | 14 +++ arch/arm/mach-at91/board-sam9263ek.c | 14 +++ arch/arm/mach-at91/board-sam9rlek.c | 14 +++ arch/arm/mach-at91/board-usb-a926x.c |2 +- arch/arm/mach-at91/board-yl-9200.c | 14 +++ 29 files changed, 728 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 05774e5..2c13783 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -374,6 +374,105 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} /* + * MMC / SD + * */ + +#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) +static u64 mmc_dmamask = DMA_BIT_MASK(32); +static struct mci_platform_data mmc_data; + +static struct resource mmc_resources[] = { + [0] = { + .start = AT91RM9200_BASE_MCI, + .end= AT91RM9200_BASE_MCI + SZ_16K - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91RM9200_ID_MCI, + .end= AT91RM9200_ID_MCI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device at91rm9200_mmc_device = { + .name = atmel_mci, + .id = -1, + .dev= { + .dma_mask = mmc_dmamask, + .coherent_dma_mask = DMA_BIT_MASK(32), + .platform_data = mmc_data, + }, + .resource = mmc_resources, + .num_resources = ARRAY_SIZE(mmc_resources), +}; + +void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) +{ + unsigned int i; + unsigned int slot_count = 0; + + if (!data) + return; + + for (i = 0; i ATMCI_MAX_NR_SLOTS; i++) { + + if (!data-slot[i].bus_width) + continue; + + /* input/irq */ + if (gpio_is_valid(data-slot[i].detect_pin)) { + at91_set_gpio_input(data-slot[i].detect_pin, 1); + at91_set_deglitch(data-slot[i].detect_pin, 1); + } + if (gpio_is_valid(data-slot[i].wp_pin)) + at91_set_gpio_input(data-slot[i].wp_pin, 1); + + switch (i) { + case 0: /* slot A */ + /* CMD */ + at91_set_A_periph(AT91_PIN_PA28, 1); + /* DAT0, maybe DAT1..DAT3 */ + at91_set_A_periph(AT91_PIN_PA29, 1); + if (data-slot[i].bus_width == 4) { + at91_set_B_periph(AT91_PIN_PB3, 1); + at91_set_B_periph(AT91_PIN_PB4, 1); + at91_set_B_periph(AT91_PIN_PB5, 1); + } + slot_count++; + break; + case 1: /* slot B */ + /* CMD */ + at91_set_B_periph(AT91_PIN_PA8, 1); + /* DAT0,
Re: [PATCH 4/4] mmc: dw_mmc: correct the calculation for CLKDIV
On Sun, May 20, 2012 at 5:27 AM, Seungwon Jeon tgih@samsung.com wrote: In case of host-bus_hz slot-clock, divider value is miscalculated. And clock divider register value is multiple of 2. If calculated divider value is odd number, result can be over-clocking. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 10 ++ 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index f2f8463..c87745e 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -617,14 +617,16 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) u32 div; if (slot-clock != host-current_speed) { - if (host-bus_hz % slot-clock) + div = host-bus_hz / slot-clock; + if (host-bus_hz % slot-clock + host-bus_hz slot-clock) /* * move the + 1 after the divide to prevent * over-clocking the card. */ This comment seems to be no longer relevant so it should be removed. - div = ((host-bus_hz / slot-clock) 1) + 1; - else - div = (host-bus_hz / slot-clock) 1; + div += 1; + + div = (host-bus_hz != slot-clock) ? DIV_ROUND_UP(div, 2) : 0; dev_info(slot-mmc-class_dev, Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ -- 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 -- 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: core: not to --qty when calculate timeout for SECURE_ERASE
On 13/04/12 07:19, Chuanxiao Dong wrote: --qty when calculating erase timeout for trim/erase secure trim/erase can prevent the erase range crossing qty+1 erase groups, which made the final timeout value is too large for the host. When operate SECURE_ERASE, driver needs the erase range is aligned with erase size, otherwise do nothing and return an error. That is to say it is not necessary for SECURE_ERASE to --qty since it will never cross an erase group. Signed-off-by: Chuanxiao Dong chuanxiao.d...@intel.com --- drivers/mmc/core/core.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e541efb..b5a393a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1761,7 +1761,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, if (!qty) return 0; - if (qty == 1) + if (qty == 1 arg != MMC_SECURE_ERASE_ARG) return 1; arg is never MMC_SECURE_ERASE_ARG /* Convert qty to sectors */ @@ -1772,6 +1772,13 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, else max_discard = --qty * card-erase_size; + /* + * since SECURE_ERASE is erase group aligned, otherwise + * it cannot be erased in secure purpose, needn't --qty + */ + if (arg == MMC_SECURE_ERASE_ARG) + max_discard += card-erase_size; + return max_discard; } What about: From: Adrian Hunter adrian.hun...@intel.com Date: Mon, 21 May 2012 13:32:42 +0300 Subject: [PATCH] mmc: core: fix max_discard calculation The maximum discard calculation was unnecessarily pessimistic in the case of erasing entire erase groups. In that case, the quantity does not need to be decreased by 1 to allow for misalignment because the erasure is always aligned to whole erase groups. Signed-off-by: Adrian Hunter adrian.hun...@intel.com --- drivers/mmc/core/core.c | 22 +- 1 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0b6141d..36bfdce 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1742,7 +1742,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, { struct mmc_host *host = card-host; unsigned int max_discard, x, y, qty = 0, max_qty, timeout; - unsigned int last_timeout = 0; + unsigned int last_timeout = 0, aligned_qty; if (card-erase_shift) max_qty = UINT_MAX card-erase_shift; @@ -1769,16 +1769,28 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, if (!qty) return 0; - if (qty == 1) - return 1; + if (arg MMC_TRIM_ARGS) { + /* +* The requested number of sectors may not be aligned to an +* erase group, so we have to decrease the quantity by 1 (unless +* it is 1) e.g. trimming 2 sectors could cause 2 erase groups +* to be affected even though 2 sectors is less than the size of +* 1 erase group. +*/ + if (qty == 1) + return 1; + aligned_qty = qty - 1; + } else { + aligned_qty = qty; + } /* Convert qty to sectors */ if (card-erase_shift) - max_discard = --qty card-erase_shift; + max_discard = aligned_qty card-erase_shift; else if (mmc_card_sd(card)) max_discard = qty; else - max_discard = --qty * card-erase_size; + max_discard = aligned_qty * card-erase_size; return max_discard; } -- 1.7.6.5 -- To unsubscribe from this list: send the line unsubscribe linux-mmc in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH]mmc: core: not to --qty when calculate timeout for SECURE_ERASE
-Original Message- From: Hunter, Adrian Sent: Monday, May 21, 2012 7:06 PM To: Dong, Chuanxiao Cc: linux-mmc@vger.kernel.org; c...@laptop.org Subject: Re: [PATCH]mmc: core: not to --qty when calculate timeout for SECURE_ERASE On 13/04/12 07:19, Chuanxiao Dong wrote: --qty when calculating erase timeout for trim/erase secure trim/erase can prevent the erase range crossing qty+1 erase groups, which made the final timeout value is too large for the host. When operate SECURE_ERASE, driver needs the erase range is aligned with erase size, otherwise do nothing and return an error. That is to say it is not necessary for SECURE_ERASE to --qty since it will never cross an erase group. Signed-off-by: Chuanxiao Dong chuanxiao.d...@intel.com --- drivers/mmc/core/core.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e541efb..b5a393a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1761,7 +1761,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, if (!qty) return 0; - if (qty == 1) + if (qty == 1 arg != MMC_SECURE_ERASE_ARG) return 1; arg is never MMC_SECURE_ERASE_ARG /* Convert qty to sectors */ @@ -1772,6 +1772,13 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, else max_discard = --qty * card-erase_size; + /* +* since SECURE_ERASE is erase group aligned, otherwise +* it cannot be erased in secure purpose, needn't --qty +*/ + if (arg == MMC_SECURE_ERASE_ARG) + max_discard += card-erase_size; + return max_discard; } What about: From: Adrian Hunter adrian.hun...@intel.com Date: Mon, 21 May 2012 13:32:42 +0300 Subject: [PATCH] mmc: core: fix max_discard calculation The maximum discard calculation was unnecessarily pessimistic in the case of erasing entire erase groups. In that case, the quantity does not need to be decreased by 1 to allow for misalignment because the erasure is always aligned to whole erase groups. Signed-off-by: Adrian Hunter adrian.hun...@intel.com --- drivers/mmc/core/core.c | 22 +- 1 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0b6141d..36bfdce 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1742,7 +1742,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, { struct mmc_host *host = card-host; unsigned int max_discard, x, y, qty = 0, max_qty, timeout; - unsigned int last_timeout = 0; + unsigned int last_timeout = 0, aligned_qty; if (card-erase_shift) max_qty = UINT_MAX card-erase_shift; @@ -1769,16 +1769,28 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, if (!qty) return 0; - if (qty == 1) - return 1; + if (arg MMC_TRIM_ARGS) { + /* + * The requested number of sectors may not be aligned to an + * erase group, so we have to decrease the quantity by 1 (unless + * it is 1) e.g. trimming 2 sectors could cause 2 erase groups + * to be affected even though 2 sectors is less than the size of + * 1 erase group. + */ + if (qty == 1) + return 1; + aligned_qty = qty - 1; + } else { + aligned_qty = qty; + } /* Convert qty to sectors */ if (card-erase_shift) - max_discard = --qty card-erase_shift; + max_discard = aligned_qty card-erase_shift; else if (mmc_card_sd(card)) max_discard = qty; else - max_discard = --qty * card-erase_size; + max_discard = aligned_qty * card-erase_size; return max_discard; } Hi Hunter, Your patch looks good to me. Since you also mentioned that the arg will never be MMC_SECURE_ERASE_ARG, I want to know why not calculate erase size for secure trim/erase operations? As specification said, secure trim/erase operations has different timeout value with trim/erase. Thanks Chuanxiao -- 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: core: not to --qty when calculate timeout for SECURE_ERASE
On 21/05/12 14:19, Dong, Chuanxiao wrote: -Original Message- From: Hunter, Adrian Sent: Monday, May 21, 2012 7:06 PM To: Dong, Chuanxiao Cc: linux-mmc@vger.kernel.org; c...@laptop.org Subject: Re: [PATCH]mmc: core: not to --qty when calculate timeout for SECURE_ERASE On 13/04/12 07:19, Chuanxiao Dong wrote: --qty when calculating erase timeout for trim/erase secure trim/erase can prevent the erase range crossing qty+1 erase groups, which made the final timeout value is too large for the host. When operate SECURE_ERASE, driver needs the erase range is aligned with erase size, otherwise do nothing and return an error. That is to say it is not necessary for SECURE_ERASE to --qty since it will never cross an erase group. Signed-off-by: Chuanxiao Dong chuanxiao.d...@intel.com --- drivers/mmc/core/core.c |9 - 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index e541efb..b5a393a 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1761,7 +1761,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, if (!qty) return 0; - if (qty == 1) + if (qty == 1 arg != MMC_SECURE_ERASE_ARG) return 1; arg is never MMC_SECURE_ERASE_ARG /* Convert qty to sectors */ @@ -1772,6 +1772,13 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, else max_discard = --qty * card-erase_size; + /* +* since SECURE_ERASE is erase group aligned, otherwise +* it cannot be erased in secure purpose, needn't --qty +*/ + if (arg == MMC_SECURE_ERASE_ARG) + max_discard += card-erase_size; + return max_discard; } What about: From: Adrian Hunter adrian.hun...@intel.com Date: Mon, 21 May 2012 13:32:42 +0300 Subject: [PATCH] mmc: core: fix max_discard calculation The maximum discard calculation was unnecessarily pessimistic in the case of erasing entire erase groups. In that case, the quantity does not need to be decreased by 1 to allow for misalignment because the erasure is always aligned to whole erase groups. Signed-off-by: Adrian Hunter adrian.hun...@intel.com --- drivers/mmc/core/core.c | 22 +- 1 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 0b6141d..36bfdce 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1742,7 +1742,7 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, { struct mmc_host *host = card-host; unsigned int max_discard, x, y, qty = 0, max_qty, timeout; -unsigned int last_timeout = 0; +unsigned int last_timeout = 0, aligned_qty; if (card-erase_shift) max_qty = UINT_MAX card-erase_shift; @@ -1769,16 +1769,28 @@ static unsigned int mmc_do_calc_max_discard(struct mmc_card *card, if (!qty) return 0; -if (qty == 1) -return 1; +if (arg MMC_TRIM_ARGS) { +/* + * The requested number of sectors may not be aligned to an + * erase group, so we have to decrease the quantity by 1 (unless + * it is 1) e.g. trimming 2 sectors could cause 2 erase groups + * to be affected even though 2 sectors is less than the size of + * 1 erase group. + */ +if (qty == 1) +return 1; +aligned_qty = qty - 1; +} else { +aligned_qty = qty; +} /* Convert qty to sectors */ if (card-erase_shift) -max_discard = --qty card-erase_shift; +max_discard = aligned_qty card-erase_shift; else if (mmc_card_sd(card)) max_discard = qty; else -max_discard = --qty * card-erase_size; +max_discard = aligned_qty * card-erase_size; return max_discard; } Hi Hunter, Your patch looks good to me. Since you also mentioned that the arg will never be MMC_SECURE_ERASE_ARG, I want to know why not calculate erase size for secure trim/erase operations? As specification said, secure trim/erase operations has different timeout value with trim/erase. There are 2 problems. First, there is only 1 value for maximum discard whether secure or not. Secondly, the timeout for secure erase can be so great that any quantity exceeds the maximum timeout. Thanks Chuanxiao -- 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 v6 1/3] mmc: core: Add packed command feature of eMMC4.5
Hi Seungwon, Sorry for commenting on this late. I have one comment below. Please check if it makes sense or not. On 5/17/2012 3:10 PM, Seungwon Jeon wrote: This patch adds packed command feature of eMMC4.5. The maximum number for packing read(or write) is offered and exception event relevant to packed command which is used for error handling is enabled. If host wants to use this feature, MMC_CAP2_PACKED_CMD should be set. Signed-off-by: Seungwon Jeontgih@samsung.com --- drivers/mmc/core/mmc.c | 24 include/linux/mmc/card.h |3 +++ include/linux/mmc/host.h |4 include/linux/mmc/mmc.h | 15 +++ 4 files changed, 46 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 2f0e11c..8310ce8 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -516,6 +516,11 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } else { card-ext_csd.data_tag_unit_size = 0; } + + card-ext_csd.max_packed_writes = + ext_csd[EXT_CSD_MAX_PACKED_WRITES]; + card-ext_csd.max_packed_reads = + ext_csd[EXT_CSD_MAX_PACKED_READS]; } out: @@ -1244,6 +1249,25 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } } + if ((host-caps2 MMC_CAP2_PACKED_CMD) + (card-ext_csd.max_packed_writes 0) + (card-ext_csd.max_packed_reads 0)) { why both max_packed_reads and max_packed_writes need to be non-zero to enable the write packing event? What if write packing is not supported by card and only read packing is supported? Shouldn't we still make the read packing work? I would suggest to change it like this: if ( (host-caps2 MMC_CAP2_PACKED_WR card-ext_csd.max_packed_writes 0) || (host-caps2 MMC_CAP2_PACKED_RD card-ext_csd.max_packed_reads 0) + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_EXP_EVENTS_CTRL, + EXT_CSD_PACKED_EVENT_EN, + card-ext_csd.generic_cmd6_time); + if (err err != -EBADMSG) + goto free_card; + if (err) { + pr_warning(%s: Enabling packed event failed\n, + mmc_hostname(card-host)); + card-ext_csd.packed_event_en = 0; + err = 0; + } else { + card-ext_csd.packed_event_en = 1; + } + } + if (!oldcard) host-card = card; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index d76513b..4aeb4e9 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -53,6 +53,9 @@ struct mmc_ext_csd { u8 part_config; u8 cache_ctrl; u8 rst_n_function; + u8 max_packed_writes; + u8 max_packed_reads; + u8 packed_event_en; unsigned intpart_time; /* Units: ms */ unsigned intsa_timeout; /* Units: 100ns */ unsigned intgeneric_cmd6_time; /* Units: 10ms */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 0707d22..9d0d946 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -238,6 +238,10 @@ struct mmc_host { #define MMC_CAP2_BROKEN_VOLTAGE (1 7) /* Use the broken voltage */ #define MMC_CAP2_DETECT_ON_ERR(1 8) /* On I/O err check card removal */ #define MMC_CAP2_HC_ERASE_SZ (1 9) /* High-capacity erase size */ +#define MMC_CAP2_PACKED_RD (1 10) /* Allow packed read */ +#define MMC_CAP2_PACKED_WR (1 11) /* Allow packed write */ +#define MMC_CAP2_PACKED_CMD(MMC_CAP2_PACKED_RD | \ +MMC_CAP2_PACKED_WR) /* Allow packed commands */ mmc_pm_flag_t pm_caps;/* supported pm features */ unsigned intpower_notify_type; diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index d425cab..254901a 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode) #define R1_CURRENT_STATE(x) ((x 0x1E00) 9) /* sx, b (4 bits) */ #define R1_READY_FOR_DATA (1 8) /* sx, a */ #define R1_SWITCH_ERROR (1 7) /* sx, c */ +#define R1_EXP_EVENT (1 6) /* sr, a */ #define R1_APP_CMD(1 5) /* sr, c */ #define R1_STATE_IDLE 0 @@ -274,6 +275,10 @@ struct _mmc_csd { #define EXT_CSD_FLUSH_CACHE 32 /* W */ #define EXT_CSD_CACHE_CTRL33 /* R/W */ #define
[PATCH] mmc: mxs-mmc: Add wp-inverted property
The write-protect GPIO is inverted on some boards. Handle such case. Signed-off-by: Marek Vasut ma...@denx.de Cc: Shawn Guo shawn@linaro.org Cc: Fabio Estevam fabio.este...@freescale.com Cc: linux-mmc@vger.kernel.org Cc: Chris Ball c...@laptop.org Cc: Lothar Waßmann l...@karo-electronics.de --- drivers/mmc/host/mxs-mmc.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 277161d..9bfd08e 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -164,16 +164,23 @@ struct mxs_mmc_host { spinlock_t lock; int sdio_irq_en; int wp_gpio; + int wp_inverted:1; }; static int mxs_mmc_get_ro(struct mmc_host *mmc) { struct mxs_mmc_host *host = mmc_priv(mmc); + int ret; if (!gpio_is_valid(host-wp_gpio)) return -EINVAL; - return gpio_get_value(host-wp_gpio); + ret = gpio_get_value(host-wp_gpio); + + if (host-wp_inverted) + ret = !ret; + + return ret; } static int mxs_mmc_get_cd(struct mmc_host *mmc) @@ -707,6 +714,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) struct pinctrl *pinctrl; int ret = 0, irq_err, irq_dma; dma_cap_mask_t mask; + enum of_gpio_flags flags; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -785,7 +793,10 @@ static int mxs_mmc_probe(struct platform_device *pdev) mmc-caps |= MMC_CAP_4_BIT_DATA; else if (bus_width == 8) mmc-caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; - host-wp_gpio = of_get_named_gpio(np, wp-gpios, 0); + host-wp_gpio = of_get_named_gpio_flags(np, wp-gpios, 0, + flags); + if (flags OF_GPIO_ACTIVE_LOW) + host-wp_inverted = 1; } else { if (pdata-flags SLOTF_8_BIT_CAPABLE) mmc-caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; -- 1.7.10 -- 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: mxs-mmc: Add wp-inverted property
On Mon, 21 May 2012, Marek Vasut wrote: The write-protect GPIO is inverted on some boards. Handle such case. Signed-off-by: Marek Vasut ma...@denx.de Cc: Shawn Guo shawn@linaro.org Cc: Fabio Estevam fabio.este...@freescale.com Cc: linux-mmc@vger.kernel.org Cc: Chris Ball c...@laptop.org Cc: Lothar Waßmann l...@karo-electronics.de --- drivers/mmc/host/mxs-mmc.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 277161d..9bfd08e 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -164,16 +164,23 @@ struct mxs_mmc_host { spinlock_t lock; int sdio_irq_en; int wp_gpio; + int wp_inverted:1; I think, many mmc drivers could use such a flag, so, I proposed this http://www.mail-archive.com/linux-mmc@vger.kernel.org/msg14018.html and I'm planning to respin that entire patch-series, taking reviews into account. However, that specific patch doesn't depend on anything, so, it can be taken directly. Then drivers would just use the new CAP2 flag, instead of adding similar flags to their private data. Another advantage of having that flag centrally is, that it will enable its use from the slot function helper module http://www.mail-archive.com/linux-mmc@vger.kernel.org/msg14031.html which I'll also respin soon. Thanks Guennadi }; static int mxs_mmc_get_ro(struct mmc_host *mmc) { struct mxs_mmc_host *host = mmc_priv(mmc); + int ret; if (!gpio_is_valid(host-wp_gpio)) return -EINVAL; - return gpio_get_value(host-wp_gpio); + ret = gpio_get_value(host-wp_gpio); + + if (host-wp_inverted) + ret = !ret; + + return ret; } static int mxs_mmc_get_cd(struct mmc_host *mmc) @@ -707,6 +714,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) struct pinctrl *pinctrl; int ret = 0, irq_err, irq_dma; dma_cap_mask_t mask; + enum of_gpio_flags flags; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); @@ -785,7 +793,10 @@ static int mxs_mmc_probe(struct platform_device *pdev) mmc-caps |= MMC_CAP_4_BIT_DATA; else if (bus_width == 8) mmc-caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; - host-wp_gpio = of_get_named_gpio(np, wp-gpios, 0); + host-wp_gpio = of_get_named_gpio_flags(np, wp-gpios, 0, + flags); + if (flags OF_GPIO_ACTIVE_LOW) + host-wp_inverted = 1; } else { if (pdata-flags SLOTF_8_BIT_CAPABLE) mmc-caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; -- 1.7.10 -- 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 --- Guennadi Liakhovetski, Ph.D. Freelance Open-Source Software Developer http://www.open-technology.de/ -- 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/2] ARM: dt: tegra: remove legacy support-8bit property
From: Stephen Warren swar...@nvidia.com The driver supports the new bus-width property, so remove the legacy support-8bit property. Signed-off-by: Stephen Warren swar...@nvidia.com --- arch/arm/boot/dts/tegra-cardhu.dts |1 - arch/arm/boot/dts/tegra-harmony.dts |1 - arch/arm/boot/dts/tegra-paz00.dts|1 - arch/arm/boot/dts/tegra-seaboard.dts |1 - arch/arm/boot/dts/tegra-ventana.dts |1 - arch/arm/boot/dts/tegra-whistler.dts |2 -- 6 files changed, 0 insertions(+), 7 deletions(-) diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts index 36321bc..c169bce 100644 --- a/arch/arm/boot/dts/tegra-cardhu.dts +++ b/arch/arm/boot/dts/tegra-cardhu.dts @@ -144,7 +144,6 @@ sdhci@78000600 { status = okay; - support-8bit; bus-width = 8; }; diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts index 7de7013..f146dbf 100644 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ b/arch/arm/boot/dts/tegra-harmony.dts @@ -307,7 +307,6 @@ cd-gpios = gpio 58 0; /* gpio PH2 */ wp-gpios = gpio 59 0; /* gpio PH3 */ power-gpios = gpio 70 0; /* gpio PI6 */ - support-8bit; bus-width = 8; }; diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts index bfeb117..684a9e1 100644 --- a/arch/arm/boot/dts/tegra-paz00.dts +++ b/arch/arm/boot/dts/tegra-paz00.dts @@ -301,7 +301,6 @@ sdhci@c8000600 { status = okay; - support-8bit; bus-width = 8; }; diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts index 1ea26c2..07030bf 100644 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ b/arch/arm/boot/dts/tegra-seaboard.dts @@ -450,7 +450,6 @@ sdhci@c8000600 { status = okay; - support-8bit; bus-width = 8; }; diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts index 445343b..be90544 100644 --- a/arch/arm/boot/dts/tegra-ventana.dts +++ b/arch/arm/boot/dts/tegra-ventana.dts @@ -314,7 +314,6 @@ sdhci@c8000600 { status = okay; - support-8bit; bus-width = 8; }; diff --git a/arch/arm/boot/dts/tegra-whistler.dts b/arch/arm/boot/dts/tegra-whistler.dts index 2548648..6916310 100644 --- a/arch/arm/boot/dts/tegra-whistler.dts +++ b/arch/arm/boot/dts/tegra-whistler.dts @@ -276,13 +276,11 @@ sdhci@c8000400 { status = okay; wp-gpios = gpio 173 0; /* gpio PV5 */ - support-8bit; bus-width = 8; }; sdhci@c8000600 { status = okay; - support-8bit; bus-width = 8; }; -- 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 1/2] mmc: tegra: use bus-width property instead of support-8bit
From: Stephen Warren swar...@nvidia.com Update the driver to parse the new unified bus-width property introduced in commit 7f21779 mmc: dt: Consolidate DT bindings, instead of the legacy support-8bit property. Signed-off-by: Stephen Warren swar...@nvidia.com --- These should go into 3.6; both patches have a bunch of dependencies in 3.5 that would be hard to manage. I think you can take both changes through the MMC tree in 3.6 without risk of significant conflicts. drivers/mmc/host/sdhci-tegra.c |5 - 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index b38d8a7..6e5338a 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -223,6 +223,7 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata( { struct tegra_sdhci_platform_data *plat; struct device_node *np = pdev-dev.of_node; + u32 bus_width; if (!np) return NULL; @@ -236,7 +237,9 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata( plat-cd_gpio = of_get_named_gpio(np, cd-gpios, 0); plat-wp_gpio = of_get_named_gpio(np, wp-gpios, 0); plat-power_gpio = of_get_named_gpio(np, power-gpios, 0); - if (of_find_property(np, support-8bit, NULL)) + + if (of_property_read_u32(np, bus-width, bus_width) == 0 + bus_width == 8) plat-is_8bit = 1; return plat; -- 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 2/4] mmc: dw_mmc: fix the IDMAC sw reset
Will Newton will.new...@gmail.com wrote: On Sun, May 20, 2012 at 5:27 AM, Seungwon Jeon tgih@samsung.com wrote: IDMAC may not be cleaned in driver probe if it has been already used in boot time. So IDMAC needs sw reset newly. And DMA interface reset precedes the internal DMAC reset. Additionally SDMMC_IDMAC_SWRESET is replaced with magic code. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 18 ++ 1 files changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index b46faf0..44aa292 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -418,6 +418,8 @@ static int dw_mci_idmac_init(struct dw_mci *host) p-des3 = host-sg_dma; p-des0 = IDMAC_DES0_ER; + mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET); + /* Mask out interrupts - get Tx Rx complete only */ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI); @@ -1724,7 +1726,8 @@ static void dw_mci_work_routine_card(struct work_struct *work) #ifdef CONFIG_MMC_DW_IDMAC ctrl = mci_readl(host, BMOD); - ctrl |= 0x01; /* Software reset of DMA */ + /* Software reset of DMA */ + ctrl |= SDMMC_IDMAC_SWRESET; mci_writel(host, BMOD, ctrl); #endif @@ -1949,10 +1952,6 @@ int dw_mci_probe(struct dw_mci *host) spin_lock_init(host-lock); INIT_LIST_HEAD(host-queue); - - host-dma_ops = host-pdata-dma_ops; - dw_mci_init_dma(host); - /* * Get the host data width - this assumes that HCON has been set with * the correct values. @@ -1985,6 +1984,9 @@ int dw_mci_probe(struct dw_mci *host) goto err_dmaunmap; } + host-dma_ops = host-pdata-dma_ops; + dw_mci_init_dma(host); + I think this change may break the error handling. The error label err_dmaunmap jumped to above expects that host-dma_ops is non-NULL. Please check that the error handling is ok. Right. I'll apply it. Thanks, Seungwon Jeon -- 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 -- 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 4/4] mmc: dw_mmc: correct the calculation for CLKDIV
Will Newton will.new...@gmail.com wrote: On Sun, May 20, 2012 at 5:27 AM, Seungwon Jeon tgih@samsung.com wrote: In case of host-bus_hz slot-clock, divider value is miscalculated. And clock divider register value is multiple of 2. If calculated divider value is odd number, result can be over-clocking. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 10 ++ 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index f2f8463..c87745e 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -617,14 +617,16 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) u32 div; if (slot-clock != host-current_speed) { - if (host-bus_hz % slot-clock) + div = host-bus_hz / slot-clock; + if (host-bus_hz % slot-clock + host-bus_hz slot-clock) /* * move the + 1 after the divide to prevent * over-clocking the card. */ This comment seems to be no longer relevant so it should be removed. - div = ((host-bus_hz / slot-clock) 1) + 1; - else - div = (host-bus_hz / slot-clock) 1; + div += 1; div += 1; It's still effective. Best regards, Seungwon Jeon + + div = (host-bus_hz != slot-clock) ? DIV_ROUND_UP(div, 2) : 0; dev_info(slot-mmc-class_dev, Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ -- 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 -- 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 -- 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 v6 1/3] mmc: core: Add packed command feature of eMMC4.5
Subhash Jadavani subha...@codeaurora.org wrote: Hi Seungwon, Sorry for commenting on this late. I have one comment below. Please check if it makes sense or not. On 5/17/2012 3:10 PM, Seungwon Jeon wrote: This patch adds packed command feature of eMMC4.5. The maximum number for packing read(or write) is offered and exception event relevant to packed command which is used for error handling is enabled. If host wants to use this feature, MMC_CAP2_PACKED_CMD should be set. Signed-off-by: Seungwon Jeontgih@samsung.com --- drivers/mmc/core/mmc.c | 24 include/linux/mmc/card.h |3 +++ include/linux/mmc/host.h |4 include/linux/mmc/mmc.h | 15 +++ 4 files changed, 46 insertions(+), 0 deletions(-) diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 2f0e11c..8310ce8 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -516,6 +516,11 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } else { card-ext_csd.data_tag_unit_size = 0; } + + card-ext_csd.max_packed_writes = + ext_csd[EXT_CSD_MAX_PACKED_WRITES]; + card-ext_csd.max_packed_reads = + ext_csd[EXT_CSD_MAX_PACKED_READS]; } out: @@ -1244,6 +1249,25 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, } } + if ((host-caps2 MMC_CAP2_PACKED_CMD) + (card-ext_csd.max_packed_writes 0) + (card-ext_csd.max_packed_reads 0)) { why both max_packed_reads and max_packed_writes need to be non-zero to enable the write packing event? What if write packing is not supported by card and only read packing is supported? Shouldn't we still make the read packing work? I have not experienced that case. But it seems like possible actually. Spec doesn't mention two should be satisfied for packed command. I'll apply your comment. Best regards, Seungwon Jeon I would suggest to change it like this: if ( (host-caps2 MMC_CAP2_PACKED_WR card-ext_csd.max_packed_writes 0) || (host-caps2 MMC_CAP2_PACKED_RD card-ext_csd.max_packed_reads 0) + err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_EXP_EVENTS_CTRL, + EXT_CSD_PACKED_EVENT_EN, + card-ext_csd.generic_cmd6_time); + if (err err != -EBADMSG) + goto free_card; + if (err) { + pr_warning(%s: Enabling packed event failed\n, + mmc_hostname(card-host)); + card-ext_csd.packed_event_en = 0; + err = 0; + } else { + card-ext_csd.packed_event_en = 1; + } + } + if (!oldcard) host-card = card; diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index d76513b..4aeb4e9 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -53,6 +53,9 @@ struct mmc_ext_csd { u8 part_config; u8 cache_ctrl; u8 rst_n_function; + u8 max_packed_writes; + u8 max_packed_reads; + u8 packed_event_en; unsigned intpart_time; /* Units: ms */ unsigned intsa_timeout; /* Units: 100ns */ unsigned intgeneric_cmd6_time; /* Units: 10ms */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 0707d22..9d0d946 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -238,6 +238,10 @@ struct mmc_host { #define MMC_CAP2_BROKEN_VOLTAGE (1 7)/* Use the broken voltage */ #define MMC_CAP2_DETECT_ON_ERR(1 8)/* On I/O err check card removal */ #define MMC_CAP2_HC_ERASE_SZ (1 9)/* High-capacity erase size */ +#define MMC_CAP2_PACKED_RD (1 10) /* Allow packed read */ +#define MMC_CAP2_PACKED_WR (1 11) /* Allow packed write */ +#define MMC_CAP2_PACKED_CMD(MMC_CAP2_PACKED_RD | \ +MMC_CAP2_PACKED_WR) /* Allow packed commands */ mmc_pm_flag_t pm_caps;/* supported pm features */ unsigned intpower_notify_type; diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index d425cab..254901a 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h @@ -139,6 +139,7 @@ static inline bool mmc_op_multi(u32 opcode) #define R1_CURRENT_STATE(x) ((x 0x1E00) 9) /* sx, b (4 bits) */ #define R1_READY_FOR_DATA (1 8)/* sx, a */ #define R1_SWITCH_ERROR (1 7)/* sx, c */
[PATCH v2 0/4] mmc: dw_mmc: some fiex for hosw driver
This patch-set includes fixes for the Synopsys DesignWare MMC driver Changes in v2: - fix the error handling(mmc: dw_mmc: fix the IDMAC sw reset) Seungwon Jeon (4): mmc: dw_mmc: fix the transmission handling in IDMAC mmc: dw_mmc: fix the IDMAC sw reset mmc: dw_mmc: fix the wrong sequence mmc: dw_mmc: correct the calculation for CLKDIV drivers/mmc/host/dw_mmc.c | 36 +++- 1 files changed, 19 insertions(+), 17 deletions(-) Best regards, Seungwon Jeon. -- 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 1/4] mmc: dw_mmc: fix the transmission handling in IDMAC
DTO interrupt can be later than transmit interrupt(IDMAC) in case of write. Current handling of idmac interrupt sets EVENT_DATA_COMPLETE as well as EVENT_XFER_COMPLETE regardless DTO rising. This makes the current request be finished in tasklet and permits the next request even though current data transfer is still in progress. As a result, sequence is broken and lock-up happens. Setting EVENT_DATA_COMPLETE is not proper after IDMAC interrupt. It should be taken after DTO interrupt is generated. Reported-by: Dmitry Shmidt dimitr...@android.com Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c |1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 9bbf45f..b46faf0 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1623,7 +1623,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) if (pending (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); - set_bit(EVENT_DATA_COMPLETE, host-pending_events); host-dma_ops-complete(host); } #endif -- 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 v2 2/4] mmc: dw_mmc: fix the IDMAC sw reset
IDMAC may not be cleaned in driver probe if it has been already used in boot time. So IDMAC needs sw reset newly. And DMA interface reset precedes the internal DMAC reset. Additionally SDMMC_IDMAC_SWRESET is replaced with magic code. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 24 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index b46faf0..98fe023 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -418,6 +418,8 @@ static int dw_mci_idmac_init(struct dw_mci *host) p-des3 = host-sg_dma; p-des0 = IDMAC_DES0_ER; + mci_writel(host, BMOD, SDMMC_IDMAC_SWRESET); + /* Mask out interrupts - get Tx Rx complete only */ mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | SDMMC_IDMAC_INT_TI); @@ -1724,7 +1726,8 @@ static void dw_mci_work_routine_card(struct work_struct *work) #ifdef CONFIG_MMC_DW_IDMAC ctrl = mci_readl(host, BMOD); - ctrl |= 0x01; /* Software reset of DMA */ + /* Software reset of DMA */ + ctrl |= SDMMC_IDMAC_SWRESET; mci_writel(host, BMOD, ctrl); #endif @@ -1949,10 +1952,6 @@ int dw_mci_probe(struct dw_mci *host) spin_lock_init(host-lock); INIT_LIST_HEAD(host-queue); - - host-dma_ops = host-pdata-dma_ops; - dw_mci_init_dma(host); - /* * Get the host data width - this assumes that HCON has been set with * the correct values. @@ -1980,10 +1979,11 @@ int dw_mci_probe(struct dw_mci *host) } /* Reset all blocks */ - if (!mci_wait_reset(host-dev, host)) { - ret = -ENODEV; - goto err_dmaunmap; - } + if (!mci_wait_reset(host-dev, host)) + return -ENODEV; + + host-dma_ops = host-pdata-dma_ops; + dw_mci_init_dma(host); /* Clear the interrupts for the host controller */ mci_writel(host, RINTSTS, 0x); @@ -2169,14 +2169,14 @@ int dw_mci_resume(struct dw_mci *host) if (host-vmmc) regulator_enable(host-vmmc); - if (host-dma_ops-init) - host-dma_ops-init(host); - if (!mci_wait_reset(host-dev, host)) { ret = -ENODEV; return ret; } + if (host-dma_ops-init) + host-dma_ops-init(host); + /* Restore the old value at FIFOTH register */ mci_writel(host, FIFOTH, host-fifoth_val); -- 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 v2 3/4] mmc: dw_mmc: fix the wrong sequence
Setting host-data to NULL is incorrect sequence in dw_mci_command_complete. This early setting makes the skip of dma_unmap_sg in dw_mci_dma_cleanup. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 98fe023..b070ee5 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -941,8 +941,8 @@ static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd mdelay(20); if (cmd-data) { - host-data = NULL; dw_mci_stop_dma(host); + host-data = NULL; } } } -- 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 v2 4/4] mmc: dw_mmc: correct the calculation for CLKDIV
In case of host-bus_hz slot-clock, divider value is miscalculated. And clock divider register value is multiple of 2. If calculated divider value is odd number, result can be over-clocking. Signed-off-by: Seungwon Jeon tgih@samsung.com --- drivers/mmc/host/dw_mmc.c | 10 ++ 1 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index b070ee5..8f5768c 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -617,14 +617,16 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) u32 div; if (slot-clock != host-current_speed) { - if (host-bus_hz % slot-clock) + div = host-bus_hz / slot-clock; + if (host-bus_hz % slot-clock + host-bus_hz slot-clock) /* * move the + 1 after the divide to prevent * over-clocking the card. */ - div = ((host-bus_hz / slot-clock) 1) + 1; - else - div = (host-bus_hz / slot-clock) 1; + div += 1; + + div = (host-bus_hz != slot-clock) ? DIV_ROUND_UP(div, 2) : 0; dev_info(slot-mmc-class_dev, Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ -- 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