summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
authorChao Fu <B44548@freescale.com>2014-09-29 05:58:00 (GMT)
committerMatthew Weigel <Matthew.Weigel@freescale.com>2014-12-11 18:37:28 (GMT)
commitb77452e4557346fe6a2b715f8033a4f2549b7a72 (patch)
treee081a5cac929b4281f408c9b97544f43b87d3b10 /drivers/mtd
parentcdbd6a3f41ff52225e07d72a0dd980d6c035bacc (diff)
downloadlinux-fsl-qoriq-b77452e4557346fe6a2b715f8033a4f2549b7a72.tar.xz
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. [3] about the dummy cycles. We set the dummy with 8 for DDR quad read by default. The m25p80.c can not support the DDR quad read, but the SPI NOR controller can set the dummy value in its child DT node, and the SPI NOR framework can parse it out. Test this patch for Spansion s25fl128s NOR flash. Signed-off-by: Huang Shijie <b32955@freescale.com> The upstream status of this patch can be found at: https://patchwork.kernel.org/patch/4074961 Change-Id: Id67e247e357bdd8bea99816e31f603898671d968 Reviewed-on: http://git.am.freescale.net:8181/20125 Reviewed-by: Zhengxiong Jin <Jason.Jin@freescale.com> Tested-by: Zhengxiong Jin <Jason.Jin@freescale.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 02236e8..792354a 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -73,7 +73,20 @@ static int read_cr(struct spi_nor *nor)
*/
static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
{
+ u32 dummy;
+
switch (nor->flash_read) {
+ case SPI_NOR_DDR_QUAD:
+ /*
+ * The m25p80.c can not support the DDR quad read.
+ * We set the dummy cycles to 8 by default. The SPI NOR
+ * controller driver can set it in its child DT node.
+ * We parse it out here.
+ */
+ if (nor->np && !of_property_read_u32(nor->np,
+ "spi-nor,ddr-quad-read-dummy", &dummy)) {
+ return dummy;
+ }
case SPI_NOR_FAST:
case SPI_NOR_DUAL:
case SPI_NOR_QUAD:
@@ -402,6 +415,7 @@ 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 SPI_NOR_DDR_QUAD_READ 0x80 /* Flash supports DDR Quad Read */
};
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
@@ -829,6 +843,24 @@ static int spansion_quad_enable(struct spi_nor *nor)
return 0;
}
+static int set_ddr_quad_mode(struct spi_nor *nor, u32 jedec_id)
+{
+ int status;
+
+ switch (JEDEC_MFR(jedec_id)) {
+ case CFI_MFR_AMD: /* Spansion, actually */
+ 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, u32 jedec_id)
{
int status;
@@ -999,8 +1031,15 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
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->jedec_id);
+ 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->jedec_id);
if (ret) {
dev_err(dev, "quad mode not supported\n");
@@ -1013,6 +1052,14 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
/* Default commands */
switch (nor->flash_read) {
+ case SPI_NOR_DDR_QUAD:
+ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { /* 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;
@@ -1040,6 +1087,9 @@ int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id,
if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) {
/* 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;