Commit 1282ac40 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-v4.4-rc1' of git://git.linaro.org/people/ulf.hansson/mmc

Pull MMC fixes from Ulf Hansson:
 "Here are some mmc fixes intended for v4.4 rc2.  It's based on a commit
  prior rc1 as I wanted to get them a bit more tested in next before
  sending you the pull request.

  MMC core:
   - Improve reliability when selecting HS200 mode
   - Improve reliability when selecting HS400 mode
   - mmc: remove bondage between REQ_META and reliable write

  MMC host:
   - pxamci: Fix read-only gpio detection polarity
   - mtk-sd: Preinitialize delay_phase to fix the case when delay is zero
   - android-goldfish: Fix build dependency by adding HAS_DMA
   - dw_mmc: Remove Seungwon Jeon from MAINTAINERS"

* tag 'mmc-v4.4-rc1' of git://git.linaro.org/people/ulf.hansson/mmc:
  mmc: remove bondage between REQ_META and reliable write
  mmc: MMC_GOLDFISH should depend on HAS_DMA
  mmc: mediatek: Preinitialize delay_phase in get_best_delay()
  MAINTAINERS: mmc: Remove Seungwon Jeon from dw_mmc
  mmc: mmc: Improve reliability of mmc_select_hs400()
  mmc: mmc: Move mmc_switch_status()
  mmc: mmc: Fix HS setting in mmc_select_hs400()
  mmc: mmc: Improve reliability of mmc_select_hs200()
  mmc: pxamci: fix read-only gpio detection polarity
