OSDN Git Service

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[uclinux-h8/linux.git] / drivers / mmc / host / dw_mmc.c
index 7128351..242f9a0 100644 (file)
@@ -234,7 +234,6 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
        struct mmc_data *data;
        struct dw_mci_slot *slot = mmc_priv(mmc);
        struct dw_mci *host = slot->host;
-       const struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 cmdr;
 
        cmd->error = -EINPROGRESS;
@@ -290,14 +289,12 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
        data = cmd->data;
        if (data) {
                cmdr |= SDMMC_CMD_DAT_EXP;
-               if (data->flags & MMC_DATA_STREAM)
-                       cmdr |= SDMMC_CMD_STRM_MODE;
                if (data->flags & MMC_DATA_WRITE)
                        cmdr |= SDMMC_CMD_DAT_WR;
        }
 
-       if (drv_data && drv_data->prepare_command)
-               drv_data->prepare_command(slot->host, &cmdr);
+       if (!test_bit(DW_MMC_CARD_NO_USE_HOLD, &slot->flags))
+               cmdr |= SDMMC_CMD_USE_HOLD_REG;
 
        return cmdr;
 }
@@ -1450,12 +1447,11 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 {
        int present;
        struct dw_mci_slot *slot = mmc_priv(mmc);
-       struct dw_mci_board *brd = slot->host->pdata;
        struct dw_mci *host = slot->host;
        int gpio_cd = mmc_gpio_get_cd(mmc);
 
        /* Use platform get_cd function, else try onboard card detect */
-       if ((brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) ||
+       if ((mmc->caps & MMC_CAP_NEEDS_POLL) ||
            (mmc->caps & MMC_CAP_NONREMOVABLE))
                present = 1;
        else if (!IS_ERR_VALUE(gpio_cd))
@@ -1477,6 +1473,34 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        return present;
 }
 
+static void dw_mci_hw_reset(struct mmc_host *mmc)
+{
+       struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci *host = slot->host;
+       int reset;
+
+       if (host->use_dma == TRANS_MODE_IDMAC)
+               dw_mci_idmac_reset(host);
+
+       if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET |
+                                    SDMMC_CTRL_FIFO_RESET))
+               return;
+
+       /*
+        * According to eMMC spec, card reset procedure:
+        * tRstW >= 1us:   RST_n pulse width
+        * tRSCA >= 200us: RST_n to Command time
+        * tRSTH >= 1us:   RST_n high period
+        */
+       reset = mci_readl(host, RST_N);
+       reset &= ~(SDMMC_RST_HWACTIVE << slot->id);
+       mci_writel(host, RST_N, reset);
+       usleep_range(1, 2);
+       reset |= SDMMC_RST_HWACTIVE << slot->id;
+       mci_writel(host, RST_N, reset);
+       usleep_range(200, 300);
+}
+
 static void dw_mci_init_card(struct mmc_host *mmc, struct mmc_card *card)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -1563,6 +1587,7 @@ static const struct mmc_host_ops dw_mci_ops = {
        .set_ios                = dw_mci_set_ios,
        .get_ro                 = dw_mci_get_ro,
        .get_cd                 = dw_mci_get_cd,
+       .hw_reset               = dw_mci_hw_reset,
        .enable_sdio_irq        = dw_mci_enable_sdio_irq,
        .execute_tuning         = dw_mci_execute_tuning,
        .card_busy              = dw_mci_card_busy,
@@ -2840,23 +2865,13 @@ static void dw_mci_dto_timer(unsigned long arg)
 }
 
 #ifdef CONFIG_OF
-static struct dw_mci_of_quirks {
-       char *quirk;
-       int id;
-} of_quirks[] = {
-       {
-               .quirk  = "broken-cd",
-               .id     = DW_MCI_QUIRK_BROKEN_CARD_DETECTION,
-       },
-};
-
 static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 {
        struct dw_mci_board *pdata;
        struct device *dev = host->dev;
        struct device_node *np = dev->of_node;
        const struct dw_mci_drv_data *drv_data = host->drv_data;
-       int idx, ret;
+       int ret;
        u32 clock_frequency;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -2864,17 +2879,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
                return ERR_PTR(-ENOMEM);
 
        /* find out number of slots supported */
-       if (of_property_read_u32(dev->of_node, "num-slots",
-                               &pdata->num_slots)) {
-               dev_info(dev,
-                        "num-slots property not found, assuming 1 slot is available\n");
-               pdata->num_slots = 1;
-       }
-
-       /* get quirks */
-       for (idx = 0; idx < ARRAY_SIZE(of_quirks); idx++)
-               if (of_get_property(np, of_quirks[idx].quirk, NULL))
-                       pdata->quirks |= of_quirks[idx].id;
+       of_property_read_u32(np, "num-slots", &pdata->num_slots);
 
        if (of_property_read_u32(np, "fifo-depth", &pdata->fifo_depth))
                dev_info(dev,
@@ -2908,18 +2913,19 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
 static void dw_mci_enable_cd(struct dw_mci *host)
 {
-       struct dw_mci_board *brd = host->pdata;
        unsigned long irqflags;
        u32 temp;
        int i;
+       struct dw_mci_slot *slot;
 
-       /* No need for CD if broken card detection */
-       if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
-               return;
-
-       /* No need for CD if all slots have a non-error GPIO */
+       /*
+        * No need for CD if all slots have a non-error GPIO
+        * as well as broken card detection is found.
+        */
        for (i = 0; i < host->num_slots; i++) {
-               struct dw_mci_slot *slot = host->slot[i];
+               slot = host->slot[i];
+               if (slot->mmc->caps & MMC_CAP_NEEDS_POLL)
+                       return;
 
                if (IS_ERR_VALUE(mmc_gpio_get_cd(slot->mmc)))
                        break;
@@ -2949,12 +2955,6 @@ int dw_mci_probe(struct dw_mci *host)
                }
        }
 
-       if (host->pdata->num_slots < 1) {
-               dev_err(host->dev,
-                       "Platform data must supply num_slots.\n");
-               return -ENODEV;
-       }
-
        host->biu_clk = devm_clk_get(host->dev, "biu");
        if (IS_ERR(host->biu_clk)) {
                dev_dbg(host->dev, "biu clock not available\n");
@@ -3052,8 +3052,10 @@ int dw_mci_probe(struct dw_mci *host)
        }
 
        /* Reset all blocks */
-       if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS))
-               return -ENODEV;
+       if (!dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS)) {
+               ret = -ENODEV;
+               goto err_clk_ciu;
+       }
 
        host->dma_ops = host->pdata->dma_ops;
        dw_mci_init_dma(host);
@@ -3111,13 +3113,20 @@ int dw_mci_probe(struct dw_mci *host)
        if (host->pdata->num_slots)
                host->num_slots = host->pdata->num_slots;
        else
-               host->num_slots = SDMMC_GET_SLOT_NUM(mci_readl(host, HCON));
+               host->num_slots = 1;
+
+       if (host->num_slots < 1 ||
+           host->num_slots > SDMMC_GET_SLOT_NUM(mci_readl(host, HCON))) {
+               dev_err(host->dev,
+                       "Platform data must supply correct num_slots.\n");
+               ret = -ENODEV;
+               goto err_clk_ciu;
+       }
 
        /*
         * Enable interrupts for command done, data over, data empty,
         * receive ready and error such as transmit, receive timeout, crc error
         */
-       mci_writel(host, RINTSTS, 0xFFFFFFFF);
        mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
                   SDMMC_INT_TXDR | SDMMC_INT_RXDR |
                   DW_MCI_ERROR_FLAGS);