From 5c77f3e001100be15007608c950260f1f6ca1b6f Mon Sep 17 00:00:00 2001 From: duk hyun kwon Date: Thu, 9 May 2019 17:39:35 +0900 Subject: [PATCH] [RAMEN9610-15074] [COMMON] mmc: dw_mmc: sdcard power off when to card detect. to occur lock warring is regulator disable in irq status. so add sdcard regulator disable tasklet and fix up USIM broken issue Change-Id: If10f4d4fb3e9aad2a2bd32355f3a946af0fd8fe7 Signed-off-by: duk hyun kwon --- drivers/mmc/host/dw_mmc.c | 24 +++++++++++++++++------- drivers/mmc/host/dw_mmc.h | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index ed9d979d70e8..d3555748d400 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2507,6 +2507,20 @@ static bool dw_mci_clear_pending_cmd_complete(struct dw_mci *host) return true; } +static void dw_mci_sd_power_off(unsigned long priv) +{ + struct dw_mci *host = (struct dw_mci *)priv; + struct mmc_host *mmc = host->slot->mmc; + struct dw_mci_slot *slot = host->slot; + + if (!IS_ERR(mmc->supply.vmmc)) + mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); + if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) + regulator_disable(mmc->supply.vqmmc); + slot->host->vqmmc_enabled = false; + +} + static void dw_mci_tasklet_func(unsigned long priv) { struct dw_mci *host = (struct dw_mci *)priv; @@ -3475,14 +3489,9 @@ static void dw_mci_slot_of_parse(struct dw_mci_slot *slot) static irqreturn_t dw_mci_detect_interrupt(int irq, void *dev_id) { struct dw_mci *host = dev_id; - struct mmc_host *mmc = host->slot->mmc; - struct dw_mci_slot *slot = host->slot; - if (!IS_ERR(mmc->supply.vmmc)) - mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0); - if (!IS_ERR(mmc->supply.vqmmc) && slot->host->vqmmc_enabled) - regulator_disable(mmc->supply.vqmmc); - slot->host->vqmmc_enabled = false; + /* sdcard power off */ + tasklet_schedule(&host->pw_tasklet); queue_work(host->card_workqueue, &host->card_work); @@ -4290,6 +4299,7 @@ int dw_mci_probe(struct dw_mci *host) host->fifo_reg = host->regs + DATA_240A_OFFSET; tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); + tasklet_init(&host->pw_tasklet, dw_mci_sd_power_off, (unsigned long)host); host->card_workqueue = alloc_workqueue("dw-mci-card", WQ_MEM_RECLAIM, 1); if (!host->card_workqueue) { diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 3c27ddae0807..e10d91d1dc39 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -203,6 +203,7 @@ struct dw_mci { u32 dir_status; struct tasklet_struct tasklet; u32 tasklet_state; + struct tasklet_struct pw_tasklet; struct work_struct card_work; unsigned long pending_events; unsigned long completed_events; -- 2.20.1