Skip to content

Commit

Permalink
Merge tag 'mmc-v4.5' of git://git.linaro.org/people/ulf.hansson/mmc
Browse files Browse the repository at this point in the history
Pull MMC updates from Ulf Hansson:
 "MMC core:
   - Optimize boot time by detecting cards simultaneously
   - Make runtime resume default behavior for MMC/SD
   - Enable MMC/SD/SDIO devices to suspend/resume asynchronously
   - Allow more than 8 partitions per card
   - Introduce MMC_CAP2_NO_SDIO to prevent unsupported SDIO commands
   - Support the standard DT wakeup-source property
   - Fix driver strength switching for HS200 and HS400
   - Fix switch command timeout
   - Fix invalid vdd in voltage switch power cycle for SDIO

  MMC host:
   - sdhci: Restore behavior when setting VDD via external regulator
   - sdhci: A couple of changes/fixes related to the dma support
   - sdhci-tegra: Add Tegra210 support
   - sdhci-tegra: Support for UHS-I cards including tuning support
   - sdhci-of-at91: Add PM support
   - sh_mmcif: Rework dma channel handling
   - mvsdio: Delete platform data code path"

* tag 'mmc-v4.5' of git://git.linaro.org/people/ulf.hansson/mmc: (52 commits)
  mmc: dw_mmc: remove the unused quirks
  mmc: sdhci-pci: use to_pci_dev()
  mmc: cb710: use to_platform_device()
  mmc: tegra: use correct accessor for misc ctrl register
  mmc: tegra: enable UHS-I modes
  mmc: tegra: implement UHS tuning
  mmc: tegra: disable SPI_MODE_CLKEN
  mmc: tegra: implement module external clock change
  mmc: sdhci: restore behavior when setting VDD via external regulator
  mmc: It is not an error for the card to be removed while suspended
  mmc: block: Allow more than 8 partitions per card
  mmc: core: Optimize boot time by detecting cards simultaneously
  mmc: dw_mmc: use resource_size_t to store physical address
  mmc: core: fix __mmc_switch timeout caused by preempt
  mmc: usdhi6rol0: handle NULL data in timeout
  mmc: of_mmc_spi: Add IRQF_ONESHOT to interrupt flags
  mmc: mediatek: change some dev_err to dev_dbg
  mmc: enable MMC/SD/SDIO device to suspend/resume asynchronously
  mmc: sdhci: Fix sdhci_runtime_pm_bus_on/off()
  mmc: sdhci: 64-bit DMA actually has 4-byte alignment
  ...
  • Loading branch information
torvalds committed Jan 12, 2016
2 parents 8c93020 + 01a999e commit fb591fb
Show file tree
Hide file tree
Showing 40 changed files with 626 additions and 549 deletions.
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/mmc/renesas,mmcif.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Required properties:
- "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs
- "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs
- "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs
- "renesas,mmcif-r8a7793" for the MMCIF found in r8a7793 SoCs
- "renesas,mmcif-r8a7794" for the MMCIF found in r8a7794 SoCs

- clocks: reference to the functional clock
Expand Down
1 change: 0 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -1896,7 +1896,6 @@ ATMEL AT91 / AT32 MCI DRIVER
M: Ludovic Desroches <[email protected]>
S: Maintained
F: drivers/mmc/host/atmel-mci.c
F: drivers/mmc/host/atmel-mci-regs.h

ATMEL AT91 / AT32 SERIAL DRIVER
M: Nicolas Ferre <[email protected]>
Expand Down
11 changes: 4 additions & 7 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,7 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)

static inline int mmc_get_devidx(struct gendisk *disk)
{
int devmaj = MAJOR(disk_devt(disk));
int devidx = MINOR(disk_devt(disk)) / perdev_minors;

if (!devmaj)
devidx = disk->first_minor / perdev_minors;
int devidx = disk->first_minor / perdev_minors;
return devidx;
}

Expand Down Expand Up @@ -344,7 +340,7 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
struct mmc_blk_ioc_data *idata;
int err;

idata = kzalloc(sizeof(*idata), GFP_KERNEL);
idata = kmalloc(sizeof(*idata), GFP_KERNEL);
if (!idata) {
err = -ENOMEM;
goto out;
Expand All @@ -364,7 +360,7 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
if (!idata->buf_bytes)
return idata;

idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
idata->buf = kmalloc(idata->buf_bytes, GFP_KERNEL);
if (!idata->buf) {
err = -ENOMEM;
goto idata_err;
Expand Down Expand Up @@ -2244,6 +2240,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
md->disk->queue = md->queue.queue;
md->disk->driverfs_dev = parent;
set_disk_ro(md->disk, md->read_only || default_ro);
md->disk->flags = GENHD_FL_EXT_DEVT;
if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT))
md->disk->flags |= GENHD_FL_NO_PART_SCAN;

Expand Down
2 changes: 2 additions & 0 deletions drivers/mmc/core/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ int mmc_add_card(struct mmc_card *card)

card->dev.of_node = mmc_of_find_child_device(card->host, 0);

device_enable_async_suspend(&card->dev);

