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

Commit c8be24c2 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Chris Ball
Browse files

mmc: tmio_mmc: support the generic MMC GPIO card hotplug helper



If the platform specifies the TMIO_MMC_HAS_COLD_CD flag, use the generic
MMC GPIO card hotplug helper.

Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent 2b1ac5c2
Loading
Loading
Loading
Loading
+0 −4
Original line number Original line Diff line number Diff line
@@ -53,10 +53,6 @@ struct tmio_mmc_host {
	void (*set_pwr)(struct platform_device *host, int state);
	void (*set_pwr)(struct platform_device *host, int state);
	void (*set_clk_div)(struct platform_device *host, int state);
	void (*set_clk_div)(struct platform_device *host, int state);


	int			pm_error;
	/* recognise system-wide suspend in runtime PM methods */
	bool			pm_global;

	/* pio related stuff */
	/* pio related stuff */
	struct scatterlist      *sg_ptr;
	struct scatterlist      *sg_ptr;
	struct scatterlist      *sg_orig;
	struct scatterlist      *sg_orig;
+31 −38
Original line number Original line Diff line number Diff line
@@ -34,6 +34,7 @@
#include <linux/io.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irq.h>
#include <linux/mfd/tmio.h>
#include <linux/mfd/tmio.h>
#include <linux/mmc/cd-gpio.h>
#include <linux/mmc/host.h>
#include <linux/mmc/host.h>
#include <linux/mmc/tmio.h>
#include <linux/mmc/tmio.h>
#include <linux/module.h>
#include <linux/module.h>
@@ -791,8 +792,10 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
	spin_unlock_irqrestore(&host->lock, flags);
	spin_unlock_irqrestore(&host->lock, flags);


	/*
	/*
	 * pdata->power == false only if COLD_CD is available, otherwise only
	 * pdata->power toggles between false and true in both cases - either
	 * in short time intervals during probing or resuming
	 * or not the controller can be runtime-suspended during inactivity.
	 * But if the controller has to be kept on, the runtime-pm usage_count
	 * is kept positive, so no suspending actually takes place.
	 */
	 */
	if (ios->power_mode == MMC_POWER_ON && ios->clock) {
	if (ios->power_mode == MMC_POWER_ON && ios->clock) {
		if (!pdata->power) {
		if (!pdata->power) {
@@ -916,7 +919,7 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
	else
	else
		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;


	_host->native_hotplug = !(pdata->flags & TMIO_MMC_HAS_COLD_CD ||
	_host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
				  mmc->caps & MMC_CAP_NEEDS_POLL ||
				  mmc->caps & MMC_CAP_NEEDS_POLL ||
				  mmc->caps & MMC_CAP_NONREMOVABLE);
				  mmc->caps & MMC_CAP_NONREMOVABLE);


@@ -933,8 +936,9 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
	 *  3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL
	 *  3) a worker thread polls the sdhi - indicated by MMC_CAP_NEEDS_POLL
	 *  4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE
	 *  4) the medium is non-removable - indicated by MMC_CAP_NONREMOVABLE
	 *
	 *
	 *  While we increment the rtpm counter for all scenarios when the mmc
	 *  While we increment the runtime PM counter for all scenarios when
	 *  core activates us by calling an appropriate set_ios(), we must
	 *  the mmc core activates us by calling an appropriate set_ios(), we
	 *  must additionally ensure that in case 2) the tmio mmc hardware stays
	 *  additionally ensure that in case 2) the tmio mmc hardware stays
	 *  additionally ensure that in case 2) the tmio mmc hardware stays
	 *  powered on during runtime for the card detection to work.
	 *  powered on during runtime for the card detection to work.
	 */
	 */
@@ -973,6 +977,14 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,


	tmio_mmc_enable_mmc_irqs(_host, irq_mask);
	tmio_mmc_enable_mmc_irqs(_host, irq_mask);


	if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
		ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio);
		if (ret < 0) {
			tmio_mmc_host_remove(_host);
			return ret;
		}
	}

	*host = _host;
	*host = _host;


	return 0;
	return 0;
