Patchwork [U-Boot,PATCHv2,7/8] driver: spi: Add memory mapped read support

login
register
mail settings
Submitter Poddar, Sourav
Date July 23, 2013, 8:59 a.m.
Message ID <1374569979-28660-8-git-send-email-sourav.poddar@ti.com>
Download mbox | patch
Permalink /patch/260996/
State Superseded
Delegated to: Jagannadha Sutradharudu Teki
Headers show

Comments

Poddar, Sourav - July 23, 2013, 8:59 a.m.
Qspi controller has a memory mapped port which can be used for
data transfers. First controller need to be configured through
configuration port, then for data read switch the controller
to memory mapped and read from the predefined location.

Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
 drivers/mtd/spi/spansion.c   |    1 +
 drivers/mtd/spi/spi_flash.c  |    8 +++-
 drivers/spi/ti_qspi.c        |   85 +++++++++++++++++++++++++++++++++++-------
 include/configs/dra7xx_evm.h |    3 +-
 include/spi.h                |    3 +
 5 files changed, 84 insertions(+), 16 deletions(-)
Wolfgang Denk - July 23, 2013, 9:29 a.m.
Dear Sourav Poddar,

In message <1374569979-28660-8-git-send-email-sourav.poddar@ti.com> you wrote:
> Qspi controller has a memory mapped port which can be used for
> data transfers. First controller need to be configured through
> configuration port, then for data read switch the controller
> to memory mapped and read from the predefined location.
> 
> Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
> ---
>  drivers/mtd/spi/spansion.c   |    1 +
>  drivers/mtd/spi/spi_flash.c  |    8 +++-
>  drivers/spi/ti_qspi.c        |   85 +++++++++++++++++++++++++++++++++++-------
>  include/configs/dra7xx_evm.h |    3 +-
>  include/spi.h                |    3 +
>  5 files changed, 84 insertions(+), 16 deletions(-)

changelog missing, and an awful lot of checkpatch issues which need to
be fixed:


ERROR: code indent should use tabs where possible
#112: FILE: drivers/mtd/spi/spansion.c:154:
+        flash->memory_map = spi->memory_map;$

WARNING: please, no spaces at the start of a line
#112: FILE: drivers/mtd/spi/spansion.c:154:
+        flash->memory_map = spi->memory_map;$

ERROR: code indent should use tabs where possible
#154: FILE: drivers/spi/ti_qspi.c:26:
+        u32 cmd;$

WARNING: please, no spaces at the start of a line
#154: FILE: drivers/spi/ti_qspi.c:26:
+        u32 cmd;$

ERROR: code indent should use tabs where possible
#155: FILE: drivers/spi/ti_qspi.c:27:
+        u32 dc;$

WARNING: please, no spaces at the start of a line
#155: FILE: drivers/spi/ti_qspi.c:27:
+        u32 dc;$

ERROR: code indent should use tabs where possible
#233: FILE: drivers/spi/ti_qspi.c:237:
+        qslave->dc = 0;$

WARNING: please, no spaces at the start of a line
#233: FILE: drivers/spi/ti_qspi.c:237:
+        qslave->dc = 0;$

ERROR: code indent should use tabs where possible
#234: FILE: drivers/spi/ti_qspi.c:238:
+        if (qslave->mode & SPI_CPHA)$

WARNING: please, no spaces at the start of a line
#234: FILE: drivers/spi/ti_qspi.c:238:
+        if (qslave->mode & SPI_CPHA)$

ERROR: code indent should use tabs where possible
#235: FILE: drivers/spi/ti_qspi.c:239:
+                qslave->dc |= QSPI_CKPHA(slave->cs);$

WARNING: please, no spaces at the start of a line
#235: FILE: drivers/spi/ti_qspi.c:239:
+                qslave->dc |= QSPI_CKPHA(slave->cs);$

ERROR: code indent should use tabs where possible
#236: FILE: drivers/spi/ti_qspi.c:240:
+        if (qslave->mode & SPI_CPOL)$

WARNING: please, no spaces at the start of a line
#236: FILE: drivers/spi/ti_qspi.c:240:
+        if (qslave->mode & SPI_CPOL)$

ERROR: code indent should use tabs where possible
#237: FILE: drivers/spi/ti_qspi.c:241:
+                qslave->dc |= QSPI_CKPOL(slave->cs);$

