Commit 1ddca057 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mmc-fixes-for-3.4-rc2' of git://git.kernel.org/pub/scm/linux/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
  ...
parents f68e556e 3bdc9ba8
...@@ -1623,24 +1623,6 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md) ...@@ -1623,24 +1623,6 @@ static int mmc_blk_alloc_parts(struct mmc_card *card, struct mmc_blk_data *md)
return ret; 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) static void mmc_blk_remove_req(struct mmc_blk_data *md)
{ {
struct mmc_card *card; struct mmc_card *card;
...@@ -1768,7 +1750,6 @@ static const struct mmc_fixup blk_fixups[] = ...@@ -1768,7 +1750,6 @@ static const struct mmc_fixup blk_fixups[] =
static int mmc_blk_probe(struct mmc_card *card) static int mmc_blk_probe(struct mmc_card *card)
{ {
struct mmc_blk_data *md, *part_md; struct mmc_blk_data *md, *part_md;
int err;
char cap_str[10]; char cap_str[10];
/* /*
...@@ -1781,10 +1762,6 @@ static int mmc_blk_probe(struct mmc_card *card) ...@@ -1781,10 +1762,6 @@ static int mmc_blk_probe(struct mmc_card *card)
if (IS_ERR(md)) if (IS_ERR(md))
return PTR_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, string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
cap_str, sizeof(cap_str)); cap_str, sizeof(cap_str));
pr_info("%s: %s %s %s %s\n", pr_info("%s: %s %s %s %s\n",
...@@ -1809,7 +1786,7 @@ static int mmc_blk_probe(struct mmc_card *card) ...@@ -1809,7 +1786,7 @@ static int mmc_blk_probe(struct mmc_card *card)
out: out:
mmc_blk_remove_parts(card, md); mmc_blk_remove_parts(card, md);
mmc_blk_remove_req(md); mmc_blk_remove_req(md);
return err; return 0;
} }
static void mmc_blk_remove(struct mmc_card *card) static void mmc_blk_remove(struct mmc_card *card)
...@@ -1845,8 +1822,6 @@ static int mmc_blk_resume(struct mmc_card *card) ...@@ -1845,8 +1822,6 @@ static int mmc_blk_resume(struct mmc_card *card)
struct mmc_blk_data *md = mmc_get_drvdata(card); struct mmc_blk_data *md = mmc_get_drvdata(card);
if (md) { if (md) {
mmc_blk_set_blksize(md, card);
/* /*
* Resume involves the card going into idle state, * Resume involves the card going into idle state,
* so current partition is always the main one. * so current partition is always the main one.
......
...@@ -267,6 +267,15 @@ int mmc_add_card(struct mmc_card *card) ...@@ -267,6 +267,15 @@ int mmc_add_card(struct mmc_card *card)
{ {
int ret; int ret;
const char *type; 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); dev_set_name(&card->dev, "%s:%04x", mmc_hostname(card->host), card->rca);
...@@ -296,6 +305,10 @@ int mmc_add_card(struct mmc_card *card) ...@@ -296,6 +305,10 @@ int mmc_add_card(struct mmc_card *card)
break; 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)) { if (mmc_host_is_spi(card->host)) {
pr_info("%s: new %s%s%s card on SPI\n", pr_info("%s: new %s%s%s card on SPI\n",
mmc_hostname(card->host), mmc_hostname(card->host),
...@@ -303,13 +316,13 @@ int mmc_add_card(struct mmc_card *card) ...@@ -303,13 +316,13 @@ int mmc_add_card(struct mmc_card *card)
mmc_card_ddr_mode(card) ? "DDR " : "", mmc_card_ddr_mode(card) ? "DDR " : "",
type); type);
} else { } 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_hostname(card->host),
mmc_card_uhs(card) ? "ultra high speed " : mmc_card_uhs(card) ? "ultra high speed " :
(mmc_card_highspeed(card) ? "high speed " : ""), (mmc_card_highspeed(card) ? "high speed " : ""),
(mmc_card_hs200(card) ? "HS200 " : ""), (mmc_card_hs200(card) ? "HS200 " : ""),
mmc_card_ddr_mode(card) ? "DDR " : "", mmc_card_ddr_mode(card) ? "DDR " : "",
type, card->rca); uhs_bus_speed_mode, type, card->rca);
} }
#ifdef CONFIG_DEBUG_FS #ifdef CONFIG_DEBUG_FS
......
...@@ -527,10 +527,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) ...@@ -527,10 +527,14 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
if (data->flags & MMC_DATA_WRITE) if (data->flags & MMC_DATA_WRITE)
/* /*
* The limit is really 250 ms, but that is * The MMC spec "It is strongly recommended
* insufficient for some crappy cards. * 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 else
limit_us = 100000; limit_us = 100000;
......
...@@ -695,6 +695,11 @@ static int mmc_select_powerclass(struct mmc_card *card, ...@@ -695,6 +695,11 @@ static int mmc_select_powerclass(struct mmc_card *card,
else if (host->ios.clock <= 200000000) else if (host->ios.clock <= 200000000)
index = EXT_CSD_PWR_CL_200_195; index = EXT_CSD_PWR_CL_200_195;
break; 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_32_33:
case MMC_VDD_33_34: case MMC_VDD_33_34:
case MMC_VDD_34_35: case MMC_VDD_34_35:
...@@ -1111,11 +1116,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -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_bits = (bus_width == MMC_BUS_WIDTH_8) ?
EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4; EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
err = mmc_select_powerclass(card, ext_csd_bits, ext_csd); err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
if (err) { if (err)
pr_err("%s: power class selection to bus width %d failed\n", pr_warning("%s: power class selection to bus width %d"
mmc_hostname(card->host), 1 << bus_width); " failed\n", mmc_hostname(card->host),
goto err; 1 << bus_width);
}
} }
/* /*
...@@ -1147,10 +1151,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -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], err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
ext_csd); ext_csd);
if (err) if (err)
pr_err("%s: power class selection to " pr_warning("%s: power class selection to "
"bus width %d failed\n", "bus width %d failed\n",
mmc_hostname(card->host), mmc_hostname(card->host),
1 << bus_width); 1 << bus_width);
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,
...@@ -1178,10 +1182,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, ...@@ -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], err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
ext_csd); ext_csd);
if (err) if (err)
pr_err("%s: power class selection to " pr_warning("%s: power class selection to "
"bus width %d ddr %d failed\n", "bus width %d ddr %d failed\n",
mmc_hostname(card->host), mmc_hostname(card->host),
1 << bus_width, ddr); 1 << bus_width, 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,
......
...@@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device *dev) ...@@ -192,9 +192,15 @@ static int sdio_bus_remove(struct device *dev)
return ret; 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 = { 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( SET_RUNTIME_PM_OPS(
pm_generic_runtime_suspend, pm_generic_runtime_suspend,
pm_generic_runtime_resume, pm_generic_runtime_resume,
...@@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_pm_ops = { ...@@ -204,11 +210,11 @@ static const struct dev_pm_ops sdio_bus_pm_ops = {
#define SDIO_PM_OPS_PTR (&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 #define SDIO_PM_OPS_PTR NULL
#endif /* !CONFIG_PM_RUNTIME */ #endif /* !CONFIG_PM */
static struct bus_type sdio_bus_type = { static struct bus_type sdio_bus_type = {
.name = "sdio", .name = "sdio",
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */ # define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */ # define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */ # 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_DTOR 0x0008 /* Data Timeout */
# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */ # define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */ # define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
......
...@@ -77,6 +77,7 @@ struct atmel_mci_caps { ...@@ -77,6 +77,7 @@ struct atmel_mci_caps {
bool has_cstor_reg; bool has_cstor_reg;
bool has_highspeed; bool has_highspeed;
bool has_rwproof; bool has_rwproof;
bool has_odd_clk_div;
}; };
struct atmel_mci_dma { struct atmel_mci_dma {
...@@ -482,7 +483,14 @@ err: ...@@ -482,7 +483,14 @@ err:
static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host, static inline unsigned int atmci_ns_to_clocks(struct atmel_mci *host,
unsigned int ns) 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, static void atmci_set_timeout(struct atmel_mci *host,
...@@ -1127,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -1127,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
} }
/* Calculate clock divider */ /* Calculate clock divider */
clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; if (host->caps.has_odd_clk_div) {
if (clkdiv > 255) { clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2;
dev_warn(&mmc->class_dev, if (clkdiv > 511) {
"clock %u too slow; using %lu\n", dev_warn(&mmc->class_dev,
clock_min, host->bus_hz / (2 * 256)); "clock %u too slow; using %lu\n",
clkdiv = 255; 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 * WRPROOF and RDPROOF prevent overruns/underruns by
* stopping the clock when the FIFO is full/empty. * stopping the clock when the FIFO is full/empty.
...@@ -2007,35 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host) ...@@ -2007,35 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host)
"version: 0x%x\n", version); "version: 0x%x\n", version);
host->caps.has_dma = 0; host->caps.has_dma = 0;
host->caps.has_pdc = 0; host->caps.has_pdc = 1;
host->caps.has_cfg_reg = 0; host->caps.has_cfg_reg = 0;
host->caps.has_cstor_reg = 0; host->caps.has_cstor_reg = 0;
host->caps.has_highspeed = 0; host->caps.has_highspeed = 0;
host->caps.has_rwproof = 0; host->caps.has_rwproof = 0;
host->caps.has_odd_clk_div = 0;
/* keep only major version number */ /* keep only major version number */
switch (version & 0xf00) { switch (version & 0xf00) {
case 0x100:
case 0x200:
host->caps.has_pdc = 1;
host->caps.has_rwproof = 1;
break;
case 0x300:
case 0x400:
case 0x500: case 0x500:
host->caps.has_odd_clk_div = 1;
case 0x400:
case 0x300:
#ifdef CONFIG_AT_HDMAC #ifdef CONFIG_AT_HDMAC
host->caps.has_dma = 1; host->caps.has_dma = 1;
#else #else
host->caps.has_dma = 0;
dev_info(&host->pdev->dev, dev_info(&host->pdev->dev,
"has dma capability but dma engine is not selected, then use pio\n"); "has dma capability but dma engine is not selected, then use pio\n");
#endif #endif
host->caps.has_pdc = 0;
host->caps.has_cfg_reg = 1; host->caps.has_cfg_reg = 1;
host->caps.has_cstor_reg = 1; host->caps.has_cstor_reg = 1;
host->caps.has_highspeed = 1; host->caps.has_highspeed = 1;
case 0x200:
host->caps.has_rwproof = 1; host->caps.has_rwproof = 1;
case 0x100:
break; break;
default: default:
host->caps.has_pdc = 0;
dev_warn(&host->pdev->dev, dev_warn(&host->pdev->dev,
"Unmanaged mci version, set minimum capabilities\n"); "Unmanaged mci version, set minimum capabilities\n");
break; break;
......
...@@ -1785,7 +1785,7 @@ static inline struct omap_mmc_platform_data ...@@ -1785,7 +1785,7 @@ static inline struct omap_mmc_platform_data
} }
#endif #endif
static int __init omap_hsmmc_probe(struct platform_device *pdev) static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
{ {
struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; struct omap_mmc_platform_data *pdata = pdev->dev.platform_data;
struct mmc_host *mmc; struct mmc_host *mmc;
...@@ -1818,8 +1818,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1818,8 +1818,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
if (res == NULL || irq < 0) if (res == NULL || irq < 0)
return -ENXIO; return -ENXIO;
res->start += pdata->reg_offset;
res->end += pdata->reg_offset;
res = request_mem_region(res->start, resource_size(res), pdev->name); res = request_mem_region(res->start, resource_size(res), pdev->name);
if (res == NULL) if (res == NULL)
return -EBUSY; return -EBUSY;
...@@ -1843,7 +1841,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1843,7 +1841,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
host->dma_ch = -1; host->dma_ch = -1;
host->irq = irq; host->irq = irq;
host->slot_id = 0; host->slot_id = 0;
host->mapbase = res->start; host->mapbase = res->start + pdata->reg_offset;
host->base = ioremap(host->mapbase, SZ_4K); host->base = ioremap(host->mapbase, SZ_4K);
host->power_mode = MMC_POWER_OFF; host->power_mode = MMC_POWER_OFF;
host->next_data.cookie = 1; host->next_data.cookie = 1;
...@@ -1875,8 +1873,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1875,8 +1873,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
goto err1; goto err1;
} }
omap_hsmmc_context_save(host);
if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) { if (host->pdata->controller_flags & OMAP_HSMMC_BROKEN_MULTIBLOCK_READ) {
dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n"); dev_info(&pdev->dev, "multiblock reads disabled due to 35xx erratum 2.1.1.128; MMC read performance may suffer\n");
mmc->caps2 |= MMC_CAP2_NO_MULTI_READ; mmc->caps2 |= MMC_CAP2_NO_MULTI_READ;
...@@ -1887,6 +1883,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) ...@@ -1887,6 +1883,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY); pm_runtime_set_autosuspend_delay(host->dev, MMC_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(host->dev); pm_runtime_use_autosuspend(host->dev);
omap_hsmmc_context_save(host);
if (cpu_is_omap2430()) { if (cpu_is_omap2430()) {
host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck");
/* /*
...@@ -2018,8 +2016,7 @@ err_reg: ...@@ -2018,8 +2016,7 @@ err_reg:
err_irq_cd_init: err_irq_cd_init:
free_irq(host->irq, host); free_irq(host->irq, host);
err_irq: err_irq:
pm_runtime_mark_last_busy(host->dev); pm_runtime_put_sync(host->dev);
pm_runtime_put_autosuspend(host->dev);
pm_runtime_disable(host->dev); pm_runtime_disable(host->dev);
clk_put(host->fclk); clk_put(host->fclk);
if (host->got_dbclk) { if (host->got_dbclk) {
...@@ -2037,35 +2034,33 @@ err: ...@@ -2037,35 +2034,33 @@ err:
return ret; return ret;
} }
static int omap_hsmmc_remove(struct platform_device *pdev) static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
{ {
struct omap_hsmmc_host *host = platform_get_drvdata(pdev); struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
struct resource *res; struct resource *res;
if (host) { pm_runtime_get_sync(host->dev);
pm_runtime_get_sync(host->dev); mmc_remove_host(host->mmc);
mmc_remove_host(host->mmc); if (host->use_reg)
if (host->use_reg) omap_hsmmc_reg_put(host);
omap_hsmmc_reg_put(host); if (host->pdata->cleanup)
if (host->pdata->cleanup) host->pdata->cleanup(&pdev->dev);
host->pdata->cleanup(&pdev->dev); free_irq(host->irq, host);
free_irq(host->irq, host); if (mmc_slot(host).card_detect_irq)
if (mmc_slot(host).card_detect_irq) free_irq(mmc_slot(host).card_detect_irq, host);
free_irq(mmc_slot(host).card_detect_irq, host);
pm_runtime_put_sync(host->dev);
pm_runtime_disable(host->dev);
clk_put(host->fclk);
if (host->got_dbclk) {
clk_disable(host->dbclk);
clk_put(host->dbclk);
}
mmc_free_host(host->mmc); pm_runtime_put_sync(host->dev);
iounmap(host->base); pm_runtime_disable(host->dev);
omap_hsmmc_gpio_free(pdev->dev.platform_data); clk_put(host->fclk);
if (host->got_dbclk) {
clk_disable(host->dbclk);
clk_put(host->dbclk);
} }
mmc_free_host(host->mmc);
iounmap(host->base);
omap_hsmmc_gpio_free(pdev->dev.platform_data);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res) if (res)
release_mem_region(res->start, resource_size(res)); release_mem_region(res->start, resource_size(res));
...@@ -2078,49 +2073,45 @@ static int omap_hsmmc_remove(struct platform_device *pdev) ...@@ -2078,49 +2073,45 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
static int omap_hsmmc_suspend(struct device *dev) static int omap_hsmmc_suspend(struct device *dev)
{ {
int ret = 0; int ret = 0;
struct platform_device *pdev = to_platform_device(dev); struct omap_hsmmc_host *host = dev_get_drvdata(dev);
struct omap_hsmmc_host *host = platform_get_drvdata(pdev);
if (host && host->suspended) if (!host)
return 0; return 0;
if (host) { if (host && host->suspended)
pm_runtime_get_sync(host->dev); return 0;
host->suspended = 1;
if (host->pdata->suspend) {
ret = host->pdata->suspend(&pdev->dev,
host->slot_id);
if (ret) {
dev_dbg(mmc_dev(