From: Boris Brezillon <boris.brezillon@free-electrons.com>
To: Cyrille Pitchen <cyrille.pitchen@atmel.com>
Cc: computersforpeace@gmail.com, linux-mtd@lists.infradead.org,
nicolas.ferre@atmel.com, marex@denx.de, vigneshr@ti.com,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org,
robh+dt@kernel.org, pawel.moll@arm.com, mark.rutland@arm.com,
ijc+devicetree@hellion.org.uk, galak@codeaurora.org
Subject: Re: [PATCH linux-next v2 03/14] mtd: spi-nor: select op codes and SPI NOR protocols by manufacturer
Date: Mon, 11 Jan 2016 11:24:21 +0100 [thread overview]
Message-ID: <20160111112421.5919b531@bbrezillon> (raw)
In-Reply-To: <fd5ca97795c35b3df5ffee95075e2e03a70c7e48.1452268345.git.cyrille.pitchen@atmel.com>
Hi,
On Fri, 8 Jan 2016 17:02:15 +0100
Cyrille Pitchen <cyrille.pitchen@atmel.com> wrote:
> This is a transitional patch to prepare the split by Manufacturer of the
> support of Single/Dual/Quad SPI modes.
>
> Indeed every QSPI NOR manufacturer (Spansion, Micron, Macronix, Winbond)
> supports Dual or Quad SPI modes on its way. Especially the Fast Read op
> code and the SPI NOR protocols to use are not quite the same depending on
> the manufacturer.
>
> For instance Quad commands can use either the SPI 1-1-4, 1-4-4 or 4-4-4
> protocol.
>
> This is why this patch will be completed by fixes for each manufacturer.
>
> Signed-off-by: Cyrille Pitchen <cyrille.pitchen@atmel.com>
> ---
> drivers/mtd/spi-nor/spi-nor.c | 110 ++++++++++++++++++++++++++++++++----------
> include/linux/mtd/spi-nor.h | 12 +++--
> 2 files changed, 92 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 8967319ea7da..8793cebbe5a9 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -1180,17 +1180,61 @@ static int set_quad_mode(struct spi_nor *nor, const struct flash_info *info)
> dev_err(nor->dev, "Macronix quad-read not enabled\n");
> return -EINVAL;
> }
> - return status;
> + /* Check whether Macronix QPI mode is enabled. */
> + if (nor->read_proto != SNOR_PROTO_4_4_4)
> + nor->read_proto = SNOR_PROTO_1_1_4;
> + break;
> +
> case SNOR_MFR_MICRON:
> - return 0;
> - default:
> + /* Check whether Micron Quad mode is enabled. */
> + if (nor->read_proto != SNOR_PROTO_4_4_4)
> + nor->read_proto = SNOR_PROTO_1_1_4;
> + break;
> +
> + case SNOR_MFR_SPANSION:
The following comment is not only related to your changes, but after
looking at the spi_nor_scan() function and a few other functions in the
core, I see a lot of vendor specific initialization.
Would it make sense to somehow set a default configuration in
spi_nor_scan() and then overload this default config using a
per-manufacturer ->init() method. Something like that.
struct spi_nor_manufacturer {
int (*init)(struct spi_nor *nor, const struct flash_info *fi);
}
static const struct spi_nor_manufacturer manufacturers[] = {
[<manuf-id>] = {
.init = <manuf-init-callback>
},
};
Of course you could add other methods if you think this differentiation
is needed after the initialization step.
> status = spansion_quad_enable(nor);
> if (status) {
> dev_err(nor->dev, "Spansion quad-read not enabled\n");
> return -EINVAL;
> }
> - return status;
> + nor->read_proto = SNOR_PROTO_1_1_4;
> + break;
> +
> + default:
> + return -EINVAL;
> }
> +
> + nor->read_opcode = SPINOR_OP_READ_1_1_4;
> + return 0;
> +}
> +
> +static int set_dual_mode(struct spi_nor *nor, const struct flash_info *info)
> +{
> + switch (JEDEC_MFR(info)) {
> + case SNOR_MFR_MICRON:
> + /* Check whether Micron Dual mode is enabled. */
> + if (nor->read_proto != SNOR_PROTO_2_2_2)
> + nor->read_proto = SNOR_PROTO_1_1_2;
> + break;
> +
> + default:
> + nor->read_proto = SNOR_PROTO_1_1_2;
> + break;
> + }
> +
> + nor->read_opcode = SPINOR_OP_READ_1_1_2;
> + return 0;
> +}
> +
> +static int set_single_mode(struct spi_nor *nor, const struct flash_info *info)
> +{
> + switch (JEDEC_MFR(info)) {
> + default:
> + nor->read_proto = SNOR_PROTO_1_1_1;
> + break;
> + }
You can just put
nor->read_proto = SNOR_PROTO_1_1_1;
until you have a manufacturer specific case.
> +
> + return 0;
> }
>
> static int spi_nor_check(struct spi_nor *nor)
> @@ -1338,7 +1382,30 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
> if (info->flags & SPI_NOR_NO_FR)
> nor->flash_read = SPI_NOR_NORMAL;
>
> - /* Quad/Dual-read mode takes precedence over fast/normal */
> + /* Default commands */
> + if (nor->flash_read == SPI_NOR_NORMAL)
> + nor->read_opcode = SPINOR_OP_READ;
> + else
> + nor->read_opcode = SPINOR_OP_READ_FAST;
> +
> + nor->program_opcode = SPINOR_OP_PP;
> +
> + /*
> + * Quad/Dual-read mode takes precedence over fast/normal.
> + *
> + * Manufacturer specific modes are discovered when reading the JEDEC ID
> + * and are reported by the nor->read_proto value:
> + * - SNOR_PROTO_4_4_4 is either:
> + * + Micron Quad mode enabled
> + * + Macronix/Winbond QPI mode enabled
> + * - SNOR_PROTO_2_2_2 is either:
> + * + Micron Dual mode enabled
> + *
> + * The opcodes and the protocols are updated depending on the
> + * manufacturer.
> + * The read opcode and protocol should be updated by the relevant
> + * function when entering Quad or Dual mode.
> + */
> if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
> ret = set_quad_mode(nor, info);
> if (ret) {
> @@ -1347,30 +1414,21 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
> }
> nor->flash_read = SPI_NOR_QUAD;
> } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) {
> + ret = set_dual_mode(nor, info);
> + if (ret) {
> + dev_err(dev, "dual mode not supported\n");
> + return ret;
> + }
> nor->flash_read = SPI_NOR_DUAL;
> + } else if (info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)) {
> + /* We may need to leave a Quad or Dual mode */
> + ret = set_single_mode(nor, info);
> + if (ret) {
> + dev_err(dev, "failed to switch back to single mode\n");
> + return ret;
> + }
> }
>
> - /* Default commands */
> - switch (nor->flash_read) {
> - case SPI_NOR_QUAD:
> - nor->read_opcode = SPINOR_OP_READ_1_1_4;
> - break;
> - case SPI_NOR_DUAL:
> - nor->read_opcode = SPINOR_OP_READ_1_1_2;
> - break;
> - case SPI_NOR_FAST:
> - nor->read_opcode = SPINOR_OP_READ_FAST;
> - break;
> - case SPI_NOR_NORMAL:
> - nor->read_opcode = SPINOR_OP_READ;
> - break;
> - default:
> - dev_err(dev, "No Read opcode defined\n");
> - return -EINVAL;
> - }
> -
> - nor->program_opcode = SPINOR_OP_PP;
> -
> if (info->addr_width)
> nor->addr_width = info->addr_width;
> else if (mtd->size > 0x1000000) {
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index 53932c87bcf2..89e3228ec1d0 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -42,8 +42,10 @@
> #define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
> #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
> #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_1_2 0x3b /* Read data bytes (Dual Output SPI) */
> +#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */
> +#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */
> +#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O 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 */
> @@ -57,8 +59,10 @@
> /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
> #define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
> #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_1_2 0x3c /* Read data bytes (Dual Output SPI) */
> +#define SPINOR_OP_READ4_1_2_2 0xbc /* Read data bytes (Dual I/O SPI) */
> +#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad Output SPI) */
> +#define SPINOR_OP_READ4_1_4_4 0xec /* Read data bytes (Quad I/O SPI) */
> #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
> #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
>
--
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
next prev parent reply other threads:[~2016-01-11 10:24 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-08 16:02 [PATCH linux-next v2 00/14] mtd: spi-nor: add driver for Atmel QSPI controller Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 01/14] mtd: spi-nor: remove micron_quad_enable() Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 05/14] mtd: spi-nor: fix support of Winbond memories Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 06/14] mtd: spi-nor: fix support of Micron memories Cyrille Pitchen
[not found] ` <cover.1452268345.git.cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
2016-01-08 16:02 ` [PATCH linux-next v2 02/14] mtd: spi-nor: properly detect the memory when it boots in Quad or Dual mode Cyrille Pitchen
[not found] ` <fd8f4e779b050a1634f197baf748683099ec2445.1452268345.git.cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
2016-01-11 10:08 ` Boris Brezillon
2016-01-11 13:56 ` Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 03/14] mtd: spi-nor: select op codes and SPI NOR protocols by manufacturer Cyrille Pitchen
2016-01-11 10:24 ` Boris Brezillon [this message]
2016-01-11 14:30 ` Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 04/14] mtd: spi-nor: fix support of Macronix memories Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 07/14] mtd: spi-nor: fix support of Spansion memories Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 08/14] mtd: spi-nor: configure the number of dummy clock cycles by manufacturer Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 09/14] mtd: spi-nor: configure the number of dummy clock cycles on Micron memories Cyrille Pitchen
2016-01-08 16:10 ` [PATCH linux-next v2 11/14] mtd: spi-nor: configure the number of dummy clock cycles on Spansion memories Cyrille Pitchen
2016-01-08 16:10 ` [PATCH linux-next v2 12/14] mtd: m25p80: add support of dual and quad spi protocols to all commands Cyrille Pitchen
2016-01-08 16:10 ` [PATCH linux-next v2 13/14] Documentation: atmel-quadspi: add binding file for Atmel QSPI driver Cyrille Pitchen
2016-01-08 16:10 ` [PATCH linux-next v2 14/14] mtd: atmel-quadspi: add driver for Atmel QSPI controller Cyrille Pitchen
2016-01-08 16:02 ` [PATCH linux-next v2 10/14] mtd: spi-nor: configure the number of dummy clock cycles on Macronix memories Cyrille Pitchen
[not found] ` <caaf19555ae684e0a1ccdd79cd7326ee1fbf1197.1452268345.git.cyrille.pitchen-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
2016-01-29 13:29 ` Cyrille Pitchen
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=20160111112421.5919b531@bbrezillon \
--to=boris.brezillon@free-electrons.com \
--cc=computersforpeace@gmail.com \
--cc=cyrille.pitchen@atmel.com \
--cc=devicetree@vger.kernel.org \
--cc=galak@codeaurora.org \
--cc=ijc+devicetree@hellion.org.uk \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=marex@denx.de \
--cc=mark.rutland@arm.com \
--cc=nicolas.ferre@atmel.com \
--cc=pawel.moll@arm.com \
--cc=robh+dt@kernel.org \
--cc=vigneshr@ti.com \
/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).