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

Commit d37e89ef authored by Veerabhadrarao Badiganti's avatar Veerabhadrarao Badiganti Committed by Ram Prakash Gupta
Browse files

mmc: core: Update SD card removal logic based on cd gpio state



Update SD card removal event processing logic. Instead of pinging
the card to know the card presence rely on card-detect gpio state.

On multi-card tray designs, the same card-tray would be used for SD
card and SIM cards. If SD card is placed at the rightmost location
in the tray, then SIM card may come in contact with SD card power-
supply while removing the tray. It may result in SIM damage.

For protecting SIM from this issue, in multi-card tray designs,
a h/w fix done such that pmic gets a notification of SD card
removal event (through hardwiring) and it turns off the SD card
voltage regulators immediately. All this will be done much before SD
card driver starts processing card removal event.

To support this design, SD card driver shouldn't turn-on the
regulator while processing card removal event. But the present mmc
driver turns-on regulator (multiple times if the card was in suspend
state). To avoid turning on SD card regulator in card removal path,
updating the card removal processing logic is based on card detect
gpio state.

Change-Id: I13708a60c9378519713ebec8071ae3b130012a93
Signed-off-by: default avatarVeerabhadrarao Badiganti <vbadigan@codeaurora.org>
parent b76f4279
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -3002,9 +3002,7 @@ static int mmc_blk_probe(struct mmc_card *card)

	dev_set_drvdata(&card->dev, md);

#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
	mmc_set_bus_resume_policy(card->host, 1);
#endif
	if (mmc_add_disk(md))
		goto out;

@@ -3053,9 +3051,7 @@ static void mmc_blk_remove(struct mmc_card *card)
	pm_runtime_put_noidle(&card->dev);
	mmc_blk_remove_req(md);
	dev_set_drvdata(&card->dev, NULL);
#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
	mmc_set_bus_resume_policy(card->host, 0);
#endif
	destroy_workqueue(card->complete_wq);
}

+13 −7
Original line number Diff line number Diff line
@@ -1496,10 +1496,9 @@ EXPORT_SYMBOL(mmc_is_req_done);
 */
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
	if (mmc_bus_needs_resume(host))
		mmc_resume_bus(host);
#endif

	__mmc_start_req(host, mrq);

	if (!mrq->cap_cmd_during_tfr)
@@ -1789,10 +1788,9 @@ void mmc_get_card(struct mmc_card *card, struct mmc_ctx *ctx)
{
	pm_runtime_get_sync(&card->dev);
	__mmc_claim_host(card->host, ctx, NULL);
#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME

	if (mmc_bus_needs_resume(card->host))
		mmc_resume_bus(card->host);
#endif
}

EXPORT_SYMBOL(mmc_get_card);
@@ -2658,6 +2656,7 @@ int mmc_resume_bus(struct mmc_host *host)
{
	unsigned long flags;
	int err = 0;
	int card_present = true;

	if (!mmc_bus_needs_resume(host))
		return -EINVAL;
@@ -2668,7 +2667,10 @@ int mmc_resume_bus(struct mmc_host *host)
	spin_unlock_irqrestore(&host->lock, flags);

	mmc_bus_get(host);
	if (host->bus_ops && !host->bus_dead && host->card) {
	if (host->ops->get_cd)
		card_present = host->ops->get_cd(host);

	if (host->bus_ops && !host->bus_dead && host->card && card_present) {
		mmc_power_up(host, host->card->ocr);
		BUG_ON(!host->bus_ops->deferred_resume);
		err = host->bus_ops->deferred_resume(host);
@@ -3717,7 +3719,7 @@ static int mmc_pm_notify(struct notifier_block *notify_block,
	struct mmc_host *host = container_of(
		notify_block, struct mmc_host, pm_notify);
	unsigned long flags;
	int err = 0;
	int err = 0, present = 0;

	switch (mode) {
	case PM_HIBERNATION_PREPARE:
@@ -3760,8 +3762,12 @@ static int mmc_pm_notify(struct notifier_block *notify_block,

		spin_lock_irqsave(&host->lock, flags);
		host->rescan_disable = 0;
		if (host->ops->get_cd)
			present = host->ops->get_cd(host);

		if (mmc_bus_manual_resume(host) &&
				!host->ignore_bus_resume_flags) {
				!host->ignore_bus_resume_flags &&
				present) {
			spin_unlock_irqrestore(&host->lock, flags);
			break;
		}
+19 −0
Original line number Diff line number Diff line
@@ -1200,6 +1200,9 @@ static void mmc_sd_remove(struct mmc_host *host)
 */
static int mmc_sd_alive(struct mmc_host *host)
{
	if (host->ops->get_cd && !host->ops->get_cd(host))
		return -ENOMEDIUM;

	return mmc_send_status(host->card, NULL);
}

@@ -1212,11 +1215,19 @@ static void mmc_sd_detect(struct mmc_host *host)

	mmc_get_card(host->card, NULL);

	if (host->ops->get_cd && !host->ops->get_cd(host)) {
		err = -ENOMEDIUM;
		mmc_card_set_removed(host->card);
		mmc_card_clr_suspended(host->card);
		goto out;
	}

	/*
	 * Just check if our card has been removed.
	 */
	err = _mmc_detect_card_removed(host);

out:
	mmc_put_card(host->card, NULL);

	if (err) {
@@ -1292,6 +1303,11 @@ static int _mmc_sd_resume(struct mmc_host *host)
	if (!mmc_card_suspended(host->card))
		goto out;

	if (host->ops->get_cd && !host->ops->get_cd(host)) {
		mmc_card_clr_suspended(host->card);
		goto out;
	}

	mmc_power_up(host, host->card->ocr);
	err = mmc_sd_init_card(host, host->card->ocr, host->card);
	if (err == -ENOENT) {
@@ -1414,6 +1430,9 @@ static int mmc_sd_runtime_resume(struct mmc_host *host)

static int mmc_sd_hw_reset(struct mmc_host *host)
{
	if (host->ops->get_cd && !host->ops->get_cd(host))
		return -ENOMEDIUM;

	mmc_power_cycle(host, host->card->ocr);
	return mmc_sd_init_card(host, host->card->ocr, host->card);
}
+4 −0
Original line number Diff line number Diff line
@@ -37,6 +37,10 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
	/* Schedule a card detection after a debounce timeout */
	struct mmc_host *host = dev_id;
	struct mmc_gpio *ctx = host->slot.handler_priv;
	int present = host->ops->get_cd(host);

	pr_debug("%s: cd gpio irq, gpio state %d (CARD_%s)\n",
		mmc_hostname(host), present, present?"INSERT":"REMOVAL");

	host->trigger_card_event = true;
	mmc_detect_change(host, msecs_to_jiffies(ctx->cd_debounce_delay_ms));
+6 −0
Original line number Diff line number Diff line
@@ -667,6 +667,7 @@ static inline void *mmc_priv(struct mmc_host *host)
#define mmc_bus_manual_resume(host) ((host)->bus_resume_flags & \
				MMC_BUSRESUME_MANUAL_RESUME)

#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
static inline void mmc_set_bus_resume_policy(struct mmc_host *host, int manual)
{
	if (manual)
@@ -674,6 +675,11 @@ static inline void mmc_set_bus_resume_policy(struct mmc_host *host, int manual)
	else
		host->bus_resume_flags &= ~MMC_BUSRESUME_MANUAL_RESUME;
}
#else
static inline void mmc_set_bus_resume_policy(struct mmc_host *host, int manual)
{
}
#endif

extern int mmc_resume_bus(struct mmc_host *host);