diff options
Diffstat (limited to 'drivers/mmc/tifm_sd.c')
-rw-r--r-- | drivers/mmc/tifm_sd.c | 198 |
1 files changed, 68 insertions, 130 deletions
diff --git a/drivers/mmc/tifm_sd.c b/drivers/mmc/tifm_sd.c index fe8cb1aa681f..52499548abe8 100644 --- a/drivers/mmc/tifm_sd.c +++ b/drivers/mmc/tifm_sd.c | |||
@@ -484,19 +484,40 @@ static void tifm_sd_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
484 | if (r_data) { | 484 | if (r_data) { |
485 | tifm_sd_set_data_timeout(host, r_data); | 485 | tifm_sd_set_data_timeout(host, r_data); |
486 | 486 | ||
487 | sg_count = tifm_map_sg(sock, r_data->sg, r_data->sg_len, | 487 | if (host->no_dma) { |
488 | mrq->cmd->flags & MMC_DATA_WRITE | 488 | host->buffer_size = mrq->cmd->data->blocks |
489 | ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); | 489 | * mrq->cmd->data->blksz; |
490 | if (sg_count != 1) { | 490 | |
491 | printk(KERN_ERR DRIVER_NAME | 491 | writel(TIFM_MMCSD_BUFINT |
492 | ": scatterlist map failed\n"); | 492 | | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
493 | spin_unlock_irqrestore(&sock->lock, flags); | 493 | sock->addr + SOCK_MMCSD_INT_ENABLE); |
494 | goto err_out; | 494 | writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) |
495 | } | 495 | | (TIFM_MMCSD_FIFO_SIZE - 1), |
496 | sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | ||
497 | |||
498 | host->written_blocks = 0; | ||
499 | host->cmd_flags &= ~CARD_BUSY; | ||
500 | host->buffer_pos = 0; | ||
501 | writel(r_data->blocks - 1, | ||
502 | sock->addr + SOCK_MMCSD_NUM_BLOCKS); | ||
503 | writel(r_data->blksz - 1, | ||
504 | sock->addr + SOCK_MMCSD_BLOCK_LEN); | ||
505 | } else { | ||
506 | sg_count = tifm_map_sg(sock, r_data->sg, r_data->sg_len, | ||
507 | mrq->cmd->flags & MMC_DATA_WRITE | ||
508 | ? PCI_DMA_TODEVICE | ||
509 | : PCI_DMA_FROMDEVICE); | ||
510 | if (sg_count != 1) { | ||
511 | printk(KERN_ERR DRIVER_NAME | ||
512 | ": scatterlist map failed\n"); | ||
513 | spin_unlock_irqrestore(&sock->lock, flags); | ||
514 | goto err_out; | ||
515 | } | ||
496 | 516 | ||
497 | host->written_blocks = 0; | 517 | host->written_blocks = 0; |
498 | host->cmd_flags &= ~CARD_BUSY; | 518 | host->cmd_flags &= ~CARD_BUSY; |
499 | tifm_sd_prepare_data(host, mrq->cmd); | 519 | tifm_sd_prepare_data(host, mrq->cmd); |
520 | } | ||
500 | } | 521 | } |
501 | 522 | ||
502 | host->req = mrq; | 523 | host->req = mrq; |
@@ -542,128 +563,47 @@ static void tifm_sd_end_cmd(unsigned long data) | |||
542 | 563 | ||
543 | r_data = mrq->cmd->data; | 564 | r_data = mrq->cmd->data; |
544 | if (r_data) { | 565 | if (r_data) { |
545 | if (r_data->flags & MMC_DATA_WRITE) { | 566 | if (host->no_dma) { |
546 | r_data->bytes_xfered = host->written_blocks | 567 | writel((~TIFM_MMCSD_BUFINT) & |
547 | * r_data->blksz; | 568 | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), |
548 | } else { | 569 | sock->addr + SOCK_MMCSD_INT_ENABLE); |
549 | r_data->bytes_xfered = r_data->blocks - | 570 | |
550 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; | 571 | if (r_data->flags & MMC_DATA_WRITE) { |
551 | r_data->bytes_xfered *= r_data->blksz; | 572 | r_data->bytes_xfered = host->written_blocks |
552 | r_data->bytes_xfered += r_data->blksz - | 573 | * r_data->blksz; |
553 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; | 574 | } else { |
554 | } | 575 | r_data->bytes_xfered = r_data->blocks - |
555 | tifm_unmap_sg(sock, r_data->sg, r_data->sg_len, | 576 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) |
556 | (r_data->flags & MMC_DATA_WRITE) | 577 | - 1; |
557 | ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); | 578 | r_data->bytes_xfered *= r_data->blksz; |
558 | } | 579 | r_data->bytes_xfered += r_data->blksz |
559 | 580 | - readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) | |
560 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), | 581 | + 1; |
561 | sock->addr + SOCK_CONTROL); | 582 | } |
562 | 583 | host->buffer_pos = 0; | |
563 | spin_unlock_irqrestore(&sock->lock, flags); | 584 | host->buffer_size = 0; |
564 | mmc_request_done(mmc, mrq); | ||
565 | } | ||
566 | |||
567 | static void tifm_sd_request_nodma(struct mmc_host *mmc, struct mmc_request *mrq) | ||
568 | { | ||
569 | struct tifm_sd *host = mmc_priv(mmc); | ||
570 | struct tifm_dev *sock = host->dev; | ||
571 | unsigned long flags; | ||
572 | struct mmc_data *r_data = mrq->cmd->data; | ||
573 | |||
574 | spin_lock_irqsave(&sock->lock, flags); | ||
575 | if (host->eject) { | ||
576 | spin_unlock_irqrestore(&sock->lock, flags); | ||
577 | goto err_out; | ||
578 | } | ||
579 | |||
580 | if (host->req) { | ||
581 | printk(KERN_ERR DRIVER_NAME ": unfinished request detected\n"); | ||
582 | spin_unlock_irqrestore(&sock->lock, flags); | ||
583 | goto err_out; | ||
584 | } | ||
585 | |||
586 | if (r_data) { | ||
587 | tifm_sd_set_data_timeout(host, r_data); | ||
588 | |||
589 | host->buffer_size = mrq->cmd->data->blocks | ||
590 | * mrq->cmd->data->blksz; | ||
591 | |||
592 | writel(TIFM_MMCSD_BUFINT | ||
593 | | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), | ||
594 | sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
595 | writel(((TIFM_MMCSD_FIFO_SIZE - 1) << 8) | ||
596 | | (TIFM_MMCSD_FIFO_SIZE - 1), | ||
597 | sock->addr + SOCK_MMCSD_BUFFER_CONFIG); | ||
598 | |||
599 | host->written_blocks = 0; | ||
600 | host->cmd_flags &= ~CARD_BUSY; | ||
601 | host->buffer_pos = 0; | ||
602 | writel(r_data->blocks - 1, sock->addr + SOCK_MMCSD_NUM_BLOCKS); | ||
603 | writel(r_data->blksz - 1, sock->addr + SOCK_MMCSD_BLOCK_LEN); | ||
604 | } | ||
605 | |||
606 | host->req = mrq; | ||
607 | mod_timer(&host->timer, jiffies + host->timeout_jiffies); | ||
608 | host->state = CMD; | ||
609 | writel(TIFM_CTRL_LED | readl(sock->addr + SOCK_CONTROL), | ||
610 | sock->addr + SOCK_CONTROL); | ||
611 | tifm_sd_exec(host, mrq->cmd); | ||
612 | spin_unlock_irqrestore(&sock->lock, flags); | ||
613 | return; | ||
614 | |||
615 | err_out: | ||
616 | mrq->cmd->error = MMC_ERR_TIMEOUT; | ||
617 | mmc_request_done(mmc, mrq); | ||
618 | } | ||
619 | |||
620 | static void tifm_sd_end_cmd_nodma(unsigned long data) | ||
621 | { | ||
622 | struct tifm_sd *host = (struct tifm_sd*)data; | ||
623 | struct tifm_dev *sock = host->dev; | ||
624 | struct mmc_host *mmc = tifm_get_drvdata(sock); | ||
625 | struct mmc_request *mrq; | ||
626 | struct mmc_data *r_data = NULL; | ||
627 | unsigned long flags; | ||
628 | |||
629 | spin_lock_irqsave(&sock->lock, flags); | ||
630 | |||
631 | del_timer(&host->timer); | ||
632 | mrq = host->req; | ||
633 | host->req = NULL; | ||
634 | host->state = IDLE; | ||
635 | |||
636 | if (!mrq) { | ||
637 | printk(KERN_ERR DRIVER_NAME ": no request to complete?\n"); | ||
638 | spin_unlock_irqrestore(&sock->lock, flags); | ||
639 | return; | ||
640 | } | ||
641 | |||
642 | r_data = mrq->cmd->data; | ||
643 | if (r_data) { | ||
644 | writel((~TIFM_MMCSD_BUFINT) & | ||
645 | readl(sock->addr + SOCK_MMCSD_INT_ENABLE), | ||
646 | sock->addr + SOCK_MMCSD_INT_ENABLE); | ||
647 | |||
648 | if (r_data->flags & MMC_DATA_WRITE) { | ||
649 | r_data->bytes_xfered = host->written_blocks | ||
650 | * r_data->blksz; | ||
651 | } else { | 585 | } else { |
652 | r_data->bytes_xfered = r_data->blocks - | 586 | if (r_data->flags & MMC_DATA_WRITE) { |
653 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; | 587 | r_data->bytes_xfered = host->written_blocks |
654 | r_data->bytes_xfered *= r_data->blksz; | 588 | * r_data->blksz; |
655 | r_data->bytes_xfered += r_data->blksz - | 589 | } else { |
656 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) + 1; | 590 | r_data->bytes_xfered = r_data->blocks - |
591 | readl(sock->addr + SOCK_MMCSD_NUM_BLOCKS) - 1; | ||
592 | r_data->bytes_xfered *= r_data->blksz; | ||
593 | r_data->bytes_xfered += r_data->blksz - | ||
594 | readl(sock->addr + SOCK_MMCSD_BLOCK_LEN) | ||
595 | + 1; | ||
596 | } | ||
597 | tifm_unmap_sg(sock, r_data->sg, r_data->sg_len, | ||
598 | (r_data->flags & MMC_DATA_WRITE) | ||
599 | ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); | ||
657 | } | 600 | } |
658 | host->buffer_pos = 0; | ||
659 | host->buffer_size = 0; | ||
660 | } | 601 | } |
661 | 602 | ||
662 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), | 603 | writel((~TIFM_CTRL_LED) & readl(sock->addr + SOCK_CONTROL), |
663 | sock->addr + SOCK_CONTROL); | 604 | sock->addr + SOCK_CONTROL); |
664 | 605 | ||
665 | spin_unlock_irqrestore(&sock->lock, flags); | 606 | spin_unlock_irqrestore(&sock->lock, flags); |
666 | |||
667 | mmc_request_done(mmc, mrq); | 607 | mmc_request_done(mmc, mrq); |
668 | } | 608 | } |
669 | 609 | ||
@@ -755,7 +695,7 @@ static int tifm_sd_ro(struct mmc_host *mmc) | |||
755 | return rc; | 695 | return rc; |
756 | } | 696 | } |
757 | 697 | ||
758 | static struct mmc_host_ops tifm_sd_ops = { | 698 | static const struct mmc_host_ops tifm_sd_ops = { |
759 | .request = tifm_sd_request, | 699 | .request = tifm_sd_request, |
760 | .set_ios = tifm_sd_ios, | 700 | .set_ios = tifm_sd_ios, |
761 | .get_ro = tifm_sd_ro | 701 | .get_ro = tifm_sd_ro |
@@ -846,12 +786,10 @@ static int tifm_sd_probe(struct tifm_dev *sock) | |||
846 | host->dev = sock; | 786 | host->dev = sock; |
847 | host->timeout_jiffies = msecs_to_jiffies(1000); | 787 | host->timeout_jiffies = msecs_to_jiffies(1000); |
848 | 788 | ||
849 | tasklet_init(&host->finish_tasklet, | 789 | tasklet_init(&host->finish_tasklet, tifm_sd_end_cmd, |
850 | host->no_dma ? tifm_sd_end_cmd_nodma : tifm_sd_end_cmd, | ||
851 | (unsigned long)host); | 790 | (unsigned long)host); |
852 | setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host); | 791 | setup_timer(&host->timer, tifm_sd_abort, (unsigned long)host); |
853 | 792 | ||
854 | tifm_sd_ops.request = host->no_dma ? tifm_sd_request_nodma : tifm_sd_request; | ||
855 | mmc->ops = &tifm_sd_ops; | 793 | mmc->ops = &tifm_sd_ops; |
856 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 794 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
857 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; | 795 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_MULTIWRITE; |