Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb591fbd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents 8c930204 01a999e4
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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
+0 −1
Original line number Diff line number Diff line
@@ -1896,7 +1896,6 @@ ATMEL AT91 / AT32 MCI DRIVER
M:	Ludovic Desroches <ludovic.desroches@atmel.com>
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 <nicolas.ferre@atmel.com>
+4 −7
Original line number Diff line number Diff line
@@ -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;
}

@@ -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;
@@ -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;
@@ -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;

+2 −0
Original line number Diff line number Diff line
@@ -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;
+43 −42
Original line number Diff line number Diff line
@@ -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 };

/*
@@ -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.
	 * 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.
	 */
static void mmc_flush_scheduled_work(void)
{
	flush_workqueue(workqueue);
	return queue_delayed_work(system_freezable_wq, work, delay);
}

#ifdef CONFIG_FAIL_MMC_REQUEST
@@ -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)
@@ -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;
@@ -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
	 */
	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 (!(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))
@@ -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;

@@ -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
@@ -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;

@@ -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);

	/*
@@ -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;
@@ -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;
@@ -2759,13 +2758,12 @@ 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,
static int mmc_pm_notify(struct notifier_block *notify_block,
			unsigned long mode, void *unused)
{
	struct mmc_host *host = container_of(
@@ -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

/**
@@ -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)
@@ -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;
}

@@ -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);
Loading