pxamci: fix byte aligned DMA transfers
PATCH 1/1 pxamci: fix byte aligned DMA transfers
The pxa27x DMA controller defaults to 64-bit alignment. This caused the SCR reads to fail (and, depending on card type, error out) when card->raw_scr was not aligned on a 8-byte boundary.
For performance reasons all scatter-gather addresses passed to pxamci_request should be aligned on 8-byte boundaries, but if this can't be guaranteed, byte aligned DMA transfers in the have to be enabled in the controller to get correct behaviour.
Signed-off-by Philipp Zabel <[email protected]>
--- drivers/mmc/host/pxamci.c | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-)
drivers/mmc/host/pxamci.c +13 -0
@@ -114,6 +114,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)unsigned int nob = data->blocks;unsigned long long clks;unsigned int timeout; +bool dalgn =0 ;u32 dcmd;int i;
@@ -152,6 +153,9 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) host->sg_cpu[i].dcmd = dcmd | length;if (length &31 && !(data->flags &MMC_DATA_READ )) host->sg_cpu[i].dcmd |=DCMD_ENDIRQEN ; +/* Not aligned to 8-byte boundary? */ +if (sg_dma_address (&data->sg[i]) &0x7 ) + dalgn =1 ;if (data->flags &MMC_DATA_READ ) { host->sg_cpu[i].dsadr = host->res->start +MMC_RXFIFO ; host->sg_cpu[i].dtadr =sg_dma_address (&data->sg[i]);
@@ -165,6 +169,15 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) host->sg_cpu[host->dma_len -1 ].ddadr =DDADR_STOP ;wmb (); +/* +* The PXA27x DMA controller encounters overhead when working with +* unaligned (to 8-byte boundaries) data, so switch on byte alignment +* mode only if we have unaligned data. +*/ +if (dalgn) +DALGN |= (1 << host->dma); +else +DALGN &= (1 << host->dma);DDADR (host->dma) = host->sg_dma;DCSR (host->dma) =DCSR_RUN ; }
Signature · 1 line
1.5.6