Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/cjb/mmc

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc:
  mmc: sdhci: 8-bit bus width changes
  mmc: sdio: fix runtime PM anomalies by introducing MMC_CAP_POWER_OFF_CARD
  mmc: sdio: fix nasty oops in mmc_sdio_detect
  mmc: omap4: hsmmc: Fix improper card detection while booting
  mmc: fix rmmod race for hosts using card-detection polling
  mmc: sdhci: Fix crash on boot with C0 stepping Moorestown platforms
  mmc: sdhci-esdhc-imx: enable QUIRK_NO_MULTIBLOCK only for i.MX25 and i.MX35
  mmc: sdhci-esdhc-imx: fix timeout on i.MX's sdhci
  mmc: sdhci: Properly enable SDIO IRQ wakeups
  mmc: ushc: Return proper error code for ushc_probe()
  mmc: Fix printing of card DDR type
  • Loading branch information
Linus Torvalds committed Nov 26, 2010
2 parents b127c6f + 15ec446 commit 5c3b9ba
Show file tree
Hide file tree
Showing 14 changed files with 179 additions and 62 deletions.
3 changes: 3 additions & 0 deletions arch/arm/plat-pxa/include/plat/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
/* Require clock free running */
#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)

/* Board design supports 8-bit data on SD/SDIO BUS */
#define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2)

/*
* struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
* @max_speed: the maximum speed supported
Expand Down
2 changes: 1 addition & 1 deletion drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1559,7 +1559,7 @@ void mmc_stop_host(struct mmc_host *host)

if (host->caps & MMC_CAP_DISABLE)
cancel_delayed_work(&host->disable);
cancel_delayed_work(&host->detect);
cancel_delayed_work_sync(&host->detect);
mmc_flush_scheduled_work();

/* clear pm flags now and let card drivers set them as needed */
Expand Down
8 changes: 6 additions & 2 deletions drivers/mmc/core/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
{
struct mmc_card *card;
int err, ddr = MMC_SDR_MODE;
int err, ddr = 0;
u32 cid[4];
unsigned int max_dtr;

Expand Down Expand Up @@ -562,7 +562,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
1 << bus_width, ddr);
err = 0;
} else {
mmc_card_set_ddr_mode(card);
if (ddr)
mmc_card_set_ddr_mode(card);
else
ddr = MMC_SDR_MODE;

mmc_set_bus_width_ddr(card->host, bus_width, ddr);
}
}
Expand Down
51 changes: 35 additions & 16 deletions drivers/mmc/core/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,9 +547,11 @@ static void mmc_sdio_detect(struct mmc_host *host)
BUG_ON(!host->card);

/* Make sure card is powered before detecting it */
err = pm_runtime_get_sync(&host->card->dev);
if (err < 0)
goto out;
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
err = pm_runtime_get_sync(&host->card->dev);
if (err < 0)
goto out;
}

mmc_claim_host(host);

Expand All @@ -560,6 +562,20 @@ static void mmc_sdio_detect(struct mmc_host *host)

mmc_release_host(host);

/*
* Tell PM core it's OK to power off the card now.
*
* The _sync variant is used in order to ensure that the card
* is left powered off in case an error occurred, and the card
* is going to be removed.
*
* Since there is no specific reason to believe a new user
* is about to show up at this point, the _sync variant is
* desirable anyway.
*/
if (host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_sync(&host->card->dev);

out:
if (err) {
mmc_sdio_remove(host);
Expand All @@ -568,9 +584,6 @@ static void mmc_sdio_detect(struct mmc_host *host)
mmc_detach_bus(host);
mmc_release_host(host);
}

/* Tell PM core that we're done */
pm_runtime_put(&host->card->dev);
}

/*
Expand Down Expand Up @@ -718,16 +731,21 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
card = host->card;

/*
* Let runtime PM core know our card is active
* Enable runtime PM only if supported by host+card+board
*/
err = pm_runtime_set_active(&card->dev);
if (err)
goto remove;
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
/*
* Let runtime PM core know our card is active
*/
err = pm_runtime_set_active(&card->dev);
if (err)
goto remove;

/*
* Enable runtime PM for this card
*/
pm_runtime_enable(&card->dev);
/*
* Enable runtime PM for this card
*/
pm_runtime_enable(&card->dev);
}

/*
* The number of functions on the card is encoded inside
Expand All @@ -745,9 +763,10 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
goto remove;

/*
* Enable Runtime PM for this func
* Enable Runtime PM for this func (if supported)
*/
pm_runtime_enable(&card->sdio_func[i]->dev);
if (host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_enable(&card->sdio_func[i]->dev);
}

mmc_release_host(host);
Expand Down
33 changes: 22 additions & 11 deletions drivers/mmc/core/sdio_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/pm_runtime.h>

#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdio_func.h>

#include "sdio_cis.h"
Expand Down Expand Up @@ -132,9 +133,11 @@ static int sdio_bus_probe(struct device *dev)
* it should call pm_runtime_put_noidle() in its probe routine and
* pm_runtime_get_noresume() in its remove routine.
*/
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto out;
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto out;
}

/* Set the default block size so the driver is sure it's something
* sensible. */
Expand All @@ -151,7 +154,8 @@ static int sdio_bus_probe(struct device *dev)
return 0;

