diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-05 13:18:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-05 13:18:21 -0400 |
commit | 0a053e8c71d666daf30da2d407147b1293923d8b (patch) | |
tree | 9ba3967845db9053cb2ca045f01a9454eb5e6230 /drivers/mmc/host/omap_hsmmc.c | |
parent | 601cc11d054ae4b5e9b5babec3d8e4667a2cb9b5 (diff) | |
parent | 32ab83a56fdf42f543b86c349143c2a86ead9707 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (42 commits)
atmel-mci: fix sdc_reg typo
tmio_mmc: add maintainer
mmc: Add OpenFirmware bindings for SDHCI driver
sdhci: Add quirk for forcing maximum block size to 2048 bytes
sdhci: Add quirk for controllers that need IRQ re-init after reset
sdhci: Add quirk for controllers that need small delays for PIO
sdhci: Add set_clock callback and a quirk for nonstandard clocks
sdhci: Add get_{max,timeout}_clock callbacks
sdhci: Add support for hosts reporting inverted write-protect state
sdhci: Add support for card-detection polling
sdhci: Enable only relevant (DMA/PIO) interrupts during transfers
sdhci: Split card-detection IRQs management from sdhci_init()
sdhci: Add support for bus-specific IO memory accessors
mmc_spi: adjust for delayed data token response
omap_hsmmc: Wait for SDBP
omap_hsmmc: Fix MMC3 dma
omap_hsmmc: Disable SDBP at suspend
omap_hsmmc: Do not prefix slot name
omap_hsmmc: Allow cover switch to cause rescan
omap_hsmmc: Add 8-bit bus width mode support
...
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 355 |
1 files changed, 205 insertions, 150 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 3916a5618e28..d183be6f2a5f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #define SDVS18 (0x5 << 9) | 56 | #define SDVS18 (0x5 << 9) |
57 | #define SDVS30 (0x6 << 9) | 57 | #define SDVS30 (0x6 << 9) |
58 | #define SDVS33 (0x7 << 9) | 58 | #define SDVS33 (0x7 << 9) |
59 | #define SDVS_MASK 0x00000E00 | ||
59 | #define SDVSCLR 0xFFFFF1FF | 60 | #define SDVSCLR 0xFFFFF1FF |
60 | #define SDVSDET 0x00000400 | 61 | #define SDVSDET 0x00000400 |
61 | #define AUTOIDLE 0x1 | 62 | #define AUTOIDLE 0x1 |
@@ -76,6 +77,7 @@ | |||
76 | #define MSBS (1 << 5) | 77 | #define MSBS (1 << 5) |
77 | #define BCE (1 << 1) | 78 | #define BCE (1 << 1) |
78 | #define FOUR_BIT (1 << 1) | 79 | #define FOUR_BIT (1 << 1) |
80 | #define DW8 (1 << 5) | ||
79 | #define CC 0x1 | 81 | #define CC 0x1 |
80 | #define TC 0x02 | 82 | #define TC 0x02 |
81 | #define OD 0x1 | 83 | #define OD 0x1 |
@@ -98,10 +100,8 @@ | |||
98 | */ | 100 | */ |
99 | #define OMAP_MMC1_DEVID 0 | 101 | #define OMAP_MMC1_DEVID 0 |
100 | #define OMAP_MMC2_DEVID 1 | 102 | #define OMAP_MMC2_DEVID 1 |
103 | #define OMAP_MMC3_DEVID 2 | ||
101 | 104 | ||
102 | #define OMAP_MMC_DATADIR_NONE 0 | ||
103 | #define OMAP_MMC_DATADIR_READ 1 | ||
104 | #define OMAP_MMC_DATADIR_WRITE 2 | ||
105 | #define MMC_TIMEOUT_MS 20 | 105 | #define MMC_TIMEOUT_MS 20 |
106 | #define OMAP_MMC_MASTER_CLOCK 96000000 | 106 | #define OMAP_MMC_MASTER_CLOCK 96000000 |
107 | #define DRIVER_NAME "mmci-omap-hs" | 107 | #define DRIVER_NAME "mmci-omap-hs" |
@@ -137,18 +137,18 @@ struct mmc_omap_host { | |||
137 | resource_size_t mapbase; | 137 | resource_size_t mapbase; |
138 | unsigned int id; | 138 | unsigned int id; |
139 | unsigned int dma_len; | 139 | unsigned int dma_len; |
140 | unsigned int dma_dir; | 140 | unsigned int dma_sg_idx; |
141 | unsigned char bus_mode; | 141 | unsigned char bus_mode; |
142 | unsigned char datadir; | ||
143 | u32 *buffer; | 142 | u32 *buffer; |
144 | u32 bytesleft; | 143 | u32 bytesleft; |
145 | int suspended; | 144 | int suspended; |
146 | int irq; | 145 | int irq; |
147 | int carddetect; | 146 | int carddetect; |
148 | int use_dma, dma_ch; | 147 | int use_dma, dma_ch; |
149 | int initstr; | 148 | int dma_line_tx, dma_line_rx; |
150 | int slot_id; | 149 | int slot_id; |
151 | int dbclk_enabled; | 150 | int dbclk_enabled; |
151 | int response_busy; | ||
152 | struct omap_mmc_platform_data *pdata; | 152 | struct omap_mmc_platform_data *pdata; |
153 | }; | 153 | }; |
154 | 154 | ||
@@ -218,7 +218,7 @@ mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr, | |||
218 | struct mmc_omap_host *host = mmc_priv(mmc); | 218 | struct mmc_omap_host *host = mmc_priv(mmc); |
219 | struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id]; | 219 | struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id]; |
220 | 220 | ||
221 | return sprintf(buf, "slot:%s\n", slot.name); | 221 | return sprintf(buf, "%s\n", slot.name); |
222 | } | 222 | } |
223 | 223 | ||
224 | static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL); | 224 | static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL); |
@@ -243,10 +243,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, | |||
243 | OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | 243 | OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); |
244 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | 244 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); |
245 | 245 | ||
246 | host->response_busy = 0; | ||
246 | if (cmd->flags & MMC_RSP_PRESENT) { | 247 | if (cmd->flags & MMC_RSP_PRESENT) { |
247 | if (cmd->flags & MMC_RSP_136) | 248 | if (cmd->flags & MMC_RSP_136) |
248 | resptype = 1; | 249 | resptype = 1; |
249 | else | 250 | else if (cmd->flags & MMC_RSP_BUSY) { |
251 | resptype = 3; | ||
252 | host->response_busy = 1; | ||
253 | } else | ||
250 | resptype = 2; | 254 | resptype = 2; |
251 | } | 255 | } |
252 | 256 | ||
@@ -275,19 +279,35 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, | |||
275 | OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); | 279 | OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); |
276 | } | 280 | } |
277 | 281 | ||
282 | static int | ||
283 | mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data) | ||
284 | { | ||
285 | if (data->flags & MMC_DATA_WRITE) | ||
286 | return DMA_TO_DEVICE; | ||
287 | else | ||
288 | return DMA_FROM_DEVICE; | ||
289 | } | ||
290 | |||
278 | /* | 291 | /* |
279 | * Notify the transfer complete to MMC core | 292 | * Notify the transfer complete to MMC core |
280 | */ | 293 | */ |
281 | static void | 294 | static void |
282 | mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) | 295 | mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) |
283 | { | 296 | { |
297 | if (!data) { | ||
298 | struct mmc_request *mrq = host->mrq; | ||
299 | |||
300 | host->mrq = NULL; | ||
301 | mmc_omap_fclk_lazy_disable(host); | ||
302 | mmc_request_done(host->mmc, mrq); | ||
303 | return; | ||
304 | } | ||
305 | |||
284 | host->data = NULL; | 306 | host->data = NULL; |
285 | 307 | ||
286 | if (host->use_dma && host->dma_ch != -1) | 308 | if (host->use_dma && host->dma_ch != -1) |
287 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, | 309 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, |
288 | host->dma_dir); | 310 | mmc_omap_get_dma_dir(host, data)); |
289 | |||
290 | host->datadir = OMAP_MMC_DATADIR_NONE; | ||
291 | 311 | ||
292 | if (!data->error) | 312 | if (!data->error) |
293 | data->bytes_xfered += data->blocks * (data->blksz); | 313 | data->bytes_xfered += data->blocks * (data->blksz); |
@@ -322,7 +342,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) | |||
322 | cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); | 342 | cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); |
323 | } | 343 | } |
324 | } | 344 | } |
325 | if (host->data == NULL || cmd->error) { | 345 | if ((host->data == NULL && !host->response_busy) || cmd->error) { |
326 | host->mrq = NULL; | 346 | host->mrq = NULL; |
327 | mmc_request_done(host->mmc, cmd->mrq); | 347 | mmc_request_done(host->mmc, cmd->mrq); |
328 | } | 348 | } |
@@ -331,19 +351,18 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) | |||
331 | /* | 351 | /* |
332 | * DMA clean up for command errors | 352 | * DMA clean up for command errors |
333 | */ | 353 | */ |
334 | static void mmc_dma_cleanup(struct mmc_omap_host *host) | 354 | static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno) |
335 | { | 355 | { |
336 | host->data->error = -ETIMEDOUT; | 356 | host->data->error = errno; |
337 | 357 | ||
338 | if (host->use_dma && host->dma_ch != -1) { | 358 | if (host->use_dma && host->dma_ch != -1) { |
339 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, | 359 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, |
340 | host->dma_dir); | 360 | mmc_omap_get_dma_dir(host, host->data)); |
341 | omap_free_dma(host->dma_ch); | 361 | omap_free_dma(host->dma_ch); |
342 | host->dma_ch = -1; | 362 | host->dma_ch = -1; |
343 | up(&host->sem); | 363 | up(&host->sem); |
344 | } | 364 | } |
345 | host->data = NULL; | 365 | host->data = NULL; |
346 | host->datadir = OMAP_MMC_DATADIR_NONE; | ||
347 | } | 366 | } |
348 | 367 | ||
349 | /* | 368 | /* |
@@ -412,7 +431,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
412 | struct mmc_data *data; | 431 | struct mmc_data *data; |
413 | int end_cmd = 0, end_trans = 0, status; | 432 | int end_cmd = 0, end_trans = 0, status; |
414 | 433 | ||
415 | if (host->cmd == NULL && host->data == NULL) { | 434 | if (host->mrq == NULL) { |
416 | OMAP_HSMMC_WRITE(host->base, STAT, | 435 | OMAP_HSMMC_WRITE(host->base, STAT, |
417 | OMAP_HSMMC_READ(host->base, STAT)); | 436 | OMAP_HSMMC_READ(host->base, STAT)); |
418 | return IRQ_HANDLED; | 437 | return IRQ_HANDLED; |
@@ -437,18 +456,24 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
437 | } | 456 | } |
438 | end_cmd = 1; | 457 | end_cmd = 1; |
439 | } | 458 | } |
440 | if (host->data) { | 459 | if (host->data || host->response_busy) { |
441 | mmc_dma_cleanup(host); | 460 | if (host->data) |
461 | mmc_dma_cleanup(host, -ETIMEDOUT); | ||
462 | host->response_busy = 0; | ||
442 | mmc_omap_reset_controller_fsm(host, SRD); | 463 | mmc_omap_reset_controller_fsm(host, SRD); |
443 | } | 464 | } |
444 | } | 465 | } |
445 | if ((status & DATA_TIMEOUT) || | 466 | if ((status & DATA_TIMEOUT) || |
446 | (status & DATA_CRC)) { | 467 | (status & DATA_CRC)) { |
447 | if (host->data) { | 468 | if (host->data || host->response_busy) { |
448 | if (status & DATA_TIMEOUT) | 469 | int err = (status & DATA_TIMEOUT) ? |
449 | mmc_dma_cleanup(host); | 470 | -ETIMEDOUT : -EILSEQ; |
471 | |||
472 | if (host->data) | ||
473 | mmc_dma_cleanup(host, err); | ||
450 | else | 474 | else |
451 | host->data->error = -EILSEQ; | 475 | host->mrq->cmd->error = err; |
476 | host->response_busy = 0; | ||
452 | mmc_omap_reset_controller_fsm(host, SRD); | 477 | mmc_omap_reset_controller_fsm(host, SRD); |
453 | end_trans = 1; | 478 | end_trans = 1; |
454 | } | 479 | } |
@@ -473,6 +498,19 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
473 | return IRQ_HANDLED; | 498 | return IRQ_HANDLED; |
474 | } | 499 | } |
475 | 500 | ||
501 | static void set_sd_bus_power(struct mmc_omap_host *host) | ||
502 | { | ||
503 | unsigned long i; | ||
504 | |||
505 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
506 | OMAP_HSMMC_READ(host->base, HCTL) | SDBP); | ||
507 | for (i = 0; i < loops_per_jiffy; i++) { | ||
508 | if (OMAP_HSMMC_READ(host->base, HCTL) & SDBP) | ||
509 | break; | ||
510 | cpu_relax(); | ||
511 | } | ||
512 | } | ||
513 | |||
476 | /* | 514 | /* |
477 | * Switch MMC interface voltage ... only relevant for MMC1. | 515 | * Switch MMC interface voltage ... only relevant for MMC1. |
478 | * | 516 | * |
@@ -485,9 +523,6 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) | |||
485 | u32 reg_val = 0; | 523 | u32 reg_val = 0; |
486 | int ret; | 524 | int ret; |
487 | 525 | ||
488 | if (host->id != OMAP_MMC1_DEVID) | ||
489 | return 0; | ||
490 | |||
491 | /* Disable the clocks */ | 526 | /* Disable the clocks */ |
492 | clk_disable(host->fclk); | 527 | clk_disable(host->fclk); |
493 | clk_disable(host->iclk); | 528 | clk_disable(host->iclk); |
@@ -532,9 +567,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) | |||
532 | reg_val |= SDVS30; | 567 | reg_val |= SDVS30; |
533 | 568 | ||
534 | OMAP_HSMMC_WRITE(host->base, HCTL, reg_val); | 569 | OMAP_HSMMC_WRITE(host->base, HCTL, reg_val); |
535 | 570 | set_sd_bus_power(host); | |
536 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
537 | OMAP_HSMMC_READ(host->base, HCTL) | SDBP); | ||
538 | 571 | ||
539 | return 0; | 572 | return 0; |
540 | err: | 573 | err: |
@@ -551,7 +584,10 @@ static void mmc_omap_detect(struct work_struct *work) | |||
551 | mmc_carddetect_work); | 584 | mmc_carddetect_work); |
552 | struct omap_mmc_slot_data *slot = &mmc_slot(host); | 585 | struct omap_mmc_slot_data *slot = &mmc_slot(host); |
553 | 586 | ||
554 | host->carddetect = slot->card_detect(slot->card_detect_irq); | 587 | if (mmc_slot(host).card_detect) |
588 | host->carddetect = slot->card_detect(slot->card_detect_irq); | ||
589 | else | ||
590 | host->carddetect = -ENOSYS; | ||
555 | 591 | ||
556 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); | 592 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); |
557 | if (host->carddetect) { | 593 | if (host->carddetect) { |
@@ -574,6 +610,48 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id) | |||
574 | return IRQ_HANDLED; | 610 | return IRQ_HANDLED; |
575 | } | 611 | } |
576 | 612 | ||
613 | static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host, | ||
614 | struct mmc_data *data) | ||
615 | { | ||
616 | int sync_dev; | ||
617 | |||
618 | if (data->flags & MMC_DATA_WRITE) | ||
619 | sync_dev = host->dma_line_tx; | ||
620 | else | ||
621 | sync_dev = host->dma_line_rx; | ||
622 | return sync_dev; | ||
623 | } | ||
624 | |||
625 | static void mmc_omap_config_dma_params(struct mmc_omap_host *host, | ||
626 | struct mmc_data *data, | ||
627 | struct scatterlist *sgl) | ||
628 | { | ||
629 | int blksz, nblk, dma_ch; | ||
630 | |||
631 | dma_ch = host->dma_ch; | ||
632 | if (data->flags & MMC_DATA_WRITE) { | ||
633 | omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, | ||
634 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
635 | omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, | ||
636 | sg_dma_address(sgl), 0, 0); | ||
637 | } else { | ||
638 | omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, | ||
639 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
640 | omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, | ||
641 | sg_dma_address(sgl), 0, 0); | ||
642 | } | ||
643 | |||
644 | blksz = host->data->blksz; | ||
645 | nblk = sg_dma_len(sgl) / blksz; | ||
646 | |||
647 | omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, | ||
648 | blksz / 4, nblk, OMAP_DMA_SYNC_FRAME, | ||
649 | mmc_omap_get_dma_sync_dev(host, data), | ||
650 | !(data->flags & MMC_DATA_WRITE)); | ||
651 | |||
652 | omap_start_dma(dma_ch); | ||
653 | } | ||
654 | |||
577 | /* | 655 | /* |
578 | * DMA call back function | 656 | * DMA call back function |
579 | */ | 657 | */ |
@@ -587,6 +665,14 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) | |||
587 | if (host->dma_ch < 0) | 665 | if (host->dma_ch < 0) |
588 | return; | 666 | return; |
589 | 667 | ||
668 | host->dma_sg_idx++; | ||
669 | if (host->dma_sg_idx < host->dma_len) { | ||
670 | /* Fire up the next transfer. */ | ||
671 | mmc_omap_config_dma_params(host, host->data, | ||
672 | host->data->sg + host->dma_sg_idx); | ||
673 | return; | ||
674 | } | ||
675 | |||
590 | omap_free_dma(host->dma_ch); | 676 | omap_free_dma(host->dma_ch); |
591 | host->dma_ch = -1; | 677 | host->dma_ch = -1; |
592 | /* | 678 | /* |
@@ -597,38 +683,28 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) | |||
597 | } | 683 | } |
598 | 684 | ||
599 | /* | 685 | /* |
600 | * Configure dma src and destination parameters | ||
601 | */ | ||
602 | static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host, | ||
603 | struct mmc_data *data) | ||
604 | { | ||
605 | if (sync_dir == 0) { | ||
606 | omap_set_dma_dest_params(host->dma_ch, 0, | ||
607 | OMAP_DMA_AMODE_CONSTANT, | ||
608 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
609 | omap_set_dma_src_params(host->dma_ch, 0, | ||
610 | OMAP_DMA_AMODE_POST_INC, | ||
611 | sg_dma_address(&data->sg[0]), 0, 0); | ||
612 | } else { | ||
613 | omap_set_dma_src_params(host->dma_ch, 0, | ||
614 | OMAP_DMA_AMODE_CONSTANT, | ||
615 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
616 | omap_set_dma_dest_params(host->dma_ch, 0, | ||
617 | OMAP_DMA_AMODE_POST_INC, | ||
618 | sg_dma_address(&data->sg[0]), 0, 0); | ||
619 | } | ||
620 | return 0; | ||
621 | } | ||
622 | /* | ||
623 | * Routine to configure and start DMA for the MMC card | 686 | * Routine to configure and start DMA for the MMC card |
624 | */ | 687 | */ |
625 | static int | 688 | static int |
626 | mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) | 689 | mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) |
627 | { | 690 | { |
628 | int sync_dev, sync_dir = 0; | 691 | int dma_ch = 0, ret = 0, err = 1, i; |
629 | int dma_ch = 0, ret = 0, err = 1; | ||
630 | struct mmc_data *data = req->data; | 692 | struct mmc_data *data = req->data; |
631 | 693 | ||
694 | /* Sanity check: all the SG entries must be aligned by block size. */ | ||
695 | for (i = 0; i < host->dma_len; i++) { | ||
696 | struct scatterlist *sgl; | ||
697 | |||
698 | sgl = data->sg + i; | ||
699 | if (sgl->length % data->blksz) | ||
700 | return -EINVAL; | ||
701 | } | ||
702 | if ((data->blksz % 4) != 0) | ||
703 | /* REVISIT: The MMC buffer increments only when MSB is written. | ||
704 | * Return error for blksz which is non multiple of four. | ||
705 | */ | ||
706 | return -EINVAL; | ||
707 | |||
632 | /* | 708 | /* |
633 | * If for some reason the DMA transfer is still active, | 709 | * If for some reason the DMA transfer is still active, |
634 | * we wait for timeout period and free the dma | 710 | * we wait for timeout period and free the dma |
@@ -647,49 +723,22 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) | |||
647 | return err; | 723 | return err; |
648 | } | 724 | } |
649 | 725 | ||
650 | if (!(data->flags & MMC_DATA_WRITE)) { | 726 | ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD", |
651 | host->dma_dir = DMA_FROM_DEVICE; | 727 | mmc_omap_dma_cb,host, &dma_ch); |
652 | if (host->id == OMAP_MMC1_DEVID) | ||
653 | sync_dev = OMAP24XX_DMA_MMC1_RX; | ||
654 | else | ||
655 | sync_dev = OMAP24XX_DMA_MMC2_RX; | ||
656 | } else { | ||
657 | host->dma_dir = DMA_TO_DEVICE; | ||
658 | if (host->id == OMAP_MMC1_DEVID) | ||
659 | sync_dev = OMAP24XX_DMA_MMC1_TX; | ||
660 | else | ||
661 | sync_dev = OMAP24XX_DMA_MMC2_TX; | ||
662 | } | ||
663 | |||
664 | ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb, | ||
665 | host, &dma_ch); | ||
666 | if (ret != 0) { | 728 | if (ret != 0) { |
667 | dev_dbg(mmc_dev(host->mmc), | 729 | dev_err(mmc_dev(host->mmc), |
668 | "%s: omap_request_dma() failed with %d\n", | 730 | "%s: omap_request_dma() failed with %d\n", |
669 | mmc_hostname(host->mmc), ret); | 731 | mmc_hostname(host->mmc), ret); |
670 | return ret; | 732 | return ret; |
671 | } | 733 | } |
672 | 734 | ||
673 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, | 735 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, |
674 | data->sg_len, host->dma_dir); | 736 | data->sg_len, mmc_omap_get_dma_dir(host, data)); |
675 | host->dma_ch = dma_ch; | 737 | host->dma_ch = dma_ch; |
738 | host->dma_sg_idx = 0; | ||
676 | 739 | ||
677 | if (!(data->flags & MMC_DATA_WRITE)) | 740 | mmc_omap_config_dma_params(host, data, data->sg); |
678 | mmc_omap_config_dma_param(1, host, data); | ||
679 | else | ||
680 | mmc_omap_config_dma_param(0, host, data); | ||
681 | |||
682 | if ((data->blksz % 4) == 0) | ||
683 | omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, | ||
684 | (data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME, | ||
685 | sync_dev, sync_dir); | ||
686 | else | ||
687 | /* REVISIT: The MMC buffer increments only when MSB is written. | ||
688 | * Return error for blksz which is non multiple of four. | ||
689 | */ | ||
690 | return -EINVAL; | ||
691 | 741 | ||
692 | omap_start_dma(dma_ch); | ||
693 | return 0; | 742 | return 0; |
694 | } | 743 | } |
695 | 744 | ||
@@ -739,7 +788,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) | |||
739 | host->data = req->data; | 788 | host->data = req->data; |
740 | 789 | ||
741 | if (req->data == NULL) { | 790 | if (req->data == NULL) { |
742 | host->datadir = OMAP_MMC_DATADIR_NONE; | ||
743 | OMAP_HSMMC_WRITE(host->base, BLK, 0); | 791 | OMAP_HSMMC_WRITE(host->base, BLK, 0); |
744 | return 0; | 792 | return 0; |
745 | } | 793 | } |
@@ -748,9 +796,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) | |||
748 | | (req->data->blocks << 16)); | 796 | | (req->data->blocks << 16)); |
749 | set_data_timeout(host, req); | 797 | set_data_timeout(host, req); |
750 | 798 | ||
751 | host->datadir = (req->data->flags & MMC_DATA_WRITE) ? | ||
752 | OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ; | ||
753 | |||
754 | if (host->use_dma) { | 799 | if (host->use_dma) { |
755 | ret = mmc_omap_start_dma_transfer(host, req); | 800 | ret = mmc_omap_start_dma_transfer(host, req); |
756 | if (ret != 0) { | 801 | if (ret != 0) { |
@@ -782,36 +827,29 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
782 | u16 dsor = 0; | 827 | u16 dsor = 0; |
783 | unsigned long regval; | 828 | unsigned long regval; |
784 | unsigned long timeout; | 829 | unsigned long timeout; |
830 | u32 con; | ||
785 | 831 | ||
786 | switch (ios->power_mode) { | 832 | switch (ios->power_mode) { |
787 | case MMC_POWER_OFF: | 833 | case MMC_POWER_OFF: |
788 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); | 834 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); |
789 | /* | ||
790 | * Reset interface voltage to 3V if it's 1.8V now; | ||
791 | * only relevant on MMC-1, the others always use 1.8V. | ||
792 | * | ||
793 | * REVISIT: If we are able to detect cards after unplugging | ||
794 | * a 1.8V card, this code should not be needed. | ||
795 | */ | ||
796 | if (host->id != OMAP_MMC1_DEVID) | ||
797 | break; | ||
798 | if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) { | ||
799 | int vdd = fls(host->mmc->ocr_avail) - 1; | ||
800 | if (omap_mmc_switch_opcond(host, vdd) != 0) | ||
801 | host->mmc->ios.vdd = vdd; | ||
802 | } | ||
803 | break; | 835 | break; |
804 | case MMC_POWER_UP: | 836 | case MMC_POWER_UP: |
805 | mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd); | 837 | mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd); |
806 | break; | 838 | break; |
807 | } | 839 | } |
808 | 840 | ||
841 | con = OMAP_HSMMC_READ(host->base, CON); | ||
809 | switch (mmc->ios.bus_width) { | 842 | switch (mmc->ios.bus_width) { |
843 | case MMC_BUS_WIDTH_8: | ||
844 | OMAP_HSMMC_WRITE(host->base, CON, con | DW8); | ||
845 | break; | ||
810 | case MMC_BUS_WIDTH_4: | 846 | case MMC_BUS_WIDTH_4: |
847 | OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); | ||
811 | OMAP_HSMMC_WRITE(host->base, HCTL, | 848 | OMAP_HSMMC_WRITE(host->base, HCTL, |
812 | OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT); | 849 | OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT); |
813 | break; | 850 | break; |
814 | case MMC_BUS_WIDTH_1: | 851 | case MMC_BUS_WIDTH_1: |
852 | OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); | ||
815 | OMAP_HSMMC_WRITE(host->base, HCTL, | 853 | OMAP_HSMMC_WRITE(host->base, HCTL, |
816 | OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT); | 854 | OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT); |
817 | break; | 855 | break; |
@@ -891,6 +929,33 @@ static int omap_hsmmc_get_ro(struct mmc_host *mmc) | |||
891 | return pdata->slots[0].get_ro(host->dev, 0); | 929 | return pdata->slots[0].get_ro(host->dev, 0); |
892 | } | 930 | } |
893 | 931 | ||
932 | static void omap_hsmmc_init(struct mmc_omap_host *host) | ||
933 | { | ||
934 | u32 hctl, capa, value; | ||
935 | |||
936 | /* Only MMC1 supports 3.0V */ | ||
937 | if (host->id == OMAP_MMC1_DEVID) { | ||
938 | hctl = SDVS30; | ||
939 | capa = VS30 | VS18; | ||
940 | } else { | ||
941 | hctl = SDVS18; | ||
942 | capa = VS18; | ||
943 | } | ||
944 | |||
945 | value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK; | ||
946 | OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl); | ||
947 | |||
948 | value = OMAP_HSMMC_READ(host->base, CAPA); | ||
949 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); | ||
950 | |||
951 | /* Set the controller to AUTO IDLE mode */ | ||
952 | value = OMAP_HSMMC_READ(host->base, SYSCONFIG); | ||
953 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); | ||
954 | |||
955 | /* Set SD bus power bit */ | ||
956 | set_sd_bus_power(host); | ||
957 | } | ||
958 | |||
894 | static struct mmc_host_ops mmc_omap_ops = { | 959 | static struct mmc_host_ops mmc_omap_ops = { |
895 | .request = omap_mmc_request, | 960 | .request = omap_mmc_request, |
896 | .set_ios = omap_mmc_set_ios, | 961 | .set_ios = omap_mmc_set_ios, |
@@ -906,7 +971,6 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
906 | struct mmc_omap_host *host = NULL; | 971 | struct mmc_omap_host *host = NULL; |
907 | struct resource *res; | 972 | struct resource *res; |
908 | int ret = 0, irq; | 973 | int ret = 0, irq; |
909 | u32 hctl, capa; | ||
910 | 974 | ||
911 | if (pdata == NULL) { | 975 | if (pdata == NULL) { |
912 | dev_err(&pdev->dev, "Platform Data is missing\n"); | 976 | dev_err(&pdev->dev, "Platform Data is missing\n"); |
@@ -996,10 +1060,11 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
996 | else | 1060 | else |
997 | host->dbclk_enabled = 1; | 1061 | host->dbclk_enabled = 1; |
998 | 1062 | ||
999 | #ifdef CONFIG_MMC_BLOCK_BOUNCE | 1063 | /* Since we do only SG emulation, we can have as many segs |
1000 | mmc->max_phys_segs = 1; | 1064 | * as we want. */ |
1001 | mmc->max_hw_segs = 1; | 1065 | mmc->max_phys_segs = 1024; |
1002 | #endif | 1066 | mmc->max_hw_segs = 1024; |
1067 | |||
1003 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ | 1068 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ |
1004 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ | 1069 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ |
1005 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1070 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
@@ -1008,31 +1073,31 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1008 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | 1073 | mmc->ocr_avail = mmc_slot(host).ocr_mask; |
1009 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; | 1074 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; |
1010 | 1075 | ||
1011 | if (pdata->slots[host->slot_id].wires >= 4) | 1076 | if (pdata->slots[host->slot_id].wires >= 8) |
1077 | mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
1078 | else if (pdata->slots[host->slot_id].wires >= 4) | ||
1012 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1079 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1013 | 1080 | ||
1014 | /* Only MMC1 supports 3.0V */ | 1081 | omap_hsmmc_init(host); |
1015 | if (host->id == OMAP_MMC1_DEVID) { | ||
1016 | hctl = SDVS30; | ||
1017 | capa = VS30 | VS18; | ||
1018 | } else { | ||
1019 | hctl = SDVS18; | ||
1020 | capa = VS18; | ||
1021 | } | ||
1022 | |||
1023 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1024 | OMAP_HSMMC_READ(host->base, HCTL) | hctl); | ||
1025 | |||
1026 | OMAP_HSMMC_WRITE(host->base, CAPA, | ||
1027 | OMAP_HSMMC_READ(host->base, CAPA) | capa); | ||
1028 | |||
1029 | /* Set the controller to AUTO IDLE mode */ | ||
1030 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, | ||
1031 | OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); | ||
1032 | 1082 | ||
1033 | /* Set SD bus power bit */ | 1083 | /* Select DMA lines */ |
1034 | OMAP_HSMMC_WRITE(host->base, HCTL, | 1084 | switch (host->id) { |
1035 | OMAP_HSMMC_READ(host->base, HCTL) | SDBP); | 1085 | case OMAP_MMC1_DEVID: |
1086 | host->dma_line_tx = OMAP24XX_DMA_MMC1_TX; | ||
1087 | host->dma_line_rx = OMAP24XX_DMA_MMC1_RX; | ||
1088 | break; | ||
1089 | case OMAP_MMC2_DEVID: | ||
1090 | host->dma_line_tx = OMAP24XX_DMA_MMC2_TX; | ||
1091 | host->dma_line_rx = OMAP24XX_DMA_MMC2_RX; | ||
1092 | break; | ||
1093 | case OMAP_MMC3_DEVID: | ||
1094 | host->dma_line_tx = OMAP34XX_DMA_MMC3_TX; | ||
1095 | host->dma_line_rx = OMAP34XX_DMA_MMC3_RX; | ||
1096 | break; | ||
1097 | default: | ||
1098 | dev_err(mmc_dev(host->mmc), "Invalid MMC id\n"); | ||
1099 | goto err_irq; | ||
1100 | } | ||
1036 | 1101 | ||
1037 | /* Request IRQ for MMC operations */ | 1102 | /* Request IRQ for MMC operations */ |
1038 | ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED, | 1103 | ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED, |
@@ -1051,7 +1116,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1051 | } | 1116 | } |
1052 | 1117 | ||
1053 | /* Request IRQ for card detect */ | 1118 | /* Request IRQ for card detect */ |
1054 | if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) { | 1119 | if ((mmc_slot(host).card_detect_irq)) { |
1055 | ret = request_irq(mmc_slot(host).card_detect_irq, | 1120 | ret = request_irq(mmc_slot(host).card_detect_irq, |
1056 | omap_mmc_cd_handler, | 1121 | omap_mmc_cd_handler, |
1057 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 1122 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
@@ -1074,8 +1139,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1074 | if (ret < 0) | 1139 | if (ret < 0) |
1075 | goto err_slot_name; | 1140 | goto err_slot_name; |
1076 | } | 1141 | } |
1077 | if (mmc_slot(host).card_detect_irq && mmc_slot(host).card_detect && | 1142 | if (mmc_slot(host).card_detect_irq && |
1078 | host->pdata->slots[host->slot_id].get_cover_state) { | 1143 | host->pdata->slots[host->slot_id].get_cover_state) { |
1079 | ret = device_create_file(&mmc->class_dev, | 1144 | ret = device_create_file(&mmc->class_dev, |
1080 | &dev_attr_cover_switch); | 1145 | &dev_attr_cover_switch); |
1081 | if (ret < 0) | 1146 | if (ret < 0) |
@@ -1173,20 +1238,8 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
1173 | " level suspend\n"); | 1238 | " level suspend\n"); |
1174 | } | 1239 | } |
1175 | 1240 | ||
1176 | if (host->id == OMAP_MMC1_DEVID | 1241 | OMAP_HSMMC_WRITE(host->base, HCTL, |
1177 | && !(OMAP_HSMMC_READ(host->base, HCTL) | 1242 | OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); |
1178 | & SDVSDET)) { | ||
1179 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1180 | OMAP_HSMMC_READ(host->base, HCTL) | ||
1181 | & SDVSCLR); | ||
1182 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1183 | OMAP_HSMMC_READ(host->base, HCTL) | ||
1184 | | SDVS30); | ||
1185 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1186 | OMAP_HSMMC_READ(host->base, HCTL) | ||
1187 | | SDBP); | ||
1188 | } | ||
1189 | |||
1190 | clk_disable(host->fclk); | 1243 | clk_disable(host->fclk); |
1191 | clk_disable(host->iclk); | 1244 | clk_disable(host->iclk); |
1192 | clk_disable(host->dbclk); | 1245 | clk_disable(host->dbclk); |
@@ -1222,6 +1275,8 @@ static int omap_mmc_resume(struct platform_device *pdev) | |||
1222 | dev_dbg(mmc_dev(host->mmc), | 1275 | dev_dbg(mmc_dev(host->mmc), |
1223 | "Enabling debounce clk failed\n"); | 1276 | "Enabling debounce clk failed\n"); |
1224 | 1277 | ||
1278 | omap_hsmmc_init(host); | ||
1279 | |||
1225 | if (host->pdata->resume) { | 1280 | if (host->pdata->resume) { |
1226 | ret = host->pdata->resume(&pdev->dev, host->slot_id); | 1281 | ret = host->pdata->resume(&pdev->dev, host->slot_id); |
1227 | if (ret) | 1282 | if (ret) |