WARNING: please, no spaces at the start of a line
#237: FILE: drivers/spi/ti_qspi.c:241:
+                qslave->dc |= QSPI_CKPOL(slave->cs);$

ERROR: code indent should use tabs where possible
#238: FILE: drivers/spi/ti_qspi.c:242:
+        if (qslave->mode & SPI_CS_HIGH)$

WARNING: please, no spaces at the start of a line
#238: FILE: drivers/spi/ti_qspi.c:242:
+        if (qslave->mode & SPI_CS_HIGH)$

ERROR: code indent should use tabs where possible
#239: FILE: drivers/spi/ti_qspi.c:243:
+                qslave->dc |= QSPI_CSPOL(slave->cs);$

WARNING: please, no spaces at the start of a line
#239: FILE: drivers/spi/ti_qspi.c:243:
+                qslave->dc |= QSPI_CSPOL(slave->cs);$

ERROR: code indent should use tabs where possible
#241: FILE: drivers/spi/ti_qspi.c:245:
+        writel(qslave->dc, &qspi->spi_dc);$

WARNING: please, no spaces at the start of a line
#241: FILE: drivers/spi/ti_qspi.c:245:
+        writel(qslave->dc, &qspi->spi_dc);$

ERROR: code indent should use tabs where possible
#243: FILE: drivers/spi/ti_qspi.c:247:
+        if (flags == SPI_XFER_MEM_MAP) {$

WARNING: please, no spaces at the start of a line
#243: FILE: drivers/spi/ti_qspi.c:247:
+        if (flags == SPI_XFER_MEM_MAP) {$

ERROR: code indent should use tabs where possible
#244: FILE: drivers/spi/ti_qspi.c:248:
+                writel(MM_SWITCH, &qspi->spi_switch);$

WARNING: please, no spaces at the start of a line
#244: FILE: drivers/spi/ti_qspi.c:248:
+                writel(MM_SWITCH, &qspi->spi_switch);$

ERROR: code indent should use tabs where possible
#245: FILE: drivers/spi/ti_qspi.c:249:
+                val = readl(CORE_CTRL_IO);$

WARNING: please, no spaces at the start of a line
#245: FILE: drivers/spi/ti_qspi.c:249:
+                val = readl(CORE_CTRL_IO);$

ERROR: code indent should use tabs where possible
#246: FILE: drivers/spi/ti_qspi.c:250:
+                val |= MEM_CS;$

WARNING: please, no spaces at the start of a line
#246: FILE: drivers/spi/ti_qspi.c:250:
+                val |= MEM_CS;$

ERROR: code indent should use tabs where possible
#247: FILE: drivers/spi/ti_qspi.c:251:
+                writel(val, CORE_CTRL_IO);$

WARNING: please, no spaces at the start of a line
#247: FILE: drivers/spi/ti_qspi.c:251:
+                writel(val, CORE_CTRL_IO);$

ERROR: code indent should use tabs where possible
#248: FILE: drivers/spi/ti_qspi.c:252:
+                return 0;$

WARNING: please, no spaces at the start of a line
#248: FILE: drivers/spi/ti_qspi.c:252:
+                return 0;$

ERROR: code indent should use tabs where possible
#249: FILE: drivers/spi/ti_qspi.c:253:
+        } else if (flags == SPI_XFER_MEM_MAP_END) {$

WARNING: please, no spaces at the start of a line
#249: FILE: drivers/spi/ti_qspi.c:253:
+        } else if (flags == SPI_XFER_MEM_MAP_END) {$

ERROR: code indent should use tabs where possible
#250: FILE: drivers/spi/ti_qspi.c:254:
+                writel(~MM_SWITCH, &qspi->spi_switch);$

WARNING: please, no spaces at the start of a line
#250: FILE: drivers/spi/ti_qspi.c:254:
+                writel(~MM_SWITCH, &qspi->spi_switch);$

ERROR: code indent should use tabs where possible
#251: FILE: drivers/spi/ti_qspi.c:255:
+                val = readl(CORE_CTRL_IO);$

WARNING: please, no spaces at the start of a line
#251: FILE: drivers/spi/ti_qspi.c:255:
+                val = readl(CORE_CTRL_IO);$

ERROR: code indent should use tabs where possible
#252: FILE: drivers/spi/ti_qspi.c:256:
+                val &= MEM_CS_UNSELECT;$

WARNING: please, no spaces at the start of a line
#252: FILE: drivers/spi/ti_qspi.c:256:
+                val &= MEM_CS_UNSELECT;$

ERROR: code indent should use tabs where possible
#253: FILE: drivers/spi/ti_qspi.c:257:
+                writel(val, CORE_CTRL_IO);$

WARNING: please, no spaces at the start of a line
#253: FILE: drivers/spi/ti_qspi.c:257:
+                writel(val, CORE_CTRL_IO);$

ERROR: code indent should use tabs where possible
#254: FILE: drivers/spi/ti_qspi.c:258:
+                return 0;$

WARNING: please, no spaces at the start of a line
#254: FILE: drivers/spi/ti_qspi.c:258:
+                return 0;$

ERROR: code indent should use tabs where possible
#255: FILE: drivers/spi/ti_qspi.c:259:
+        }$

WARNING: please, no spaces at the start of a line
#255: FILE: drivers/spi/ti_qspi.c:259:
+        }$