parents 34258a32 d3df0465
...@@ -9315,7 +9315,6 @@ F: drivers/i2c/busses/i2c-designware-* ...@@ -9315,7 +9315,6 @@ F: drivers/i2c/busses/i2c-designware-*
F: include/linux/platform_data/i2c-designware.h F: include/linux/platform_data/i2c-designware.h
SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
M: Seungwon Jeon <tgih.jun@samsung.com>
M: Jaehoon Chung <jh80.chung@samsung.com> M: Jaehoon Chung <jh80.chung@samsung.com>
L: linux-mmc@vger.kernel.org L: linux-mmc@vger.kernel.org
S: Maintained S: Maintained
......
...@@ -65,8 +65,7 @@ MODULE_ALIAS("mmc:block"); ...@@ -65,8 +65,7 @@ MODULE_ALIAS("mmc:block");
#define MMC_SANITIZE_REQ_TIMEOUT 240000 #define MMC_SANITIZE_REQ_TIMEOUT 240000
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16) #define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)
#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \ #define mmc_req_rel_wr(req) ((req->cmd_flags & REQ_FUA) && \
(req->cmd_flags & REQ_META)) && \
(rq_data_dir(req) == WRITE)) (rq_data_dir(req) == WRITE))
#define PACKED_CMD_VER 0x01 #define PACKED_CMD_VER 0x01
#define PACKED_CMD_WR 0x02 #define PACKED_CMD_WR 0x02
...@@ -1467,13 +1466,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, ...@@ -1467,13 +1466,9 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
/* /*
* Reliable writes are used to implement Forced Unit Access and * Reliable writes are used to implement Forced Unit Access and
* REQ_META accesses, and are supported only on MMCs. * are supported only on MMCs.
*
* XXX: this really needs a good explanation of why REQ_META
* is treated special.
*/ */
bool do_rel_wr = ((req->cmd_flags & REQ_FUA) || bool do_rel_wr = (req->cmd_flags & REQ_FUA) &&
(req->cmd_flags & REQ_META)) &&
(rq_data_dir(req) == WRITE) && (rq_data_dir(req) == WRITE) &&
(md->flags & MMC_BLK_REL_WR); (md->flags & MMC_BLK_REL_WR);
......
...@@ -1040,9 +1040,24 @@ static int mmc_select_hs_ddr(struct mmc_card *card) ...@@ -1040,9 +1040,24 @@ static int mmc_select_hs_ddr(struct mmc_card *card)
return err; return err;
} }
/* Caller must hold re-tuning */
static int mmc_switch_status(struct mmc_card *card)
{
u32 status;
int err;
err = mmc_send_status(card, &status);
if (err)
return err;
return mmc_switch_status_error(card->host, status);
}
static int mmc_select_hs400(struct mmc_card *card) static int mmc_select_hs400(struct mmc_card *card)
{ {
struct mmc_host *host = card->host; struct mmc_host *host = card->host;
bool send_status = true;
unsigned int max_dtr;
int err = 0; int err = 0;
u8 val; u8 val;
...@@ -1053,25 +1068,36 @@ static int mmc_select_hs400(struct mmc_card *card) ...@@ -1053,25 +1068,36 @@ static int mmc_select_hs400(struct mmc_card *card)
host->ios.bus_width == MMC_BUS_WIDTH_8)) host->ios.bus_width == MMC_BUS_WIDTH_8))
return 0; return 0;
/* if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
* Before switching to dual data rate operation for HS400, send_status = false;
* it is required to convert from HS200 mode to HS mode.
*/
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
mmc_set_bus_speed(card);
/* Reduce frequency to HS frequency */
max_dtr = card->ext_csd.hs_max_dtr;
mmc_set_clock(host, max_dtr);
/* Switch card to HS mode */
val = EXT_CSD_TIMING_HS | val = EXT_CSD_TIMING_HS |
card->drive_strength << EXT_CSD_DRV_STR_SHIFT; card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val, EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time, card->ext_csd.generic_cmd6_time,
true, true, true); true, send_status, true);
if (err) { if (err) {
pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", pr_err("%s: switch to high-speed from hs200 failed, err:%d\n",
mmc_hostname(host), err); mmc_hostname(host), err);
return err; return err;
} }
/* Set host controller to HS timing */
mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
if (!send_status) {
err = mmc_switch_status(card);
if (err)
goto out_err;
}
/* Switch card to DDR */
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH,
EXT_CSD_DDR_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8,
...@@ -1082,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card) ...@@ -1082,22 +1108,35 @@ static int mmc_select_hs400(struct mmc_card *card)
return err; return err;
} }
/* Switch card to HS400 */
val = EXT_CSD_TIMING_HS400 | val = EXT_CSD_TIMING_HS400 |
card->drive_strength << EXT_CSD_DRV_STR_SHIFT; card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val, EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time, card->ext_csd.generic_cmd6_time,
true, true, true); true, send_status, true);
if (err) { if (err) {
pr_err("%s: switch to hs400 failed, err:%d\n", pr_err("%s: switch to hs400 failed, err:%d\n",
mmc_hostname(host), err); mmc_hostname(host), err);
return err; return err;
} }
/* Set host controller to HS400 timing and frequency */
mmc_set_timing(host, MMC_TIMING_MMC_HS400); mmc_set_timing(host, MMC_TIMING_MMC_HS400);
mmc_set_bus_speed(card); mmc_set_bus_speed(card);
if (!send_status) {
err = mmc_switch_status(card);
if (err)
goto out_err;
}
return 0; return 0;
out_err:
pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
__func__, err);
return err;
} }
int mmc_hs200_to_hs400(struct mmc_card *card) int mmc_hs200_to_hs400(struct mmc_card *card)
...@@ -1105,19 +1144,6 @@ int mmc_hs200_to_hs400(struct mmc_card *card) ...@@ -1105,19 +1144,6 @@ int mmc_hs200_to_hs400(struct mmc_card *card)
return mmc_select_hs400(card); return mmc_select_hs400(card);
} }
/* Caller must hold re-tuning */
static int mmc_switch_status(struct mmc_card *card)
{
u32 status;
int err;
err = mmc_send_status(card, &status);
if (err)
return err;
return mmc_switch_status_error(card->host, status);
}
int mmc_hs400_to_hs200(struct mmc_card *card) int mmc_hs400_to_hs200(struct mmc_card *card)
{ {
struct mmc_host *host = card->host; struct mmc_host *host = card->host;
...@@ -1219,6 +1245,8 @@ static void mmc_select_driver_type(struct mmc_card *card) ...@@ -1219,6 +1245,8 @@ static void mmc_select_driver_type(struct mmc_card *card)
static int mmc_select_hs200(struct mmc_card *card) static int mmc_select_hs200(struct mmc_card *card)
{ {
struct mmc_host *host = card->host; struct mmc_host *host = card->host;
bool send_status = true;
unsigned int old_timing;
int err = -EINVAL; int err = -EINVAL;
u8 val; u8 val;
...@@ -1234,6 +1262,9 @@ static int mmc_select_hs200(struct mmc_card *card) ...@@ -1234,6 +1262,9 @@ static int mmc_select_hs200(struct mmc_card *card)
mmc_select_driver_type(card); mmc_select_driver_type(card);
if (host->caps & MMC_CAP_WAIT_WHILE_BUSY)
send_status = false;
/* /*
* Set the bus width(4 or 8) with host's support and * Set the bus width(4 or 8) with host's support and
* switch to HS200 mode if bus width is set successfully. * switch to HS200 mode if bus width is set successfully.
...@@ -1245,11 +1276,25 @@ static int mmc_select_hs200(struct mmc_card *card) ...@@ -1245,11 +1276,25 @@ static int mmc_select_hs200(struct mmc_card *card)
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val, EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time, card->ext_csd.generic_cmd6_time,
true, true, true); true, send_status, true);
if (!err) if (err)
mmc_set_timing(host, MMC_TIMING_MMC_HS200); goto err;
old_timing = host->ios.timing;
mmc_set_timing(host, MMC_TIMING_MMC_HS200);
if (!send_status) {
err = mmc_switch_status(card);
/*
* mmc_select_timing() assumes timing has not changed if
* it is a switch error.
*/
if (err == -EBADMSG)
mmc_set_timing(host, old_timing);
}
} }
err: err:
if (err)
pr_err("%s: %s failed, error %d\n", mmc_hostname(card->host),
__func__, err);
return err; return err;
} }
......
...@@ -473,6 +473,7 @@ config MMC_DAVINCI ...@@ -473,6 +473,7 @@ config MMC_DAVINCI
config MMC_GOLDFISH config MMC_GOLDFISH
tristate "goldfish qemu Multimedia Card Interface support" tristate "goldfish qemu Multimedia Card Interface support"
depends on HAS_DMA
depends on GOLDFISH || COMPILE_TEST depends on GOLDFISH || COMPILE_TEST
help help
This selects the Goldfish Multimedia card Interface emulation This selects the Goldfish Multimedia card Interface emulation
......
...@@ -1276,7 +1276,7 @@ static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay) ...@@ -1276,7 +1276,7 @@ static struct msdc_delay_phase get_best_delay(struct msdc_host *host, u32 delay)
int start = 0, len = 0; int start = 0, len = 0;
int start_final = 0, len_final = 0; int start_final = 0, len_final = 0;
u8 final_phase = 0xff; u8 final_phase = 0xff;
struct msdc_delay_phase delay_phase; struct msdc_delay_phase delay_phase = { 0, };
if (delay == 0) { if (delay == 0) {
dev_err(host->dev, "phase error: [map:%x]\n", delay); dev_err(host->dev, "phase error: [map:%x]\n", delay);
......
...@@ -805,7 +805,7 @@ static int pxamci_probe(struct platform_device *pdev) ...@@ -805,7 +805,7 @@ static int pxamci_probe(struct platform_device *pdev)
goto out; goto out;
} else { } else {
mmc->caps |= host->pdata->gpio_card_ro_invert ? mmc->caps |= host->pdata->gpio_card_ro_invert ?
MMC_CAP2_RO_ACTIVE_HIGH : 0; 0 : MMC_CAP2_RO_ACTIVE_HIGH;
} }
if (gpio_is_valid(gpio_cd)) if (gpio_is_valid(gpio_cd))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment