Skip to content

Commit

Permalink
Merge tag 'mmc-fixes-for-3.4-rc2' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/cjb/mmc

Pull MMC fixes from Chris Ball:
 - Disable use of MSI in sdhci-pci, which caused multiple chipsets to
   stop working in 3.4-rc1.  I'll wait to turn this on again until we
   have a chipset whitelist for it.
 - Fix a libertas SDIO powered-resume regression introduced in 3.3;
   thanks to Neil Brown and Rafael Wysocki for this fix.
 - Fix module reloading on omap_hsmmc.
 - Stop trusting the spec/card's specified maximum data timeout length,
   and use three seconds instead.  Previously we used 300ms.

Also cleanups and fixes for s3c, atmel, sh_mmcif and omap_hsmmc.

* tag 'mmc-fixes-for-3.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (28 commits)
  mmc: use really long write timeout to deal with crappy cards
  mmc: sdhci-dove: Fix compile error by including module.h
  mmc: Prevent 1.8V switch for SD hosts that don't support UHS modes.
  Revert "mmc: sdhci-pci: Add MSI support"
  Revert "mmc: sdhci-pci: add quirks for broken MSI on O2Micro controllers"
  mmc: core: fix power class selection
  mmc: omap_hsmmc: fix module re-insertion
  mmc: omap_hsmmc: convert to module_platform_driver
  mmc: omap_hsmmc: make it behave well as a module
  mmc: omap_hsmmc: trivial cleanups
  mmc: omap_hsmmc: context save after enabling runtime pm
  mmc: omap_hsmmc: use runtime put sync in probe error patch
  mmc: sdio: Use empty system suspend/resume callbacks at the bus level
  mmc: bus: print bus speed mode of UHS-I card
  mmc: sdhci-pci: add quirks for broken MSI on O2Micro controllers
  mmc: sh_mmcif: Simplify calculation of mmc->f_min
  mmc: sh_mmcif: mmc->f_max should be half of the bus clock
  mmc: sh_mmcif: double clock speed
  mmc: block: Remove use of mmc_blk_set_blksize
  mmc: atmel-mci: add support for odd clock dividers
  ...
  • Loading branch information
Linus Torvalds committed Apr 7, 2012
2 parents f68e556 + 3bdc9ba commit 1ddca05
Show file tree
Hide file tree
Showing 13 changed files with 299 additions and 218 deletions.
27 changes: 1 addition & 26 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -1623,24 +1623,6 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
return ret;
}

static int
mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card)
{
int err;

mmc_claim_host(card->host);
err = mmc_set_blocklen(card, 512);
mmc_release_host(card->host);

if (err) {
pr_err("%s: unable to set block size to 512: %d\n",
md->disk->disk_name, err);
return -EINVAL;
}

return 0;
}

static void mmc_blk_remove_req(struct mmc_blk_data *md)
{
struct mmc_card *card;
Expand Down Expand Up @@ -1768,7 +1750,6 @@ static const struct mmc_fixup blk_fixups[] =
static int mmc_blk_probe(struct mmc_card *card)
{
struct mmc_blk_data *md, *part_md;
int err;
char cap_str[10];

/*
Expand All @@ -1781,10 +1762,6 @@ static int mmc_blk_probe(struct mmc_card *card)
if (IS_ERR(md))
return PTR_ERR(md);

err = mmc_blk_set_blksize(md, card);
if (err)
goto out;

string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
cap_str, sizeof(cap_str));
pr_info("%s: %s %s %s %s\n",
Expand All @@ -1809,7 +1786,7 @@ static int mmc_blk_probe(struct mmc_card *card)
out:
mmc_blk_remove_parts(card, md);
mmc_blk_remove_req(md);
return err;
return 0;
}

static void mmc_blk_remove(struct mmc_card *card)
Expand Down Expand Up @@ -1845,8 +1822,6 @@ static int mmc_blk_resume(struct mmc_card *card)
struct mmc_blk_data *md = mmc_get_drvdata(card);

if (md) {
mmc_blk_set_blksize(md, card);

/*
* Resume involves the card going into idle state,
* so current partition is always the main one.
Expand Down
17 changes: 15 additions & 2 deletions drivers/mmc/core/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,15 @@ int mmc_add_card(struct mmc_card *card)
{
int ret;
const char *type;
const char *uhs_bus_speed_mode = "";
static const char *const uhs_speeds[] = {
[UHS_SDR12_BUS_SPEED] = "SDR12 ",
[UHS_SDR25_BUS_SPEED] = "SDR25 ",
[UHS_SDR50_BUS_SPEED] = "SDR50 ",
[UHS_SDR104_BUS_SPEED] = "SDR104 ",
[UHS_DDR50_BUS_SPEED] = "DDR50 ",
};


dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);

Expand Down Expand Up @@ -296,20 +305,24 @@ int mmc_add_card(struct mmc_card *card)
break;
}

if (mmc_sd_card_uhs(card) &&
(card->sd_bus_speed < ARRAY_SIZE(uhs_speeds)))
uhs_bus_speed_mode = uhs_speeds[card->sd_bus_speed];

if (mmc_host_is_spi(card->host)) {
pr_info("%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host),
mmc_card_highspeed(card) ? "high speed " : "",
mmc_card_ddr_mode(card) ? "DDR " : "",
type);
} else {
pr_info("%s: new %s%s%s%s card at address %04x\n",
pr_info("%s: new %s%s%s%s%s card at address %04x\n",
mmc_hostname(card->host),
mmc_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""),
(mmc_card_hs200(card) ? "HS200 " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "",
type, card->rca);
uhs_bus_speed_mode, type, card->rca);
}

#ifdef CONFIG_DEBUG_FS
Expand Down
10 changes: 7 additions & 3 deletions drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,10 +527,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)

if (data->flags & MMC_DATA_WRITE)
/*
* The limit is really 250 ms, but that is
* insufficient for some crappy cards.
* The MMC spec "It is strongly recommended
* for hosts to implement more than 500ms
* timeout value even if the card indicates
* the 250ms maximum busy length." Even the
* previous value of 300ms is known to be
* insufficient for some cards.
*/
limit_us = 300000;
limit_us = 3000000;
else
limit_us = 100000;

Expand Down
30 changes: 17 additions & 13 deletions drivers/mmc/core/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,11 @@ static int mmc_select_powerclass(struct mmc_card *card,
else if (host->ios.clock <= 200000000)
index = EXT_CSD_PWR_CL_200_195;
break;
case MMC_VDD_27_28:
case MMC_VDD_28_29:
case MMC_VDD_29_30:
case MMC_VDD_30_31:
case MMC_VDD_31_32:
case MMC_VDD_32_33:
case MMC_VDD_33_34:
case MMC_VDD_34_35:
Expand Down Expand Up @@ -1111,11 +1116,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
ext_csd_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
if (err) {
pr_err("%s: power class selection to bus width %d failed\n",
mmc_hostname(card->host), 1 << bus_width);
goto err;
}
if (err)
pr_warning("%s: power class selection to bus width %d"
" failed\n", mmc_hostname(card->host),
1 << bus_width);
}

/*
Expand Down Expand Up @@ -1147,10 +1151,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
ext_csd);
if (err)
pr_err("%s: power class selection to "
"bus width %d failed\n",
mmc_hostname(card->host),
1 << bus_width);
pr_warning("%s: power class selection to "
"bus width %d failed\n",
mmc_hostname(card->host),
1 << bus_width);

err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
Expand Down Expand Up @@ -1178,10 +1182,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
ext_csd);
if (err)
pr_err("%s: power class selection to "
"bus width %d ddr %d failed\n",
mmc_hostname(card->host),
1 << bus_width, ddr);
pr_warning("%s: power class selection to "
"bus width %d ddr %d failed\n",
mmc_hostname(card->host),
1 << bus_width, ddr);

err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
Expand Down
12 changes: 9 additions & 3 deletions drivers/mmc/core/sdio_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device *dev)
return ret;
}

#ifdef CONFIG_PM_RUNTIME
#ifdef CONFIG_PM

static int pm_no_operation(struct device *dev)
{
return 0;
}

static const struct dev_pm_ops sdio_bus_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_no_operation, pm_no_operation)
SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend,
pm_generic_runtime_resume,
Expand All @@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {

#define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops)

#else /* !CONFIG_PM_RUNTIME */
#else /* !CONFIG_PM */

#define SDIO_PM_OPS_PTR NULL

#endif /* !CONFIG_PM_RUNTIME */
#endif /* !CONFIG_PM */

static struct bus_type sdio_bus_type = {
.name = "sdio",
Expand Down
1 change: 1 addition & 0 deletions drivers/mmc/host/atmel-mci-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */
# define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */
#define ATMCI_DTOR 0x0008 /* Data Timeout */
# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
Expand Down
55 changes: 37 additions & 18 deletions drivers/mmc/host/atmel-mci.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct atmel_mci_caps {
bool has_cstor_reg;
bool has_highspeed;
bool has_rwproof;
bool has_odd_clk_div;
};

struct atmel_mci_dma {
Expand Down Expand Up @@ -482,7 +483,14 @@ static void atmci_init_debugfs(struct atmel_mci_slot *slot)
static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
unsigned int ns)
{
return (ns * (host->bus_hz / 1000000) + 999) / 1000;
/*
* It is easier here to use us instead of ns for the timeout,
* it prevents from overflows during calculation.
*/
unsigned int us = DIV_ROUND_UP(ns, 1000);

/* Maximum clock frequency is host->bus_hz/2 */
return us * (DIV_ROUND_UP(host->bus_hz, 2000000));
}

static void atmci_set_timeout(struct atmel_mci *host,
Expand Down Expand Up @@ -1127,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}

/* Calculate clock divider */
clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
if (clkdiv > 255) {
dev_warn(&mmc->class_dev,
"clock %u too slow; using %lu\n",
clock_min, host->bus_hz / (2 * 256));
clkdiv = 255;
if (host->caps.has_odd_clk_div) {
clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2;
if (clkdiv > 511) {
dev_warn(&mmc->class_dev,
"clock %u too slow; using %lu\n",
clock_min, host->bus_hz / (511 + 2));
clkdiv = 511;
}
host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1)
| ATMCI_MR_CLKODD(clkdiv & 1);
} else {
clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
if (clkdiv > 255) {
dev_warn(&mmc->class_dev,
"clock %u too slow; using %lu\n",
clock_min, host->bus_hz / (2 * 256));
clkdiv = 255;
}
host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
}

host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);

/*
* WRPROOF and RDPROOF prevent overruns/underruns by
* stopping the clock when the FIFO is full/empty.
Expand Down Expand Up @@ -2007,35 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host)
"version: 0x%x\n", version);

host->caps.has_dma = 0;
host->caps.has_pdc = 0;
host->caps.has_pdc = 1;
host->caps.has_cfg_reg = 0;
host->caps.has_cstor_reg = 0;
host->caps.has_highspeed = 0;
host->caps.has_rwproof = 0;
host->caps.has_odd_clk_div = 0;

/* keep only major version number */
switch (version & 0xf00) {
case 0x100:
case 0x200:
host->caps.has_pdc = 1;
host->caps.has_rwproof = 1;
break;
case 0x300:
case 0x400:
case 0x500:
host->caps.has_odd_clk_div = 1;
case 0x400:
case 0x300:
#ifdef CONFIG_AT_HDMAC
host->caps.has_dma = 1;
#else
host->caps.has_dma = 0;
dev_info(&host->pdev->dev,
"has dma capability but dma engine is not selected, then use pio\n");
#endif
host->caps.has_pdc = 0;
host->caps.has_cfg_reg = 1;
host->caps.has_cstor_reg = 1;
host->caps.has_highspeed = 1;
case 0x200:
host->caps.has_rwproof = 1;
case 0x100:
break;
default:
host->caps.has_pdc = 0;
dev_warn(&host->pdev->dev,
"Unmanaged mci version, set minimum capabilities\n");
break;
Expand Down
Loading

0 comments on commit 1ddca05

Please sign in to comment.