@@ -990,20 +1002,22 @@ EXPORT_SYMBOL(tmio_mmc_host_probe);
void tmio_mmc_host_remove(struct tmio_mmc_host *host)
void tmio_mmc_host_remove(struct tmio_mmc_host *host)
{
{
	struct platform_device *pdev = host->pdev;
	struct platform_device *pdev = host->pdev;
	struct tmio_mmc_data *pdata = host->pdata;
	struct mmc_host *mmc = host->mmc;


	if (pdata->flags & TMIO_MMC_USE_GPIO_CD)
		/*
		/*
	 * We don't have to manipulate pdata->power here: if there is a card in
		 * This means we can miss a card-eject, but this is anyway
	 * the slot, the runtime PM is active and our .runtime_resume() will not
		 * possible, because of delayed processing of hotplug events.
	 * be run. If there is no card in the slot and the platform can suspend
	 * the controller, the runtime PM is suspended and pdata->power == false,
	 * so, our .runtime_resume() will not try to detect a card in the slot.
		 */
		 */
		mmc_cd_gpio_free(mmc);

	if (!host->native_hotplug)
	if (!host->native_hotplug)
		pm_runtime_get_sync(&pdev->dev);
		pm_runtime_get_sync(&pdev->dev);


	dev_pm_qos_hide_latency_limit(&pdev->dev);
	dev_pm_qos_hide_latency_limit(&pdev->dev);


	mmc_remove_host(host->mmc);
	mmc_remove_host(mmc);
	cancel_work_sync(&host->done);
	cancel_work_sync(&host->done);
	cancel_delayed_work_sync(&host->delayed_reset_work);
	cancel_delayed_work_sync(&host->delayed_reset_work);
	tmio_mmc_release_dma(host);
	tmio_mmc_release_dma(host);
@@ -1012,7 +1026,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
	pm_runtime_disable(&pdev->dev);
	pm_runtime_disable(&pdev->dev);


	iounmap(host->ctl);
	iounmap(host->ctl);
	mmc_free_host(host->mmc);
	mmc_free_host(mmc);
}
}
EXPORT_SYMBOL(tmio_mmc_host_remove);
EXPORT_SYMBOL(tmio_mmc_host_remove);


@@ -1026,8 +1040,6 @@ int tmio_mmc_host_suspend(struct device *dev)
	if (!ret)
	if (!ret)
		tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL);
		tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL);


	host->pm_error = pm_runtime_put_sync(dev);

	return ret;
	return ret;
}
}
EXPORT_SYMBOL(tmio_mmc_host_suspend);
EXPORT_SYMBOL(tmio_mmc_host_suspend);
@@ -1037,20 +1049,10 @@ int tmio_mmc_host_resume(struct device *dev)
	struct mmc_host *mmc = dev_get_drvdata(dev);
	struct mmc_host *mmc = dev_get_drvdata(dev);
	struct tmio_mmc_host *host = mmc_priv(mmc);
	struct tmio_mmc_host *host = mmc_priv(mmc);


	/* The MMC core will perform the complete set up */
	host->pdata->power = false;

	host->pm_global = true;
	if (!host->pm_error)
		pm_runtime_get_sync(dev);

	if (host->pm_global) {
		/* Runtime PM resume callback didn't run */
	tmio_mmc_reset(host);
	tmio_mmc_reset(host);
	tmio_mmc_enable_dma(host, true);
	tmio_mmc_enable_dma(host, true);
		host->pm_global = false;
	}


	/* The MMC core will perform the complete set up */
	return mmc_resume_host(mmc);
	return mmc_resume_host(mmc);
}
}
EXPORT_SYMBOL(tmio_mmc_host_resume);
EXPORT_SYMBOL(tmio_mmc_host_resume);
@@ -1067,19 +1069,10 @@ int tmio_mmc_host_runtime_resume(struct device *dev)
{
{
	struct mmc_host *mmc = dev_get_drvdata(dev);
	struct mmc_host *mmc = dev_get_drvdata(dev);
	struct tmio_mmc_host *host = mmc_priv(mmc);
	struct tmio_mmc_host *host = mmc_priv(mmc);
	struct tmio_mmc_data *pdata = host->pdata;


	tmio_mmc_reset(host);
	tmio_mmc_reset(host);
	tmio_mmc_enable_dma(host, true);
	tmio_mmc_enable_dma(host, true);


	if (pdata->power) {
		/* Only entered after a card-insert interrupt */
		if (!mmc->card)
			tmio_mmc_set_ios(mmc, &mmc->ios);
		mmc_detect_change(mmc, msecs_to_jiffies(100));
	}
	host->pm_global = false;

	return 0;
	return 0;
}
}
EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
EXPORT_SYMBOL(tmio_mmc_host_runtime_resume);
+19 −6
Original line number Original line Diff line number Diff line
#ifndef MFD_TMIO_H
#ifndef MFD_TMIO_H
#define MFD_TMIO_H
#define MFD_TMIO_H


