aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSan Mehat <san@google.com>2009-11-16 13:17:30 -0500
committerDaniel Walker <dwalker@codeaurora.org>2010-03-18 16:15:47 -0400
commit8b1c2ba274c8416afb7eab3bd788f98a917efe06 (patch)
treeaeee912e0f9fd054bd8bf4bf436426ba07ef2077 /drivers
parent865c8064a2fb07100525097983966b8e789bde1a (diff)
mmc: msm_sdcc: Wrap readl/writel calls with appropriate clk delays
As it turns out, all sdcc register writes must be delayed by at least 3 core clock cycles for the writes to take effect. *sigh* Also removes the 30us constant delay on clock enable in favor of a 3 core clock delay. Signed-off-by: San Mehat <san@google.com> Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/msm_sdcc.c116
1 files changed, 61 insertions, 55 deletions
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b4b637223b75..3b096f64ec52 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -62,6 +62,7 @@ static inline int
62msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable) 62msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
63{ 63{
64 int rc; 64 int rc;
65
65 WARN_ON(enable == host->clks_on); 66 WARN_ON(enable == host->clks_on);
66 if (enable) { 67 if (enable) {
67 rc = clk_enable(host->pclk); 68 rc = clk_enable(host->pclk);
@@ -72,7 +73,8 @@ msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
72 clk_disable(host->pclk); 73 clk_disable(host->pclk);
73 return rc; 74 return rc;
74 } 75 }
75 udelay(30); 76 udelay(1 + ((3 * USEC_PER_SEC) /
77 (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
76 host->clks_on = 1; 78 host->clks_on = 1;
77 } else { 79 } else {
78 clk_disable(host->clk); 80 clk_disable(host->clk);
@@ -82,6 +84,20 @@ msmsdcc_enable_clocks(struct msmsdcc_host *host, int enable)
82 return 0; 84 return 0;
83} 85}
84 86
87static inline unsigned int
88msmsdcc_readl(struct msmsdcc_host *host, unsigned int reg)
89{
90 return readl(host->base + reg);
91}
92
93static inline void
94msmsdcc_writel(struct msmsdcc_host *host, u32 data, unsigned int reg)
95{
96 writel(data, host->base + reg);
97 /* 3 clk delay required! */
98 udelay(1 + ((3 * USEC_PER_SEC) /
99 (host->clk_rate ? host->clk_rate : msmsdcc_fmin)));
100}
85 101
86static void 102static void
87msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, 103msmsdcc_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,
90static void 106static void
91msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq) 107msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
92{ 108{
93 writel(0, host->base + MMCICOMMAND); 109 msmsdcc_writel(host, 0, MMCICOMMAND);
94 110
95 BUG_ON(host->curr.data); 111 BUG_ON(host->curr.data);
96 112
@@ -116,7 +132,7 @@ msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
116static void 132static void
117msmsdcc_stop_data(struct msmsdcc_host *host) 133msmsdcc_stop_data(struct msmsdcc_host *host)
118{ 134{
119 writel(0, host->base + MMCIDATACTRL); 135 msmsdcc_writel(host, 0, MMCIDATACTRL);
120 host->curr.data = NULL; 136 host->curr.data = NULL;
121 host->curr.got_dataend = host->curr.got_datablkend = 0; 137 host->curr.got_dataend = host->curr.got_datablkend = 0;
122} 138}
@@ -200,7 +216,7 @@ msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
200 if (!mrq->data->error) 216 if (!mrq->data->error)
201 host->curr.data_xfered = host->curr.xfer_size; 217 host->curr.data_xfered = host->curr.xfer_size;
202 if (!mrq->data->stop || mrq->cmd->error) { 218 if (!mrq->data->stop || mrq->cmd->error) {
203 writel(0, host->base + MMCICOMMAND); 219 msmsdcc_writel(host, 0, MMCICOMMAND);
204 host->curr.mrq = NULL; 220 host->curr.mrq = NULL;
205 host->curr.cmd = NULL; 221 host->curr.cmd = NULL;
206 mrq->data->bytes_xfered = host->curr.data_xfered; 222 mrq->data->bytes_xfered = host->curr.data_xfered;
@@ -337,7 +353,6 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data)
337{ 353{
338 unsigned int datactrl, timeout; 354 unsigned int datactrl, timeout;
339 unsigned long long clks; 355 unsigned long long clks;
340 void __iomem *base = host->base;
341 unsigned int pio_irqmask = 0; 356 unsigned int pio_irqmask = 0;
342 357
343 host->curr.data = data; 358 host->curr.data = data;
@@ -352,9 +367,9 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data)
352 clks = (unsigned long long)data->timeout_ns * host->clk_rate; 367 clks = (unsigned long long)data->timeout_ns * host->clk_rate;
353 do_div(clks, NSEC_PER_SEC); 368 do_div(clks, NSEC_PER_SEC);
354 timeout = data->timeout_clks + (unsigned int)clks; 369 timeout = data->timeout_clks + (unsigned int)clks;
355 writel(timeout, base + MMCIDATATIMER); 370 msmsdcc_writel(host, timeout, MMCIDATATIMER);
356 371
357 writel(host->curr.xfer_size, base + MMCIDATALENGTH); 372 msmsdcc_writel(host, host->curr.xfer_size, MMCIDATALENGTH);
358 373
359 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4); 374 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
360 375
@@ -376,8 +391,8 @@ msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data)
376 if (data->flags & MMC_DATA_READ) 391 if (data->flags & MMC_DATA_READ)
377 datactrl |= MCI_DPSM_DIRECTION; 392 datactrl |= MCI_DPSM_DIRECTION;
378 393
379 writel(pio_irqmask, base + MMCIMASK1); 394 msmsdcc_writel(host, pio_irqmask, MMCIMASK1);
380 writel(datactrl, base + MMCIDATACTRL); 395 msmsdcc_writel(host, datactrl, MMCIDATACTRL);
381 396
382 if (datactrl & MCI_DPSM_DMAENABLE) { 397 if (datactrl & MCI_DPSM_DMAENABLE) {
383 host->dma.busy = 1; 398 host->dma.busy = 1;
@@ -398,12 +413,8 @@ snoop_cccr_abort(struct mmc_command *cmd)
398static void 413static void
399msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c) 414msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
400{ 415{
401 void __iomem *base = host->base; 416 if (msmsdcc_readl(host, MMCICOMMAND) & MCI_CPSM_ENABLE)
402 417 msmsdcc_writel(host, 0, MMCICOMMAND);
403 if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
404 writel(0, base + MMCICOMMAND);
405 udelay(2 + ((5 * 1000000) / host->clk_rate));
406 }
407 418
408 c |= cmd->opcode | MCI_CPSM_ENABLE; 419 c |= cmd->opcode | MCI_CPSM_ENABLE;
409 420
@@ -428,8 +439,8 @@ msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
428 439
429 host->stats.cmds++; 440 host->stats.cmds++;
430 441
431 writel(cmd->arg, base + MMCIARGUMENT); 442 msmsdcc_writel(host, cmd->arg, MMCIARGUMENT);
432 writel(c, base + MMCICOMMAND); 443 msmsdcc_writel(host, c, MMCICOMMAND);
433} 444}
434 445
435static void 446static void
@@ -463,13 +474,11 @@ msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
463static int 474static int
464msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain) 475msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
465{ 476{
466 void __iomem *base = host->base;
467 uint32_t *ptr = (uint32_t *) buffer; 477 uint32_t *ptr = (uint32_t *) buffer;
468 int count = 0; 478 int count = 0;
469 479
470 while (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL) { 480 while (msmsdcc_readl(host, MMCISTATUS) & MCI_RXDATAAVLBL) {
471 481 *ptr = msmsdcc_readl(host, MMCIFIFO + (count % MCI_FIFOSIZE));
472 *ptr = readl(base + MMCIFIFO + (count % MCI_FIFOSIZE));
473 ptr++; 482 ptr++;
474 count += sizeof(uint32_t); 483 count += sizeof(uint32_t);
475 484
@@ -501,7 +510,7 @@ msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
501 if (remain == 0) 510 if (remain == 0)
502 break; 511 break;
503 512
504 status = readl(base + MMCISTATUS); 513 status = msmsdcc_readl(host, MMCISTATUS);
505 } while (status & MCI_TXFIFOHALFEMPTY); 514 } while (status & MCI_TXFIFOHALFEMPTY);
506 515
507 return ptr - buffer; 516 return ptr - buffer;
@@ -511,7 +520,7 @@ static int
511msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin) 520msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin)
512{ 521{
513 while (maxspin) { 522 while (maxspin) {
514 if ((readl(host->base + MMCISTATUS) & mask)) 523 if ((msmsdcc_readl(host, MMCISTATUS) & mask))
515 return 0; 524 return 0;
516 udelay(1); 525 udelay(1);
517 --maxspin; 526 --maxspin;
@@ -523,10 +532,9 @@ static int
523msmsdcc_pio_irq(int irq, void *dev_id) 532msmsdcc_pio_irq(int irq, void *dev_id)
524{ 533{
525 struct msmsdcc_host *host = dev_id; 534 struct msmsdcc_host *host = dev_id;
526 void __iomem *base = host->base;
527 uint32_t status; 535 uint32_t status;
528 536
529 status = readl(base + MMCISTATUS); 537 status = msmsdcc_readl(host, MMCISTATUS);
530 538
531 do { 539 do {
532 unsigned long flags; 540 unsigned long flags;
@@ -581,14 +589,14 @@ msmsdcc_pio_irq(int irq, void *dev_id)
581 host->pio.sg_off = 0; 589 host->pio.sg_off = 0;
582 } 590 }
583 591
584 status = readl(base + MMCISTATUS); 592 status = msmsdcc_readl(host, MMCISTATUS);
585 } while (1); 593 } while (1);
586 594
587 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) 595 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
588 writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); 596 msmsdcc_writel(host, MCI_RXDATAAVLBLMASK, MMCIMASK1);
589 597
590 if (!host->curr.xfer_remain) 598 if (!host->curr.xfer_remain)
591 writel(0, base + MMCIMASK1); 599 msmsdcc_writel(host, 0, MMCIMASK1);
592 600
593 return IRQ_HANDLED; 601 return IRQ_HANDLED;
594} 602}
@@ -596,13 +604,12 @@ msmsdcc_pio_irq(int irq, void *dev_id)
596static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status) 604static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
597{ 605{
598 struct mmc_command *cmd = host->curr.cmd; 606 struct mmc_command *cmd = host->curr.cmd;
599 void __iomem *base = host->base;
600 607
601 host->curr.cmd = NULL; 608 host->curr.cmd = NULL;
602 cmd->resp[0] = readl(base + MMCIRESPONSE0); 609 cmd->resp[0] = msmsdcc_readl(host, MMCIRESPONSE0);
603 cmd->resp[1] = readl(base + MMCIRESPONSE1); 610 cmd->resp[1] = msmsdcc_readl(host, MMCIRESPONSE1);
604 cmd->resp[2] = readl(base + MMCIRESPONSE2); 611 cmd->resp[2] = msmsdcc_readl(host, MMCIRESPONSE2);
605 cmd->resp[3] = readl(base + MMCIRESPONSE3); 612 cmd->resp[3] = msmsdcc_readl(host, MMCIRESPONSE3);
606 613
607 del_timer(&host->command_timer); 614 del_timer(&host->command_timer);
608 if (status & MCI_CMDTIMEOUT) { 615 if (status & MCI_CMDTIMEOUT) {
@@ -699,10 +706,11 @@ msmsdcc_irq(int irq, void *dev_id)
699 spin_lock(&host->lock); 706 spin_lock(&host->lock);
700 707
701 do { 708 do {
702 status = readl(base + MMCISTATUS); 709 struct mmc_data *data;
703 710 status = msmsdcc_readl(host, MMCISTATUS);
704 status &= (readl(base + MMCIMASK0) | MCI_DATABLOCKENDMASK); 711 status &= (msmsdcc_readl(host, MMCIMASK0) |
705 writel(status, base + MMCICLEAR); 712 MCI_DATABLOCKENDMASK);
713 msmsdcc_writel(host, status, MMCICLEAR);
706 714
707 if (status & MCI_SDIOINTR) 715 if (status & MCI_SDIOINTR)
708 status &= ~MCI_SDIOINTR; 716 status &= ~MCI_SDIOINTR;
@@ -774,10 +782,11 @@ msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
774 if (host->cmdpoll && !msmsdcc_spin_on_status(host, 782 if (host->cmdpoll && !msmsdcc_spin_on_status(host,
775 MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT, 783 MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT,
776 CMD_SPINMAX)) { 784 CMD_SPINMAX)) {
777 uint32_t status = readl(host->base + MMCISTATUS); 785 uint32_t status = msmsdcc_readl(host, MMCISTATUS);
778 msmsdcc_do_cmdirq(host, status); 786 msmsdcc_do_cmdirq(host, status);
779 writel(MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT, 787 msmsdcc_writel(host,
780 host->base + MMCICLEAR); 788 MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT,
789 MMCICLEAR);
781 host->stats.cmdpoll_hits++; 790 host->stats.cmdpoll_hits++;
782 } else { 791 } else {
783 host->stats.cmdpoll_misses++; 792 host->stats.cmdpoll_misses++;
@@ -836,11 +845,11 @@ msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
836 if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) 845 if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
837 pwr |= MCI_OD; 846 pwr |= MCI_OD;
838 847
839 writel(clk, host->base + MMCICLOCK); 848 msmsdcc_writel(host, clk, MMCICLOCK);
840 849
841 if (host->pwr != pwr) { 850 if (host->pwr != pwr) {
842 host->pwr = pwr; 851 host->pwr = pwr;
843 writel(pwr, host->base + MMCIPOWER); 852 msmsdcc_writel(host, pwr, MMCIPOWER);
844 } 853 }
845 if (host->clks_on) 854 if (host->clks_on)
846 msmsdcc_enable_clocks(host, 0); 855 msmsdcc_enable_clocks(host, 0);
@@ -855,13 +864,13 @@ static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
855 864
856 spin_lock_irqsave(&host->lock, flags); 865 spin_lock_irqsave(&host->lock, flags);
857 if (msmsdcc_sdioirq == 1) { 866 if (msmsdcc_sdioirq == 1) {
858 status = readl(host->base + MMCIMASK0); 867 status = msmsdcc_readl(host, MMCIMASK0);
859 if (enable) 868 if (enable)
860 status |= MCI_SDIOINTOPERMASK; 869 status |= MCI_SDIOINTOPERMASK;
861 else 870 else
862 status &= ~MCI_SDIOINTOPERMASK; 871 status &= ~MCI_SDIOINTOPERMASK;
863 host->saved_irq0mask = status; 872 host->saved_irq0mask = status;
864 writel(status, host->base + MMCIMASK0); 873 msmsdcc_writel(host, status, MMCIMASK0);
865 } 874 }
866 spin_unlock_irqrestore(&host->lock, flags); 875 spin_unlock_irqrestore(&host->lock, flags);
867} 876}
@@ -950,19 +959,16 @@ msmsdcc_command_expired(unsigned long _data)
950 mrq = host->curr.mrq; 959 mrq = host->curr.mrq;
951 960
952 if (!mrq) { 961 if (!mrq) {
953 pr_info("%s: Command expiry misfire\n",
954 mmc_hostname(host->mmc));
955 spin_unlock_irqrestore(&host->lock, flags); 962 spin_unlock_irqrestore(&host->lock, flags);
956 return; 963 return;
957 } 964 }
958 965
959 pr_err("%s: Command timeout (%p %p %p %p)\n", 966 pr_err("%s: Controller lockup detected\n",
960 mmc_hostname(host->mmc), mrq, mrq->cmd, 967 mmc_hostname(host->mmc));
961 mrq->data, host->dma.sg);
962 mrq->cmd->error = -ETIMEDOUT; 968 mrq->cmd->error = -ETIMEDOUT;
963 msmsdcc_stop_data(host); 969 msmsdcc_stop_data(host);
964 970
965 writel(0, host->base + MMCICOMMAND); 971 msmsdcc_writel(host, 0, MMCICOMMAND);
966 972
967 host->curr.mrq = NULL; 973 host->curr.mrq = NULL;
968 host->curr.cmd = NULL; 974 host->curr.cmd = NULL;
@@ -1143,10 +1149,10 @@ msmsdcc_probe(struct platform_device *pdev)
1143 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */ 1149 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
1144 mmc->max_seg_size = mmc->max_req_size; 1150 mmc->max_seg_size = mmc->max_req_size;
1145 1151
1146 writel(0, host->base + MMCIMASK0); 1152 msmsdcc_writel(host, 0, MMCIMASK0);
1147 writel(0x5e007ff, host->base + MMCICLEAR); /* Add: 1 << 25 */ 1153 msmsdcc_writel(host, 0x5e007ff, MMCICLEAR);
1148 1154
1149 writel(MCI_IRQENABLE, host->base + MMCIMASK0); 1155 msmsdcc_writel(host, MCI_IRQENABLE, MMCIMASK0);
1150 host->saved_irq0mask = MCI_IRQENABLE; 1156 host->saved_irq0mask = MCI_IRQENABLE;
1151 1157
1152 /* 1158 /*
@@ -1269,7 +1275,7 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
1269 if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) 1275 if (mmc->card && mmc->card->type != MMC_TYPE_SDIO)
1270 rc = mmc_suspend_host(mmc, state); 1276 rc = mmc_suspend_host(mmc, state);
1271 if (!rc) { 1277 if (!rc) {
1272 writel(0, host->base + MMCIMASK0); 1278 msmsdcc_writel(host, 0, MMCIMASK0);
1273 1279
1274 if (host->clks_on) 1280 if (host->clks_on)
1275 msmsdcc_enable_clocks(host, 0); 1281 msmsdcc_enable_clocks(host, 0);
@@ -1292,7 +1298,7 @@ msmsdcc_resume(struct platform_device *dev)
1292 if (!host->clks_on) 1298 if (!host->clks_on)
1293 msmsdcc_enable_clocks(host, 1); 1299 msmsdcc_enable_clocks(host, 1);
1294 1300
1295 writel(host->saved_irq0mask, host->base + MMCIMASK0); 1301 msmsdcc_writel(host, host->saved_irq0mask, MMCIMASK0);
1296 1302
1297 spin_unlock_irqrestore(&host->lock, flags); 1303 spin_unlock_irqrestore(&host->lock, flags);
1298 1304