ret = device_add(&card->dev);
if (ret)
return ret;
Expand Down
85 changes: 43 additions & 42 deletions drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
*/
#define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */

static struct workqueue_struct *workqueue;
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };

/*
Expand All @@ -66,21 +65,16 @@ static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
bool use_spi_crc = 1;
module_param(use_spi_crc, bool, 0);

/*
* Internal function. Schedule delayed work in the MMC work queue.
*/
static int mmc_schedule_delayed_work(struct delayed_work *work,
unsigned long delay)
{
return queue_delayed_work(workqueue, work, delay);
}

/*
* Internal function. Flush all scheduled work from the MMC work queue.
*/
static void mmc_flush_scheduled_work(void)
{
flush_workqueue(workqueue);
/*
* We use the system_freezable_wq, because of two reasons.
* First, it allows several works (not the same work item) to be
* executed simultaneously. Second, the queue becomes frozen when
* userspace becomes frozen during system PM.
*/
return queue_delayed_work(system_freezable_wq, work, delay);
}

#ifdef CONFIG_FAIL_MMC_REQUEST
Expand Down Expand Up @@ -1485,7 +1479,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
if (IS_ERR(mmc->supply.vmmc)) {
if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "No vmmc regulator found\n");
dev_dbg(dev, "No vmmc regulator found\n");
} else {
ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
if (ret > 0)
Expand All @@ -1497,7 +1491,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
if (IS_ERR(mmc->supply.vqmmc)) {
if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
dev_info(dev, "No vqmmc regulator found\n");
dev_dbg(dev, "No vqmmc regulator found\n");
}

return 0;
Expand Down Expand Up @@ -2476,15 +2470,20 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
* sdio_reset sends CMD52 to reset card. Since we do not know
* if the card is being re-initialized, just send it. CMD52
* should be ignored by SD/eMMC cards.
* Skip it if we already know that we do not support SDIO commands
*/
sdio_reset(host);
if (!(host->caps2 & MMC_CAP2_NO_SDIO))
sdio_reset(host);

mmc_go_idle(host);

mmc_send_if_cond(host, host->ocr_avail);

/* Order's important: probe SDIO, then SD, then MMC */
if (!mmc_attach_sdio(host))
return 0;
if (!(host->caps2 & MMC_CAP2_NO_SDIO))
if (!mmc_attach_sdio(host))
return 0;

if (!mmc_attach_sd(host))
return 0;
if (!mmc_attach_mmc(host))
Expand All @@ -2498,9 +2497,6 @@ int _mmc_detect_card_removed(struct mmc_host *host)
{
int ret;

if (host->caps & MMC_CAP_NONREMOVABLE)
return 0;

if (!host->card || mmc_card_removed(host->card))
return 1;

Expand Down Expand Up @@ -2536,6 +2532,9 @@ int mmc_detect_card_removed(struct mmc_host *host)
if (!card)
return 1;

if (host->caps & MMC_CAP_NONREMOVABLE)
return 0;

ret = mmc_card_removed(card);
/*
* The card will be considered unchanged unless we have been asked to
Expand Down Expand Up @@ -2567,11 +2566,6 @@ void mmc_rescan(struct work_struct *work)
container_of(work, struct mmc_host, detect.work);
int i;

if (host->trigger_card_event && host->ops->card_event) {
host->ops->card_event(host);
host->trigger_card_event = false;
}

if (host->rescan_disable)
return;

Expand All @@ -2580,6 +2574,13 @@ void mmc_rescan(struct work_struct *work)
return;
host->rescan_entered = 1;

if (host->trigger_card_event && host->ops->card_event) {
mmc_claim_host(host);
host->ops->card_event(host);
mmc_release_host(host);
host->trigger_card_event = false;
}

mmc_bus_get(host);

/*
Expand Down Expand Up @@ -2611,15 +2612,14 @@ void mmc_rescan(struct work_struct *work)
*/
mmc_bus_put(host);

mmc_claim_host(host);
if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->get_cd &&
host->ops->get_cd(host) == 0) {
mmc_claim_host(host);
mmc_power_off(host);
mmc_release_host(host);
goto out;
}

mmc_claim_host(host);
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
break;
Expand Down Expand Up @@ -2663,7 +2663,6 @@ void mmc_stop_host(struct mmc_host *host)

host->rescan_disable = 1;
cancel_delayed_work_sync(&host->detect);
mmc_flush_scheduled_work();

/* clear pm flags now and let card drivers set them as needed */
host->pm_flags = 0;
Expand Down Expand Up @@ -2759,14 +2758,13 @@ int mmc_flush_cache(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_flush_cache);

#ifdef CONFIG_PM

#ifdef CONFIG_PM_SLEEP
/* Do the card removal on suspend if card is assumed removeable
* Do that in pm notifier while userspace isn't yet frozen, so we will be able
to sync the card.
*/
int mmc_pm_notify(struct notifier_block *notify_block,
unsigned long mode, void *unused)
static int mmc_pm_notify(struct notifier_block *notify_block,
unsigned long mode, void *unused)
{
struct mmc_host *host = container_of(
notify_block, struct mmc_host, pm_notify);
Expand Down Expand Up @@ -2813,6 +2811,17 @@ int mmc_pm_notify(struct notifier_block *notify_block,

return 0;
}

void mmc_register_pm_notifier(struct mmc_host *host)
{
host->pm_notify.notifier_call = mmc_pm_notify;
register_pm_notifier(&host->pm_notify);
}

void mmc_unregister_pm_notifier(struct mmc_host *host)
{
unregister_pm_notifier(&host->pm_notify);
}
#endif

/**
Expand All @@ -2836,13 +2845,9 @@ static int __init mmc_init(void)
{
int ret;

workqueue = alloc_ordered_workqueue("kmmcd", 0);
if (!workqueue)
return -ENOMEM;

ret = mmc_register_bus();
if (ret)
goto destroy_workqueue;
return ret;

ret = mmc_register_host_class();
if (ret)
Expand All @@ -2858,9 +2863,6 @@ static int __init mmc_init(void)
mmc_unregister_host_class();
unregister_bus:
mmc_unregister_bus();
destroy_workqueue:
destroy_workqueue(workqueue);

return ret;
}

Expand All @@ -2869,7 +2871,6 @@ static void __exit mmc_exit(void)
sdio_unregister_bus();
mmc_unregister_host_class();
mmc_unregister_bus();
destroy_workqueue(workqueue);
}

subsys_initcall(mmc_init);
Expand Down
8 changes: 8 additions & 0 deletions drivers/mmc/core/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,13 @@ int mmc_execute_tuning(struct mmc_card *card);
int mmc_hs200_to_hs400(struct mmc_card *card);
int mmc_hs400_to_hs200(struct mmc_card *card);

#ifdef CONFIG_PM_SLEEP
void mmc_register_pm_notifier(struct mmc_host *host);
void mmc_unregister_pm_notifier(struct mmc_host *host);
#else
static inline void mmc_register_pm_notifier(struct mmc_host *host) { }
static inline void mmc_unregister_pm_notifier(struct mmc_host *host) { }
#endif

#endif

11 changes: 4 additions & 7 deletions drivers/mmc/core/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
#include <linux/export.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/suspend.h>

#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
Expand Down Expand Up @@ -275,7 +274,8 @@ int mmc_of_parse(struct mmc_host *host)
host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
if (of_property_read_bool(np, "keep-power-in-suspend"))
host->pm_caps |= MMC_PM_KEEP_POWER;
if (of_property_read_bool(np, "enable-sdio-wakeup"))
if (of_property_read_bool(np, "wakeup-source") ||
of_property_read_bool(np, "enable-sdio-wakeup")) /* legacy */
host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
if (of_property_read_bool(np, "mmc-ddr-1_8v"))
host->caps |= MMC_CAP_1_8V_DDR;
Expand Down Expand Up @@ -348,9 +348,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
#ifdef CONFIG_PM
host->pm_notify.notifier_call = mmc_pm_notify;
#endif
setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);

/*
Expand Down Expand Up @@ -395,7 +392,7 @@ int mmc_add_host(struct mmc_host *host)
#endif

mmc_start_host(host);
register_pm_notifier(&host->pm_notify);
mmc_register_pm_notifier(host);

return 0;
}
Expand All @@ -412,7 +409,7 @@ EXPORT_SYMBOL(mmc_add_host);
*/
void mmc_remove_host(struct mmc_host *host)
{
unregister_pm_notifier(&host->pm_notify);
mmc_unregister_pm_notifier(host);
mmc_stop_host(host);

#ifdef CONFIG_DEBUG_FS
Expand Down
23 changes: 5 additions & 18 deletions drivers/mmc/core/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1076,8 +1076,7 @@ static int mmc_select_hs400(struct mmc_card *card)
mmc_set_clock(host, max_dtr);

/* Switch card to HS mode */
val = EXT_CSD_TIMING_HS |
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
Expand Down Expand Up @@ -1160,8 +1159,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
mmc_set_clock(host, max_dtr);

/* Switch HS400 to HS DDR */
val = EXT_CSD_TIMING_HS |
card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
val, card->ext_csd.generic_cmd6_time,
true, send_status, true);
Expand Down Expand Up @@ -1907,16 +1905,8 @@ static int mmc_shutdown(struct mmc_host *host)
*/
static int mmc_resume(struct mmc_host *host)
{
int err = 0;

if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
err = _mmc_resume(host);
pm_runtime_set_active(&host->card->dev);
pm_runtime_mark_last_busy(&host->card->dev);
}
pm_runtime_enable(&host->card->dev);

return err;
return 0;
}

/*
Expand Down Expand Up @@ -1944,12 +1934,9 @@ static int mmc_runtime_resume(struct mmc_host *host)
{
int err;

if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
return 0;

err = _mmc_resume(host);
if (err)
pr_err("%s: error %d doing aggressive resume\n",
if (err && err != -ENOMEDIUM)
pr_err("%s: error %d doing runtime resume\n",
mmc_hostname(host), err);

return 0;
Expand Down
Loading

0 comments on commit fb591fb

Please sign in to comment.