#include <linux/device.h>
#include <linux/fb.h>
#include <linux/fb.h>
#include <linux/io.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/pm_runtime.h>


@@ -64,8 +66,8 @@
#define TMIO_MMC_SDIO_IRQ		(1 << 2)
#define TMIO_MMC_SDIO_IRQ		(1 << 2)
/*
/*
 * Some platforms can detect card insertion events with controller powered
 * Some platforms can detect card insertion events with controller powered
 * down, in which case they have to call tmio_mmc_cd_wakeup() to power up the
 * down, using a GPIO IRQ, in which case they have to fill in cd_irq, cd_gpio,
 * controller and report the event to the driver.
 * and cd_flags fields of struct tmio_mmc_data.
 */
 */
#define TMIO_MMC_HAS_COLD_CD		(1 << 3)
#define TMIO_MMC_HAS_COLD_CD		(1 << 3)
/*
/*
@@ -73,6 +75,12 @@
 * idle before writing to some registers.
 * idle before writing to some registers.
 */
 */
#define TMIO_MMC_HAS_IDLE_WAIT		(1 << 4)
#define TMIO_MMC_HAS_IDLE_WAIT		(1 << 4)
/*
 * A GPIO is used for card hotplug detection. We need an extra flag for this,
 * because 0 is a valid GPIO number too, and requiring users to specify
 * cd_gpio < 0 to disable GPIO hotplug would break backwards compatibility.
 */
#define TMIO_MMC_USE_GPIO_CD		(1 << 5)


int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
@@ -98,18 +106,23 @@ struct tmio_mmc_data {
	struct tmio_mmc_dma		*dma;
	struct tmio_mmc_dma		*dma;
	struct device			*dev;
	struct device			*dev;
	bool				power;
	bool				power;
	unsigned int			cd_gpio;
	void (*set_pwr)(struct platform_device *host, int state);
	void (*set_pwr)(struct platform_device *host, int state);
	void (*set_clk_div)(struct platform_device *host, int state);
	void (*set_clk_div)(struct platform_device *host, int state);
	int (*get_cd)(struct platform_device *host);
	int (*get_cd)(struct platform_device *host);
	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
	int (*write16_hook)(struct tmio_mmc_host *host, int addr);
};
};


/*
 * This function is deprecated and will be removed soon. Please, convert your
 * platform to use drivers/mmc/core/cd-gpio.c
 */
#include <linux/mmc/host.h>
static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata)
static inline void tmio_mmc_cd_wakeup(struct tmio_mmc_data *pdata)
{
{
	if (pdata && !pdata->power) {
	if (pdata)
		pdata->power = true;
		mmc_detect_change(dev_get_drvdata(pdata->dev),
		pm_runtime_get(pdata->dev);
				  msecs_to_jiffies(100));
	}
}
}


/*
/*