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

Commit 083d5e24 authored by Subhash Jadavani's avatar Subhash Jadavani
Browse files

mmc: add hot plug support using extcon framework



We need to add the support for gpio based card insertion/removal event
detection support. But this is bit complicated as current platforms have
the combo card slot which can either take SD or UFS card at one time and
there is a single GPIO assigned for card detect event. This means we need
some module which takes the responsibility of controlling (configuration,
interrupt handling) this shared card detection GPIO and pass card detection
event to both MMC and UFS card drivers so they can probe to see what card
is inserted. Kernel already have the extcon-gpio module which can be used
a gpio control module and can pass the card detection event to both MMC &
UFS card drivers. So MMC driver registers the notification callback with
extcon driver and tries to detect/remove the SD card.

Change-Id: I860827272bfaa24116d9550a331657b99f53ec50
Signed-off-by: default avatarSubhash Jadavani <subhashj@codeaurora.org>
parent e5371bdd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ Optional properties:
- no-sdio: controller is limited to send sdio cmd during initialization
- no-sd: controller is limited to send sd cmd during initialization
- no-mmc: controller is limited to send mmc cmd during initialization
- extcon: phandle to external connector (Refer Documentation/devicetree/bindings/extcon/extcon-gpio.txt for more details).

*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted"
+3 −0
Original line number Diff line number Diff line
@@ -4321,6 +4321,7 @@ void mmc_start_host(struct mmc_host *host)
		mmc_power_up(host, host->ocr_avail);

	mmc_gpiod_request_cd_irq(host);
	mmc_register_extcon(host);
	mmc_release_host(host);
	_mmc_detect_change(host, 0, false);
}
@@ -4357,6 +4358,8 @@ void mmc_stop_host(struct mmc_host *host)

	BUG_ON(host->card);

	mmc_register_extcon(host);

	mmc_claim_host(host);
	mmc_power_off(host);
	mmc_release_host(host);
+48 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/extcon.h>

#include "slot-gpio.h"

@@ -154,6 +155,53 @@ void mmc_gpiod_request_cd_irq(struct mmc_host *host)
}
EXPORT_SYMBOL(mmc_gpiod_request_cd_irq);

static int mmc_card_detect_notifier(struct notifier_block *nb,
				       unsigned long event, void *ptr)
{
	struct mmc_host *host = container_of(nb, struct mmc_host,
					     card_detect_nb);

	host->trigger_card_event = true;
	mmc_detect_change(host, 0);

	return NOTIFY_DONE;
}

void mmc_register_extcon(struct mmc_host *host)
{
	struct extcon_dev *extcon = host->extcon;
	int err;

	if (!extcon)
		return;

	host->card_detect_nb.notifier_call = mmc_card_detect_notifier;
	err = extcon_register_notifier(extcon, EXTCON_MECHANICAL,
				       &host->card_detect_nb);
	if (err) {
		dev_err(mmc_dev(host), "%s: extcon_register_notifier() failed ret=%d\n",
			__func__, err);
		host->caps |= MMC_CAP_NEEDS_POLL;
	}
}
EXPORT_SYMBOL(mmc_register_extcon);

void mmc_unregister_extcon(struct mmc_host *host)
{
	struct extcon_dev *extcon = host->extcon;
	int err;

	if (!extcon)
		return;

	err = extcon_unregister_notifier(extcon, EXTCON_MECHANICAL,
					 &host->card_detect_nb);
	if (err)
		dev_err(mmc_dev(host), "%s: extcon_unregister_notifier() failed ret=%d\n",
			__func__, err);
}
EXPORT_SYMBOL(mmc_unregister_extcon);

/* Register an alternate interrupt service routine for
 * the card-detect GPIO.
 */
+2 −0
Original line number Diff line number Diff line
@@ -401,6 +401,8 @@ config MMC_SDHCI_MSM
	depends on MMC_SDHCI_PLTFM
	select PM_DEVFREQ
	select DEVFREQ_GOV_SIMPLE_ONDEMAND
	select EXTCON
	select EXTCON_GPIO
	help
	  This selects the Secure Digital Host Controller Interface (SDHCI)
	  support present in Qualcomm Technologies, Inc. SOCs. The controller
+10 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
	struct resource *iomem;
	void __iomem *ioaddr;
	int irq, ret;
	struct extcon_dev *extcon;

	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
@@ -156,6 +157,15 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
		host->quirks2 = pdata->quirks2;
	}

	extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
	if (IS_ERR(extcon) && PTR_ERR(extcon) != -ENODEV) {
		ret = PTR_ERR(extcon);
		goto err;
	}
	if (!IS_ERR(extcon))
		host->mmc->extcon = extcon;


	platform_set_drvdata(pdev, host);

	return host;
Loading