All pastes #1166704 Raw Edit

Diff

public text v1 · immutable
#1166704 ·published 2008-08-11 19:55 UTC
rendered paste body
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.cindex a8e18fe..5bbae05 100644--- a/drivers/mmc/host/pxamci.c+++ b/drivers/mmc/host/pxamci.c@@ -36,6 +36,10 @@  #include "pxamci.h" +/* FIXME: For debugging purposes */+#undef cpu_is_pxa25x+#define cpu_is_pxa25x cpu_is_pxa27x+ #define DRIVER_NAME	"pxa2xx-mci"  #define NR_SG	1@@ -67,6 +71,10 @@ struct pxamci_host { 	unsigned int		dma_dir; 	unsigned int		dma_drcmrrx; 	unsigned int		dma_drcmrtx;++	dma_addr_t		bounce_dma;+	void			*bounce_cpu;+	unsigned int            offset; };  static void pxamci_stop_clock(struct pxamci_host *host)@@ -116,7 +124,7 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) 	unsigned int timeout; 	bool dalgn = 0; 	u32 dcmd;-	int i;+	int i, j;  	host->data = data; @@ -148,22 +156,56 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) 	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, 				   host->dma_dir); -	for (i = 0; i < host->dma_len; i++) {+	for (i = 0, j = 0; i < host->dma_len; i++, j++) { 		unsigned int length = sg_dma_len(&data->sg[i]);-		host->sg_cpu[i].dcmd = dcmd | length;-		if (length & 31 && !(data->flags & MMC_DATA_READ))-			host->sg_cpu[i].dcmd |= DCMD_ENDIRQEN;+		unsigned int addr = sg_dma_address(&data->sg[i]);+		unsigned int offset = addr & 7; 		/* Not aligned to 8-byte boundary? */-		if (sg_dma_address(&data->sg[i]) & 0x7)-			dalgn = 1;+		if (offset) {+        		if (cpu_is_pxa21x() || cpu_is_pxa25x()) {+				/*+				 * PXA25x doesn't support unaligned DMA+				 * at all, use a bounce buffer once for+				 * up to 7 unaligned bytes.+				 */+				BUG_ON(host->offset != 0);+				offset = (8 - offset) & 7;+				host->sg_cpu[j].dcmd = dcmd | offset;+				if (length & 31 && !(data->flags & MMC_DATA_READ))+					host->sg_cpu[j].dcmd |= DCMD_ENDIRQEN;+				if (data->flags & MMC_DATA_READ) {+					host->sg_cpu[j].dsadr =+						host->res->start + MMC_RXFIFO;+					host->sg_cpu[j].dtadr =+						host->bounce_dma;+				} else {+					memcpy(host->bounce_cpu, X, offset);+					host->sg_cpu[j].dsadr =+						host->bounce_dma;+					host->sg_cpu[j].dtadr =+						host->res->start + MMC_TXFIFO;+				}+				host->offset = offset;+				host->dma_len++;+				length -= offset;+				addr += offset;+				j++;+			} else {+				/* PXA27x, PXA3xx can handle unaligned DMA */+				dalgn = 1;+			}+		}+		host->sg_cpu[j].dcmd = dcmd | length;+		if (length & 31 && !(data->flags & MMC_DATA_READ))+			host->sg_cpu[j].dcmd |= DCMD_ENDIRQEN; 		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]);+			host->sg_cpu[j].dsadr = host->res->start + MMC_RXFIFO;+			host->sg_cpu[j].dtadr = addr; 		} else {-			host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]);-			host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;+			host->sg_cpu[j].dsadr = addr;+			host->sg_cpu[j].dtadr = host->res->start + MMC_TXFIFO; 		}-		host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *+		host->sg_cpu[j].ddadr = host->sg_dma + (j + 1) * 					sizeof(struct pxa_dma_desc); 	} 	host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP;@@ -174,10 +216,12 @@ static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) 	 * 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);+	if (!cpu_is_pxa21x() && !cpu_is_pxa25x()) {+		if (dalgn)+			DALGN |= (1 << host->dma);+		else+			DALGN &= ~(1 << host->dma);+	} 	DDADR(host->dma) = host->sg_dma; 	DCSR(host->dma) = DCSR_RUN; }@@ -281,6 +325,12 @@ static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) 	if (!data) 		return 0; +	if ((cpu_is_pxa21x() || cpu_is_pxa25x())+			&& host->offset && data->flags & MMC_DATA_READ) {+		memcpy(XX, host->bounce_cpu, host->offset);+		host->offset = 0;+	}+ 	DCSR(host->dma) = 0; 	dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, 		     host->dma_dir);@@ -562,11 +612,20 @@ static int pxamci_probe(struct platform_device *pdev) 				     MMC_CAP_SD_HIGHSPEED; 	} -	host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);+	host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,+						&host->sg_dma, GFP_KERNEL); 	if (!host->sg_cpu) { 		ret = -ENOMEM; 		goto out; 	}+	if (cpu_is_pxa25x()) {+		host->bounce = dma_alloc_coherent(&pdev->dev, PAGE_SIZE,+						&host->aligned, GFP_KERNEL);+		if (!host->bounce) {+			ret = -ENOMEM;+			goto out;+		}+	}  	spin_lock_init(&host->lock); 	host->res = r;@@ -629,7 +688,11 @@ static int pxamci_probe(struct platform_device *pdev) 		if (host->base) 			iounmap(host->base); 		if (host->sg_cpu)-			dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);+			dma_free_coherent(&pdev->dev, PAGE_SIZE,+						host->sg_cpu, host->sg_dma);+		if (cpu_is_pxa25x() && host->bounce_cpu)+			dma_free_coherent(&pdev->dev, PAGE_SIZE,+					host->bounce_cpu, host->bounce_dma); 		if (host->clk) 			clk_put(host->clk); 	}@@ -665,6 +728,9 @@ static int pxamci_remove(struct platform_device *pdev) 		pxa_free_dma(host->dma); 		iounmap(host->base); 		dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);+		if (cpu_is_pxa25x())+			dma_free_coherent(&pdev->dev, PAGE_SIZE,+					host->bounce_cpu, host->bounce_dma);  		clk_put(host->clk);