[PATCH] m25p80: Use a 512 byte page size for Spansion flash s25fl512s

Marek Vasut marek.vasut at gmail.com
Sat Feb 4 14:25:06 PST 2017


On 01/26/2017 03:58 PM, Mark Marshall wrote:
> On 24 January 2017 at 17:48, Marek Vasut <marek.vasut at gmail.com> wrote:
>> On 01/24/2017 02:52 PM, mark.marshall at omicronenergy.com wrote:
>>> From: Mark Marshall <mark.marshall at omicronenergy.com>
>>>
>>> The s25fl512s flash from Spansion has a 512 byte write page size,
>>> which means that we can write 512 bytes at a time (instead of 256).
>>>
>>> This single change makes writing to the flash about 2x faster.
>>>
>>> Signed-off-by: Mark Marshall <mark.marshall at omicronenergy.com>
>>> ---
>>>  drivers/mtd/spi-nor/spi-nor.c | 17 ++++++++++++++++-
>>>  1 file changed, 16 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
>>> index da7cd69..c9ac0bf 100644
>>> --- a/drivers/mtd/spi-nor/spi-nor.c
>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>>> @@ -775,6 +775,21 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>>>               .page_size = 256,                                       \
>>>               .flags = (_flags),
>>>
>>> +/* Used to set a custom (non 256) page_size */
>>> +#define INFOP(_jedec_id, _ext_id, _sector_size, _n_sectors, _pg_sz, _flags) \
>>> +             .id = {                                                 \
>>> +                     ((_jedec_id) >> 16) & 0xff,                     \
>>> +                     ((_jedec_id) >> 8) & 0xff,                      \
>>> +                     (_jedec_id) & 0xff,                             \
>>> +                     ((_ext_id) >> 8) & 0xff,                        \
>>> +                     (_ext_id) & 0xff,                               \
>>> +                     },                                              \
>>> +             .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \
>>> +             .sector_size = (_sector_size),                          \
>>> +             .n_sectors = (_n_sectors),                              \
>>> +             .page_size = (_pg_sz),                                  \
>>> +             .flags = (_flags),                                      \
>>> +
>>
>> Maybe it's time to introduce INFO_FULL() instead, where you could
>> specify the page size and ID length. Adding more and more custom INFOx()
>> doesn't scale. The INFOx() could then be easily converted
>> over to INFO_FULL().
>>
>> One minor bit which could be slightly problematic is the .id_len
>> field, which is precomputed now, but maybe there is a way to handle
>> that too.
>>
>> Thoughts ?

Sorry for the late reply, I've been traveling a lot recently.

> I had a go at this, and my preferred method would be to use some token
> pasting, but I'm not sure how popular this will be?

IMO not much.

> Below is the macro's I
> came up with and a few representative lines of the table.  If no one objects
> I'll prepare a complete patch.  (I've done this on a branch, and the table has
> changed slightly, where should I be basing a patch like this from?).

This makes me kinda wonder (and this might be a totally wrong idea), why
don't we replace the 6-byte ID table with an u64 id and u64 mask ?
_ID_JEDEC_EXT2 would then look something like:

#define _ID_JEDEC_EXT2(_jedec_id, _ext_id)		\
{							\
	.id = ((_ext_id) << 32) | (_jedec_id),		\
	.mask = GENMASK(47, 32) | GENMASK(23, 0),	\
},

The match would then also be much easier, that is.
->id & ->mask == ->id
instead of all the memcmp() tests. id_len would go
away too. And the matching would allow more precise
control over the test. We could even handle the n25q256(a)
specialty jedec ID 0x20baxx/0x20bbxx with this.

I don't think there'll ever be a SPI NOR with 8byte JEDEC
ID, so u64 should be good enough.

The macros below could be reworked to use a generic macro
to define the ID/extID entry and it's width, ie:

#define _ID_JEDEC(_jedec_id, _jedec_id_width, 			\
		  _ext_id, _ext_id_width)			\
{								\
	.id = ((_ext_id) << 32) | (_jedec_id),			\
	.mask = GENMASK(32 + ((_ext_id_width * 8) - 1), 32) |	\
		GENMASK(((_id_width * 8) - 1), 0),		\
},

> I've checked by building the file both before and after my change, and the
> table doesn't change.
> 
> #define _ID_NONE                \
>     .id = {},                \
>     .id_len = 0
> 
> #define _ID_JEDEC(_jedec_id)                        \
>     .id = {                                \
>         ((_jedec_id) >> 16) & 0xff,                \
>         ((_jedec_id) >> 8) & 0xff,                \
>         (_jedec_id) & 0xff,                    \
>     },                                \
>     .id_len = 3
> 
> #define _ID_JEDEC_EXT2(_jedec_id, _ext_id)                \
>     .id = {                                \
>         ((_jedec_id) >> 16) & 0xff,                \
>         ((_jedec_id) >> 8) & 0xff,                \
>         (_jedec_id) & 0xff,                    \
>         ((_ext_id) >> 8) & 0xff,                \
>         (_ext_id) & 0xff,                    \
>     },                                \
>     .id_len = 5
> 
> #define _ID_JEDEC_EXT3(_jedec_id, _ext_id)                \
>     .id = {                                \
>         ((_jedec_id) >> 16) & 0xff,                \
>         ((_jedec_id) >> 8) & 0xff,                \
>         (_jedec_id) & 0xff,                    \
>         ((_ext_id) >> 16) & 0xff,                \
>         ((_ext_id) >> 8) & 0xff,                \
>         (_ext_id) & 0xff,                    \
>     },                                \
>     .id_len = 6
> 
> #define INFO_FULL(_id, _sector_size, _n_sectors, _pg_sz, _addr_width, _flags) \
>     _ID_ ## _id,                            \
>     .sector_size = (_sector_size),                    \
>     .n_sectors = (_n_sectors),                    \
>     .page_size = (_pg_sz),                        \
>     .addr_width = (_addr_width),                    \
>     .flags = (_flags),
> 
> #define INFO(_id, _sector_size, _n_sectors, _flags)    \
>     INFO_FULL(_id, _sector_size, _n_sectors, 256, 0, _flags)
> 
> static const struct flash_info spi_nor_ids[] = {
>     { "at25fs010",  INFO(JEDEC(0x1f6601), 32 * 1024,   4, SECT_4K) },
>     { "at25fs040",  INFO(JEDEC(0x1f6604), 64 * 1024,   8, SECT_4K) },
>     { "mr25h256", INFO_FULL(NONE,  32 * 1024, 1, 256, 2,
> SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
>     { "s25sl032p",  INFO(JEDEC_EXT2(0x010215, 0x4d00),  64 * 1024,
> 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
>     { "s25fl512s",  INFO_FULL(JEDEC_EXT2(0x010220, 0x4d00), 256 *
> 1024, 256, 256, 0, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
>     { "s25fl128s",    INFO(JEDEC_EXT3(0x012018, 0x4d0180), 64 * 1024,
> 256, SECT_4K | SPI_NOR_QUAD_READ) },
>     { "cat25c11", INFO_FULL(NONE,   16, 8, 16, 1, SPI_NOR_NO_ERASE |
> SPI_NOR_NO_FR) },
> 
> Regards,
> 
> Mark
> 


-- 
Best regards,
Marek Vasut



More information about the linux-mtd mailing list