diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mmc/host/mxcmmc.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index dcc9cdb2a4df..f4cbe473670e 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -162,7 +162,7 @@ static void mxcmci_softreset(struct mxcmci_host *host) | |||
162 | writew(0xff, host->base + MMC_REG_RES_TO); | 162 | writew(0xff, host->base + MMC_REG_RES_TO); |
163 | } | 163 | } |
164 | 164 | ||
165 | static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | 165 | static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) |
166 | { | 166 | { |
167 | unsigned int nob = data->blocks; | 167 | unsigned int nob = data->blocks; |
168 | unsigned int blksz = data->blksz; | 168 | unsigned int blksz = data->blksz; |
@@ -170,6 +170,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
170 | #ifdef HAS_DMA | 170 | #ifdef HAS_DMA |
171 | struct scatterlist *sg; | 171 | struct scatterlist *sg; |
172 | int i; | 172 | int i; |
173 | int ret; | ||
173 | #endif | 174 | #endif |
174 | if (data->flags & MMC_DATA_STREAM) | 175 | if (data->flags & MMC_DATA_STREAM) |
175 | nob = 0xffff; | 176 | nob = 0xffff; |
@@ -185,7 +186,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
185 | for_each_sg(data->sg, sg, data->sg_len, i) { | 186 | for_each_sg(data->sg, sg, data->sg_len, i) { |
186 | if (sg->offset & 3 || sg->length & 3) { | 187 | if (sg->offset & 3 || sg->length & 3) { |
187 | host->do_dma = 0; | 188 | host->do_dma = 0; |
188 | return; | 189 | return 0; |
189 | } | 190 | } |
190 | } | 191 | } |
191 | 192 | ||
@@ -194,23 +195,30 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
194 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, | 195 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, |
195 | data->sg_len, host->dma_dir); | 196 | data->sg_len, host->dma_dir); |
196 | 197 | ||
197 | imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, | 198 | ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, |
198 | host->res->start + MMC_REG_BUFFER_ACCESS, | 199 | datasize, |
199 | DMA_MODE_READ); | 200 | host->res->start + MMC_REG_BUFFER_ACCESS, |
201 | DMA_MODE_READ); | ||
200 | } else { | 202 | } else { |
201 | host->dma_dir = DMA_TO_DEVICE; | 203 | host->dma_dir = DMA_TO_DEVICE; |
202 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, | 204 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, |
203 | data->sg_len, host->dma_dir); | 205 | data->sg_len, host->dma_dir); |
204 | 206 | ||
205 | imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, | 207 | ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, |
206 | host->res->start + MMC_REG_BUFFER_ACCESS, | 208 | datasize, |
207 | DMA_MODE_WRITE); | 209 | host->res->start + MMC_REG_BUFFER_ACCESS, |
210 | DMA_MODE_WRITE); | ||
208 | } | 211 | } |
209 | 212 | ||
213 | if (ret) { | ||
214 | dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret); | ||
215 | return ret; | ||
216 | } | ||
210 | wmb(); | 217 | wmb(); |
211 | 218 | ||
212 | imx_dma_enable(host->dma); | 219 | imx_dma_enable(host->dma); |
213 | #endif /* HAS_DMA */ | 220 | #endif /* HAS_DMA */ |
221 | return 0; | ||
214 | } | 222 | } |
215 | 223 | ||
216 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | 224 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, |
@@ -536,6 +544,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) | |||
536 | { | 544 | { |
537 | struct mxcmci_host *host = mmc_priv(mmc); | 545 | struct mxcmci_host *host = mmc_priv(mmc); |
538 | unsigned int cmdat = host->cmdat; | 546 | unsigned int cmdat = host->cmdat; |
547 | int error; | ||
539 | 548 | ||
540 | WARN_ON(host->req != NULL); | 549 | WARN_ON(host->req != NULL); |
541 | 550 | ||
@@ -545,7 +554,12 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) | |||
545 | host->do_dma = 1; | 554 | host->do_dma = 1; |
546 | #endif | 555 | #endif |
547 | if (req->data) { | 556 | if (req->data) { |
548 | mxcmci_setup_data(host, req->data); | 557 | error = mxcmci_setup_data(host, req->data); |
558 | if (error) { | ||
559 | req->cmd->error = error; | ||
560 | goto out; | ||
561 | } | ||
562 | |||
549 | 563 | ||
550 | cmdat |= CMD_DAT_CONT_DATA_ENABLE; | 564 | cmdat |= CMD_DAT_CONT_DATA_ENABLE; |
551 | 565 | ||
@@ -553,7 +567,9 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) | |||
553 | cmdat |= CMD_DAT_CONT_WRITE; | 567 | cmdat |= CMD_DAT_CONT_WRITE; |
554 | } | 568 | } |
555 | 569 | ||
556 | if (mxcmci_start_cmd(host, req->cmd, cmdat)) | 570 | error = mxcmci_start_cmd(host, req->cmd, cmdat); |
571 | out: | ||
572 | if (error) | ||
557 | mxcmci_finish_request(host, req); | 573 | mxcmci_finish_request(host, req); |
558 | } | 574 | } |
559 | 575 | ||