[RAMEN9610-15074] [COMMON] mmc: dw_mmc: sdcard power off when to card detect.
authorduk hyun kwon <d_hyun.kwon@samsung.com>
Thu, 9 May 2019 08:39:35 +0000 (17:39 +0900)
committerKim Gunho <gunho.kim@samsung.com>
Fri, 28 Jun 2019 14:45:29 +0000 (23:45 +0900)
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 <d_hyun.kwon@samsung.com>
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/dw_mmc.h

index ed9d979d70e8de4d2280642916d11d71811c8658..d3555748d4003eb306a681dc4e9aeaf7cbabeb4d 100644 (file)
@@ -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) {
index 3c27ddae08071e383e1f7137e6eddd8f7f7522ee..e10d91d1dc39dc9a644939d3a092f90fbe3792ad 100644 (file)
@@ -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;