diff options
author | Seungwon Jeon <tgih.jun@samsung.com> | 2011-12-22 04:01:29 -0500 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-01-11 23:58:44 -0500 |
commit | 053b3ce6c15f0199c20b3fb06c3ae479de0324e2 (patch) | |
tree | c8d3b4a2dcb50d7a02197c9bd727d632da57907b /drivers/mmc | |
parent | 5b93a4595b6c39f78b69cc6eb9a3fa0ae6efe4a6 (diff) |
mmc: dw_mmc: Support predefined mutiple block transfers
This patch adds the support for predefined multiple block r/w.
dw_mmc can support MMC_CAP_CMD23 capability.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Acked-by: Will Newton <will.newton@imgtec.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 9b839fabfb3c..c583b943f615 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -588,11 +588,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot) | |||
588 | mci_writel(host, CTYPE, (slot->ctype << slot->id)); | 588 | mci_writel(host, CTYPE, (slot->ctype << slot->id)); |
589 | } | 589 | } |
590 | 590 | ||
591 | static void dw_mci_start_request(struct dw_mci *host, | 591 | static void __dw_mci_start_request(struct dw_mci *host, |
592 | struct dw_mci_slot *slot) | 592 | struct dw_mci_slot *slot, |
593 | struct mmc_command *cmd) | ||
593 | { | 594 | { |
594 | struct mmc_request *mrq; | 595 | struct mmc_request *mrq; |
595 | struct mmc_command *cmd; | ||
596 | struct mmc_data *data; | 596 | struct mmc_data *data; |
597 | u32 cmdflags; | 597 | u32 cmdflags; |
598 | 598 | ||
@@ -610,14 +610,13 @@ static void dw_mci_start_request(struct dw_mci *host, | |||
610 | host->completed_events = 0; | 610 | host->completed_events = 0; |
611 | host->data_status = 0; | 611 | host->data_status = 0; |
612 | 612 | ||
613 | data = mrq->data; | 613 | data = cmd->data; |
614 | if (data) { | 614 | if (data) { |
615 | dw_mci_set_timeout(host); | 615 | dw_mci_set_timeout(host); |
616 | mci_writel(host, BYTCNT, data->blksz*data->blocks); | 616 | mci_writel(host, BYTCNT, data->blksz*data->blocks); |
617 | mci_writel(host, BLKSIZ, data->blksz); | 617 | mci_writel(host, BLKSIZ, data->blksz); |
618 | } | 618 | } |
619 | 619 | ||
620 | cmd = mrq->cmd; | ||
621 | cmdflags = dw_mci_prepare_command(slot->mmc, cmd); | 620 | cmdflags = dw_mci_prepare_command(slot->mmc, cmd); |
622 | 621 | ||
623 | /* this is the first command, send the initialization clock */ | 622 | /* this is the first command, send the initialization clock */ |
@@ -635,6 +634,16 @@ static void dw_mci_start_request(struct dw_mci *host, | |||
635 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); | 634 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); |
636 | } | 635 | } |
637 | 636 | ||
637 | static void dw_mci_start_request(struct dw_mci *host, | ||
638 | struct dw_mci_slot *slot) | ||
639 | { | ||
640 | struct mmc_request *mrq = slot->mrq; | ||
641 | struct mmc_command *cmd; | ||
642 | |||
643 | cmd = mrq->sbc ? mrq->sbc : mrq->cmd; | ||
644 | __dw_mci_start_request(host, slot, cmd); | ||
645 | } | ||
646 | |||
638 | /* must be called with host->lock held */ | 647 | /* must be called with host->lock held */ |
639 | static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, | 648 | static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, |
640 | struct mmc_request *mrq) | 649 | struct mmc_request *mrq) |
@@ -889,7 +898,14 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
889 | cmd = host->cmd; | 898 | cmd = host->cmd; |
890 | host->cmd = NULL; | 899 | host->cmd = NULL; |
891 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); | 900 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); |
892 | dw_mci_command_complete(host, host->mrq->cmd); | 901 | dw_mci_command_complete(host, cmd); |
902 | if (cmd == host->mrq->sbc && !cmd->error) { | ||
903 | prev_state = state = STATE_SENDING_CMD; | ||
904 | __dw_mci_start_request(host, host->cur_slot, | ||
905 | host->mrq->cmd); | ||
906 | goto unlock; | ||
907 | } | ||
908 | |||
893 | if (!host->mrq->data || cmd->error) { | 909 | if (!host->mrq->data || cmd->error) { |
894 | dw_mci_request_end(host, host->mrq); | 910 | dw_mci_request_end(host, host->mrq); |
895 | goto unlock; | 911 | goto unlock; |
@@ -967,6 +983,12 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
967 | goto unlock; | 983 | goto unlock; |
968 | } | 984 | } |
969 | 985 | ||
986 | if (host->mrq->sbc && !data->error) { | ||
987 | data->stop->error = 0; | ||
988 | dw_mci_request_end(host, host->mrq); | ||
989 | goto unlock; | ||
990 | } | ||
991 | |||
970 | prev_state = state = STATE_SENDING_STOP; | 992 | prev_state = state = STATE_SENDING_STOP; |
971 | if (!data->error) | 993 | if (!data->error) |
972 | send_stop_cmd(host, data); | 994 | send_stop_cmd(host, data); |