|
@@ -62,6 +62,7 @@ static inline int
|
|
|
msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
|
|
|
{
|
|
|
int rc;
|
|
|
+
|
|
|
WARN_ON(enable == host->clks_on);
|
|
|
if (enable) {
|
|
|
rc = clk_enable(host->pclk);
|
|
@@ -72,7 +73,8 @@ msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
|
|
|
clk_disable(host->pclk);
|
|
|
return rc;
|
|
|
}
|
|
|
- udelay(30);
|
|
|
+ udelay(1 + ((3 * USEC_PER_SEC) /
|
|
|
+ (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
|
|
|
host->clks_on = 1;
|
|
|
} else {
|
|
|
clk_disable(host->clk);
|
|
@@ -82,6 +84,20 @@ msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static inline unsigned int
|
|
|
+msmsdcc_readl(struct msmsdcc_host *host, unsigned int reg)
|
|
|
+{
|
|
|
+ return readl(host->base + reg);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void
|
|
|
+msmsdcc_writel(struct msmsdcc_host *host, u32 data, unsigned int reg)
|
|
|
+{
|
|
|
+ writel(data, host->base + reg);
|
|
|
+ /* 3 clk delay required! */
|
|
|
+ udelay(1 + ((3 * USEC_PER_SEC) /
|
|
|
+ (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
|
|
|
+}
|
|
|
|
|
|
static void
|
|
|
msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
|
|
@@ -90,7 +106,7 @@ msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
|
|
|
static void
|
|
|
msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
|
|
|
{
|
|
|
- writel(0, host->base + MMCICOMMAND);
|
|
|
+ msmsdcc_writel(host, 0, MMCICOMMAND);
|
|
|
|
|
|
BUG_ON(host->curr.data);
|
|
|
|
|
@@ -116,7 +132,7 @@ msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
|
|
|
static void
|
|
|
msmsdcc_stop_data(struct msmsdcc_host *host)
|
|
|
{
|
|
|
- writel(0, host->base + MMCIDATACTRL);
|
|
|
+ msmsdcc_writel(host, 0, MMCIDATACTRL);
|
|
|
host->curr.data = NULL;
|
|
|
host->curr.got_dataend = host->curr.got_datablkend = 0;
|
|
|
}
|
|
@@ -200,7 +216,7 @@ msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
|
|
|
if (!mrq->data->error)
|
|
|
host->curr.data_xfered = host->curr.xfer_size;
|
|
|
if (!mrq->data->stop || mrq->cmd->error) {
|
|
|
- writel(0, host->base + MMCICOMMAND);
|
|
|
+ msmsdcc_writel(host, 0, MMCICOMMAND);
|
|
|
host->curr.mrq = NULL;
|
|
|
host->curr.cmd = NULL;
|
|
|
mrq->data->bytes_xfered = host->curr.data_xfered;
|
|
@@ -337,7 +353,6 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data)
|
|
|
{
|
|
|
unsigned int datactrl, timeout;
|
|
|
unsigned long long clks;
|
|
|
- void __iomem *base = host->base;
|
|
|
unsigned int pio_irqmask = 0;
|
|
|
|
|
|
host->curr.data = data;
|
|
@@ -352,9 +367,9 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data)
|
|
|
clks = (unsigned long long)data->timeout_ns * host->clk_rate;
|
|
|
do_div(clks, NSEC_PER_SEC);
|
|
|
timeout = data->timeout_clks + (unsigned int)clks;
|
|
|
- writel(timeout, base + MMCIDATATIMER);
|
|
|
+ msmsdcc_writel(host, timeout, MMCIDATATIMER);
|
|
|
|
|
|
- writel(host->curr.xfer_size, base + MMCIDATALENGTH);
|
|
|
+ msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH);
|
|
|
|
|
|
datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
|
|
|
|
|
@@ -376,8 +391,8 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data)
|
|
|
if (data->flags & MMC_DATA_READ)
|
|
|
datactrl |= MCI_DPSM_DIRECTION;
|
|
|
|
|
|
- writel(pio_irqmask, base + MMCIMASK1);
|
|
|
- writel(datactrl, base + MMCIDATACTRL);
|
|
|
+ msmsdcc_writel(host, pio_irqmask, MMCIMASK1);
|
|
|
+ msmsdcc_writel(host, datactrl, MMCIDATACTRL);
|
|
|
|
|
|
if (datactrl & MCI_DPSM_DMAENABLE) {
|
|
|
host->dma.busy = 1;
|
|
@@ -398,12 +413,8 @@ snoop_cccr_abort(struct mmc_command *cmd)
|
|
|
static void
|
|
|
msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
|
|
|
{
|
|
|
- void __iomem *base = host->base;
|
|
|
-
|
|
|
- if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
|
|
|
- writel(0, base + MMCICOMMAND);
|
|
|
- udelay(2 + ((5 * 1000000) / host->clk_rate));
|
|
|
- }
|
|
|
+ if (msmsdcc_readl(host, MMCICOMMAND) & MCI_CPSM_ENABLE)
|
|
|
+ msmsdcc_writel(host, 0, MMCICOMMAND);
|
|
|
|
|
|
c |= cmd->opcode | MCI_CPSM_ENABLE;
|
|
|
|
|
@@ -428,8 +439,8 @@ msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
|
|
|
|
|
|
host->stats.cmds++;
|
|
|
|
|
|
- writel(cmd->arg, base + MMCIARGUMENT);
|
|
|
- writel(c, base + MMCICOMMAND);
|
|
|
+ msmsdcc_writel(host, cmd->arg, MMCIARGUMENT);
|
|
|
+ msmsdcc_writel(host, c, MMCICOMMAND);
|
|
|
}
|
|
|
|
|
|
static void
|
|
@@ -463,13 +474,11 @@ msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
|
|
|
static int
|
|
|
msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
|
|
|
{
|
|
|
- void __iomem *base = host->base;
|
|
|
uint32_t *ptr = (uint32_t *) buffer;
|
|
|
int count = 0;
|
|
|
|
|
|
- while (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
|
|
|
-
|
|
|
- *ptr = readl(base + MMCIFIFO + (count % MCI_FIFOSIZE));
|
|
|
+ while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) {
|
|
|
+ *ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE));
|
|
|
ptr++;
|
|
|
count += sizeof(uint32_t);
|
|
|
|
|
@@ -501,7 +510,7 @@ msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
|
|
|
if (remain == 0)
|
|
|
break;
|
|
|
|
|
|
- status = readl(base + MMCISTATUS);
|
|
|
+ status = msmsdcc_readl(host, MMCISTATUS);
|
|
|
} while (status & MCI_TXFIFOHALFEMPTY);
|
|
|
|
|
|
return ptr - buffer;
|
|
@@ -511,7 +520,7 @@ static int
|
|
|
msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin)
|
|
|
{
|
|
|
while (maxspin) {
|
|
|
- if ((readl(host->base + MMCISTATUS) & mask))
|
|
|
+ if ((msmsdcc_readl(host, MMCISTATUS) & mask))
|
|
|
return 0;
|
|
|
udelay(1);
|
|
|
--maxspin;
|
|
@@ -523,10 +532,9 @@ static int
|
|
|
msmsdcc_pio_irq(int irq, void *dev_id)
|
|
|
{
|
|
|
struct msmsdcc_host *host = dev_id;
|
|
|
- void __iomem *base = host->base;
|
|
|
uint32_t status;
|
|
|
|
|
|
- status = readl(base + MMCISTATUS);
|
|
|
+ status = msmsdcc_readl(host, MMCISTATUS);
|
|
|
|
|
|
do {
|
|
|
unsigned long flags;
|
|
@@ -581,14 +589,14 @@ msmsdcc_pio_irq(int irq, void *dev_id)
|
|
|
host->pio.sg_off = 0;
|
|
|
}
|
|
|
|
|
|
- status = readl(base + MMCISTATUS);
|
|
|
+ status = msmsdcc_readl(host, MMCISTATUS);
|
|
|
} while (1);
|
|
|
|
|
|
if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
|
|
|
- writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
|
|
|
+ msmsdcc_writel(host, MCI_RXDATAAVLBLMASK, MMCIMASK1);
|
|
|
|
|
|
if (!host->curr.xfer_remain)
|
|
|
- writel(0, base + MMCIMASK1);
|
|
|
+ msmsdcc_writel(host, 0, MMCIMASK1);
|
|
|
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
@@ -596,13 +604,12 @@ msmsdcc_pio_irq(int irq, void *dev_id)
|
|
|
static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
|
|
|
{
|
|
|
struct mmc_command *cmd = host->curr.cmd;
|
|
|
- void __iomem *base = host->base;
|
|
|
|
|
|
host->curr.cmd = NULL;
|
|
|
- cmd->resp[0] = readl(base + MMCIRESPONSE0);
|
|
|
- cmd->resp[1] = readl(base + MMCIRESPONSE1);
|
|
|
- cmd->resp[2] = readl(base + MMCIRESPONSE2);
|
|
|
- cmd->resp[3] = readl(base + MMCIRESPONSE3);
|
|
|
+ cmd->resp[0] = msmsdcc_readl(host, MMCIRESPONSE0);
|
|
|
+ cmd->resp[1] = msmsdcc_readl(host, MMCIRESPONSE1);
|
|
|
+ cmd->resp[2] = msmsdcc_readl(host, MMCIRESPONSE2);
|
|
|
+ cmd->resp[3] = msmsdcc_readl(host, MMCIRESPONSE3);
|
|
|
|
|
|
del_timer(&host->command_timer);
|
|
|
if (status & MCI_CMDTIMEOUT) {
|
|
@@ -699,10 +706,11 @@ msmsdcc_irq(int irq, void *dev_id)
|
|
|
spin_lock(&host->lock);
|
|
|
|
|
|
do {
|
|
|
- status = readl(base + MMCISTATUS);
|
|
|
-
|
|
|
- status &= (readl(base + MMCIMASK0) | MCI_DATABLOCKENDMASK);
|
|
|
- writel(status, base + MMCICLEAR);
|
|
|
+ struct mmc_data *data;
|
|
|
+ status = msmsdcc_readl(host, MMCISTATUS);
|
|
|
+ status &= (msmsdcc_readl(host, MMCIMASK0) |
|
|
|
+ MCI_DATABLOCKENDMASK);
|
|
|
+ msmsdcc_writel(host, status, MMCICLEAR);
|
|
|
|
|
|
if (status & MCI_SDIOINTR)
|
|
|
status &= ~MCI_SDIOINTR;
|
|
@@ -774,10 +782,11 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
|
|
if (host->cmdpoll && !msmsdcc_spin_on_status(host,
|
|
|
MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT,
|
|
|
CMD_SPINMAX)) {
|
|
|
- uint32_t status = readl(host->base + MMCISTATUS);
|
|
|
+ uint32_t status = msmsdcc_readl(host, MMCISTATUS);
|
|
|
msmsdcc_do_cmdirq(host, status);
|
|
|
- writel(MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT,
|
|
|
- host->base + MMCICLEAR);
|
|
|
+ msmsdcc_writel(host,
|
|
|
+ MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT,
|
|
|
+ MMCICLEAR);
|
|
|
host->stats.cmdpoll_hits++;
|
|
|
} else {
|
|
|
host->stats.cmdpoll_misses++;
|
|
@@ -836,11 +845,11 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|
|
if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
|
|
|
pwr |= MCI_OD;
|
|
|
|
|
|
- writel(clk, host->base + MMCICLOCK);
|
|
|
+ msmsdcc_writel(host, clk, MMCICLOCK);
|
|
|
|
|
|
if (host->pwr != pwr) {
|
|
|
host->pwr = pwr;
|
|
|
- writel(pwr, host->base + MMCIPOWER);
|
|
|
+ msmsdcc_writel(host, pwr, MMCIPOWER);
|
|
|
}
|
|
|
if (host->clks_on)
|
|
|
msmsdcc_enable_clocks(host, 0);
|
|
@@ -855,13 +864,13 @@ static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
|
|
|
|
|
|
spin_lock_irqsave(&host->lock, flags);
|
|
|
if (msmsdcc_sdioirq == 1) {
|
|
|
- status = readl(host->base + MMCIMASK0);
|
|
|
+ status = msmsdcc_readl(host, MMCIMASK0);
|
|
|
if (enable)
|
|
|
status |= MCI_SDIOINTOPERMASK;
|
|
|
else
|
|
|
status &= ~MCI_SDIOINTOPERMASK;
|
|
|
host->saved_irq0mask = status;
|
|
|
- writel(status, host->base + MMCIMASK0);
|
|
|
+ msmsdcc_writel(host, status, MMCIMASK0);
|
|
|
}
|
|
|
spin_unlock_irqrestore(&host->lock, flags);
|
|
|
}
|
|
@@ -950,19 +959,16 @@ msmsdcc_command_expired(unsigned long _data)
|
|
|
mrq = host->curr.mrq;
|
|
|
|
|
|
if (!mrq) {
|
|
|
- pr_info("%s: Command expiry misfire\n",
|
|
|
- mmc_hostname(host->mmc));
|
|
|
spin_unlock_irqrestore(&host->lock, flags);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- pr_err("%s: Command timeout (%p %p %p %p)\n",
|
|
|
- mmc_hostname(host->mmc), mrq, mrq->cmd,
|
|
|
- mrq->data, host->dma.sg);
|
|
|
+ pr_err("%s: Controller lockup detected\n",
|
|
|
+ mmc_hostname(host->mmc));
|
|
|
mrq->cmd->error = -ETIMEDOUT;
|
|
|
msmsdcc_stop_data(host);
|
|
|
|
|
|
- writel(0, host->base + MMCICOMMAND);
|
|
|
+ msmsdcc_writel(host, 0, MMCICOMMAND);
|
|
|
|
|
|
host->curr.mrq = NULL;
|
|
|
host->curr.cmd = NULL;
|
|
@@ -1143,10 +1149,10 @@ msmsdcc_probe(struct platform_device *pdev)
|
|
|
mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
|
|
|
mmc->max_seg_size = mmc->max_req_size;
|
|
|
|
|
|
- writel(0, host->base + MMCIMASK0);
|
|
|
- writel(0x5e007ff, host->base + MMCICLEAR); /* Add: 1 << 25 */
|
|
|
+ msmsdcc_writel(host, 0, MMCIMASK0);
|
|
|
+ msmsdcc_writel(host, 0x5e007ff, MMCICLEAR);
|
|
|
|
|
|
- writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
|
|
+ msmsdcc_writel(host, MCI_IRQENABLE, MMCIMASK0);
|
|
|
host->saved_irq0mask = MCI_IRQENABLE;
|
|
|
|
|
|
/*
|
|
@@ -1269,7 +1275,7 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
|
|
|
if (mmc->card && mmc->card->type != MMC_TYPE_SDIO)
|
|
|
rc = mmc_suspend_host(mmc, state);
|
|
|
if (!rc) {
|
|
|
- writel(0, host->base + MMCIMASK0);
|
|
|
+ msmsdcc_writel(host, 0, MMCIMASK0);
|
|
|
|
|
|
if (host->clks_on)
|
|
|
msmsdcc_enable_clocks(host, 0);
|
|
@@ -1292,7 +1298,7 @@ msmsdcc_resume(struct platform_device *dev)
|
|
|
if (!host->clks_on)
|
|
|
msmsdcc_enable_clocks(host, 1);
|
|
|
|
|
|
- writel(host->saved_irq0mask, host->base + MMCIMASK0);
|
|
|
+ msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0);
|
|
|
|
|
|
spin_unlock_irqrestore(&host->lock, flags);
|
|
|
|