diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c
--- a/drivers/spi/atmel_spi.c
+++ b/drivers/spi/atmel_spi.c
@@ -647,6 +647,22 @@ static void atmel_spi_next_message(struct spi_master *master)
 	atmel_spi_next_xfer(master, msg);
 }
 
+static void *adjust_buffer_location(struct device *dev, void *buf)
+{
+	if (likely(buf < high_memory)) {
+		return buf;
+	} else {
+		struct page *pg;
+
+		pg = vmalloc_to_page(buf);
+		if (pg == 0) {
+			dev_err(dev, "failed to vmalloc_to_page\n");
+			return NULL;
+		}
+		return page_address(pg) + ((size_t)buf & ~PAGE_MASK);
+	}
+}
+
 /*
  * For DMA, tx_buf/tx_dma have the same relationship as rx_buf/rx_dma:
  *  - The buffer is either valid for CPU access, else NULL
@@ -658,23 +674,24 @@ static int
 atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer)
 {
 	struct device	*dev = &as->pdev->dev;
+	void 		*ptr;
 
 	xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS;
 	if (xfer->tx_buf) {
-		/* tx_buf is a const void* where we need a void * for the dma
-		 * mapping */
-		void *nonconst_tx = (void *)xfer->tx_buf;
-
-		xfer->tx_dma = dma_map_single(dev,
-				nonconst_tx, xfer->len,
-				DMA_TO_DEVICE);
+		ptr = adjust_buffer_location(dev, (void *)xfer->tx_buf);
+		if (ptr)
+			xfer->tx_dma = dma_map_single(dev,
+					ptr, xfer->len,
+					DMA_TO_DEVICE);
 		if (dma_mapping_error(dev, xfer->tx_dma))
 			return -ENOMEM;
 	}
 	if (xfer->rx_buf) {
-		xfer->rx_dma = dma_map_single(dev,
-				xfer->rx_buf, xfer->len,
-				DMA_FROM_DEVICE);
+		ptr = adjust_buffer_location(dev, xfer->rx_buf);
+		if (ptr)
+			xfer->rx_dma = dma_map_single(dev,
+					ptr, xfer->len,
+					DMA_FROM_DEVICE);
 		if (dma_mapping_error(dev, xfer->rx_dma)) {
 			if (xfer->tx_buf)
 				dma_unmap_single(dev,diff --git a/arch/arm/mach-at91/board-
