[PATCH 1/3] mtd: m25p80: utilize dedicated 4-byte addressing commands
Marek Vasut
marex at denx.de
Sun Mar 10 07:18:18 EDT 2013
Dear Brian Norris,
> Traditionally, the command set used by SPI flash only supported a 3-byte
> address. However, large SPI flash (>= 32MB, or 256Mbit) require 4 bytes
> to address the entire flash. Most manufacturers have supplied a mode
> switch (via a "bank register writer", or a "enable 4-byte mode"
> command), which tells the flash to expect 4 address cycles from now on,
> instead of 3. This mode remains until power is cut, the reset line is
> triggered (on packages where present), or a command is sent to reset the
> flash or to reset the 3-byte addressing mode.
>
> As an alternative, some flash manufacturers have developed a new command
> set that accept a full 4-byte address. They can be used orthogonally to
> any of the modes; that is, they can be used when the flash is in either
> 3-byte or 4-byte address mode.
>
> Now, there are a number of reasons why the "stateful" 4-byte address
> mode switch may not be acceptable. For instance, some SoC's perform a
> dumb boot sequence in which they only send 3-byte read commands to the
> flash. However, if an unexpected reset occurs, the flash chip cannot be
> guaranteed to return to its 3-byte mode. Thus, the SoC controller and
> flash will not understand each other. (One might consider hooking up the
> aforementioned reset pin to the system reset line so that any system
> reset will reset the flash to 3-byte mode, but some packages do not
> provide this pin. And in some other packages, one must choose between
> having a reset pin and having enough pins for 4-output QSPI support.
> It is an error prone process choosing a flash that will support a
> hardware reset pin!)
>
> This patch provides support for the new stateless command set, so that
> we can avoid the problems that come with a stateful addressing mode
> change. The flash can be left in "3-byte mode" while still accessing the
> entire flash.
>
> Note that Spansion supports this command set on all its large flash
> (e.g, S25FL512S), and Macronix has begun supporting this command set on
> some new flash (e.g., MX25L25635F). For the moment, I don't know how to
> differentiate the Macronix that don't support this command set (e.g.,
> MX25L25635E) from those that do, so this patch only supports Spansion.
>
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
Looks reasonable
Acked-by: Marek Vasut <marex at denx.de>
What system/CPU do you observe these issue on just out of curiosity?
> ---
> drivers/mtd/devices/m25p80.c | 36 +++++++++++++++++++++++++++++-------
> 1 file changed, 29 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
> index e80db9e..5ff14ee 100644
> --- a/drivers/mtd/devices/m25p80.c
> +++ b/drivers/mtd/devices/m25p80.c
> @@ -48,6 +48,12 @@
> #define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB)
*/
> #define OPCODE_RDID 0x9f /* Read JEDEC ID */
>
> +/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
> +#define OPCODE_NORM_READ_4B 0x13 /* Read data bytes (low
frequency) */
> +#define OPCODE_FAST_READ_4B 0x0c /* Read data bytes (high
frequency) */
> +#define OPCODE_PP_4B 0x12 /* Page program (up to 256
bytes) */
> +#define OPCODE_SE_4B 0xdc /* Sector erase (usually 64KiB)
*/
> +
> /* Used for SST flashes only. */
> #define OPCODE_BP 0x02 /* Byte program */
> #define OPCODE_WRDI 0x04 /* Write disable */
> @@ -84,6 +90,8 @@ struct m25p {
> u16 page_size;
> u16 addr_width;
> u8 erase_opcode;
> + u8 read_opcode;
> + u8 program_opcode;
> u8 *command;
> bool fast_read;
> };
> @@ -371,7 +379,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t
> from, size_t len, */
>
> /* Set up the write data buffer. */
> - opcode = flash->fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ;
> + opcode = flash->read_opcode;
> flash->command[0] = opcode;
> m25p_addr2cmd(flash, from, flash->command);
>
> @@ -422,7 +430,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t
> to, size_t len, write_enable(flash);
>
> /* Set up the opcode in the write buffer. */
> - flash->command[0] = OPCODE_PP;
> + flash->command[0] = flash->program_opcode;
> m25p_addr2cmd(flash, to, flash->command);
>
> page_offset = to & (flash->page_size - 1);
> @@ -1017,6 +1025,11 @@ static int m25p_probe(struct spi_device *spi)
> flash->erase_opcode = OPCODE_SE;
> flash->mtd.erasesize = info->sector_size;
> }
> + /* Default commands */
> + flash->read_opcode = flash->fast_read ?
> + OPCODE_FAST_READ :
> + OPCODE_NORM_READ;
> + flash->program_opcode = OPCODE_PP;
>
> if (info->flags & M25P_NO_ERASE)
> flash->mtd.flags |= MTD_NO_ERASE;
> @@ -1038,13 +1051,22 @@ static int m25p_probe(struct spi_device *spi)
>
> if (info->addr_width)
> flash->addr_width = info->addr_width;
> - else {
> + else if (flash->mtd.size > 0x1000000) {
> /* enable 4-byte addressing if the device exceeds 16MiB */
> - if (flash->mtd.size > 0x1000000) {
> - flash->addr_width = 4;
> + flash->addr_width = 4;
> + if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) {
> + /* Dedicated 4-byte command set */
> + flash->read_opcode = flash->fast_read ?
> + OPCODE_FAST_READ_4B :
> + OPCODE_NORM_READ_4B;
> + flash->program_opcode = OPCODE_PP_4B;
> + /* No small sector erase for 4-byte command set */
> + flash->erase_opcode = OPCODE_SE_4B;
> + flash->mtd.erasesize = info->sector_size;
> + } else {
> set_4byte(flash, info->jedec_id, 1);
> - } else
> - flash->addr_width = 3;
> + } else
> + flash->addr_width = 3;
> }
>
> dev_info(&spi->dev, "%s (%lld Kbytes)\n", id->name,
More information about the linux-mtd
mailing list