linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: Sourav Poddar <sourav.poddar@ti.com>
To: Jagan Teki <jagannadh.teki@gmail.com>
Cc: Rajendra nayak <rnayak@ti.com>,
	jagannadha.sutradharudu-teki@xilinx.com,
	Felipe Balbi <balbi@ti.com>,
	u-boot@lists.denx.de, linux-mtd@lists.infradead.org,
	Tom Rini <trini@ti.com>
Subject: Re: [U-Boot] U-boot: Erase/read/write issue with S25fl256S flash device
Date: Mon, 17 Jun 2013 13:11:35 +0530	[thread overview]
Message-ID: <51BEBDAF.7000201@ti.com> (raw)
In-Reply-To: <CAD6G_RRNT5ukFovS1Spa7uMmX72kLpZ-YycfcdDdESTMHnNU9Q@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 13037 bytes --]

Hi Jagan,
On Monday 17 June 2013 01:04 PM, Jagan Teki wrote:
> On Mon, Jun 17, 2013 at 12:49 PM, Sourav Poddar<sourav.poddar@ti.com>  wrote:
>> On Monday 17 June 2013 12:44 PM, Jagan Teki wrote:
>>> On Mon, Jun 17, 2013 at 12:41 PM, Sourav Poddar<sourav.poddar@ti.com>
>>> wrote:
>>>> On Monday 17 June 2013 12:35 PM, Jagan Teki wrote:
>>>>> On Mon, Jun 17, 2013 at 12:28 PM, Sourav Poddar<sourav.poddar@ti.com>
>>>>> wrote:
>>>>>> HI Jagan,
>>>>>>
>>>>>> On Monday 17 June 2013 12:17 PM, Jagan Teki wrote:
>>>>>>> Hi Sourav,
>>>>>>>
>>>>>>> On Mon, Jun 17, 2013 at 11:44 AM, Sourav Poddar<sourav.poddar@ti.com>
>>>>>>> wrote:
>>>>>>>> Hi Jagan,
>>>>>>>>
>>>>>>>> On Saturday 15 June 2013 09:47 PM, Jagan Teki wrote:
>>>>>>>>> On 14-06-2013 20:13, Sourav Poddar wrote:
>>>>>>>>>> Hi Jagan,
>>>>>>>>>> On Friday 14 June 2013 08:08 PM, Jagan Teki wrote:
>>>>>>>>>>> On 14-06-2013 20:03, Sourav Poddar wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> Hi,
>>>>>>>>>>>>
>>>>>>>>>>>> On Wednesday 12 June 2013 01:00 PM, Sourav Poddar wrote:
>>>>>>>>>>>>> Hi,
>>>>>>>>>>>>>
>>>>>>>>>>>>> I am working on qspi flash device S25FL256S at u-boot level. I
>>>>>>>>>>>>> am
>>>>>>>>>>>>> trying to
>>>>>>>>>>>>> make use of the existing spi_flash.c framework available at
>>>>>>>>>>>>> u-boot
>>>>>>>>>>>>> for
>>>>>>>>>>>>> erasing/reading/writing
>>>>>>>>>>>>> into the flash device.
>>>>>>>>>>>>>
>>>>>>>>>>>>> There are several issues(mentioned below), which I faced while
>>>>>>>>>>>>> using
>>>>>>>>>>>>> S25FL256s flash device
>>>>>>>>>>>>> with my dra7xx board which has a qspi controller to which the
>>>>>>>>>>>>> above
>>>>>>>>>>>>> mentioned flash device is attached.
>>>>>>>>>>>>>
>>>>>>>>>>>>> 1. Erase (spi_flash_cmd_erase)
>>>>>>>>>>>>>
>>>>>>>>>>>>> Issuing a command something like this..
>>>>>>>>>>>>>
>>>>>>>>>>>>> sf erase 0x0 0x50000
>>>>>>>>>>>>>      - erases only first 0x20000 bytes of flash device, anything
>>>>>>>>>>>>> above
>>>>>>>>>>>>> that is not erase. I need to
>>>>>>>>>>>>>        issue separate commands after 0x20000 for every 0x10000
>>>>>>>>>>>>> bytes.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Am i missing anything here?
>>>>>>>>>>>>>
>>>>>>>>>>>>> 2. read
>>>>>>>>>>>>>
>>>>>>>>>>>>> sf read 81000000 0 0x10000
>>>>>>>>>>>>>
>>>>>>>>>>>>> Read is not happening properly. The last few byte along the 4k
>>>>>>>>>>>>> boundary always shows zero.
>>>>>>>>>>>>> Above 4k bytes, read is not happening.
>>>>>>>>>>>>>
>>>>>>>>>>>>> For ex:
>>>>>>>>>>>>>      DRA752 EVM # md 81000f00
>>>>>>>>>>>>> 81000f00: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f10: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f20: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f30: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f40: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f50: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f60: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f70: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f80: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000f90: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000fa0: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000fb0: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000fc0: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000fd0: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000fe0: ffffffff ffffffff ffffffff ffffffff
>>>>>>>>>>>>> ................
>>>>>>>>>>>>> 81000ff0: ffffffff ffffffff 00ffffff 00000000
>>>>>>>>>>>>> ................
>>>>>>>>>>>>>
>>>>>>>>>>>>> In this dump, if you see 81000ff0 the last column shows 000000
>>>>>>>>>>>>> which
>>>>>>>>>>>>> is
>>>>>>>>>>>>> not expected. and it happens along every 4k bytes.
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> So, to get rid of the above issue, I switched to page read with
>>>>>>>>>>>>> the
>>>>>>>>>>>>> below patch[1],
>>>>>>>>>>>>> which is giving me the correct result.
>>>>>>>>>>>>> [1]:
>>>>>>>>>>>>> @@ -147,17 +153,40 @@ int spi_flash_read_common(struct spi_flash
>>>>>>>>>>>>> *flash, const u8 *cmd,
>>>>>>>>>>>>>      int spi_flash_cmd_read_fast(struct spi_flash *flash, u32
>>>>>>>>>>>>> offset,
>>>>>>>>>>>>>                     size_t len, void *data)
>>>>>>>>>>>>>      {
>>>>>>>>>>>>> -       u8 cmd[5];
>>>>>>>>>>>>> +       unsigned long page_addr, byte_addr, page_size;
>>>>>>>>>>>>> +       size_t chunk_len, actual;
>>>>>>>>>>>>> +       int ret = 0;
>>>>>>>>>>>>> +       u8 cmd[4];
>>>>>>>>>>>>>
>>>>>>>>>>>>>             /* Handle memory-mapped SPI */
>>>>>>>>>>>>>             if (flash->memory_map)
>>>>>>>>>>>>>                     memcpy(data, flash->memory_map + offset,
>>>>>>>>>>>>> len);
>>>>>>>>>>>>> +       page_size = flash->page_size;
>>>>>>>>>>>>> +       page_addr = offset / page_size;
>>>>>>>>>>>>> +       byte_addr = offset % page_size;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +       cmd[0] = CMD_READ_ARRAY_SLOW;
>>>>>>>>>>>>> +       for (actual = 0; actual<     len; actual += chunk_len) {
>>>>>>>>>>>>> +               chunk_len = min(len - actual, page_size -
>>>>>>>>>>>>> byte_addr);
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +               cmd[1] = page_addr>>     8;
>>>>>>>>>>>>> +               cmd[2] = page_addr;
>>>>>>>>>>>>> +               cmd[3] = byte_addr;
>>>>>>>>>>>>> +
>>>>>>>>>>>>> +               ret = spi_flash_read_common(flash, cmd,
>>>>>>>>>>>>> sizeof(cmd),
>>>>>>>>>>>>> data + actual, chunk_len);
>>>>>>>>>>>>> +               if (ret<     0) {
>>>>>>>>>>>>> +                       debug("SF: read failed");
>>>>>>>>>>>>> +                       break;
>>>>>>>>>>>>> +               }
>>>>>>>>>>>>>
>>>>>>>>>>>>> -       cmd[0] = CMD_READ_ARRAY_FAST;
>>>>>>>>>>>>> -       spi_flash_addr(offset, cmd);
>>>>>>>>>>>>> -       cmd[4] = 0x00;
>>>>>>>>>>>>> +               byte_addr += chunk_len;
>>>>>>>>>>>>> +               if (byte_addr == page_size) {
>>>>>>>>>>>>> +                       page_addr++;
>>>>>>>>>>>>> +                       byte_addr = 0;
>>>>>>>>>>>>> +               }
>>>>>>>>>>>>> +       }
>>>>>>>>>>>>>
>>>>>>>>>>>>> -       return spi_flash_read_common(flash, cmd, sizeof(cmd),
>>>>>>>>>>>>> data,
>>>>>>>>>>>>> len);
>>>>>>>>>>>>> +       return ret;
>>>>>>>>>>>>>      }
>>>>>>>>>>>>>
>>>>>>>>>>>>> Any idea about this?
>>>>>>>>>>>>>
>>>>>>>>>>>>> 3.  write (spi_flash_cmd_write_multi)
>>>>>>>>>>>>>       write not happening properly.
>>>>>>>>>>>>>
>>>>>>>>>>>>> observations: only able to write single page, anything after a
>>>>>>>>>>>>> page
>>>>>>>>>>>>> is
>>>>>>>>>>>>> not getting
>>>>>>>>>>>>>             written.
>>>>>>>>>>>>> Workaround:
>>>>>>>>>>>>> I did a write disable latch at the end of every write cycle(page
>>>>>>>>>>>>> program) and enable it
>>>>>>>>>>>>> again for the next loop. With this, I see I get rid of the above
>>>>>>>>>>>>> issue.
>>>>>>>>>>>>>
>>>>>>>>>>>>>      @@ -117,6 +117,12 @@ int spi_flash_cmd_write_multi(struct
>>>>>>>>>>>>> spi_flash
>>>>>>>>>>>>> *flash, u32 offset,
>>>>>>>>>>>>>                     if (ret)
>>>>>>>>>>>>>                             break;
>>>>>>>>>>>>>
>>>>>>>>>>>>> +               ret = spi_flash_cmd_write_disable(flash);
>>>>>>>>>>>>> +               if (ret<     0) {
>>>>>>>>>>>>> +                       printf("SF: disabling write failed\n");
>>>>>>>>>>>>> +                       break;
>>>>>>>>>>>>> +               }
>>>>>>>>>>>>> +
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Have anyone seen the above mentioned issues regarding
>>>>>>>>>>>>> read/write/erase? OR is there any
>>>>>>>>>>>>> configurations that I might be missing ?
>>>>>>>>>>>>>
>>>>>>>>>>>> Any Input on this?
>>>>>>>>>>>
>>>>>>>>>>> Please wait, I am pushing some changes tonight or so.
>>>>>>>>>>>
>>>>>>>>>>> We will continue this thread, after testing your part with these
>>>>>>>>>>> new
>>>>>>>>>>> changes.
>>>>>>>>>>>
>>>>>>>>>>> I will intimate you once the push done.
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> Thanks,
>>>>>>>>>>> Jagan.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>> Thanks a lot for the reply.
>>>>>>>>>> Sure, will wait for your changes to go in.
>>>>>>>>>
>>>>>>>>> Will take some time go these changes on master.
>>>>>>>>>
>>>>>>>>> Please checkout master-work branch in u-boot-spi repo
>>>>>>>>> git://git.denx.de/u-boot-spi.git
>>>>>>>>>
>>>>>>>>> and try to test 256S parts, fyi: I tested the same part got the
>>>>>>>>> +ve result.
>>>>>>>>>
>>>>>>>> Tested the above tree on my board.
>>>>>>>> But, still the issues remain the same for me in all the three
>>>>>>>> cases(erase/read/write).
>>>>>>>>
>>>>>>>> Here is the short log of the read command..
>>>>>>>> DRA752 EVM # sf probe 0
>>>>>>>> SF: Detected S25FL256S_64K with page size 64 KiB, total 32 MiB
>>>>>>>> SF: Warning - Only lower 16MiB accessible, Full access #define
>>>>>>>> CONFIG_SPI_FLASH_BAR
>>>>>>>> DRA752 EVM # sf erase 0x0 0x10000
>>>>>>>> SF: 65536 bytes @ 0x0 Erased: OK
>>>>>>>> DRA752 EVM # mw.b 0x81000100 0xff 0x10000
>>>>>>>> DRA752 EVM # sf read 0x81003000 0x0 0x10000
>>>>>>>> SF: 65536 bytes @ 0x0 Read: OK
>>>>>>>> DRA752 EVM # cmp.b 0x81003000  0x81000100  0x10000
>>>>>>>> byte at 0x81003ffb (0x0) != byte at 0x810010fb (0xff)
>>>>>>>> Total of 4091 byte(s) were the same
>>>>>>>>
>>>>>>>>
>>>>>>>> Erase: not able to do with a single command, need to issue for every
>>>>>>>> 0x10000
>>>>>>>> bytes.
>>>>>>>>
>>>>>>>> Write: Need to disable latch after every write to make it properly
>>>>>>>> work.
>>>>>>>>
>>>>>>>> Is it possible for you to  give me  basic commands which you might
>>>>>>>> have
>>>>>>>> ran
>>>>>>>> to confirm
>>>>>>>> the read/write and erase ??
>>>>>>> I tested the same part - for me i couldn't see the issues with SL256S
>>>>>>>
>>>>>>> OK! can enable the log on poll function, spi_flash_cmd_wait_ready()
>>>>>>> make debug ->     printf.
>>>>>>> Do the same test.! and send the log file.
>>>>>>>
>>>>>>> --
>>>>>>> Thanks,
>>>>>>> Jagan.
>>>>>> Here is the output log, no change..
>>>>>>
>>>>>>
>>>>>> DRA752 EVM # sf probe 0
>>>>>> SF: Detected S25FL256S_64K with page size 64 KiB, total 32 MiB
>>>>>> DRA752 EVM # sf erase 0x0 0x10000
>>>>>> SF: 65536 bytes @ 0x0 Erased: OK
>>>>>> DRA752 EVM # mw.b 0x81000100 0xff 0x10000
>>>>>> DRA752 EVM # sf read 0x81003000 0x0 0x10000
>>>>>> SF: 65536 bytes @ 0x0 Read: OK
>>>>>> DRA752 EVM # cmp.b 0x81003000  0x81000100  0x10000
>>>>>> byte at 0x81003ffb (0x0) != byte at 0x810010fb (0xff)
>>>>>> Total of 4091 byte(s) were the same
>>>>>> DRA752 EVM #
>>>>>>
>>>>>>
>>>>>> Code change: for above output.
>>>>>> --- a/drivers/mtd/spi/spi_flash.c
>>>>>> +++ b/drivers/mtd/spi/spi_flash.c
>>>>>> @@ -85,7 +85,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash *flash,
>>>>>> unsigned long timeout)
>>>>>>
>>>>>>            ret = spi_xfer(spi, 8,&cmd, NULL, SPI_XFER_BEGIN);
>>>>>>
>>>>>>            if (ret) {This is still not sent out for review. I can send you the patch 
>>>>>> -               debug("SF: fail to read %s status register\n",
>>>>>> +               printf("SF: fail to read %s status register\n",
>>>>>>                            cmd == CMD_READ_STATUS ? "read" : "flag");
>>>>>>                    return ret;
>>>>>>            }
>>>>>> @@ -109,7 +109,7 @@ int spi_flash_cmd_wait_ready(struct spi_flash
>>>>>> *flash,
>>>>>> unsigned long timeout)
>>>>>>                    return 0;
>>>>>>
>>>>>>            /* Timed out */
>>>>>> -       debug("SF: time out!\n");
>>>>>> +       printf("SF: time out!\n");
>>>>>>            return -1;
>>>>>>     }
>>>>>>
>>>>> Ohh..
>>>>>
>>>>> - What if you erase the entire flash and read back, same result is it?
>>>> Yes.
>>>>
>>>>> - please send the paths for config file for this board?
>>>> include/configs/dra7xx_evm.h
>>> I couldn't find any SPI flash configs on above config file,
>>> Can you point me the relevant configurations.
>>>
>> Following are the configuration details for spi..
>> #define CONFIG_SPI_FLASH_BAR
>> #define CONFIG_TI_QSPI
> Where can i find this?
>
I have attached the required patches in the thread.
Patch 0002 is my ti qspi controller.
Patch 0004 is my workarounds done for the all the issues
mentioned in the $subject patch.
Patch 0001 and 0002 are other configs.
>> #define CONFIG_SPI_FLASH
>> #define CONFIG_SPI_FLASH_SPANSION
>> #define CONFIG_CMD_SF
>> #define CONFIG_CMD_SPI
>> #define CONFIG_SF_DEFAULT_SPEED         12000000
>> #define CONFIG_DEFAULT_SPI_MODE         SPI_MODE_3
>>
>> /* SPI SPL */
>> #define CONFIG_SPL_SPI_SUPPORT
>> #define CONFIG_SPL_SPI_LOAD
>> #define CONFIG_SPL_SPI_FLASH_SUPPORT
>> #define CONFIG_SPL_SPI_BUS              0
>> #define CONFIG_SPL_SPI_CS               0
>> #define CONFIG_SYS_SPI_U_BOOT_OFFS      0x20000
> --
> Thanks,
> Jagan.


[-- Attachment #2: 0001-omap5-add-qspi-support.patch --]
[-- Type: text/x-diff, Size: 3683 bytes --]

>From 42584552cfe3055abebe4ac8a824fc5d527db9e2 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@ti.com>
Date: Mon, 6 May 2013 15:31:45 -0400
Subject: [PATCH 1/5] omap5: add qspi support

Add QSPI definitions and clock configuration support.

Signed-off-by: Matt Porter <mporter@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
 arch/arm/cpu/armv7/omap5/hw_data.c     |    5 ++++-
 arch/arm/cpu/armv7/omap5/prcm-regs.c   |    1 +
 arch/arm/include/asm/arch-omap5/omap.h |    3 +++
 arch/arm/include/asm/arch-omap5/spl.h  |    1 +
 arch/arm/include/asm/omap_common.h     |    1 +
 5 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/arch/arm/cpu/armv7/omap5/hw_data.c b/arch/arm/cpu/armv7/omap5/hw_data.c
index 716b931..c7a27e2 100644
--- a/arch/arm/cpu/armv7/omap5/hw_data.c
+++ b/arch/arm/cpu/armv7/omap5/hw_data.c
@@ -194,7 +194,7 @@ static const struct dpll_params per_dpll_params_768mhz_dra7xx[NUM_SYS_CLKS] = {
 	{192, 12, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 26 MHz   */
 	{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},	/* 27 MHz   */
 	{10, 0, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1},		/* 38.4 MHz */
-	{96, 4, 4, 1, 3, 4, 10, 2, -1, -1, -1, -1}		/* 20 MHz   */
+	{96, 4, 4, 1, 3, 4, 4, 2, -1, -1, -1, -1}		/* 20 MHz   */
 };
 
 static const struct dpll_params iva_dpll_params_2330mhz[NUM_SYS_CLKS] = {
@@ -488,6 +488,7 @@ void enable_basic_clocks(void)
 		(*prcm)->cm_wkup_wdtimer2_clkctrl,
 		(*prcm)->cm_l4per_uart3_clkctrl,
 		(*prcm)->cm_l4per_i2c1_clkctrl,
+		(*prcm)->cm_l4per_qspi_clkctrl,
 		0
 	};
 
@@ -516,6 +517,8 @@ void enable_basic_clocks(void)
 			 clk_modules_explicit_en_essential,
 			 1);
 
+	setbits_le32((*prcm)->cm_l4per_qspi_clkctrl, (1<<24));
+
 	/* Enable SCRM OPT clocks for PER and CORE dpll */
 	setbits_le32((*prcm)->cm_wkupaon_scrm_clkctrl,
 			OPTFCLKEN_SCRM_PER_MASK);
diff --git a/arch/arm/cpu/armv7/omap5/prcm-regs.c b/arch/arm/cpu/armv7/omap5/prcm-regs.c
index 426b50f..a7aa922 100644
--- a/arch/arm/cpu/armv7/omap5/prcm-regs.c
+++ b/arch/arm/cpu/armv7/omap5/prcm-regs.c
@@ -933,6 +933,7 @@ struct prcm_regs const dra7xx_prcm = {
 	.cm_l4per_gpio8_clkctrl			= 0x4a009818,
 	.cm_l4per_mmcsd3_clkctrl		= 0x4a009820,
 	.cm_l4per_mmcsd4_clkctrl		= 0x4a009828,
+	.cm_l4per_qspi_clkctrl			= 0x4a009838,
 	.cm_l4per_uart1_clkctrl			= 0x4a009840,
 	.cm_l4per_uart2_clkctrl			= 0x4a009848,
 	.cm_l4per_uart3_clkctrl			= 0x4a009850,
diff --git a/arch/arm/include/asm/arch-omap5/omap.h b/arch/arm/include/asm/arch-omap5/omap.h
index 9ecc096..ab526ae 100644
--- a/arch/arm/include/asm/arch-omap5/omap.h
+++ b/arch/arm/include/asm/arch-omap5/omap.h
@@ -67,6 +67,9 @@
 /* GPMC */
 #define OMAP54XX_GPMC_BASE	0x50000000
 
+/* QSPI */
+#define QSPI_BASE		0x4B300000
+
 /*
  * Hardware Register Details
  */
diff --git a/arch/arm/include/asm/arch-omap5/spl.h b/arch/arm/include/asm/arch-omap5/spl.h
index d4d353c..8905cb8 100644
--- a/arch/arm/include/asm/arch-omap5/spl.h
+++ b/arch/arm/include/asm/arch-omap5/spl.h
@@ -31,6 +31,7 @@
 #define BOOT_DEVICE_MMC1        5
 #define BOOT_DEVICE_MMC2        6
 #define BOOT_DEVICE_MMC2_2	7
+#define BOOT_DEVICE_SPI		10
 
 #define MMC_BOOT_DEVICES_START	BOOT_DEVICE_MMC1
 #define MMC_BOOT_DEVICES_END	BOOT_DEVICE_MMC2_2
diff --git a/arch/arm/include/asm/omap_common.h b/arch/arm/include/asm/omap_common.h
index a678bc0..55deacb 100644
--- a/arch/arm/include/asm/omap_common.h
+++ b/arch/arm/include/asm/omap_common.h
@@ -280,6 +280,7 @@ struct prcm_regs {
 	u32 cm_l4per_mmcsd4_clkctrl;
 	u32 cm_l4per_msprohg_clkctrl;
 	u32 cm_l4per_slimbus2_clkctrl;
+	u32 cm_l4per_qspi_clkctrl;
 	u32 cm_l4per_uart1_clkctrl;
 	u32 cm_l4per_uart2_clkctrl;
 	u32 cm_l4per_uart3_clkctrl;
-- 
1.7.1


[-- Attachment #3: 0002-spi-add-TI-QSPI-driver.patch --]
[-- Type: text/x-diff, Size: 7593 bytes --]

>From 47b503ff2d3f331010a19874a4d3e8f4bb88c604 Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@ti.com>
Date: Mon, 6 May 2013 15:32:15 -0400
Subject: [PATCH 2/5] spi: add TI QSPI driver

Adds a SPI master driver for the TI QSPI peripheral.

Signed-off-by: Matt Porter <mporter@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
 drivers/spi/Makefile  |    1 +
 drivers/spi/ti_qspi.c |  262 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 263 insertions(+), 0 deletions(-)
 create mode 100644 drivers/spi/ti_qspi.c

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index d08609e..f51033d 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -54,6 +54,7 @@ COBJS-$(CONFIG_FDT_SPI) += fdt_spi.o
 COBJS-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
 COBJS-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
 COBJS-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
+COBJS-$(CONFIG_TI_QSPI) += ti_qspi.o
 COBJS-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 
 COBJS	:= $(COBJS-y)
diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c
new file mode 100644
index 0000000..1973b85
--- /dev/null
+++ b/drivers/spi/ti_qspi.c
@@ -0,0 +1,262 @@
+/*
+ * TI QSPI driver
+ *
+ * Copyright (C) 2013, Texas Instruments, Incorporated
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR /PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/omap.h>
+#include <malloc.h>
+#include <spi.h>
+
+struct qspi_slave {
+	struct spi_slave slave;
+	unsigned int mode;
+	u32 cmd;
+	u32 dc;
+};
+
+#define to_qspi_slave(s) container_of(s, struct qspi_slave, slave)
+
+struct qspi_regs {
+	u32 pid;
+	u32 pad0[3];
+	u32 sysconfig;
+	u32 pad1[3];
+	u32 intr_status_raw_set;
+	u32 intr_status_enabled_clear;
+	u32 intr_enable_set;
+	u32 intr_enable_clear;
+	u32 intc_eoi;
+	u32 pad2[3];
+	u32 spi_clock_cntrl;
+	u32 spi_dc;
+	u32 spi_cmd;
+	u32 spi_status;
+	u32 spi_data;
+	u32 spi_setup0;
+	u32 spi_setup1;
+	u32 spi_setup2;
+	u32 spi_setup3;
+	u32 spi_switch;
+	u32 spi_data1;
+	u32 spi_data2;
+	u32 spi_data3;
+};
+
+static struct qspi_regs *qspi = (struct qspi_regs *)QSPI_BASE;
+
+#define QSPI_TIMEOUT			2000000
+
+#define QSPI_FCLK			192000000
+
+/* Clock Control */
+#define QSPI_CLK_EN			(1 << 31)
+#define QSPI_CLK_DIV_MAX		0xffff
+
+/* Command */
+#define QSPI_EN_CS(n)			(n << 28)
+#define QSPI_WLEN(n)			((n-1) << 19)
+#define QSPI_3_PIN			(1 << 18)
+#define QSPI_RD_SNGL			(1 << 16)
+#define QSPI_WR_SNGL			(2 << 16)
+#define QSPI_INVAL			(4 << 16)
+
+/* Device Control */
+#define QSPI_DD(m, n)			(m << (3 + n*8))
+#define QSPI_CKPHA(n)			(1 << (2 + n*8))
+#define QSPI_CSPOL(n)			(1 << (1 + n*8))
+#define QSPI_CKPOL(n)			(1 << (n*8))
+
+/* Status */
+#define QSPI_WC				(1 << 1)
+#define QSPI_BUSY			(1 << 0)
+#define QSPI_WC_BUSY			(QSPI_WC | QSPI_BUSY)
+#define QSPI_XFER_DONE			QSPI_WC
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+	return 1;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	/* CS handled in xfer */
+	return;
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	/* CS handled in xfer */
+	return;
+}
+
+void spi_init(void)
+{
+	/* nothing to do */
+}
+
+void spi_set_speed(struct spi_slave *slave, uint hz)
+{
+	uint clk_div;
+
+	if (!hz)
+		clk_div = 0;
+	else
+		clk_div = (QSPI_FCLK / hz) - 1;
+
+	debug("%s: hz: %d, clock divider %d\n", __func__, hz, clk_div);
+
+	/* disable SCLK */
+	writel(readl(&qspi->spi_clock_cntrl) & ~QSPI_CLK_EN, &qspi->spi_clock_cntrl);
+
+	if (clk_div < 0) {
+		debug("%s: clock divider < 0, using /1 divider\n", __func__);
+		clk_div = 0;
+	}
+
+	if (clk_div > QSPI_CLK_DIV_MAX) {
+		debug("%s: clock divider >%d , using /%d divider\n",
+			__func__, QSPI_CLK_DIV_MAX, QSPI_CLK_DIV_MAX + 1);
+		clk_div = QSPI_CLK_DIV_MAX;
+	}
+
+	/* enable SCLK */
+	writel(QSPI_CLK_EN | clk_div, &qspi->spi_clock_cntrl);
+	debug("%s: spi_clock_cntrl %08x\n", __func__, readl(&qspi->spi_clock_cntrl));
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+				  unsigned int max_hz, unsigned int mode)
+{
+	struct qspi_slave *qslave;
+
+	qslave = spi_alloc_slave(struct qspi_slave, bus, cs);
+	if (!qslave)
+		return NULL;
+
+	spi_set_speed(&qslave->slave, max_hz);
+	qslave->mode = mode;
+	debug("%s: bus:%i cs:%i mode:%i\n", __func__, bus, cs, mode);
+
+	return &qslave->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct qspi_slave *qslave = to_qspi_slave(slave);
+	free(qslave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+
+	writel(0, &qspi->spi_dc);
+	writel(0, &qspi->spi_cmd);
+	writel(0, &qspi->spi_data);
+
+	return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+
+	writel(0, &qspi->spi_dc);
+	writel(0, &qspi->spi_cmd);
+	writel(0, &qspi->spi_data);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+	     void *din, unsigned long flags)
+{
+	struct qspi_slave *qslave = to_qspi_slave(slave);
+	uint words = bitlen >> 3; /* fixed 8-bit word length */
+	const uchar *txp = dout;
+	uchar *rxp = din;
+	uint status;
+	int timeout;
+
+	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;
+
+	if (bitlen % 8) {
+		flags |= SPI_XFER_END;
+		return -1;
+	}
+
+	/* setup command reg */
+	qslave->cmd = 0;
+	qslave->cmd |= QSPI_WLEN(8);
+	qslave->cmd |= QSPI_EN_CS(slave->cs);
+	if (flags & SPI_3WIRE)
+		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",
+			      qslave->cmd | QSPI_WR_SNGL, qslave->dc, *txp);
+			writel(*txp++, &qspi->spi_data);
+			writel(qslave->dc, &qspi->spi_dc);
+			writel(qslave->cmd | QSPI_WR_SNGL, &qspi->spi_cmd);
+			status = readl(&qspi->spi_status);
+			timeout = QSPI_TIMEOUT;
+			while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+				if (--timeout < 0) {
+					printf("QSPI tx timed out\n");
+					return -1;
+				}
+				status = readl(&qspi->spi_status);
+			}
+			debug("tx done, status %08x\n", status);
+		}
+		if (rxp) {
+			debug("rx cmd %08x dc %08x\n",
+			      qslave->cmd | QSPI_RD_SNGL, qslave->dc);
+			writel(qslave->dc, &qspi->spi_dc);
+			writel(qslave->cmd | QSPI_RD_SNGL, &qspi->spi_cmd);
+			status = readl(&qspi->spi_status);
+			timeout = QSPI_TIMEOUT;
+			while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+				if (--timeout < 0) {
+					printf("QSPI rx timed out\n");
+					return -1;
+				}
+				status = readl(&qspi->spi_status);
+			}
+			*rxp++ = readl(&qspi->spi_data);
+			debug("rx done, status %08x, read %02x\n",
+			      status, *(rxp-1));
+		}
+	}
+
+	/* Terminate frame */
+	if (flags & SPI_XFER_END)
+		writel(qslave->cmd | QSPI_INVAL, &qspi->spi_cmd);
+
+	return 0;
+}
-- 
1.7.1


