diff mbox

[1/3] mtd: m25p80: utilize dedicated 4-byte addressing commands

Message ID 1362904877-20144-1-git-send-email-computersforpeace@gmail.com
State Superseded
Headers show

Commit Message

Brian Norris March 10, 2013, 8:41 a.m. UTC
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@gmail.com>
---
 drivers/mtd/devices/m25p80.c | 36 +++++++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 7 deletions(-)

Comments

Marek Vasut March 10, 2013, 11:18 a.m. UTC | #1
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@gmail.com>

Looks reasonable

Acked-by: Marek Vasut <marex@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,
Brian Norris March 14, 2013, 5:46 a.m. UTC | #2
On Sun, Mar 10, 2013 at 4:18 AM, Marek Vasut <marex@denx.de> wrote:
>> 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@gmail.com>
>
> Looks reasonable
>
> Acked-by: Marek Vasut <marex@denx.de>
>
> What system/CPU do you observe these issue on just out of curiosity?

A Broadcom 74xx series SoC.

Brian
Marek Vasut March 14, 2013, 9:17 a.m. UTC | #3
Dear Brian Norris,

> On Sun, Mar 10, 2013 at 4:18 AM, Marek Vasut <marex@denx.de> wrote:
> >> 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@gmail.com>
> > 
> > Looks reasonable
> > 
> > Acked-by: Marek Vasut <marex@denx.de>
> > 
> > What system/CPU do you observe these issue on just out of curiosity?
> 
> A Broadcom 74xx series SoC.

