openwrtv3/target/linux/layerscape/patches-4.4/1105-mtd-spi-nor-add-DDR-quad-read-support.patch
Yutang Jiang 15a14cf166 layerscape: add 64b/32b target for ls1012ardb device
The QorIQ LS1012A processor, optimized for battery-backed or
USB-powered, integrates a single ARM Cortex-A53 core with a hardware
packet forwarding engine and high-speed interfaces to deliver
line-rate networking performance.
QorIQ LS1012A Reference Design System (LS1012ARDB) is a high-performance
development platform, with a complete debugging environment.
The LS1012ARDB board supports the QorIQ LS1012A processor and is
optimized to support the high-bandwidth DDR3L memory and
a full complement of high-speed SerDes ports.

LEDE/OPENWRT will auto strip executable program file while make. So we
need select CONFIG_NO_STRIP=y while make menuconfig to avoid the ppfe network
fiemware be destroyed, then run make to build ls1012ardb firmware.

The fsl-quadspi flash with jffs2 fs is unstable and arise some failed message.
This issue have noticed the IP owner for investigate, hope he can solve it
earlier. So the ls1012ardb now also provide a xx-firmware.ext4.bin as default
firmware, and the uboot bootcmd will run wrtboot_ext4rfs for "rootfstype=ext4"
bootargs.

Signed-off-by: Yutang Jiang <yutang.jiang@nxp.com>
2016-10-31 17:00:10 +01:00

181 lines
6.5 KiB
Diff

From 924f021c0344554a4b61746e5c4dcfc91d618ce2 Mon Sep 17 00:00:00 2001
From: Yunhui Cui <yunhui.cui@nxp.com>
Date: Thu, 18 Feb 2016 16:41:53 +0800
Subject: [PATCH 105/113] mtd: spi-nor: add DDR quad read support
This patch adds the DDR quad read support by the following:
[1] add SPI_NOR_DDR_QUAD read mode.
[2] add DDR Quad read opcodes:
SPINOR_OP_READ_1_4_4_D / SPINOR_OP_READ4_1_4_4_D
[3] add set_ddr_quad_mode() to initialize for the DDR quad read.
Currently it only works for Spansion NOR.
[4] set dummy with 6 for Spansion family
Test this patch for Spansion s25fl128s NOR flash.
Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
---
drivers/mtd/spi-nor/spi-nor.c | 53 ++++++++++++++++++++++++++++++++++++-----
include/linux/mtd/spi-nor.h | 8 +++++--
2 files changed, 53 insertions(+), 8 deletions(-)
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -73,7 +73,8 @@ struct flash_info {
#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */
#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */
#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */
-#define USE_FSR 0x80 /* use flag status register */
+#define SPI_NOR_DDR_QUAD_READ 0x80 /* Flash supports DDR Quad Read */
+#define USE_FSR 0x100 /* use flag status register */
};
#define JEDEC_MFR(info) ((info)->id[0])
@@ -144,13 +145,17 @@ static int read_cr(struct spi_nor *nor)
* It can be used to support more commands with
* different dummy cycle requirements.
*/
-static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
+static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor,
+ const struct flash_info *info)
{
switch (nor->flash_read) {
case SPI_NOR_FAST:
case SPI_NOR_DUAL:
case SPI_NOR_QUAD:
return 8;
+ case SPI_NOR_DDR_QUAD:
+ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION)
+ return 6;
case SPI_NOR_NORMAL:
return 0;
}
@@ -797,7 +802,8 @@ static const struct flash_info spi_nor_i
{ "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
{ "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
- { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ) },
+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SECT_4K | SPI_NOR_QUAD_READ
+ | SPI_NOR_DDR_QUAD_READ) },
{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
{ "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
@@ -1186,6 +1192,23 @@ static int spansion_quad_enable(struct s
return 0;
}
+static int set_ddr_quad_mode(struct spi_nor *nor, const struct flash_info *info)
+{
+ int status;
+
+ switch (JEDEC_MFR(info)) {
+ case SNOR_MFR_SPANSION:
+ status = spansion_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "Spansion DDR quad-read not enabled\n");
+ return status;
+ }
+ return status;
+ default:
+ return -EINVAL;
+ }
+}
+
static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
{
int status;
@@ -1375,8 +1398,15 @@ int spi_nor_scan(struct spi_nor *nor, co
if (info->flags & SPI_NOR_NO_FR)
nor->flash_read = SPI_NOR_NORMAL;
- /* Quad/Dual-read mode takes precedence over fast/normal */
- if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
+ /* DDR Quad/Quad/Dual-read mode takes precedence over fast/normal */
+ if (mode == SPI_NOR_DDR_QUAD && info->flags & SPI_NOR_DDR_QUAD_READ) {
+ ret = set_ddr_quad_mode(nor, info);
+ if (ret) {
+ dev_err(dev, "DDR quad mode not supported\n");
+ return ret;
+ }
+ nor->flash_read = SPI_NOR_DDR_QUAD;
+ } else if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
ret = set_quad_mode(nor, info);
if (ret) {
dev_err(dev, "quad mode not supported\n");
@@ -1389,6 +1419,14 @@ int spi_nor_scan(struct spi_nor *nor, co
/* Default commands */
switch (nor->flash_read) {
+ case SPI_NOR_DDR_QUAD:
+ if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) { /* Spansion */
+ nor->read_opcode = SPINOR_OP_READ_1_4_4_D;
+ } else {
+ dev_err(dev, "DDR Quad Read is not supported.\n");
+ return -EINVAL;
+ }
+ break;
case SPI_NOR_QUAD:
nor->read_opcode = SPINOR_OP_READ_1_1_4;
break;
@@ -1416,6 +1454,9 @@ int spi_nor_scan(struct spi_nor *nor, co
if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
/* Dedicated 4-byte command set */
switch (nor->flash_read) {
+ case SPI_NOR_DDR_QUAD:
+ nor->read_opcode = SPINOR_OP_READ4_1_4_4_D;
+ break;
case SPI_NOR_QUAD:
nor->read_opcode = SPINOR_OP_READ4_1_1_4;
break;
@@ -1445,7 +1486,7 @@ int spi_nor_scan(struct spi_nor *nor, co
return -EINVAL;
}
- nor->read_dummy = spi_nor_read_dummy_cycles(nor);
+ nor->read_dummy = spi_nor_read_dummy_cycles(nor, info);
dev_info(dev, "%s (%lld Kbytes)\n", info->name,
(long long)mtd->size >> 10);
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -30,10 +30,11 @@
/*
* Note on opcode nomenclature: some opcodes have a format like
- * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
+ * SPINOR_OP_FUNCTION{4,}_x_y_z{_D}. The numbers x, y,and z stand for the number
* of I/O lines used for the opcode, address, and data (respectively). The
* FUNCTION has an optional suffix of '4', to represent an opcode which
- * requires a 4-byte (32-bit) address.
+ * requires a 4-byte (32-bit) address. The suffix of 'D' stands for the
+ * DDR mode.
*/
/* Flash opcodes. */
@@ -44,6 +45,7 @@
#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_READ_1_4_4_D 0xed /* Read data bytes (DDR Quad SPI) */
#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
@@ -59,6 +61,7 @@
#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_READ4_1_4_4_D 0xee /* Read data bytes (DDR Quad SPI) */
#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
@@ -107,6 +110,7 @@ enum read_mode {
SPI_NOR_FAST,
SPI_NOR_DUAL,
SPI_NOR_QUAD,
+ SPI_NOR_DDR_QUAD,
};
#define SPI_NOR_MAX_CMD_SIZE 8