#include <linux/regulator/rockchip_io_vol_domain.h>
#include "../../clk/rockchip/clk-ops.h"
-#define RK_SDMMC_DRIVER_VERSION "Ver 1.12 2014-07-08"
+#define RK_SDMMC_DRIVER_VERSION "Ver 1.13 2014-09-05"
/* Common flag combinations */
#define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DRTO | SDMMC_INT_DCRC | \
static int dw_mci_edmac_init(struct dw_mci *host)
{
- /* 1) request external dma channel, SHOULD decide chn in dts */
- host->dms = (struct dw_mci_dma_slave *)kmalloc(sizeof(struct dw_mci_dma_slave),GFP_KERNEL);
+ /* Request external dma channel, SHOULD decide chn in dts */
+ host->dms = NULL;
+ host->dms = (struct dw_mci_dma_slave *)kmalloc
+ (sizeof(struct dw_mci_dma_slave), GFP_KERNEL);
+ if (NULL == host->dms) {
+ dev_err(host->dev, "No enough memory to alloc dms.\n");
+ goto err_exit;
+ }
+
host->dms->ch = dma_request_slave_channel(host->dev, "dw_mci");
- if (!host->dms->ch){
+ if (!host->dms->ch) {
dev_err(host->dev, "Failed to get external DMA channel: channel id = %d\n",
host->dms->ch->chan_id);
goto err_exit;
}
- /* anything? */
-
return 0;
err_exit:
- return -ENODEV;
+ if (NULL != host->dms) {
+ kfree(host->dms);
+ host->dms = NULL;
+ }
+ return -ENXIO;
}
static void dw_mci_edmac_exit(struct dw_mci *host)
{
- dma_release_channel(host->dms->ch);
+ if (NULL != host->dms) {
+ if (NULL != host->dms->ch) {
+ dma_release_channel(host->dms->ch);
+ host->dms->ch = NULL;
+ }
+ kfree(host->dms);
+ host->dms = NULL;
+ }
}
static const struct dw_mci_dma_ops dw_mci_edmac_ops = {
mmcblk0: retrying using single block read
mmcblk0: error -110 sending status command, retrying
- How to: If eMMC HW version < 4.51, or > 4.51 but no caps2-mmc-hs200 support in dts
- Please set dts emmc clk to 100M or 150M, I will workaround it!
+ We assume all eMMC in RK platform with 3.10 kernel, at least version 4.5
*/
+ if ((div == 0) &&
+ (host->mmc->caps & (MMC_CAP_1_8V_DDR | MMC_CAP_1_2V_DDR)) &&
+ !(host->mmc->caps2 & MMC_CAP2_HS200)) {
+ /* Fixup DDR MMC */
+ div = 1;
+ host->set_div = div;
+ host->bus_hz = host->set_speed * 2;
+ MMC_DBG_BOOT_FUNC(host->mmc,
+ "dw_mci_setup_bus: workaround div = %d, host->bus_hz = %d [%s]",
+ div, host->bus_hz, mmc_hostname(host->mmc));
+ }
if (host->verid < DW_MMC_240A)
clk_set_rate(host->clk_mmc,(host->bus_hz));
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct dw_mci *host = slot->host;
+ //unsigned long flags;
u32 int_mask;
u32 sdio_int;
+ //spin_lock_irqsave(&host->lock, flags);
+
/* Enable/disable Slot Specific SDIO interrupt */
int_mask = mci_readl(host, INTMASK);
mci_writel(host, INTMASK,
(int_mask & ~sdio_int));
}
+
+ //spin_unlock_irqrestore(&host->lock, flags);
}
#ifdef CONFIG_MMC_DW_ROCKCHIP_SWITCH_VOLTAGE
static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
{
- u32 multi, unit;
+ u32 multi, unit = SZ_2M;
if (!host->cmd_status)
host->cmd_status = status;
- if(!host->cmd)
+ if (!host->cmd)
goto cmd_exit;
- if((MMC_STOP_TRANSMISSION != host->cmd->opcode))
- {
- unit = 2*1024*1024;
- multi = mci_readl(host, BYTCNT)/unit;
- multi += ((mci_readl(host, BYTCNT) % unit) ? 1 :0 );
- multi = (multi > 0) ? multi : 1;
- multi += (host->cmd->retries > 2)? 2 : host->cmd->retries;
- mod_timer(&host->dto_timer, jiffies + msecs_to_jiffies(4500 * multi));//max wait 8s larger
+ if ((MMC_STOP_TRANSMISSION != host->cmd->opcode)) {
+ multi = (mci_readl(host, BYTCNT) / unit) +
+ ((mci_readl(host, BYTCNT) % unit) ? 1 :0 ) +
+ ((host->cmd->retries > 2) ? 2 : host->cmd->retries);
+ /* Max limit time: 8s for dto */
+ mod_timer(&host->dto_timer, jiffies + msecs_to_jiffies(4000 * multi));
}
cmd_exit:
if (ret < 0) {
irq = ret;
dev_err(host->dev, "Request cd-gpio %d interrupt error!\n", gpio);
+ } else{
+ /* enable wakeup event for gpio-cd in idle or deep suspend*/
+ enable_irq_wake(irq);
}
} else {
dev_err(host->dev, "Cannot convert gpio %d to irq!\n", gpio);
mmc->f_min = DW_MCI_FREQ_MIN;
mmc->f_max = DW_MCI_FREQ_MAX;
- printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__,__FUNCTION__,
- mmc->f_min, mmc->f_max, mmc_hostname(mmc));
+ printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__, __FUNCTION__,
+ mmc->f_min, mmc->f_max, mmc_hostname(mmc));
} else {
mmc->f_min = freq[0];
mmc->f_max = freq[1];
- printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__,__FUNCTION__,
- mmc->f_min, mmc->f_max, mmc_hostname(mmc));
+ printk("%d..%s: fmin=%d, fmax=%d [%s]\n", __LINE__, __FUNCTION__,
+ mmc->f_min, mmc->f_max, mmc_hostname(mmc));
}
-
- if(strstr("mmc0",mmc_hostname(mmc)))
- printk("Line%d..%s: The rk_sdmmc %s",__LINE__, __FUNCTION__,RK_SDMMC_DRIVER_VERSION);
+
+ printk("%s : Rockchip specific MHSC: %s\n", mmc_hostname(mmc), RK_SDMMC_DRIVER_VERSION);
if (of_find_property(host->dev->of_node, "supports-sd", NULL))
mmc->restrict_caps |= RESTRICT_CARD_TYPE_SD;
mmc->restrict_caps |= RESTRICT_CARD_TYPE_SDIO;
if (of_find_property(host->dev->of_node, "supports-emmc", NULL))
mmc->restrict_caps |= RESTRICT_CARD_TYPE_EMMC;
+ /* Fixup for tSD */
+ if (of_find_property(host->dev->of_node, "supports-tSD", NULL))
+ mmc->restrict_caps |= RESTRICT_CARD_TYPE_TSD;
+
/* We assume only low-level chip use gpio_cd */
if (cpu_is_rk312x() &&