aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc/host')
-rw-r--r--drivers/mmc/host/dw_mmc.c121
-rw-r--r--drivers/mmc/host/dw_mmc.h2
2 files changed, 20 insertions, 103 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 545f62191afd..bb46b1b8d16b 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -34,7 +34,6 @@
34#include <linux/mmc/dw_mmc.h> 34#include <linux/mmc/dw_mmc.h>
35#include <linux/bitops.h> 35#include <linux/bitops.h>
36#include <linux/regulator/consumer.h> 36#include <linux/regulator/consumer.h>
37#include <linux/workqueue.h>
38#include <linux/of.h> 37#include <linux/of.h>
39#include <linux/of_gpio.h> 38#include <linux/of_gpio.h>
40#include <linux/mmc/slot-gpio.h> 39#include <linux/mmc/slot-gpio.h>
@@ -1959,6 +1958,23 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
1959 tasklet_schedule(&host->tasklet); 1958 tasklet_schedule(&host->tasklet);
1960} 1959}
1961 1960
1961static void dw_mci_handle_cd(struct dw_mci *host)
1962{
1963 int i;
1964
1965 for (i = 0; i < host->num_slots; i++) {
1966 struct dw_mci_slot *slot = host->slot[i];
1967
1968 if (!slot)
1969 continue;
1970
1971 if (slot->mmc->ops->card_event)
1972 slot->mmc->ops->card_event(slot->mmc);
1973 mmc_detect_change(slot->mmc,
1974 msecs_to_jiffies(host->pdata->detect_delay_ms));
1975 }
1976}
1977
1962static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) 1978static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
1963{ 1979{
1964 struct dw_mci *host = dev_id; 1980 struct dw_mci *host = dev_id;
@@ -2034,7 +2050,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
2034 2050
2035 if (pending & SDMMC_INT_CD) { 2051 if (pending & SDMMC_INT_CD) {
2036 mci_writel(host, RINTSTS, SDMMC_INT_CD); 2052 mci_writel(host, RINTSTS, SDMMC_INT_CD);
2037 queue_work(host->card_workqueue, &host->card_work); 2053 dw_mci_handle_cd(host);
2038 } 2054 }
2039 2055
2040 /* Handle SDIO Interrupts */ 2056 /* Handle SDIO Interrupts */
@@ -2061,88 +2077,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
2061 return IRQ_HANDLED; 2077 return IRQ_HANDLED;
2062} 2078}
2063 2079
2064static void dw_mci_work_routine_card(struct work_struct *work)
2065{
2066 struct dw_mci *host = container_of(work, struct dw_mci, card_work);
2067 int i;
2068
2069 for (i = 0; i < host->num_slots; i++) {
2070 struct dw_mci_slot *slot = host->slot[i];
2071 struct mmc_host *mmc = slot->mmc;
2072 struct mmc_request *mrq;
2073 int present;
2074
2075 present = dw_mci_get_cd(mmc);
2076 while (present != slot->last_detect_state) {
2077 dev_dbg(&slot->mmc->class_dev, "card %s\n",
2078 present ? "inserted" : "removed");
2079
2080 spin_lock_bh(&host->lock);
2081
2082 /* Card change detected */
2083 slot->last_detect_state = present;
2084
2085 /* Clean up queue if present */
2086 mrq = slot->mrq;
2087 if (mrq) {
2088 if (mrq == host->mrq) {
2089 host->data = NULL;
2090 host->cmd = NULL;
2091
2092 switch (host->state) {
2093 case STATE_IDLE:
2094 case STATE_WAITING_CMD11_DONE:
2095 break;
2096 case STATE_SENDING_CMD11:
2097 case STATE_SENDING_CMD:
2098 mrq->cmd->error = -ENOMEDIUM;
2099 if (!mrq->data)
2100 break;
2101 /* fall through */
2102 case STATE_SENDING_DATA:
2103 mrq->data->error = -ENOMEDIUM;
2104 dw_mci_stop_dma(host);
2105 break;
2106 case STATE_DATA_BUSY:
2107 case STATE_DATA_ERROR:
2108 if (mrq->data->error == -EINPROGRESS)
2109 mrq->data->error = -ENOMEDIUM;
2110 /* fall through */
2111 case STATE_SENDING_STOP:
2112 if (mrq->stop)
2113 mrq->stop->error = -ENOMEDIUM;
2114 break;
2115 }
2116
2117 dw_mci_request_end(host, mrq);
2118 } else {
2119 list_del(&slot->queue_node);
2120 mrq->cmd->error = -ENOMEDIUM;
2121 if (mrq->data)
2122 mrq->data->error = -ENOMEDIUM;
2123 if (mrq->stop)
2124 mrq->stop->error = -ENOMEDIUM;
2125
2126 spin_unlock(&host->lock);
2127 mmc_request_done(slot->mmc, mrq);
2128 spin_lock(&host->lock);
2129 }
2130 }
2131
2132 /* Power down slot */
2133 if (present == 0)
2134 dw_mci_reset(host);
2135
2136 spin_unlock_bh(&host->lock);
2137
2138 present = dw_mci_get_cd(mmc);
2139 }
2140
2141 mmc_detect_change(slot->mmc,
2142 msecs_to_jiffies(host->pdata->detect_delay_ms));
2143 }
2144}
2145
2146#ifdef CONFIG_OF 2080#ifdef CONFIG_OF
2147/* given a slot id, find out the device node representing that slot */ 2081/* given a slot id, find out the device node representing that slot */
2148static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) 2082static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
@@ -2294,9 +2228,6 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
2294 dw_mci_init_debugfs(slot); 2228 dw_mci_init_debugfs(slot);
2295#endif 2229#endif
2296 2230
2297 /* Card initially undetected */
2298 slot->last_detect_state = 0;
2299
2300 return 0; 2231 return 0;
2301 2232
2302err_host_allocated: 2233err_host_allocated:
@@ -2677,17 +2608,10 @@ int dw_mci_probe(struct dw_mci *host)
2677 host->data_offset = DATA_240A_OFFSET; 2608 host->data_offset = DATA_240A_OFFSET;
2678 2609
2679 tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); 2610 tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
2680 host->card_workqueue = alloc_workqueue("dw-mci-card",
2681 WQ_MEM_RECLAIM, 1);
2682 if (!host->card_workqueue) {
2683 ret = -ENOMEM;
2684 goto err_dmaunmap;
2685 }
2686 INIT_WORK(&host->card_work, dw_mci_work_routine_card);
2687 ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, 2611 ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
2688 host->irq_flags, "dw-mci", host); 2612 host->irq_flags, "dw-mci", host);
2689 if (ret) 2613 if (ret)
2690 goto err_workqueue; 2614 goto err_dmaunmap;
2691 2615
2692 if (host->pdata->num_slots) 2616 if (host->pdata->num_slots)
2693 host->num_slots = host->pdata->num_slots; 2617 host->num_slots = host->pdata->num_slots;
@@ -2723,7 +2647,7 @@ int dw_mci_probe(struct dw_mci *host)
2723 } else { 2647 } else {
2724 dev_dbg(host->dev, "attempted to initialize %d slots, " 2648 dev_dbg(host->dev, "attempted to initialize %d slots, "
2725 "but failed on all\n", host->num_slots); 2649 "but failed on all\n", host->num_slots);
2726 goto err_workqueue; 2650 goto err_dmaunmap;
2727 } 2651 }
2728 2652
2729 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) 2653 if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
@@ -2731,9 +2655,6 @@ int dw_mci_probe(struct dw_mci *host)
2731 2655
2732 return 0; 2656 return 0;
2733 2657
2734err_workqueue:
2735 destroy_workqueue(host->card_workqueue);
2736
2737err_dmaunmap: 2658err_dmaunmap:
2738 if (host->use_dma && host->dma_ops->exit) 2659 if (host->use_dma && host->dma_ops->exit)
2739 host->dma_ops->exit(host); 2660 host->dma_ops->exit(host);
@@ -2767,8 +2688,6 @@ void dw_mci_remove(struct dw_mci *host)
2767 mci_writel(host, CLKENA, 0); 2688 mci_writel(host, CLKENA, 0);
2768 mci_writel(host, CLKSRC, 0); 2689 mci_writel(host, CLKSRC, 0);
2769 2690
2770 destroy_workqueue(host->card_workqueue);
2771
2772 if (host->use_dma && host->dma_ops->exit) 2691 if (host->use_dma && host->dma_ops->exit)
2773 host->dma_ops->exit(host); 2692 host->dma_ops->exit(host);
2774 2693
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 01b99e8a9190..71d499557edc 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -214,7 +214,6 @@ extern int dw_mci_resume(struct dw_mci *host);
214 * with CONFIG_MMC_CLKGATE. 214 * with CONFIG_MMC_CLKGATE.
215 * @flags: Random state bits associated with the slot. 215 * @flags: Random state bits associated with the slot.
216 * @id: Number of this slot. 216 * @id: Number of this slot.
217 * @last_detect_state: Most recently observed card detect state.
218 */ 217 */
219struct dw_mci_slot { 218struct dw_mci_slot {
220 struct mmc_host *mmc; 219 struct mmc_host *mmc;
@@ -234,7 +233,6 @@ struct dw_mci_slot {
234#define DW_MMC_CARD_PRESENT 0 233#define DW_MMC_CARD_PRESENT 0
235#define DW_MMC_CARD_NEED_INIT 1 234#define DW_MMC_CARD_NEED_INIT 1
236 int id; 235 int id;
237 int last_detect_state;
238}; 236};
239 237
240struct dw_mci_tuning_data { 238struct dw_mci_tuning_data {