ERROR: code indent should use tabs where possible
#257: FILE: drivers/spi/ti_qspi.c:261:
+        if (bitlen == 0)$

WARNING: please, no spaces at the start of a line
#257: FILE: drivers/spi/ti_qspi.c:261:
+        if (bitlen == 0)$

ERROR: code indent should use tabs where possible
#258: FILE: drivers/spi/ti_qspi.c:262:
+                return -1;$

WARNING: please, no spaces at the start of a line
#258: FILE: drivers/spi/ti_qspi.c:262:
+                return -1;$

total: 26 errors, 26 warnings, 0 checks, 177 lines checked

NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or
      scripts/cleanfile

NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE NETWORKING_BLOCK_COMMENT_STYLE USLEEP_RANGE

/home/wd/Mail/U-Boot/16312 has style problems, please review.

If any of these errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.

Best regards,

Wolfgang Denk
Poddar, Sourav - July 23, 2013, 9:34 a.m.
On Tuesday 23 July 2013 02:59 PM, Wolfgang Denk wrote:
> Dear Sourav Poddar,
>
> In message<1374569979-28660-8-git-send-email-sourav.poddar@ti.com>  you wrote:
>> Qspi controller has a memory mapped port which can be used for
>> data transfers. First controller need to be configured through
>> configuration port, then for data read switch the controller
>> to memory mapped and read from the predefined location.
>>
>> Signed-off-by: Sourav Poddar<sourav.poddar@ti.com>
>> ---
>>   drivers/mtd/spi/spansion.c   |    1 +
>>   drivers/mtd/spi/spi_flash.c  |    8 +++-
>>   drivers/spi/ti_qspi.c        |   85 +++++++++++++++++++++++++++++++++++-------
>>   include/configs/dra7xx_evm.h |    3 +-
>>   include/spi.h                |    3 +
>>   5 files changed, 84 insertions(+), 16 deletions(-)
> changelog missing, and an awful lot of checkpatch issues which need to
> be fixed:
>
My bad. I think I missed this, will correct it in the next version.
> ERROR: code indent should use tabs where possible
> #112: FILE: drivers/mtd/spi/spansion.c:154:
> +        flash->memory_map = spi->memory_map;$
>
> WARNING: please, no spaces at the start of a line
> #112: FILE: drivers/mtd/spi/spansion.c:154:
> +        flash->memory_map = spi->memory_map;$
>
> ERROR: code indent should use tabs where possible
> #154: FILE: drivers/spi/ti_qspi.c:26:
> +        u32 cmd;$
>
> WARNING: please, no spaces at the start of a line
> #154: FILE: drivers/spi/ti_qspi.c:26:
> +        u32 cmd;$
>
> ERROR: code indent should use tabs where possible
> #155: FILE: drivers/spi/ti_qspi.c:27:
> +        u32 dc;$
>
> WARNING: please, no spaces at the start of a line
> #155: FILE: drivers/spi/ti_qspi.c:27:
> +        u32 dc;$
>
> ERROR: code indent should use tabs where possible
> #233: FILE: drivers/spi/ti_qspi.c:237:
> +        qslave->dc = 0;$
>
> WARNING: please, no spaces at the start of a line
> #233: FILE: drivers/spi/ti_qspi.c:237:
> +        qslave->dc = 0;$
>
> ERROR: code indent should use tabs where possible
> #234: FILE: drivers/spi/ti_qspi.c:238:
> +        if (qslave->mode&  SPI_CPHA)$
>
> WARNING: please, no spaces at the start of a line
> #234: FILE: drivers/spi/ti_qspi.c:238:
> +        if (qslave->mode&  SPI_CPHA)$
>
> ERROR: code indent should use tabs where possible
> #235: FILE: drivers/spi/ti_qspi.c:239:
> +                qslave->dc |= QSPI_CKPHA(slave->cs);$
>
> WARNING: please, no spaces at the start of a line
> #235: FILE: drivers/spi/ti_qspi.c:239:
> +                qslave->dc |= QSPI_CKPHA(slave->cs);$
>
> ERROR: code indent should use tabs where possible
> #236: FILE: drivers/spi/ti_qspi.c:240:
> +        if (qslave->mode&  SPI_CPOL)$
>
> WARNING: please, no spaces at the start of a line
> #236: FILE: drivers/spi/ti_qspi.c:240:
> +        if (qslave->mode&  SPI_CPOL)$
>
> ERROR: code indent should use tabs where possible
> #237: FILE: drivers/spi/ti_qspi.c:241:
> +                qslave->dc |= QSPI_CKPOL(slave->cs);$
>
> WARNING: please, no spaces at the start of a line
> #237: FILE: drivers/spi/ti_qspi.c:241:
> +                qslave->dc |= QSPI_CKPOL(slave->cs);$
>
> ERROR: code indent should use tabs where possible
> #238: FILE: drivers/spi/ti_qspi.c:242:
> +        if (qslave->mode&  SPI_CS_HIGH)$
>
> WARNING: please, no spaces at the start of a line
> #238: FILE: drivers/spi/ti_qspi.c:242:
> +        if (qslave->mode&  SPI_CS_HIGH)$
>
> ERROR: code indent should use tabs where possible
> #239: FILE: drivers/spi/ti_qspi.c:243:
> +                qslave->dc |= QSPI_CSPOL(slave->cs);$
>
> WARNING: please, no spaces at the start of a line
> #239: FILE: drivers/spi/ti_qspi.c:243:
> +                qslave->dc |= QSPI_CSPOL(slave->cs);$
>
> ERROR: code indent should use tabs where possible
> #241: FILE: drivers/spi/ti_qspi.c:245:
> +        writel(qslave->dc,&qspi->spi_dc);$
>
> WARNING: please, no spaces at the start of a line
> #241: FILE: drivers/spi/ti_qspi.c:245:
> +        writel(qslave->dc,&qspi->spi_dc);$
>
> ERROR: code indent should use tabs where possible
> #243: FILE: drivers/spi/ti_qspi.c:247:
> +        if (flags == SPI_XFER_MEM_MAP) {$
>
> WARNING: please, no spaces at the start of a line
> #243: FILE: drivers/spi/ti_qspi.c:247:
> +        if (flags == SPI_XFER_MEM_MAP) {$
>
> ERROR: code indent should use tabs where possible
> #244: FILE: drivers/spi/ti_qspi.c:248:
> +                writel(MM_SWITCH,&qspi->spi_switch);$
>
> WARNING: please, no spaces at the start of a line
> #244: FILE: drivers/spi/ti_qspi.c:248:
> +                writel(MM_SWITCH,&qspi->spi_switch);$
>
> ERROR: code indent should use tabs where possible
> #245: FILE: drivers/spi/ti_qspi.c:249:
> +                val = readl(CORE_CTRL_IO);$
>
> WARNING: please, no spaces at the start of a line
> #245: FILE: drivers/spi/ti_qspi.c:249:
> +                val = readl(CORE_CTRL_IO);$
>
> ERROR: code indent should use tabs where possible
> #246: FILE: drivers/spi/ti_qspi.c:250:
> +                val |= MEM_CS;$
>
> WARNING: please, no spaces at the start of a line
> #246: FILE: drivers/spi/ti_qspi.c:250:
> +                val |= MEM_CS;$
>
> ERROR: code indent should use tabs where possible
> #247: FILE: drivers/spi/ti_qspi.c:251:
> +                writel(val, CORE_CTRL_IO);$
>
> WARNING: please, no spaces at the start of a line
> #247: FILE: drivers/spi/ti_qspi.c:251:
> +                writel(val, CORE_CTRL_IO);$
>
> ERROR: code indent should use tabs where possible
> #248: FILE: drivers/spi/ti_qspi.c:252:
> +                return 0;$
>
> WARNING: please, no spaces at the start of a line
> #248: FILE: drivers/spi/ti_qspi.c:252:
> +                return 0;$
>
> ERROR: code indent should use tabs where possible
> #249: FILE: drivers/spi/ti_qspi.c:253:
> +        } else if (flags == SPI_XFER_MEM_MAP_END) {$
>
> WARNING: please, no spaces at the start of a line
> #249: FILE: drivers/spi/ti_qspi.c:253:
> +        } else if (flags == SPI_XFER_MEM_MAP_END) {$
>
> ERROR: code indent should use tabs where possible
> #250: FILE: drivers/spi/ti_qspi.c:254:
> +                writel(~MM_SWITCH,&qspi->spi_switch);$
>
> WARNING: please, no spaces at the start of a line
> #250: FILE: drivers/spi/ti_qspi.c:254:
> +                writel(~MM_SWITCH,&qspi->spi_switch);$
>
> ERROR: code indent should use tabs where possible
> #251: FILE: drivers/spi/ti_qspi.c:255:
> +                val = readl(CORE_CTRL_IO);$
>
> WARNING: please, no spaces at the start of a line
> #251: FILE: drivers/spi/ti_qspi.c:255:
> +                val = readl(CORE_CTRL_IO);$
>
> ERROR: code indent should use tabs where possible
> #252: FILE: drivers/spi/ti_qspi.c:256:
> +                val&= MEM_CS_UNSELECT;$
>
> WARNING: please, no spaces at the start of a line
> #252: FILE: drivers/spi/ti_qspi.c:256:
> +                val&= MEM_CS_UNSELECT;$
>
> ERROR: code indent should use tabs where possible
> #253: FILE: drivers/spi/ti_qspi.c:257:
> +                writel(val, CORE_CTRL_IO);$
>
> WARNING: please, no spaces at the start of a line
> #253: FILE: drivers/spi/ti_qspi.c:257:
> +                writel(val, CORE_CTRL_IO);$
>
> ERROR: code indent should use tabs where possible
> #254: FILE: drivers/spi/ti_qspi.c:258:
> +                return 0;$
>
> WARNING: please, no spaces at the start of a line
> #254: FILE: drivers/spi/ti_qspi.c:258:
> +                return 0;$
>
> ERROR: code indent should use tabs where possible
> #255: FILE: drivers/spi/ti_qspi.c:259:
> +        }$
>
> WARNING: please, no spaces at the start of a line
> #255: FILE: drivers/spi/ti_qspi.c:259:
> +        }$
>
> ERROR: code indent should use tabs where possible
> #257: FILE: drivers/spi/ti_qspi.c:261:
> +        if (bitlen == 0)$
>
> WARNING: please, no spaces at the start of a line
> #257: FILE: drivers/spi/ti_qspi.c:261:
> +        if (bitlen == 0)$
>
> ERROR: code indent should use tabs where possible
> #258: FILE: drivers/spi/ti_qspi.c:262:
> +                return -1;$
>
> WARNING: please, no spaces at the start of a line
> #258: FILE: drivers/spi/ti_qspi.c:262:
> +                return -1;$
>
> total: 26 errors, 26 warnings, 0 checks, 177 lines checked
>
> NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or
>        scripts/cleanfile
>
> NOTE: Ignored message types: COMPLEX_MACRO CONSIDER_KSTRTO MINMAX MULTISTATEMENT_MACRO_USE_DO_WHILE NETWORKING_BLOCK_COMMENT_STYLE USLEEP_RANGE
>
> /home/wd/Mail/U-Boot/16312 has style problems, please review.
>
> If any of these errors are false positives, please report
> them to the maintainer, see CHECKPATCH in MAINTAINERS.
>
> Best regards,
>
> Wolfgang Denk
>