Oh ok. The bootrom programmers really do a poor job :(

Best regards,
Marek Vasut
Artem Bityutskiy March 18, 2013, 7:21 a.m. UTC | #4
On Sun, 2013-03-10 at 00:41 -0800, Brian Norris wrote:
> 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.

Aiaiai!

Build fails on all my general testing defconfigs.

--------------------------------------------------------------------------------
Failed to build the following commit for configuration "arm-omap2plus_defconfig" (architecture arm)":

d4222c5 mtd: nand: reword nand_chip bad block interface comments

drivers/mtd/devices/m25p80.c:1073: warning: type defaults to 'int' in declaration of '_dev_info'
drivers/mtd/devices/m25p80.c:1073: warning: function declaration isn't a prototype
drivers/mtd/devices/m25p80.c:1073: error: conflicting types for '_dev_info'
drivers/mtd/devices/m25p80.c:1073: note: a parameter list with an ellipsis can't match an empty parameter name list declaration
include/linux/device.h:960: note: previous declaration of '_dev_info' was here
drivers/mtd/devices/m25p80.c:1076: error: expected declaration specifiers or '...' before string constant
drivers/mtd/devices/m25p80.c:1076: error: expected declaration specifiers or '...' before 'flash'
drivers/mtd/devices/m25p80.c:1076: error: expected declaration specifiers or '...' before '(' token
drivers/mtd/devices/m25p80.c:1076: error: expected declaration specifiers or '...' before '(' token
drivers/mtd/devices/m25p80.c:1076: error: expected declaration specifiers or '...' before 'flash'
drivers/mtd/devices/m25p80.c:1076: error: expected declaration specifiers or '...' before 'flash'
drivers/mtd/devices/m25p80.c:1076: error: expected declaration specifiers or '...' before 'flash'
drivers/mtd/devices/m25p80.c:1076: warning: data definition has no type or storage class
drivers/mtd/devices/m25p80.c:1076: warning: type defaults to 'int' in declaration of 'no_printk'
drivers/mtd/devices/m25p80.c:1076: warning: function declaration isn't a prototype
drivers/mtd/devices/m25p80.c:1076: error: conflicting types for 'no_printk'
drivers/mtd/devices/m25p80.c:1076: note: a parameter list with an ellipsis can't match an empty parameter name list declaration
include/linux/printk.h:93: note: previous definition of 'no_printk' was here
drivers/mtd/devices/m25p80.c:1083: error: expected identifier or '(' before 'if'
drivers/mtd/devices/m25p80.c:1084: error: expected '=', ',', ';', 'asm' or '__attribute__' before '<' token
drivers/mtd/devices/m25p80.c:1084: error: expected '=', ',', ';', 'asm' or '__attribute__' before '++' token
drivers/mtd/devices/m25p80.c:1097: error: expected identifier or '(' before 'return'
drivers/mtd/devices/m25p80.c:1100: error: expected identifier or '(' before '}' token
make[4]: *** [drivers/mtd/devices/m25p80.o] Error 1

... ans so on for other configurations.
Brian Norris March 18, 2013, 7:55 a.m. UTC | #5
On Mon, Mar 18, 2013 at 12:21 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> On Sun, 2013-03-10 at 00:41 -0800, Brian Norris wrote:
>> 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.
>
> Aiaiai!
>
> Build fails on all my general testing defconfigs.
>
> --------------------------------------------------------------------------------
> Failed to build the following commit for configuration "arm-omap2plus_defconfig" (architecture arm)":
>
> d4222c5 mtd: nand: reword nand_chip bad block interface comments
<snip>

Wow, my bad. I actually wrote and tested this against an older kernel,
then ported it. In fixing some conflicts, I misplaced my braces...

Anyway, this error (plus a logical mistake that I noticed, regarding
the placement of the "fast_read" check) tells me I should take a
closer look at this one. I'll get back with v2 eventually.

Brian
Peter Korsgaard March 18, 2013, 8:35 a.m. UTC | #6
>>>>> "B" == Brian Norris <computersforpeace@gmail.com> writes:

Hi,

 B> This patch provides support for the new stateless command set, so that
 B> we can avoid the problems that come with a stateful addressing mode
 B> change. The flash can be left in "3-byte mode" while still accessing the
 B> entire flash.

Patch looks good (besides the build issue ;)

 B> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
 B> index e80db9e..5ff14ee 100644
 B> --- a/drivers/mtd/devices/m25p80.c
 B> +++ b/drivers/mtd/devices/m25p80.c
 B> @@ -48,6 +48,12 @@
 B>  #define	OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
 B>  #define	OPCODE_RDID		0x9f	/* Read JEDEC ID */
 
 B> +/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
 B> +#define	OPCODE_NORM_READ_4B	0x13	/* Read data bytes (low frequency) */
 B> +#define	OPCODE_FAST_READ_4B	0x0c	/* Read data bytes (high frequency) */
 B> +#define	OPCODE_PP_4B		0x12	/* Page program (up to 256 bytes) */
 B> +#define	OPCODE_SE_4B		0xdc	/* Sector erase (usually 64KiB) */

FYI, looking at a Micron N25Q datasheet, they support the same 4B
read/fast read commands, but NOT the 4B PP/SE ones - So for those you
need the enter-4B / exit-4B dance :/
Matthieu CASTET March 18, 2013, 3:31 p.m. UTC | #7
Brian Norris a écrit :
> 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.
What's funny is the other side work :

you can have a ROM that use 4-byte mode with 3-byte or 2-byte device as soon as
the read command is the same. [1]

What's happen is that the first 1/2 bytes will be skipped and you need to take
care of that when flasing the device.

Matthieu

[1]
- send Read Data (03h)command
- send 32 bits address
- read data
Matthieu CASTET March 18, 2013, 3:37 p.m. UTC | #8
Peter Korsgaard a écrit :
>>>>>> "B" == Brian Norris <computersforpeace@gmail.com> writes:
> 
> Hi,
> 
>  B> This patch provides support for the new stateless command set, so that
>  B> we can avoid the problems that come with a stateful addressing mode
>  B> change. The flash can be left in "3-byte mode" while still accessing the
>  B> entire flash.
> 
> Patch looks good (besides the build issue ;)
> 
>  B> diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
>  B> index e80db9e..5ff14ee 100644
>  B> --- a/drivers/mtd/devices/m25p80.c
>  B> +++ b/drivers/mtd/devices/m25p80.c
>  B> @@ -48,6 +48,12 @@
>  B>  #define	OPCODE_SE		0xd8	/* Sector erase (usually 64KiB) */
>  B>  #define	OPCODE_RDID		0x9f	/* Read JEDEC ID */
>  
>  B> +/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
>  B> +#define	OPCODE_NORM_READ_4B	0x13	/* Read data bytes (low frequency) */
>  B> +#define	OPCODE_FAST_READ_4B	0x0c	/* Read data bytes (high frequency) */
>  B> +#define	OPCODE_PP_4B		0x12	/* Page program (up to 256 bytes) */
>  B> +#define	OPCODE_SE_4B		0xdc	/* Sector erase (usually 64KiB) */
> 
> FYI, looking at a Micron N25Q datasheet, they support the same 4B
> read/fast read commands, but NOT the 4B PP/SE ones - So for those you
> need the enter-4B / exit-4B dance :/
> 
Same for windbond chip.
Marek Vasut March 18, 2013, 3:39 p.m. UTC | #9
Dear Matthieu CASTET,

> Brian Norris a écrit :
> > 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.
> 
> What's funny is the other side work :
> 
> you can have a ROM that use 4-byte mode with 3-byte or 2-byte device as
> soon as the read command is the same. [1]

Well, all of these are crap design. The SPI flash shall be power-cycled if the 
platform reboots no matter what exactly to prevent having it in undefined state.

Best regards,
Marek Vasut
Matthieu CASTET March 18, 2013, 4:13 p.m. UTC | #10
Marek Vasut a écrit :
> Dear Matthieu CASTET,
> 
>> What's funny is the other side work :
>>
>> you can have a ROM that use 4-byte mode with 3-byte or 2-byte device as
>> soon as the read command is the same. [1]
> 
> Well, all of these are crap design. The SPI flash shall be power-cycled if the 
> platform reboots no matter what exactly to prevent having it in undefined state.
> 
This side (ROM that use 4-byte mode with 3-byte or 2-byte device) is used to
avoid detection of the flash by the rom (no need to know if spi eeprom or spi nor).
Brian Norris March 18, 2013, 4:40 p.m. UTC | #11
On 03/18/2013 08:39 AM, Marek Vasut wrote:
> Dear Matthieu CASTET,
>
>> Brian Norris a écrit :
>>> 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.
>>
>> What's funny is the other side work :
>>
>> you can have a ROM that use 4-byte mode with 3-byte or 2-byte device as
>> soon as the read command is the same. [1]
>
> Well, all of these are crap design. The SPI flash shall be power-cycled if the
> platform reboots no matter what exactly to prevent having it in undefined state.

While I agree that ideally, the flash should always be 
reset/power-cycled on reboot, these type of flash have traditionally 
been stateless (and have no RESET command) and flash manufacturers have 
done nothing to help this as they added state (e.g., non-standard 
command sets; partially-supported command sets). Plus, as I mentioned, 
not all flash have reset pins, as they try to skimp on pins or take them 
over for other uses.

What exactly is your recommended non-crap design on these stateful flash 
that have no reset pin? Just a smarter boot ROM which can handle 
different states/flash types?

Brian
diff mbox

Patch

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,