Hi Graham,
On 07/24/2015 10:17 AM, Graham Moore wrote:
Signed-off-by: Graham Moore <grmoore@xxxxxxxxxxxxxxxxxxxxx>
---
V2: use NULL instead of modalias in spi_nor_scan call
V3: Use existing property is-decoded-cs instead of creating duplicate.
V4: Support Micron quad mode by snooping command stream for EVCR command
and subsequently configuring Cadence controller for quad mode.
V5: Clean up sparse and smatch complaints. Remove snooping of Micron
quad mode. Add comment on XIP mode bit and dummy clock cycles. Set
up SRAM partition at 1:1 during init.
---
arch/arm/boot/dts/socfpga.dtsi | 1 +
arch/arm/boot/dts/socfpga_cyclone5_socdk.dts | 1 -
drivers/mtd/spi-nor/Kconfig | 6 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/cadence-quadspi.c | 1261 ++++++++++++++++++++++++++
5 files changed, 1269 insertions(+), 1 deletion(-)
create mode 100644 drivers/mtd/spi-nor/cadence-quadspi.c
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index c71a705..e9ecdce 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -695,6 +695,7 @@
is-decoded-cs = <1>;
fifo-depth = <128>;
status = "disabled";
+ m25p,fast-read;
This patch is not applicable to l2-mtd master or linus master repo, might need to rebase it.
+#include <linux/timer.h>
+
+#define CQSPI_NAME "cadence-qspi"
replace space with tabs.
+
+#define CQSPI_FIFO_WIDTH 4
FIFO width could be 4 or 8 etc depending on the SOC, it would be better to get it from device.
You can refer to u-boot code for the same.
+
+#define CQSPI_INDIRECTTRIGGER_ADDR_MASK 0xFFFFF
Mask value of 0xFFFFF is specific to socfpga platform.
Please refer to u-boot patchset for same discussion.
+static void cqspi_fifo_read(void *dest, const void __iomem *src_ahb_addr,
+ unsigned int bytes)
+{
+ unsigned int temp;
+ int remaining = bytes;
+ unsigned int *dest_ptr = (unsigned int *)dest;
+
+ while (remaining >= CQSPI_FIFO_WIDTH) {
+ *dest_ptr = readl(src_ahb_addr);
+ dest_ptr++;
+ remaining -= CQSPI_FIFO_WIDTH;
this logic only works when fifo width is 4 with "unsigned int" data of 4 bytes.
It has been corrected in mainline u-boot or in the u-boot patches.
+static int cqspi_indirect_read_setup(struct spi_nor *nor,
+ unsigned int from_addr)
+{
+ unsigned int reg;
+ unsigned int dummy_clk = 0;
+ struct cqspi_st *cqspi = nor->priv;
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int ahb_phy_addr = cqspi->ahb_phy_addr;
+
+ writel((ahb_phy_addr & CQSPI_INDIRECTTRIGGER_ADDR_MASK),
+ reg_base + CQSPI_REG_INDIRECTTRIGGER);
+ writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR);
Base trigger register address (0x1c register) corresponds to the address which
should be put on AHB bus to handle indirect transfer triggered before.
To handle indirect transfer we need to issue addresses from (value of 0x1c) to
(value of 0x1c) + 15*4 ("4" corresponds to size of SRAM location).
There are no obstacles in issuing const address just equal to 0x1c. Important
thing to note is that indirect trigger address has nothing in common with your
physical or mapped NOR Flash address.
Transfer read/write start addresses should be programmed with the absolute flash address
to be read/written.
+ watermark = cqspi->fifo_depth * CQSPI_FIFO_WIDTH / 2;
+ writel(watermark, reg_base + CQSPI_REG_INDIRECTRDWATERMARK);
+ writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES);
+ writel(cqspi->fifo_depth - CQSPI_REG_SRAM_RESV_WORDS,
+ reg_base + CQSPI_REG_SRAMPARTITION);
sram partioning is not needed to be changed at every read/write, it should be ok to configure it
in the init like divide half for read & half for write.
Rgds,
Vikas