Patch

diff --git a/drivers/mtd/spi/spansion.c b/drivers/mtd/spi/spansion.c
index 3ec2151..1f60456 100644
--- a/drivers/mtd/spi/spansion.c
+++ b/drivers/mtd/spi/spansion.c
@@ -151,6 +151,7 @@  struct spi_flash *spi_flash_probe_spansion(struct spi_slave *spi, u8 *idcode)
 	flash->page_size = 256;
 	flash->sector_size = 256 * params->pages_per_sector;
 	flash->size = flash->sector_size * params->nr_sectors;
+        flash->memory_map = spi->memory_map;
 
 	return flash;
 }
diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index c81f402..c1173d8 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -288,8 +288,12 @@  int spi_flash_cmd_read_quad(struct spi_flash *flash, u32 offset,
 
 	spi->quad_enable = 1;
 	/* Handle memory-mapped SPI */
-	if (flash->memory_map)
+	if (flash->memory_map) {
+		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MEM_MAP);
 		memcpy(data, flash->memory_map + offset, len);
+		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MEM_MAP_END);
+		return 0;
+	}
 
 	page_size = flash->page_size;
 	page_addr = offset / page_size;
@@ -330,7 +334,9 @@  int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 
 	/* Handle memory-mapped SPI */
 	if (flash->memory_map) {
+		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MEM_MAP);
 		memcpy(data, flash->memory_map + offset, len);
