blob: 68bce6460d96e55bc99f928c54733500c8bd8775 [file] [log] [blame]
San Mehat9d2bd732009-09-22 16:44:22 -07001/*
2 * linux/drivers/mmc/host/msm_sdcc.c - Qualcomm MSM 7X00A SDCC Driver
3 *
4 * Copyright (C) 2007 Google Inc,
5 * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Based on mmci.c
12 *
13 * Author: San Mehat (san@android.com)
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/init.h>
20#include <linux/ioport.h>
21#include <linux/device.h>
22#include <linux/interrupt.h>
23#include <linux/delay.h>
24#include <linux/err.h>
25#include <linux/highmem.h>
26#include <linux/log2.h>
27#include <linux/mmc/host.h>
28#include <linux/mmc/card.h>
29#include <linux/clk.h>
30#include <linux/scatterlist.h>
31#include <linux/platform_device.h>
32#include <linux/dma-mapping.h>
33#include <linux/debugfs.h>
34#include <linux/io.h>
35#include <linux/memory.h>
36
37#include <asm/cacheflush.h>
38#include <asm/div64.h>
39#include <asm/sizes.h>
40
41#include <asm/mach/mmc.h>
42#include <mach/msm_iomap.h>
43#include <mach/dma.h>
44#include <mach/htc_pwrsink.h>
45
46
47#include "msm_sdcc.h"
48
49#define DRIVER_NAME "msm-sdcc"
50
51static unsigned int msmsdcc_fmin = 144000;
52static unsigned int msmsdcc_fmax = 50000000;
53static unsigned int msmsdcc_4bit = 1;
54static unsigned int msmsdcc_pwrsave = 1;
55static unsigned int msmsdcc_piopoll = 1;
56static unsigned int msmsdcc_sdioirq;
57
58#define PIO_SPINMAX 30
59#define CMD_SPINMAX 20
60
61
62
63static void
64msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd,
65 u32 c);
66
67static void
68msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq)
69{
70 writel(0, host->base + MMCICOMMAND);
71
72 BUG_ON(host->curr.data);
73
74 host->curr.mrq = NULL;
75 host->curr.cmd = NULL;
76
77 if (mrq->data)
78 mrq->data->bytes_xfered = host->curr.data_xfered;
79 if (mrq->cmd->error == -ETIMEDOUT)
80 mdelay(5);
81
82 /*
83 * Need to drop the host lock here; mmc_request_done may call
84 * back into the driver...
85 */
86 spin_unlock(&host->lock);
87 mmc_request_done(host->mmc, mrq);
88 spin_lock(&host->lock);
89}
90
91static void
92msmsdcc_stop_data(struct msmsdcc_host *host)
93{
94 writel(0, host->base + MMCIDATACTRL);
95 host->curr.data = NULL;
96 host->curr.got_dataend = host->curr.got_datablkend = 0;
97}
98
99uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host)
100{
101 if (host->pdev_id == 1)
102 return MSM_SDC1_PHYS + MMCIFIFO;
103 else if (host->pdev_id == 2)
104 return MSM_SDC2_PHYS + MMCIFIFO;
105 else if (host->pdev_id == 3)
106 return MSM_SDC3_PHYS + MMCIFIFO;
107 else if (host->pdev_id == 4)
108 return MSM_SDC4_PHYS + MMCIFIFO;
109 else
110 BUG();
111 return 0;
112}
113
114static void
115msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd,
116 unsigned int result,
117 struct msm_dmov_errdata *err)
118{
119 struct msmsdcc_dma_data *dma_data =
120 container_of(cmd, struct msmsdcc_dma_data, hdr);
121 struct msmsdcc_host *host = dma_data->host;
122 unsigned long flags;
123 struct mmc_request *mrq;
124
125 spin_lock_irqsave(&host->lock, flags);
126 mrq = host->curr.mrq;
127 BUG_ON(!mrq);
128
129 if (!(result & DMOV_RSLT_VALID)) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700130 pr_err("msmsdcc: Invalid DataMover result\n");
San Mehat9d2bd732009-09-22 16:44:22 -0700131 goto out;
132 }
133
134 if (result & DMOV_RSLT_DONE) {
135 host->curr.data_xfered = host->curr.xfer_size;
136 } else {
137 /* Error or flush */
138 if (result & DMOV_RSLT_ERROR)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700139 pr_err("%s: DMA error (0x%.8x)\n",
San Mehat9d2bd732009-09-22 16:44:22 -0700140 mmc_hostname(host->mmc), result);
141 if (result & DMOV_RSLT_FLUSH)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700142 pr_err("%s: DMA channel flushed (0x%.8x)\n",
San Mehat9d2bd732009-09-22 16:44:22 -0700143 mmc_hostname(host->mmc), result);
144 if (err)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700145 pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n",
San Mehat9d2bd732009-09-22 16:44:22 -0700146 err->flush[0], err->flush[1], err->flush[2],
147 err->flush[3], err->flush[4], err->flush[5]);
148 if (!mrq->data->error)
149 mrq->data->error = -EIO;
150 }
151 host->dma.busy = 0;
152 dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
153 host->dma.dir);
154
155 if (host->curr.user_pages) {
156 struct scatterlist *sg = host->dma.sg;
157 int i;
158
159 for (i = 0; i < host->dma.num_ents; i++, sg++)
160 flush_dcache_page(sg_page(sg));
161 }
162
163 host->dma.sg = NULL;
164
165 if ((host->curr.got_dataend && host->curr.got_datablkend)
166 || mrq->data->error) {
167
168 /*
169 * If we've already gotten our DATAEND / DATABLKEND
170 * for this request, then complete it through here.
171 */
172 msmsdcc_stop_data(host);
173
174 if (!mrq->data->error)
175 host->curr.data_xfered = host->curr.xfer_size;
176 if (!mrq->data->stop || mrq->cmd->error) {
177 writel(0, host->base + MMCICOMMAND);
178 host->curr.mrq = NULL;
179 host->curr.cmd = NULL;
180 mrq->data->bytes_xfered = host->curr.data_xfered;
181
182 spin_unlock_irqrestore(&host->lock, flags);
183 mmc_request_done(host->mmc, mrq);
184 return;
185 } else
186 msmsdcc_start_command(host, mrq->data->stop, 0);
187 }
188
189out:
190 spin_unlock_irqrestore(&host->lock, flags);
191 return;
192}
193
194static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data)
195{
196 if (host->dma.channel == -1)
197 return -ENOENT;
198
199 if ((data->blksz * data->blocks) < MCI_FIFOSIZE)
200 return -EINVAL;
201 if ((data->blksz * data->blocks) % MCI_FIFOSIZE)
202 return -EINVAL;
203 return 0;
204}
205
206static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data)
207{
208 struct msmsdcc_nc_dmadata *nc;
209 dmov_box *box;
210 uint32_t rows;
211 uint32_t crci;
212 unsigned int n;
213 int i, rc;
214 struct scatterlist *sg = data->sg;
215
216 rc = validate_dma(host, data);
217 if (rc)
218 return rc;
219
220 host->dma.sg = data->sg;
221 host->dma.num_ents = data->sg_len;
222
223 nc = host->dma.nc;
224
225 if (host->pdev_id == 1)
226 crci = MSMSDCC_CRCI_SDC1;
227 else if (host->pdev_id == 2)
228 crci = MSMSDCC_CRCI_SDC2;
229 else if (host->pdev_id == 3)
230 crci = MSMSDCC_CRCI_SDC3;
231 else if (host->pdev_id == 4)
232 crci = MSMSDCC_CRCI_SDC4;
233 else {
234 host->dma.sg = NULL;
235 host->dma.num_ents = 0;
236 return -ENOENT;
237 }
238
239 if (data->flags & MMC_DATA_READ)
240 host->dma.dir = DMA_FROM_DEVICE;
241 else
242 host->dma.dir = DMA_TO_DEVICE;
243
244 host->curr.user_pages = 0;
245
246 n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg,
247 host->dma.num_ents, host->dma.dir);
248
249 if (n != host->dma.num_ents) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700250 pr_err("%s: Unable to map in all sg elements\n",
San Mehat9d2bd732009-09-22 16:44:22 -0700251 mmc_hostname(host->mmc));
252 host->dma.sg = NULL;
253 host->dma.num_ents = 0;
254 return -ENOMEM;
255 }
256
257 box = &nc->cmd[0];
258 for (i = 0; i < host->dma.num_ents; i++) {
259 box->cmd = CMD_MODE_BOX;
260
261 if (i == (host->dma.num_ents - 1))
262 box->cmd |= CMD_LC;
263 rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ?
264 (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 :
265 (sg_dma_len(sg) / MCI_FIFOSIZE) ;
266
267 if (data->flags & MMC_DATA_READ) {
268 box->src_row_addr = msmsdcc_fifo_addr(host);
269 box->dst_row_addr = sg_dma_address(sg);
270
271 box->src_dst_len = (MCI_FIFOSIZE << 16) |
272 (MCI_FIFOSIZE);
273 box->row_offset = MCI_FIFOSIZE;
274
275 box->num_rows = rows * ((1 << 16) + 1);
276 box->cmd |= CMD_SRC_CRCI(crci);
277 } else {
278 box->src_row_addr = sg_dma_address(sg);
279 box->dst_row_addr = msmsdcc_fifo_addr(host);
280
281 box->src_dst_len = (MCI_FIFOSIZE << 16) |
282 (MCI_FIFOSIZE);
283 box->row_offset = (MCI_FIFOSIZE << 16);
284
285 box->num_rows = rows * ((1 << 16) + 1);
286 box->cmd |= CMD_DST_CRCI(crci);
287 }
288 box++;
289 sg++;
290 }
291
292 /* location of command block must be 64 bit aligned */
293 BUG_ON(host->dma.cmd_busaddr & 0x07);
294
295 nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP;
296 host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST |
297 DMOV_CMD_ADDR(host->dma.cmdptr_busaddr);
298 host->dma.hdr.complete_func = msmsdcc_dma_complete_func;
299
300 return 0;
301}
302
303static void
304msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data)
305{
306 unsigned int datactrl, timeout;
307 unsigned long long clks;
308 void __iomem *base = host->base;
309 unsigned int pio_irqmask = 0;
310
311 host->curr.data = data;
312 host->curr.xfer_size = data->blksz * data->blocks;
313 host->curr.xfer_remain = host->curr.xfer_size;
314 host->curr.data_xfered = 0;
315 host->curr.got_dataend = 0;
316 host->curr.got_datablkend = 0;
317
318 memset(&host->pio, 0, sizeof(host->pio));
319
320 clks = (unsigned long long)data->timeout_ns * host->clk_rate;
321 do_div(clks, 1000000000UL);
322 timeout = data->timeout_clks + (unsigned int)clks;
323 writel(timeout, base + MMCIDATATIMER);
324
325 writel(host->curr.xfer_size, base + MMCIDATALENGTH);
326
327 datactrl = MCI_DPSM_ENABLE | (data->blksz << 4);
328
329 if (!msmsdcc_config_dma(host, data))
330 datactrl |= MCI_DPSM_DMAENABLE;
331 else {
332 host->pio.sg = data->sg;
333 host->pio.sg_len = data->sg_len;
334 host->pio.sg_off = 0;
335
336 if (data->flags & MMC_DATA_READ) {
337 pio_irqmask = MCI_RXFIFOHALFFULLMASK;
338 if (host->curr.xfer_remain < MCI_FIFOSIZE)
339 pio_irqmask |= MCI_RXDATAAVLBLMASK;
340 } else
341 pio_irqmask = MCI_TXFIFOHALFEMPTYMASK;
342 }
343
344 if (data->flags & MMC_DATA_READ)
345 datactrl |= MCI_DPSM_DIRECTION;
346
347 writel(pio_irqmask, base + MMCIMASK1);
348 writel(datactrl, base + MMCIDATACTRL);
349
350 if (datactrl & MCI_DPSM_DMAENABLE) {
351 host->dma.busy = 1;
352 msm_dmov_enqueue_cmd(host->dma.channel, &host->dma.hdr);
353 }
354}
355
356static void
357msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c)
358{
359 void __iomem *base = host->base;
360
361 if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
362 writel(0, base + MMCICOMMAND);
363 udelay(2 + ((5 * 1000000) / host->clk_rate));
364 }
365
366 c |= cmd->opcode | MCI_CPSM_ENABLE;
367
368 if (cmd->flags & MMC_RSP_PRESENT) {
369 if (cmd->flags & MMC_RSP_136)
370 c |= MCI_CPSM_LONGRSP;
371 c |= MCI_CPSM_RESPONSE;
372 }
373
374 if ((((cmd->opcode == 17) || (cmd->opcode == 18)) ||
375 ((cmd->opcode == 24) || (cmd->opcode == 25))) ||
376 (cmd->opcode == 53))
377 c |= MCI_CSPM_DATCMD;
378
379 if (cmd == cmd->mrq->stop)
380 c |= MCI_CSPM_MCIABORT;
381
382 host->curr.cmd = cmd;
383
384 host->stats.cmds++;
385
386 writel(cmd->arg, base + MMCIARGUMENT);
387 writel(c, base + MMCICOMMAND);
388}
389
390static void
391msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data,
392 unsigned int status)
393{
394 if (status & MCI_DATACRCFAIL) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700395 pr_err("%s: Data CRC error\n", mmc_hostname(host->mmc));
396 pr_err("%s: opcode 0x%.8x\n", __func__,
San Mehat9d2bd732009-09-22 16:44:22 -0700397 data->mrq->cmd->opcode);
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700398 pr_err("%s: blksz %d, blocks %d\n", __func__,
San Mehat9d2bd732009-09-22 16:44:22 -0700399 data->blksz, data->blocks);
400 data->error = -EILSEQ;
401 } else if (status & MCI_DATATIMEOUT) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700402 pr_err("%s: Data timeout\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -0700403 data->error = -ETIMEDOUT;
404 } else if (status & MCI_RXOVERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700405 pr_err("%s: RX overrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -0700406 data->error = -EIO;
407 } else if (status & MCI_TXUNDERRUN) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700408 pr_err("%s: TX underrun\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -0700409 data->error = -EIO;
410 } else {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700411 pr_err("%s: Unknown error (0x%.8x)\n",
412 mmc_hostname(host->mmc), status);
San Mehat9d2bd732009-09-22 16:44:22 -0700413 data->error = -EIO;
414 }
415}
416
417
418static int
419msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain)
420{
421 void __iomem *base = host->base;
422 uint32_t *ptr = (uint32_t *) buffer;
423 int count = 0;
424
425 while (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL) {
426
427 *ptr = readl(base + MMCIFIFO + (count % MCI_FIFOSIZE));
428 ptr++;
429 count += sizeof(uint32_t);
430
431 remain -= sizeof(uint32_t);
432 if (remain == 0)
433 break;
434 }
435 return count;
436}
437
438static int
439msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer,
440 unsigned int remain, u32 status)
441{
442 void __iomem *base = host->base;
443 char *ptr = buffer;
444
445 do {
446 unsigned int count, maxcnt;
447
448 maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE :
449 MCI_FIFOHALFSIZE;
450 count = min(remain, maxcnt);
451
452 writesl(base + MMCIFIFO, ptr, count >> 2);
453 ptr += count;
454 remain -= count;
455
456 if (remain == 0)
457 break;
458
459 status = readl(base + MMCISTATUS);
460 } while (status & MCI_TXFIFOHALFEMPTY);
461
462 return ptr - buffer;
463}
464
465static int
466msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin)
467{
468 while (maxspin) {
469 if ((readl(host->base + MMCISTATUS) & mask))
470 return 0;
471 udelay(1);
472 --maxspin;
473 }
474 return -ETIMEDOUT;
475}
476
477static int
478msmsdcc_pio_irq(int irq, void *dev_id)
479{
480 struct msmsdcc_host *host = dev_id;
481 void __iomem *base = host->base;
482 uint32_t status;
483
484 status = readl(base + MMCISTATUS);
485
486 do {
487 unsigned long flags;
488 unsigned int remain, len;
489 char *buffer;
490
491 if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL))) {
492 if (host->curr.xfer_remain == 0 || !msmsdcc_piopoll)
493 break;
494
495 if (msmsdcc_spin_on_status(host,
496 (MCI_TXFIFOHALFEMPTY |
497 MCI_RXDATAAVLBL),
498 PIO_SPINMAX)) {
499 break;
500 }
501 }
502
503 /* Map the current scatter buffer */
504 local_irq_save(flags);
505 buffer = kmap_atomic(sg_page(host->pio.sg),
506 KM_BIO_SRC_IRQ) + host->pio.sg->offset;
507 buffer += host->pio.sg_off;
508 remain = host->pio.sg->length - host->pio.sg_off;
509 len = 0;
510 if (status & MCI_RXACTIVE)
511 len = msmsdcc_pio_read(host, buffer, remain);
512 if (status & MCI_TXACTIVE)
513 len = msmsdcc_pio_write(host, buffer, remain, status);
514
515 /* Unmap the buffer */
516 kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
517 local_irq_restore(flags);
518
519 host->pio.sg_off += len;
520 host->curr.xfer_remain -= len;
521 host->curr.data_xfered += len;
522 remain -= len;
523
524 if (remain == 0) {
525 /* This sg page is full - do some housekeeping */
526 if (status & MCI_RXACTIVE && host->curr.user_pages)
527 flush_dcache_page(sg_page(host->pio.sg));
528
529 if (!--host->pio.sg_len) {
530 memset(&host->pio, 0, sizeof(host->pio));
531 break;
532 }
533
534 /* Advance to next sg */
535 host->pio.sg++;
536 host->pio.sg_off = 0;
537 }
538
539 status = readl(base + MMCISTATUS);
540 } while (1);
541
542 if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE)
543 writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
544
545 if (!host->curr.xfer_remain)
546 writel(0, base + MMCIMASK1);
547
548 return IRQ_HANDLED;
549}
550
551static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status)
552{
553 struct mmc_command *cmd = host->curr.cmd;
554 void __iomem *base = host->base;
555
556 host->curr.cmd = NULL;
557 cmd->resp[0] = readl(base + MMCIRESPONSE0);
558 cmd->resp[1] = readl(base + MMCIRESPONSE1);
559 cmd->resp[2] = readl(base + MMCIRESPONSE2);
560 cmd->resp[3] = readl(base + MMCIRESPONSE3);
561
562 del_timer(&host->command_timer);
563 if (status & MCI_CMDTIMEOUT) {
564 cmd->error = -ETIMEDOUT;
565 } else if (status & MCI_CMDCRCFAIL &&
566 cmd->flags & MMC_RSP_CRC) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700567 pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -0700568 cmd->error = -EILSEQ;
569 }
570
571 if (!cmd->data || cmd->error) {
572 if (host->curr.data && host->dma.sg)
573 msm_dmov_stop_cmd(host->dma.channel,
574 &host->dma.hdr, 0);
575 else if (host->curr.data) { /* Non DMA */
576 msmsdcc_stop_data(host);
577 msmsdcc_request_end(host, cmd->mrq);
578 } else /* host->data == NULL */
579 msmsdcc_request_end(host, cmd->mrq);
580 } else if (!(cmd->data->flags & MMC_DATA_READ))
581 msmsdcc_start_data(host, cmd->data);
582}
583
584static irqreturn_t
585msmsdcc_irq(int irq, void *dev_id)
586{
587 struct msmsdcc_host *host = dev_id;
588 void __iomem *base = host->base;
589 u32 status;
590 int ret = 0;
591 int cardint = 0;
592
593 spin_lock(&host->lock);
594
595 do {
596 struct mmc_data *data;
597 status = readl(base + MMCISTATUS);
598
599 status &= (readl(base + MMCIMASK0) |
600 MCI_DATABLOCKENDMASK);
601 writel(status, base + MMCICLEAR);
602
603 data = host->curr.data;
604 if (data) {
605 /* Check for data errors */
606 if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|
607 MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
608 msmsdcc_data_err(host, data, status);
609 host->curr.data_xfered = 0;
610 if (host->dma.sg)
611 msm_dmov_stop_cmd(host->dma.channel,
612 &host->dma.hdr, 0);
613 else {
614 msmsdcc_stop_data(host);
615 if (!data->stop)
616 msmsdcc_request_end(host,
617 data->mrq);
618 else
619 msmsdcc_start_command(host,
620 data->stop,
621 0);
622 }
623 }
624
625 /* Check for data done */
626 if (!host->curr.got_dataend && (status & MCI_DATAEND))
627 host->curr.got_dataend = 1;
628
629 if (!host->curr.got_datablkend &&
630 (status & MCI_DATABLOCKEND)) {
631 host->curr.got_datablkend = 1;
632 }
633
634 if (host->curr.got_dataend &&
635 host->curr.got_datablkend) {
636 /*
637 * If DMA is still in progress, we complete
638 * via the completion handler
639 */
640 if (!host->dma.busy) {
641 /*
642 * There appears to be an issue in the
643 * controller where if you request a
644 * small block transfer (< fifo size),
645 * you may get your DATAEND/DATABLKEND
646 * irq without the PIO data irq.
647 *
648 * Check to see if theres still data
649 * to be read, and simulate a PIO irq.
650 */
651 if (readl(base + MMCISTATUS) &
652 MCI_RXDATAAVLBL)
653 msmsdcc_pio_irq(1, host);
654
655 msmsdcc_stop_data(host);
656 if (!data->error)
657 host->curr.data_xfered =
658 host->curr.xfer_size;
659
660 if (!data->stop)
661 msmsdcc_request_end(host,
662 data->mrq);
663 else
664 msmsdcc_start_command(host,
665 data->stop, 0);
666 }
667 }
668 }
669
670 if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL |
671 MCI_CMDTIMEOUT) && host->curr.cmd) {
672 msmsdcc_do_cmdirq(host, status);
673 }
674
675 if (status & MCI_SDIOINTOPER) {
676 cardint = 1;
677 status &= ~MCI_SDIOINTOPER;
678 }
679 ret = 1;
680 } while (status);
681
682 spin_unlock(&host->lock);
683
684 /*
685 * We have to delay handling the card interrupt as it calls
686 * back into the driver.
687 */
688 if (cardint)
689 mmc_signal_sdio_irq(host->mmc);
690
691 return IRQ_RETVAL(ret);
692}
693
694static void
695msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq)
696{
697 struct msmsdcc_host *host = mmc_priv(mmc);
698 unsigned long flags;
699
700 WARN_ON(host->curr.mrq != NULL);
701 WARN_ON(host->pwr == 0);
702
703 spin_lock_irqsave(&host->lock, flags);
704
705 host->stats.reqs++;
706
707 if (host->eject) {
708 if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) {
709 mrq->cmd->error = 0;
710 mrq->data->bytes_xfered = mrq->data->blksz *
711 mrq->data->blocks;
712 } else
713 mrq->cmd->error = -ENOMEDIUM;
714
715 spin_unlock_irqrestore(&host->lock, flags);
716 mmc_request_done(mmc, mrq);
717 return;
718 }
719
720 host->curr.mrq = mrq;
721
722 if (mrq->data && mrq->data->flags & MMC_DATA_READ)
723 msmsdcc_start_data(host, mrq->data);
724
725 msmsdcc_start_command(host, mrq->cmd, 0);
726
727 if (host->cmdpoll && !msmsdcc_spin_on_status(host,
728 MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT,
729 CMD_SPINMAX)) {
730 uint32_t status = readl(host->base + MMCISTATUS);
731 msmsdcc_do_cmdirq(host, status);
732 writel(MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT,
733 host->base + MMCICLEAR);
734 host->stats.cmdpoll_hits++;
735 } else {
736 host->stats.cmdpoll_misses++;
737 mod_timer(&host->command_timer, jiffies + HZ);
738 }
739 spin_unlock_irqrestore(&host->lock, flags);
740}
741
742static void
743msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
744{
745 struct msmsdcc_host *host = mmc_priv(mmc);
746 u32 clk = 0, pwr = 0;
747 int rc;
748
749 if (ios->clock) {
750
751 if (!host->clks_on) {
752 clk_enable(host->pclk);
753 clk_enable(host->clk);
754 host->clks_on = 1;
755 }
756 if (ios->clock != host->clk_rate) {
757 rc = clk_set_rate(host->clk, ios->clock);
758 if (rc < 0)
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700759 pr_err("%s: Error setting clock rate (%d)\n",
760 mmc_hostname(host->mmc), rc);
San Mehat9d2bd732009-09-22 16:44:22 -0700761 else
762 host->clk_rate = ios->clock;
763 }
764 clk |= MCI_CLK_ENABLE;
765 }
766
767 if (ios->bus_width == MMC_BUS_WIDTH_4)
768 clk |= (2 << 10); /* Set WIDEBUS */
769
770 if (ios->clock > 400000 && msmsdcc_pwrsave)
771 clk |= (1 << 9); /* PWRSAVE */
772
773 clk |= (1 << 12); /* FLOW_ENA */
774 clk |= (1 << 15); /* feedback clock */
775
776 if (host->plat->translate_vdd)
777 pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd);
778
779 switch (ios->power_mode) {
780 case MMC_POWER_OFF:
781 htc_pwrsink_set(PWRSINK_SDCARD, 0);
782 break;
783 case MMC_POWER_UP:
784 pwr |= MCI_PWR_UP;
785 break;
786 case MMC_POWER_ON:
787 htc_pwrsink_set(PWRSINK_SDCARD, 100);
788 pwr |= MCI_PWR_ON;
789 break;
790 }
791
792 if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN)
793 pwr |= MCI_OD;
794
795 writel(clk, host->base + MMCICLOCK);
796
797 if (host->pwr != pwr) {
798 host->pwr = pwr;
799 writel(pwr, host->base + MMCIPOWER);
800 }
801
802 if (!(clk & MCI_CLK_ENABLE) && host->clks_on) {
803 clk_disable(host->clk);
804 clk_disable(host->pclk);
805 host->clks_on = 0;
806 }
807}
808
809static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
810{
811 struct msmsdcc_host *host = mmc_priv(mmc);
812 unsigned long flags;
813 u32 status;
814
815 spin_lock_irqsave(&host->lock, flags);
816 if (msmsdcc_sdioirq == 1) {
817 status = readl(host->base + MMCIMASK0);
818 if (enable)
819 status |= MCI_SDIOINTOPERMASK;
820 else
821 status &= ~MCI_SDIOINTOPERMASK;
822 host->saved_irq0mask = status;
823 writel(status, host->base + MMCIMASK0);
824 }
825 spin_unlock_irqrestore(&host->lock, flags);
826}
827
828static const struct mmc_host_ops msmsdcc_ops = {
829 .request = msmsdcc_request,
830 .set_ios = msmsdcc_set_ios,
831 .enable_sdio_irq = msmsdcc_enable_sdio_irq,
832};
833
834static void
835msmsdcc_check_status(unsigned long data)
836{
837 struct msmsdcc_host *host = (struct msmsdcc_host *)data;
838 unsigned int status;
839
840 if (!host->plat->status) {
841 mmc_detect_change(host->mmc, 0);
842 goto out;
843 }
844
845 status = host->plat->status(mmc_dev(host->mmc));
846 host->eject = !status;
847 if (status ^ host->oldstat) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700848 pr_info("%s: Slot status change detected (%d -> %d)\n",
849 mmc_hostname(host->mmc), host->oldstat, status);
San Mehat9d2bd732009-09-22 16:44:22 -0700850 if (status)
851 mmc_detect_change(host->mmc, (5 * HZ) / 2);
852 else
853 mmc_detect_change(host->mmc, 0);
854 }
855
856 host->oldstat = status;
857
858out:
859 if (host->timer.function)
860 mod_timer(&host->timer, jiffies + HZ);
861}
862
863static irqreturn_t
864msmsdcc_platform_status_irq(int irq, void *dev_id)
865{
866 struct msmsdcc_host *host = dev_id;
867
868 printk(KERN_DEBUG "%s: %d\n", __func__, irq);
869 msmsdcc_check_status((unsigned long) host);
870 return IRQ_HANDLED;
871}
872
873static void
874msmsdcc_status_notify_cb(int card_present, void *dev_id)
875{
876 struct msmsdcc_host *host = dev_id;
877
878 printk(KERN_DEBUG "%s: card_present %d\n", mmc_hostname(host->mmc),
879 card_present);
880 msmsdcc_check_status((unsigned long) host);
881}
882
883/*
884 * called when a command expires.
885 * Dump some debugging, and then error
886 * out the transaction.
887 */
888static void
889msmsdcc_command_expired(unsigned long _data)
890{
891 struct msmsdcc_host *host = (struct msmsdcc_host *) _data;
892 struct mmc_request *mrq;
893 unsigned long flags;
894
895 spin_lock_irqsave(&host->lock, flags);
896 mrq = host->curr.mrq;
897
898 if (!mrq) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700899 pr_info("%s: Command expiry misfire\n",
900 mmc_hostname(host->mmc));
San Mehat9d2bd732009-09-22 16:44:22 -0700901 spin_unlock_irqrestore(&host->lock, flags);
902 return;
903 }
904
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700905 pr_err("%s: Command timeout (%p %p %p %p)\n",
San Mehat9d2bd732009-09-22 16:44:22 -0700906 mmc_hostname(host->mmc), mrq, mrq->cmd,
907 mrq->data, host->dma.sg);
908
909 mrq->cmd->error = -ETIMEDOUT;
910 msmsdcc_stop_data(host);
911
912 writel(0, host->base + MMCICOMMAND);
913
914 host->curr.mrq = NULL;
915 host->curr.cmd = NULL;
916
917 spin_unlock_irqrestore(&host->lock, flags);
918 mmc_request_done(host->mmc, mrq);
919}
920
921static int
922msmsdcc_init_dma(struct msmsdcc_host *host)
923{
924 memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data));
925 host->dma.host = host;
926 host->dma.channel = -1;
927
928 if (!host->dmares)
929 return -ENODEV;
930
931 host->dma.nc = dma_alloc_coherent(NULL,
932 sizeof(struct msmsdcc_nc_dmadata),
933 &host->dma.nc_busaddr,
934 GFP_KERNEL);
935 if (host->dma.nc == NULL) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700936 pr_err("Unable to allocate DMA buffer\n");
San Mehat9d2bd732009-09-22 16:44:22 -0700937 return -ENOMEM;
938 }
939 memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata));
940 host->dma.cmd_busaddr = host->dma.nc_busaddr;
941 host->dma.cmdptr_busaddr = host->dma.nc_busaddr +
942 offsetof(struct msmsdcc_nc_dmadata, cmdptr);
943 host->dma.channel = host->dmares->start;
944
945 return 0;
946}
947
948#ifdef CONFIG_MMC_MSM7X00A_RESUME_IN_WQ
949static void
950do_resume_work(struct work_struct *work)
951{
952 struct msmsdcc_host *host =
953 container_of(work, struct msmsdcc_host, resume_task);
954 struct mmc_host *mmc = host->mmc;
955
956 if (mmc) {
957 mmc_resume_host(mmc);
958 if (host->stat_irq)
959 enable_irq(host->stat_irq);
960 }
961}
962#endif
963
964static int
965msmsdcc_probe(struct platform_device *pdev)
966{
967 struct mmc_platform_data *plat = pdev->dev.platform_data;
968 struct msmsdcc_host *host;
969 struct mmc_host *mmc;
970 struct resource *cmd_irqres = NULL;
971 struct resource *pio_irqres = NULL;
972 struct resource *stat_irqres = NULL;
973 struct resource *memres = NULL;
974 struct resource *dmares = NULL;
975 int ret;
976
977 /* must have platform data */
978 if (!plat) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700979 pr_err("%s: Platform data not available\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -0700980 ret = -EINVAL;
981 goto out;
982 }
983
984 if (pdev->id < 1 || pdev->id > 4)
985 return -EINVAL;
986
987 if (pdev->resource == NULL || pdev->num_resources < 2) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -0700988 pr_err("%s: Invalid resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -0700989 return -ENXIO;
990 }
991
992 memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
993 dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
994 cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
995 "cmd_irq");
996 pio_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
997 "pio_irq");
998 stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
999 "status_irq");
1000
1001 if (!cmd_irqres || !pio_irqres || !memres) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001002 pr_err("%s: Invalid resource\n", __func__);
San Mehat9d2bd732009-09-22 16:44:22 -07001003 return -ENXIO;
1004 }
1005
1006 /*
1007 * Setup our host structure
1008 */
1009
1010 mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev);
1011 if (!mmc) {
1012 ret = -ENOMEM;
1013 goto out;
1014 }
1015
1016 host = mmc_priv(mmc);
1017 host->pdev_id = pdev->id;
1018 host->plat = plat;
1019 host->mmc = mmc;
1020
1021 host->cmdpoll = 1;
1022
1023 host->base = ioremap(memres->start, PAGE_SIZE);
1024 if (!host->base) {
1025 ret = -ENOMEM;
1026 goto out;
1027 }
1028
1029 host->cmd_irqres = cmd_irqres;
1030 host->pio_irqres = pio_irqres;
1031 host->memres = memres;
1032 host->dmares = dmares;
1033 spin_lock_init(&host->lock);
1034
1035 /*
1036 * Setup DMA
1037 */
1038 msmsdcc_init_dma(host);
1039
1040 /*
1041 * Setup main peripheral bus clock
1042 */
1043 host->pclk = clk_get(&pdev->dev, "sdc_pclk");
1044 if (IS_ERR(host->pclk)) {
1045 ret = PTR_ERR(host->pclk);
1046 goto host_free;
1047 }
1048
1049 ret = clk_enable(host->pclk);
1050 if (ret)
1051 goto pclk_put;
1052
1053 host->pclk_rate = clk_get_rate(host->pclk);
1054
1055 /*
1056 * Setup SDC MMC clock
1057 */
1058 host->clk = clk_get(&pdev->dev, "sdc_clk");
1059 if (IS_ERR(host->clk)) {
1060 ret = PTR_ERR(host->clk);
1061 goto pclk_disable;
1062 }
1063
1064 ret = clk_enable(host->clk);
1065 if (ret)
1066 goto clk_put;
1067
1068 ret = clk_set_rate(host->clk, msmsdcc_fmin);
1069 if (ret) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001070 pr_err("%s: Clock rate set failed (%d)\n", __func__, ret);
San Mehat9d2bd732009-09-22 16:44:22 -07001071 goto clk_disable;
1072 }
1073
1074 host->clk_rate = clk_get_rate(host->clk);
1075
1076 host->clks_on = 1;
1077
1078 /*
1079 * Setup MMC host structure
1080 */
1081 mmc->ops = &msmsdcc_ops;
1082 mmc->f_min = msmsdcc_fmin;
1083 mmc->f_max = msmsdcc_fmax;
1084 mmc->ocr_avail = plat->ocr_mask;
1085
1086 if (msmsdcc_4bit)
1087 mmc->caps |= MMC_CAP_4_BIT_DATA;
1088 if (msmsdcc_sdioirq)
1089 mmc->caps |= MMC_CAP_SDIO_IRQ;
1090 mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
1091
1092 mmc->max_phys_segs = NR_SG;
1093 mmc->max_hw_segs = NR_SG;
1094 mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */
1095 mmc->max_blk_count = 65536;
1096
1097 mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */
1098 mmc->max_seg_size = mmc->max_req_size;
1099
1100 writel(0, host->base + MMCIMASK0);
1101 writel(0x5e007ff, host->base + MMCICLEAR); /* Add: 1 << 25 */
1102
1103 writel(MCI_IRQENABLE, host->base + MMCIMASK0);
1104 host->saved_irq0mask = MCI_IRQENABLE;
1105
1106 /*
1107 * Setup card detect change
1108 */
1109
1110 memset(&host->timer, 0, sizeof(host->timer));
1111
1112 if (stat_irqres && !(stat_irqres->flags & IORESOURCE_DISABLED)) {
1113 unsigned long irqflags = IRQF_SHARED |
1114 (stat_irqres->flags & IRQF_TRIGGER_MASK);
1115
1116 host->stat_irq = stat_irqres->start;
1117 ret = request_irq(host->stat_irq,
1118 msmsdcc_platform_status_irq,
1119 irqflags,
1120 DRIVER_NAME " (slot)",
1121 host);
1122 if (ret) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001123 pr_err("%s: Unable to get slot IRQ %d (%d)\n",
1124 mmc_hostname(mmc), host->stat_irq, ret);
San Mehat9d2bd732009-09-22 16:44:22 -07001125 goto clk_disable;
1126 }
1127 } else if (plat->register_status_notify) {
1128 plat->register_status_notify(msmsdcc_status_notify_cb, host);
1129 } else if (!plat->status)
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001130 pr_err("%s: No card detect facilities available\n",
San Mehat9d2bd732009-09-22 16:44:22 -07001131 mmc_hostname(mmc));
1132 else {
1133 init_timer(&host->timer);
1134 host->timer.data = (unsigned long)host;
1135 host->timer.function = msmsdcc_check_status;
1136 host->timer.expires = jiffies + HZ;
1137 add_timer(&host->timer);
1138 }
1139
1140 if (plat->status) {
1141 host->oldstat = host->plat->status(mmc_dev(host->mmc));
1142 host->eject = !host->oldstat;
1143 }
1144
1145 /*
1146 * Setup a command timer. We currently need this due to
1147 * some 'strange' timeout / error handling situations.
1148 */
1149 init_timer(&host->command_timer);
1150 host->command_timer.data = (unsigned long) host;
1151 host->command_timer.function = msmsdcc_command_expired;
1152
1153 ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED,
1154 DRIVER_NAME " (cmd)", host);
1155 if (ret)
1156 goto stat_irq_free;
1157
1158 ret = request_irq(pio_irqres->start, msmsdcc_pio_irq, IRQF_SHARED,
1159 DRIVER_NAME " (pio)", host);
1160 if (ret)
1161 goto cmd_irq_free;
1162
1163 mmc_set_drvdata(pdev, mmc);
1164 mmc_add_host(mmc);
1165
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001166 pr_info("%s: Qualcomm MSM SDCC at 0x%016llx irq %d,%d dma %d\n",
1167 mmc_hostname(mmc), (unsigned long long)memres->start,
1168 (unsigned int) cmd_irqres->start,
1169 (unsigned int) host->stat_irq, host->dma.channel);
1170 pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc),
1171 (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled"));
1172 pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n",
1173 mmc_hostname(mmc), msmsdcc_fmin, msmsdcc_fmax, host->pclk_rate);
1174 pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc), host->eject);
1175 pr_info("%s: Power save feature enable = %d\n",
1176 mmc_hostname(mmc), msmsdcc_pwrsave);
San Mehat9d2bd732009-09-22 16:44:22 -07001177
1178 if (host->dma.channel != -1) {
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001179 pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n",
1180 mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr);
1181 pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n",
1182 mmc_hostname(mmc), host->dma.cmd_busaddr,
1183 host->dma.cmdptr_busaddr);
San Mehat9d2bd732009-09-22 16:44:22 -07001184 } else
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001185 pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001186 if (host->timer.function)
Joe Perches0a7ff7c2009-09-22 16:44:23 -07001187 pr_info("%s: Polling status mode enabled\n", mmc_hostname(mmc));
San Mehat9d2bd732009-09-22 16:44:22 -07001188
1189 return 0;
1190 cmd_irq_free:
1191 free_irq(cmd_irqres->start, host);
1192 stat_irq_free:
1193 if (host->stat_irq)
1194 free_irq(host->stat_irq, host);
1195 clk_disable:
1196 clk_disable(host->clk);
1197 clk_put:
1198 clk_put(host->clk);
1199 pclk_disable:
1200 clk_disable(host->pclk);
1201 pclk_put:
1202 clk_put(host->pclk);
1203 host_free:
1204 mmc_free_host(mmc);
1205 out:
1206 return ret;
1207}
1208
1209static int
1210msmsdcc_suspend(struct platform_device *dev, pm_message_t state)
1211{
1212 struct mmc_host *mmc = mmc_get_drvdata(dev);
1213 int rc = 0;
1214
1215 if (mmc) {
1216 struct msmsdcc_host *host = mmc_priv(mmc);
1217
1218 if (host->stat_irq)
1219 disable_irq(host->stat_irq);
1220
1221 if (mmc->card && mmc->card->type != MMC_TYPE_SDIO)
1222 rc = mmc_suspend_host(mmc, state);
1223 if (!rc) {
1224 writel(0, host->base + MMCIMASK0);
1225
1226 if (host->clks_on) {
1227 clk_disable(host->clk);
1228 clk_disable(host->pclk);
1229 host->clks_on = 0;
1230 }
1231 }
1232 }
1233 return rc;
1234}
1235
1236static int
1237msmsdcc_resume(struct platform_device *dev)
1238{
1239 struct mmc_host *mmc = mmc_get_drvdata(dev);
1240 unsigned long flags;
1241
1242 if (mmc) {
1243 struct msmsdcc_host *host = mmc_priv(mmc);
1244
1245 spin_lock_irqsave(&host->lock, flags);
1246
1247 if (!host->clks_on) {
1248 clk_enable(host->pclk);
1249 clk_enable(host->clk);
1250 host->clks_on = 1;
1251 }
1252
1253 writel(host->saved_irq0mask, host->base + MMCIMASK0);
1254
1255 spin_unlock_irqrestore(&host->lock, flags);
1256
1257 if (mmc->card && mmc->card->type != MMC_TYPE_SDIO)
1258 mmc_resume_host(mmc);
1259 if (host->stat_irq)
1260 enable_irq(host->stat_irq);
1261 else if (host->stat_irq)
1262 enable_irq(host->stat_irq);
1263 }
1264 return 0;
1265}
1266
1267static struct platform_driver msmsdcc_driver = {
1268 .probe = msmsdcc_probe,
1269 .suspend = msmsdcc_suspend,
1270 .resume = msmsdcc_resume,
1271 .driver = {
1272 .name = "msm_sdcc",
1273 },
1274};
1275
1276static int __init msmsdcc_init(void)
1277{
1278 return platform_driver_register(&msmsdcc_driver);
1279}
1280
1281static void __exit msmsdcc_exit(void)
1282{
1283 platform_driver_unregister(&msmsdcc_driver);
1284}
1285
1286module_init(msmsdcc_init);
1287module_exit(msmsdcc_exit);
1288
1289MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver");
1290MODULE_LICENSE("GPL");