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

Commit 79c36b07 authored by Subhash Jadavani's avatar Subhash Jadavani Committed by Ram Prakash Gupta
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>
Signed-off-by: default avatarRam Prakash Gupta <rampraka@codeaurora.org>
parent 1d45792c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3586,6 +3586,7 @@ void mmc_start_host(struct mmc_host *host)
	}

	mmc_gpiod_request_cd_irq(host);
	mmc_register_extcon(host);
	_mmc_detect_change(host, 0, false);
}

@@ -3615,6 +3616,7 @@ void mmc_stop_host(struct mmc_host *host)
	}
	mmc_bus_put(host);

	mmc_unregister_extcon(host);
	mmc_claim_host(host);
	mmc_power_off(host);
	mmc_release_host(host);
+49 −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"

@@ -162,6 +163,54 @@ 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);


int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on)
{
	int ret = 0;
+2 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ config MMC_SDHCI_ACPI
config MMC_SDHCI_PLTFM
	tristate "SDHCI platform and OF driver helper"
	depends on MMC_SDHCI
	select EXTCON
	select EXTCON_GPIO
	help
	  This selects the common helper functions support for Secure Digital
	  Host Controller Interface based platform and OF drivers.
+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;
+2 −0
Original line number Diff line number Diff line
@@ -35,5 +35,7 @@ int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on);
void mmc_gpiod_request_cd_irq(struct mmc_host *host);
bool mmc_can_gpio_cd(struct mmc_host *host);
bool mmc_can_gpio_ro(struct mmc_host *host);
void mmc_register_extcon(struct mmc_host *host);
void mmc_unregister_extcon(struct mmc_host *host);

#endif