+		spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MEM_MAP_END);
 		return 0;
 	}
 
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
index 12bba11..d314b6e 100644
--- a/drivers/spi/ti_qspi.c
+++ b/drivers/spi/ti_qspi.c
@@ -23,8 +23,8 @@ 
 struct qspi_slave {
 	struct spi_slave slave;
 	unsigned int mode;
-	u32 cmd;
-	u32 dc;
+        u32 cmd;
+        u32 dc;
 };
 
 #define to_qspi_slave(s) container_of(s, struct qspi_slave, slave)
@@ -86,6 +86,24 @@  static struct qspi_regs *qspi = (struct qspi_regs *)QSPI_BASE;
 #define QSPI_WC_BUSY			(QSPI_WC | QSPI_BUSY)
 #define QSPI_XFER_DONE			QSPI_WC
 
+#define MM_SWITCH		0x01
+#define MEM_CS                  0x100
+#define MEM_CS_UNSELECT		0xfffff0ff
+#define MMAP_START_ADDR         0x5c000000
+#define CORE_CTRL_IO            0x4a002558
+
+#define	QSPI_CMD_READ				(0x3 << 0)
+#define	QSPI_CMD_READ_QUAD			(0x6b << 0)
+#define	QSPI_CMD_READ_FAST			(0x0b << 0)
+
+#define	QSPI_SETUP0_NUM_A_BYTES			(0x2 << 8)
+#define	QSPI_SETUP0_NUM_D_BYTES_NO_BITS		(0x0 << 10)
+#define	QSPI_SETUP0_NUM_D_BYTES_8_BITS		(0x1 << 10)
+#define	QSPI_SETUP0_READ_NORMAL			(0x0 << 12)
+#define	QSPI_SETUP0_READ_QUAD			(0x3 << 12)
+#define	QSPI_CMD_WRITE				(0x2 << 16)
+#define QSPI_NUM_DUMMY_BITS			(0x0 << 24)
+
 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 {
 	return 1;
@@ -108,6 +126,24 @@  void spi_init(void)
 	/* nothing to do */
 }
 