disable_runtimepm:
pm_runtime_put_noidle(dev);
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_noidle(dev);
out:
return ret;
}
Expand All @@ -160,12 +164,14 @@ static int sdio_bus_remove(struct device *dev)
{
struct sdio_driver *drv = to_sdio_driver(dev->driver);
struct sdio_func *func = dev_to_sdio_func(dev);
int ret;
int ret = 0;

/* Make sure card is powered before invoking ->remove() */
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto out;
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
ret = pm_runtime_get_sync(dev);
if (ret < 0)
goto out;
}

drv->remove(func);

Expand All @@ -178,10 +184,12 @@ static int sdio_bus_remove(struct device *dev)
}

/* First, undo the increment made directly above */
pm_runtime_put_noidle(dev);
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_noidle(dev);

/* Then undo the runtime PM settings in sdio_bus_probe() */
pm_runtime_put_noidle(dev);
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_put_noidle(dev);

out:
return ret;
Expand All @@ -191,6 +199,8 @@ static int sdio_bus_remove(struct device *dev)

static int sdio_bus_pm_prepare(struct device *dev)
{
struct sdio_func *func = dev_to_sdio_func(dev);

/*
* Resume an SDIO device which was suspended at run time at this
* point, in order to allow standard SDIO suspend/resume paths
Expand All @@ -212,7 +222,8 @@ static int sdio_bus_pm_prepare(struct device *dev)
* since there is little point in failing system suspend if a
* device can't be resumed.
*/
pm_runtime_resume(dev);
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
pm_runtime_resume(dev);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/mmc/host/omap_hsmmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
* Monitor a 0->1 transition first
*/
if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {
while ((!(OMAP_HSMMC_READ(host, SYSCTL) & bit))
while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
&& (i++ < limit))
cpu_relax();
}
Expand Down
12 changes: 9 additions & 3 deletions drivers/mmc/host/sdhci-esdhc-imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/clk.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sdhci-pltfm.h>
#include <mach/hardware.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
#include "sdhci-esdhc.h"
Expand Down Expand Up @@ -112,6 +113,13 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
clk_enable(clk);
pltfm_host->clk = clk;

if (cpu_is_mx35() || cpu_is_mx51())
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;

/* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
if (cpu_is_mx25() || cpu_is_mx35())
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;

return 0;
}

Expand All @@ -133,10 +141,8 @@ static struct sdhci_ops sdhci_esdhc_ops = {
};

struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_MULTIBLOCK
| SDHCI_QUIRK_BROKEN_ADMA,
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
/* ADMA has issues. Might be fixable */
/* NO_MULTIBLOCK might be MX35 only (Errata: ENGcm07207) */
.ops = &sdhci_esdhc_ops,
.init = esdhc_pltfm_init,
.exit = esdhc_pltfm_exit,
Expand Down
31 changes: 23 additions & 8 deletions drivers/mmc/host/sdhci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,11 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
* ADMA operation is disabled for Moorestown platform due to
* hardware bugs.
*/
static int mrst_hc1_probe(struct sdhci_pci_chip *chip)
static int mrst_hc_probe(struct sdhci_pci_chip *chip)
{
/*
* slots number is fixed here for MRST as SDIO3 is never used and has
* hardware bugs.
* slots number is fixed here for MRST as SDIO3/5 are never used and
* have hardware bugs.
*/
chip->num_slots = 1;
return 0;
Expand All @@ -163,9 +163,9 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
.quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
};

static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1 = {
static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
.quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
.probe = mrst_hc1_probe,
.probe = mrst_hc_probe,
};

static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
Expand Down Expand Up @@ -538,7 +538,15 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
.device = PCI_DEVICE_ID_INTEL_MRST_SD1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc1,
.driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc1_hc2,
},

{
.vendor = PCI_VENDOR_ID_INTEL,
.device = PCI_DEVICE_ID_INTEL_MRST_SD2,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc1_hc2,
},

{
Expand Down Expand Up @@ -637,6 +645,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct sdhci_pci_chip *chip;
struct sdhci_pci_slot *slot;
mmc_pm_flag_t slot_pm_flags;
mmc_pm_flag_t pm_flags = 0;
int i, ret;

Expand All @@ -657,7 +666,11 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
return ret;
}

pm_flags |= slot->host->mmc->pm_flags;
slot_pm_flags = slot->host->mmc->pm_flags;
if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ)
sdhci_enable_irq_wakeups(slot->host);

pm_flags |= slot_pm_flags;
}

if (chip->fixes && chip->fixes->suspend) {
Expand All @@ -671,8 +684,10 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)

pci_save_state(pdev);
if (pm_flags & MMC_PM_KEEP_POWER) {
if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
pci_pme_active(pdev, true);
pci_enable_wake(pdev, PCI_D3hot, 1);
}
pci_set_power_state(pdev, PCI_D3hot);
} else {
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
Expand Down
4 changes: 4 additions & 0 deletions drivers/mmc/host/sdhci-pxa.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
if (pdata->quirks)
host->quirks |= pdata->quirks;

/* If slot design supports 8 bit data, indicate this to MMC. */
if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
host->mmc->caps |= MMC_CAP_8_BIT_DATA;

ret = sdhci_add_host(host);
if (ret) {
dev_err(&pdev->dev, "failed to add host\n");
Expand Down
Loading

0 comments on commit 5c3b9ba

Please sign in to comment.