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>
This commit is contained in:
parent
1712c9373f
commit
ec0baaa6b3
|
@ -467,112 +467,121 @@ static void dw_mci_dmac_complete_dma(void *arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data,
|
static inline void dw_mci_prepare_desc64(struct dw_mci *host,
|
||||||
unsigned int sg_len)
|
struct mmc_data *data,
|
||||||
|
unsigned int sg_len)
|
||||||
{
|
{
|
||||||
unsigned int desc_len;
|
unsigned int desc_len;
|
||||||
|
struct idmac_desc_64addr *desc_first, *desc_last, *desc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (host->dma_64bit_address == 1) {
|
desc_first = desc_last = desc = host->sg_cpu;
|
||||||
struct idmac_desc_64addr *desc_first, *desc_last, *desc;
|
|
||||||
|
|
||||||
desc_first = desc_last = desc = host->sg_cpu;
|
for (i = 0; i < sg_len; i++) {
|
||||||
|
unsigned int length = sg_dma_len(&data->sg[i]);
|
||||||
|
|
||||||
for (i = 0; i < sg_len; i++) {
|
u64 mem_addr = sg_dma_address(&data->sg[i]);
|
||||||
unsigned int length = sg_dma_len(&data->sg[i]);
|
|
||||||
|
|
||||||
u64 mem_addr = sg_dma_address(&data->sg[i]);
|
for ( ; length ; desc++) {
|
||||||
|
desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ?
|
||||||
|
length : DW_MCI_DESC_DATA_LENGTH;
|
||||||
|
|
||||||
for ( ; length ; desc++) {
|
length -= desc_len;
|
||||||
desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ?
|
|
||||||
length : DW_MCI_DESC_DATA_LENGTH;
|
|
||||||
|
|
||||||
length -= desc_len;
|
/*
|
||||||
|
* Set the OWN bit and disable interrupts
|
||||||
|
* for this descriptor
|
||||||
|
*/
|
||||||
|
desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
|
||||||
|
IDMAC_DES0_CH;
|
||||||
|
|
||||||
/*
|
/* Buffer length */
|
||||||
* Set the OWN bit and disable interrupts
|
IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len);
|
||||||
* for this descriptor
|
|
||||||
*/
|
|
||||||
desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC |
|
|
||||||
IDMAC_DES0_CH;
|
|
||||||
|
|
||||||
/* Buffer length */
|
/* Physical address to DMA to/from */
|
||||||
IDMAC_64ADDR_SET_BUFFER1_SIZE(desc, desc_len);
|
desc->des4 = mem_addr & 0xffffffff;
|
||||||
|
desc->des5 = mem_addr >> 32;
|
||||||
|
|
||||||
/* Physical address to DMA to/from */
|
/* Update physical address for the next desc */
|
||||||
desc->des4 = mem_addr & 0xffffffff;
|
mem_addr += desc_len;
|
||||||
desc->des5 = mem_addr >> 32;
|
|
||||||
|
|
||||||
/* Update physical address for the next desc */
|
/* Save pointer to the last descriptor */
|
||||||
mem_addr += desc_len;
|
desc_last = desc;
|
||||||
|
|
||||||
/* Save pointer to the last descriptor */
|
|
||||||
desc_last = desc;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set first descriptor */
|
|
||||||
desc_first->des0 |= IDMAC_DES0_FD;
|
|
||||||
|
|
||||||
/* Set last descriptor */
|
|
||||||
desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
|
|
||||||
desc_last->des0 |= IDMAC_DES0_LD;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
struct idmac_desc *desc_first, *desc_last, *desc;
|
|
||||||
|
|
||||||
desc_first = desc_last = desc = host->sg_cpu;
|
|
||||||
|
|
||||||
for (i = 0; i < sg_len; i++) {
|
|
||||||
unsigned int length = sg_dma_len(&data->sg[i]);
|
|
||||||
|
|
||||||
u32 mem_addr = sg_dma_address(&data->sg[i]);
|
|
||||||
|
|
||||||
for ( ; length ; desc++) {
|
|
||||||
desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ?
|
|
||||||
length : DW_MCI_DESC_DATA_LENGTH;
|
|
||||||
|
|
||||||
length -= desc_len;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the OWN bit and disable interrupts
|
|
||||||
* for this descriptor
|
|
||||||
*/
|
|
||||||
desc->des0 = cpu_to_le32(IDMAC_DES0_OWN |
|
|
||||||
IDMAC_DES0_DIC |
|
|
||||||
IDMAC_DES0_CH);
|
|
||||||
|
|
||||||
/* Buffer length */
|
|
||||||
IDMAC_SET_BUFFER1_SIZE(desc, desc_len);
|
|
||||||
|
|
||||||
/* Physical address to DMA to/from */
|
|
||||||
desc->des2 = cpu_to_le32(mem_addr);
|
|
||||||
|
|
||||||
/* Update physical address for the next desc */
|
|
||||||
mem_addr += desc_len;
|
|
||||||
|
|
||||||
/* Save pointer to the last descriptor */
|
|
||||||
desc_last = desc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set first descriptor */
|
|
||||||
desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD);
|
|
||||||
|
|
||||||
/* Set last descriptor */
|
|
||||||
desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH |
|
|
||||||
IDMAC_DES0_DIC));
|
|
||||||
desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wmb(); /* drain writebuffer */
|
/* Set first descriptor */
|
||||||
|
desc_first->des0 |= IDMAC_DES0_FD;
|
||||||
|
|
||||||
|
/* Set last descriptor */
|
||||||
|
desc_last->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC);
|
||||||
|
desc_last->des0 |= IDMAC_DES0_LD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline void dw_mci_prepare_desc32(struct dw_mci *host,
|
||||||
|
struct mmc_data *data,
|
||||||
|
unsigned int sg_len)
|
||||||
|
{
|
||||||
|
unsigned int desc_len;
|
||||||
|
struct idmac_desc *desc_first, *desc_last, *desc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
desc_first = desc_last = desc = host->sg_cpu;
|
||||||
|
|
||||||
|
for (i = 0; i < sg_len; i++) {
|
||||||
|
unsigned int length = sg_dma_len(&data->sg[i]);
|
||||||
|
|
||||||
|
u32 mem_addr = sg_dma_address(&data->sg[i]);
|
||||||
|
|
||||||
|
for ( ; length ; desc++) {
|
||||||
|
desc_len = (length <= DW_MCI_DESC_DATA_LENGTH) ?
|
||||||
|
length : DW_MCI_DESC_DATA_LENGTH;
|
||||||
|
|
||||||
|
length -= desc_len;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the OWN bit and disable interrupts
|
||||||
|
* for this descriptor
|
||||||
|
*/
|
||||||
|
desc->des0 = cpu_to_le32(IDMAC_DES0_OWN |
|
||||||
|
IDMAC_DES0_DIC |
|
||||||
|
IDMAC_DES0_CH);
|
||||||
|
|
||||||
|
/* Buffer length */
|
||||||
|
IDMAC_SET_BUFFER1_SIZE(desc, desc_len);
|
||||||
|
|
||||||
|
/* Physical address to DMA to/from */
|
||||||
|
desc->des2 = cpu_to_le32(mem_addr);
|
||||||
|
|
||||||
|
/* Update physical address for the next desc */
|
||||||
|
mem_addr += desc_len;
|
||||||
|
|
||||||
|
/* Save pointer to the last descriptor */
|
||||||
|
desc_last = desc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set first descriptor */
|
||||||
|
desc_first->des0 |= cpu_to_le32(IDMAC_DES0_FD);
|
||||||
|
|
||||||
|
/* Set last descriptor */
|
||||||
|
desc_last->des0 &= cpu_to_le32(~(IDMAC_DES0_CH |
|
||||||
|
IDMAC_DES0_DIC));
|
||||||
|
desc_last->des0 |= cpu_to_le32(IDMAC_DES0_LD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
|
static int dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
|
||||||
{
|
{
|
||||||
u32 temp;
|
u32 temp;
|
||||||
|
|
||||||
dw_mci_translate_sglist(host, host->data, sg_len);
|
if (host->dma_64bit_address == 1)
|
||||||
|
dw_mci_prepare_desc64(host, host->data, sg_len);
|
||||||
|
else
|
||||||
|
dw_mci_prepare_desc32(host, host->data, sg_len);
|
||||||
|
|
||||||
|
/* drain writebuffer */
|
||||||
|
wmb();
|
||||||
|
|
||||||
/* Make sure to reset DMA in case we did PIO before this */
|
/* Make sure to reset DMA in case we did PIO before this */
|
||||||
dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET);
|
dw_mci_ctrl_reset(host, SDMMC_CTRL_DMA_RESET);
|
||||||
|
|
Loading…
Reference in a new issue