+void spi_set_up_spi_register(struct spi_slave *slave)
+{
+	u32 memval = 0;
+
+	slave->memory_map = (void *)MMAP_START_ADDR;
+
+#ifdef CONFIG_SF_QUAD_RD
+	memval |= (QSPI_CMD_READ_QUAD | QSPI_SETUP0_NUM_A_BYTES |
+		QSPI_SETUP0_NUM_D_BYTES_8_BITS | QSPI_SETUP0_READ_QUAD |
+			QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS);
+#else
+	memval |= (QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES |
+		QSPI_SETUP0_NUM_D_BYTES_NO_BITS | QSPI_SETUP0_READ_NORMAL |
+			QSPI_CMD_WRITE | QSPI_NUM_DUMMY_BITS);
+#endif
+	writel(memval, &qspi->spi_setup0);
+}
+
 void spi_set_speed(struct spi_slave *slave, uint hz)
 {
 	uint clk_div;
@@ -149,6 +185,11 @@  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
 	spi_set_speed(&qslave->slave, max_hz);
 	qslave->mode = mode;
+
+#ifdef CONFIG_MMAP
+	spi_set_up_spi_register(&qslave->slave);
+#endif
+
 	debug("%s: bus:%i cs:%i mode:%i\n", __func__, bus, cs, mode);
 
 	return &qslave->slave;
@@ -188,12 +229,37 @@  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 	const uchar *txp = dout;
 	uchar *rxp = din;
 	uint status;
-	int timeout;
+	int timeout, val;
 
 	debug("%s: bus:%i cs:%i bitlen:%i words:%i flags:%lx\n", __func__,
 		slave->bus, slave->cs, bitlen, words, flags);
-	if (bitlen == 0)
-		return -1;
+
+        qslave->dc = 0;
+        if (qslave->mode & SPI_CPHA)
+                qslave->dc |= QSPI_CKPHA(slave->cs);
+        if (qslave->mode & SPI_CPOL)
+                qslave->dc |= QSPI_CKPOL(slave->cs);
+        if (qslave->mode & SPI_CS_HIGH)
+                qslave->dc |= QSPI_CSPOL(slave->cs);
+
+        writel(qslave->dc, &qspi->spi_dc);
+
+        if (flags == SPI_XFER_MEM_MAP) {
+                writel(MM_SWITCH, &qspi->spi_switch);
+                val = readl(CORE_CTRL_IO);
+                val |= MEM_CS;
+                writel(val, CORE_CTRL_IO);
+                return 0;
+        } else if (flags == SPI_XFER_MEM_MAP_END) {
+                writel(~MM_SWITCH, &qspi->spi_switch);
+                val = readl(CORE_CTRL_IO);
+                val &= MEM_CS_UNSELECT;
+                writel(val, CORE_CTRL_IO);
+                return 0;
+        }
+
+        if (bitlen == 0)
+                return -1;
 
 	if (bitlen % 8) {
 		flags |= SPI_XFER_END;
@@ -208,15 +274,6 @@  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 		qslave->cmd |= QSPI_3_PIN;
 	qslave->cmd |= 0xfff;
 
-	/* setup device control reg */
-	qslave->dc = 0;
-	if (qslave->mode & SPI_CPHA)
-		qslave->dc |= QSPI_CKPHA(slave->cs);
-	if (qslave->mode & SPI_CPOL)
-		qslave->dc |= QSPI_CKPOL(slave->cs);
-	if (qslave->mode & SPI_CS_HIGH)
-		qslave->dc |= QSPI_CSPOL(slave->cs);
-
 	while (words--) {
 		if (txp) {
 			debug("tx cmd %08x dc %08x data %02x\n",
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 9d11820..4d80a01 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -51,7 +51,8 @@ 
 #define CONFIG_CMD_SF
 #define CONFIG_CMD_SPI
 #define CONFIG_SF_QUAD_RD
-#define CONFIG_SF_DEFAULT_SPEED                12000000
+#define CONFIG_MMAP
+#define CONFIG_SF_DEFAULT_SPEED                48000000
 #define CONFIG_DEFAULT_SPI_MODE                SPI_MODE_3
 
 /* SPI SPL */
diff --git a/include/spi.h b/include/spi.h
index d5a0ead..890e739 100644
--- a/include/spi.h
+++ b/include/spi.h
@@ -48,6 +48,8 @@ 
 /* Header byte that marks the start of the message */
 #define SPI_PREAMBLE_END_BYTE	0xec
 
+#define SPI_XFER_MEM_MAP 0x05
+#define SPI_XFER_MEM_MAP_END 0x06
 /*-----------------------------------------------------------------------
  * Representation of a SPI slave, i.e. what we're communicating with.
  *
@@ -63,6 +65,7 @@  struct spi_slave {
 	unsigned int	cs;
 	unsigned int max_write_size;
 	bool quad_enable;
+	void *memory_map;
 };
 
 /*-----------------------------------------------------------------------