diff options
author | Shawn Lin <shawn.lin@rock-chips.com> | 2016-09-02 00:14:36 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2016-09-26 15:31:35 -0400 |
commit | ec0baaa6b33932a25432e17e0bca8d96083caffa (patch) | |
tree | 2234ceb302d97bdf746b33de836571b9dcdcd236 | |
parent | 1712c9373f98ae8ed41599a8d7841a6fba29c264 (diff) |
mmc: dw_mmc: split out preparation of desc for IDMAC32 and IDMAC64
We intend to add more check for descriptors when
preparing desc. Let's spilt out the separate body
to make the dw_mci_translate_sglist not so lengthy.
After spliting out these two functions, we could
remove dw_mci_translate_sglist and call both of them
when staring idmac.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 149 |
1 files changed, 79 insertions, 70 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index c23e252c037f..ff9b0fcf8300 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -467,112 +467,121 @@ static void dw_mci_dmac_complete_dma(void *arg) | |||
467 | } | 467 | } |
468 | } | 468 | } |
469 | 469 | ||
470 | static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, | 470 | static inline void dw_mci_prepare_desc64(struct dw_mci *host, |
471 | unsigned int sg_len) | 471 | struct mmc_data *data, |
472 | unsigned int sg_len) | ||
472 | { | 473 | { |
473 | unsigned int desc_len; | 474 | unsigned int desc_len; |
475 | struct idmac_desc_64addr *desc_first, *desc_last, *desc; | ||
474 | int i; | 476 | int i; |
475 | 477 | ||
476 | if (host->dma_64bit_address == 1) { | 478 | desc_first = desc_last = desc = host->sg_cpu; |
477 | struct idmac_desc_64addr *desc_first, *desc_last, *desc; | ||
478 | |||
479 | desc_first = desc_last = desc = host->sg_cpu; | ||
480 | 479 | ||
481 | for (i = 0; i < sg_len; i++) { | 480 | for (i = 0; i < sg_len; i++) { |
482 | unsigned int length = sg_dma_len(&data->sg[i]); | 481 | unsigned int length = sg_dma_len(&data->sg[i]); |
483 | 482 | ||
484 | u64 mem_addr = sg_dma_address(&data->sg[i]); | 483 | u64 mem_addr = sg_dma_address(&data->sg[i]); |
485 | 484 | ||
486 | for ( ; length ; desc++) { | 485 | for ( ; length ; desc++) { |
487 | desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? | 486 | desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? |
488 | length : DW_MCI_DESC_DATA_LENGTH; | 487 | length : DW_MCI_DESC_DATA_LENGTH; |
489 | 488 | ||
490 | length -= desc_len; | 489 | length -= desc_len; |
491 | 490 | ||
492 | /* | 491 | /* |
493 | * Set the OWN bit and disable interrupts | 492 | * Set the OWN bit and disable interrupts |
494 | * for this descriptor | 493 | * for this descriptor |
495 | */ | 494 | */ |
496 | desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | | 495 | desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | |
497 | IDMAC_DES0_CH; | 496 | IDMAC_DES0_CH; |
498 | 497 | ||
499 | /* Buffer length */ | 498 | /* Buffer length */ |
500 | IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len); | 499 | IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len); |
501 | 500 | ||
502 | /* Physical address to DMA to/from */ | 501 | /* Physical address to DMA to/from */ |
503 | desc->des4 = mem_addr & 0xffffffff; | 502 | desc->des4 = mem_addr & 0xffffffff; |
504 | desc->des5 = mem_addr >> 32; | 503 | desc->des5 = mem_addr >> 32; |
505 | 504 | ||
506 | /* Update physical address for the next desc */ | 505 | /* Update physical address for the next desc */ |
507 | mem_addr += desc_len; | 506 | mem_addr += desc_len; |
508 | 507 | ||
509 | /* Save pointer to the last descriptor */ | 508 | /* Save pointer to the last descriptor */ |
510 | desc_last = desc; | 509 | desc_last = desc; |
511 | } | ||
512 | } | 510 | } |
511 | } | ||
513 | 512 | ||
514 | /* Set first descriptor */ | 513 | /* Set first descriptor */ |
515 | desc_first->des0 |= IDMAC_DES0_FD; | 514 | desc_first->des0 |= IDMAC_DES0_FD; |
516 | 515 | ||
517 | /* Set last descriptor */ | 516 | /* Set last descriptor */ |
518 | desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); | 517 | desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); |
519 | desc_last->des0 |= IDMAC_DES0_LD; | 518 | desc_last->des0 |= IDMAC_DES0_LD; |
519 | } | ||
520 | 520 | ||
521 | } else { | ||
522 | struct idmac_desc *desc_first, *desc_last, *desc; | ||
523 | 521 | ||
524 | desc_first = desc_last = desc = host->sg_cpu; | 522 | static inline void dw_mci_prepare_desc32(struct dw_mci *host, |
523 | struct mmc_data *data, | ||
524 | unsigned int sg_len) | ||
525 | { | ||
526 | unsigned int desc_len; | ||
527 | struct idmac_desc *desc_first, *desc_last, *desc; | ||
528 | int i; | ||
525 | 529 | ||
526 | for (i = 0; i < sg_len; i++) { | 530 | desc_first = desc_last = desc = host->sg_cpu; |
527 | unsigned int length = sg_dma_len(&data->sg[i]); | ||
528 | 531 | ||
529 | u32 mem_addr = sg_dma_address(&data->sg[i]); | 532 | for (i = 0; i < sg_len; i++) { |
533 | unsigned int length = sg_dma_len(&data->sg[i]); | ||
530 | 534 | ||
531 | for ( ; length ; desc++) { | 535 | u32 mem_addr = sg_dma_address(&data->sg[i]); |
532 | desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? | ||
533 | length : DW_MCI_DESC_DATA_LENGTH; | ||
534 | 536 | ||
535 | length -= desc_len; | 537 | for ( ; length ; desc++) { |
538 | desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ? | ||
539 | length : DW_MCI_DESC_DATA_LENGTH; | ||
536 | 540 | ||
537 | /* | 541 | length -= desc_len; |
538 | * Set the OWN bit and disable interrupts | ||
539 | * for this descriptor | ||
540 | */ | ||
541 | desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | | ||
542 | IDMAC_DES0_DIC | | ||
543 | IDMAC_DES0_CH); | ||
544 | 542 | ||
545 | /* Buffer length */ | 543 | /* |
546 | IDMAC_SET_BUFFER1_SIZE(desc, desc_len); | 544 | * Set the OWN bit and disable interrupts |
545 | * for this descriptor | ||
546 | */ | ||
547 | desc->des0 = cpu_to_le32(IDMAC_DES0_OWN | | ||
548 | IDMAC_DES0_DIC | | ||
549 | IDMAC_DES0_CH); | ||
547 | 550 | ||
548 | /* Physical address to DMA to/from */ | 551 | /* Buffer length */ |
549 | desc->des2 = cpu_to_le32(mem_addr); | 552 | IDMAC_SET_BUFFER1_SIZE(desc, desc_len); |
550 | 553 | ||
551 | /* Update physical address for the next desc */ | 554 | /* Physical address to DMA to/from */ |
552 | mem_addr += desc_len; | 555 | desc->des2 = cpu_to_le32(mem_addr); |
553 | 556 | ||
554 | /* Save pointer to the last descriptor */ | 557 | /* Update physical address for the next desc */ |
555 | desc_last = desc; | 558 | mem_addr += desc_len; |
556 | } | ||
557 | } | ||
558 | |||
559 | /* Set first descriptor */ | ||
560 | desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD); | ||
561 | 559 | ||
562 | /* Set last descriptor */ | 560 | /* Save pointer to the last descriptor */ |
563 | desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | | 561 | desc_last = desc; |
564 | IDMAC_DES0_DIC)); | 562 | } |
565 | desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD); | ||
566 | } | 563 | } |
567 | 564 | ||
568 | wmb(); /* drain writebuffer */ | 565 | /* Set first descriptor */ |
566 | desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD); | ||
567 | |||
568 | /* Set last descriptor */ | ||
569 | desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH | | ||
570 | IDMAC_DES0_DIC)); | ||
571 | desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD); | ||
569 | } | 572 | } |
570 | 573 | ||
571 | static int dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) | 574 | static int dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) |
572 | { | 575 | { |
573 | u32 temp; | 576 | u32 temp; |
574 | 577 | ||
575 | dw_mci_translate_sglist(host, host->data, sg_len); | 578 | if (host->dma_64bit_address == 1) |
579 | dw_mci_prepare_desc64(host, host->data, sg_len); | ||
580 | else | ||
581 | dw_mci_prepare_desc32(host, host->data, sg_len); | ||
582 | |||
583 | /* drain writebuffer */ | ||
584 | wmb(); | ||
576 | 585 | ||
577 | /* Make sure to reset DMA in case we did PIO before this */ | 586 | /* Make sure to reset DMA in case we did PIO before this */ |
578 | dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET); | 587 | dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET); |