[-- Attachment #4: 0003-dra7xx_evm-add-SPL-API-QSPI-and-serial-flash-support.patch --]
[-- Type: text/x-diff, Size: 2224 bytes --]

>From 89b1ad9848df89817dc8bac7ea12a71d811921ce Mon Sep 17 00:00:00 2001
From: Matt Porter <mporter@ti.com>
Date: Mon, 6 May 2013 15:33:19 -0400
Subject: [PATCH 3/5] dra7xx_evm: add SPL API, QSPI, and serial flash support

Enables support for SPI SPL, QSPI and Spansion serial flash device
on the EVM. Configures pin muxes for QSPI mode.

Signed-off-by: Matt Porter <mporter@ti.com>
Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
 board/ti/dra7xx/mux_data.h   |   10 ++++++++++
 include/configs/dra7xx_evm.h |   17 +++++++++++++++++
 2 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/board/ti/dra7xx/mux_data.h b/board/ti/dra7xx/mux_data.h
index 5a91966..b26a9be 100644
--- a/board/ti/dra7xx/mux_data.h
+++ b/board/ti/dra7xx/mux_data.h
@@ -53,6 +53,16 @@ const struct pad_conf_entry core_padconf_array_essential[] = {
 	{UART1_RTSN, (IEN | PTU | PDIS | M3)},
 	{I2C1_SDA, (IEN | PTU | PDIS | M0)},
 	{I2C1_SCL, (IEN | PTU | PDIS | M0)},
+	{GPMC_A13, (PTU | IEN | M1)},	/* QSPI1_RTCLK */
+	{GPMC_A18, (PTU | IEN | M1)},	/* QSPI1_SCLK */
+	{GPMC_A17, (PTU | IEN | M1)},	/* QSPI1_D[0] */
+	{GPMC_A16, (PTU | IEN | M1)},	/* QSPI1_D[1] */
+	{GPMC_A15, (PTU | IEN | M1)},	/* QSPI1_D[2] */
+	{GPMC_A14, (PTU | IEN | M1)},	/* QSPI1_D[3] */
+	{GPMC_CS2, (PTU | M1)},		/* QSPI1_CS[0] */
+	{GPMC_CS3, (PTU | M1)},		/* QSPI1_CS[1] */
+	{GPMC_A3, (PTU | M1)},		/* QSPI1_CS[2] */
+	{GPMC_A4, (PTU | M1)},		/* QSPI1_CS[3] */
 };
 
 const struct pad_conf_entry core_padconf_array_non_essential[] = {
diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h
index 2518352..3671e45 100644
--- a/include/configs/dra7xx_evm.h
+++ b/include/configs/dra7xx_evm.h
@@ -56,4 +56,21 @@
 
 #define EMIF1_EMIF2
 
+/* SPI */
+#define CONFIG_TI_QSPI
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI_FLASH_SPANSION
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_SF_DEFAULT_SPEED		12000000
+#define CONFIG_DEFAULT_SPI_MODE		SPI_MODE_3
+
+/* SPI SPL */
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_BUS		0
+#define CONFIG_SPL_SPI_CS		0
+#define CONFIG_SYS_SPI_U_BOOT_OFFS	0x20000
+
 #endif /* __CONFIG_DRA7XX_EVM_H */
-- 
1.7.1


[-- Attachment #5: 0004-drivers-mtd-spi-Modify-read-write-command-for-sfl256.patch --]
[-- Type: text/x-diff, Size: 2420 bytes --]

>From e4139e66b956d17a9157a7b6d055e9f8c585041d Mon Sep 17 00:00:00 2001
From: Sourav Poddar <sourav.poddar@ti.com>
Date: Fri, 7 Jun 2013 17:15:36 +0530
Subject: [PATCH 4/5] drivers: mtd: spi: Modify read/write command for sfl256s flash.

Reading using the already supported read command is causing regression
even while reading 4k bytes, as a result doing a page by page read.

At the end of the write sequence, write enable latch should be disabled and
re enabled while doing the next page programming.

Signed-off-by: Sourav Poddar <sourav.poddar@ti.com>
---
 drivers/mtd/spi/spi_flash.c |   39 ++++++++++++++++++++++++++++++++++-----
 1 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c
index 111185a..8c3a2cf 100644
--- a/drivers/mtd/spi/spi_flash.c
+++ b/drivers/mtd/spi/spi_flash.c
@@ -117,6 +117,12 @@ int spi_flash_cmd_write_multi(struct spi_flash *flash, u32 offset,
 		if (ret)
 			break;
 
+		ret = spi_flash_cmd_write_disable(flash);
+		if (ret < 0) {
+			printf("SF: disabling write failed\n");
+			break;
+		}
+
 		byte_addr += chunk_len;
 		if (byte_addr == page_size) {
 			page_addr++;
@@ -147,17 +153,40 @@ int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd,
 int spi_flash_cmd_read_fast(struct spi_flash *flash, u32 offset,
 		size_t len, void *data)
 {
-	u8 cmd[5];
+	unsigned long page_addr, byte_addr, page_size;
+	size_t chunk_len, actual;
+	int ret = 0;
+	u8 cmd[4];
 
 	/* Handle memory-mapped SPI */
 	if (flash->memory_map)
 		memcpy(data, flash->memory_map + offset, len);
+	page_size = flash->page_size;
+	page_addr = offset / page_size;
+	byte_addr = offset % page_size;
+
+	cmd[0] = CMD_READ_ARRAY_SLOW;
+	for (actual = 0; actual < len; actual += chunk_len) {
+		chunk_len = min(len - actual, page_size - byte_addr);
+
+		cmd[1] = page_addr >> 8;
+		cmd[2] = page_addr;
+		cmd[3] = byte_addr;
+
+		ret = spi_flash_read_common(flash, cmd, sizeof(cmd), data + actual, chunk_len);
+		if (ret < 0) {
+			debug("SF: read failed");
+			break;
+		}
 
-	cmd[0] = CMD_READ_ARRAY_FAST;
-	spi_flash_addr(offset, cmd);
-	cmd[4] = 0x00;
+		byte_addr += chunk_len;
+		if (byte_addr == page_size) {
+			page_addr++;
+			byte_addr = 0;
+		}
+	}
 
-	return spi_flash_read_common(flash, cmd, sizeof(cmd), data, len);
+	return ret;
 }
 
 int spi_flash_cmd_poll_bit(struct spi_flash *flash, unsigned long timeout,
-- 
1.7.1


  reply	other threads:[~2013-06-17  7:42 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-12  7:30 U-boot: Erase/read/write issue with S25fl256S flash device Sourav Poddar
2013-06-14 14:33 ` Sourav Poddar
2013-06-14 14:38   ` [U-Boot] " Jagan Teki
2013-06-14 14:43     ` Sourav Poddar
2013-06-15 16:17       ` Jagan Teki
2013-06-17  6:14         ` Sourav Poddar
2013-06-17  6:47           ` Jagan Teki
2013-06-17  6:58             ` Sourav Poddar
2013-06-17  7:05               ` Jagan Teki
2013-06-17  7:11                 ` Sourav Poddar
2013-06-17  7:14                   ` Jagan Teki
2013-06-17  7:19                     ` Sourav Poddar
2013-06-17  7:34                       ` Jagan Teki
2013-06-17  7:41                         ` Sourav Poddar [this message]
2013-06-17  8:39                           ` Jagan Teki
2013-06-17  8:45                             ` Sourav Poddar
2013-06-17  9:58                               ` Jagan Teki
2013-06-17 10:20                                 ` Sourav Poddar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=51BEBDAF.7000201@ti.com \
    --to=sourav.poddar@ti.com \
    --cc=balbi@ti.com \
    --cc=jagannadh.teki@gmail.com \
    --cc=jagannadha.sutradharudu-teki@xilinx.com \
    --cc=linux-mtd@lists.infradead.org \
    --cc=rnayak@ti.com \
    --cc=trini@ti.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).