diff mbox series

[v1,3/6] mtd: spi-nor: get rid of SPI_NOR_NO_FR

Message ID 20240412134405.381832-4-mwalle@kernel.org
State Superseded
Headers show
Series mtd: spi-nor: spring cleaning | expand

Commit Message

Michael Walle April 12, 2024, 1:44 p.m. UTC
The evervision FRAM devices are the only user of the NO_FR flag. Drop
the global flag and instead use a manufacturer fixup for the evervision
flashes to drop the fast read support.

Signed-off-by: Michael Walle <mwalle@kernel.org>
---
Please note, that the fast read opcode will still be set in
spi_nor_init_default_params(), but the selection of the read opcodes
just depends on the mask.

That is also something I want to fix soon: the opcodes can always
be set and the drivers/SFDP will only set the mask. Opcodes then can be
switched between 3b and 4b ones if necessary.
---
 drivers/mtd/spi-nor/core.c     | 12 +++++-------
 drivers/mtd/spi-nor/core.h     |  2 --
 drivers/mtd/spi-nor/everspin.c | 19 +++++++++++++++----
 3 files changed, 20 insertions(+), 13 deletions(-)

Comments

Tudor Ambarus April 12, 2024, 2 p.m. UTC | #1
On 4/12/24 14:44, Michael Walle wrote:
> The evervision FRAM devices are the only user of the NO_FR flag. Drop
> the global flag and instead use a manufacturer fixup for the evervision
> flashes to drop the fast read support.
> 

Don't we want to get rid of FRAMs from SPI NOR? Why the dance then?
Michael Walle April 12, 2024, 2:03 p.m. UTC | #2
On Fri Apr 12, 2024 at 4:00 PM CEST, Tudor Ambarus wrote:
>
>
> On 4/12/24 14:44, Michael Walle wrote:
> > The evervision FRAM devices are the only user of the NO_FR flag. Drop
> > the global flag and instead use a manufacturer fixup for the evervision
> > flashes to drop the fast read support.
> > 
>
> Don't we want to get rid of FRAMs from SPI NOR? Why the dance then?

Yes, but it isn't that easy. There are (three?) in-tree users of
these chips. But we can already move all the special handling out of
the core.

-michael
Tudor Ambarus April 16, 2024, 4:47 a.m. UTC | #3
On 4/12/24 15:03, Michael Walle wrote:
> On Fri Apr 12, 2024 at 4:00 PM CEST, Tudor Ambarus wrote:
>>
>>
>> On 4/12/24 14:44, Michael Walle wrote:
>>> The evervision FRAM devices are the only user of the NO_FR flag. Drop
>>> the global flag and instead use a manufacturer fixup for the evervision
>>> flashes to drop the fast read support.
>>>
>>
>> Don't we want to get rid of FRAMs from SPI NOR? Why the dance then?
> 
> Yes, but it isn't that easy. There are (three?) in-tree users of
> these chips. But we can already move all the special handling out of
> the core.
> 

Okay.
Pratyush Yadav April 17, 2024, 1:39 p.m. UTC | #4
Hi Michael,

On Fri, Apr 12 2024, Michael Walle wrote:

> The evervision FRAM devices are the only user of the NO_FR flag. Drop
> the global flag and instead use a manufacturer fixup for the evervision
> flashes to drop the fast read support.
>
> Signed-off-by: Michael Walle <mwalle@kernel.org>
> ---
> Please note, that the fast read opcode will still be set in
> spi_nor_init_default_params(), but the selection of the read opcodes
> just depends on the mask.

Since that is the case now, might as well drop the

    if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)

in spi_nor_init_default_params().

>
> That is also something I want to fix soon: the opcodes can always
> be set and the drivers/SFDP will only set the mask. Opcodes then can be
> switched between 3b and 4b ones if necessary.
> ---
>  drivers/mtd/spi-nor/core.c     | 12 +++++-------
>  drivers/mtd/spi-nor/core.h     |  2 --
>  drivers/mtd/spi-nor/everspin.c | 19 +++++++++++++++----
>  3 files changed, 20 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index fb76e0522665..65e6531ada0a 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2952,14 +2952,12 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
>  	params->page_size = info->page_size ?: SPI_NOR_DEFAULT_PAGE_SIZE;
>  	params->n_banks = info->n_banks ?: SPI_NOR_DEFAULT_N_BANKS;
>  
> -	if (!(info->flags & SPI_NOR_NO_FR)) {
> -		/* Default to Fast Read for DT and non-DT platform devices. */
> -		params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
> +	/* Default to Fast Read for DT and non-DT platform devices. */
> +	params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
>  
> -		/* Mask out Fast Read if not requested at DT instantiation. */
> -		if (np && !of_property_read_bool(np, "m25p,fast-read"))
> -			params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
> -	}
> +	/* Mask out Fast Read if not requested at DT instantiation. */
> +	if (np && !of_property_read_bool(np, "m25p,fast-read"))
> +		params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;

Nit: move this above where SNOR_CMD_READ_FAST is set up.

Also, I think this is a bit clearer:

	/* Default to Fast Read for non-DT and enable it if requested by DT. */
	if (!np || of_property_read_bool(np, "m25p,fast-read"))
		params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;

>  
>  	/* (Fast) Read settings. */
>  	params->hwcaps.mask |= SNOR_HWCAPS_READ;
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 072c69b0d06c..9aa7d6399c8a 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -479,7 +479,6 @@ struct spi_nor_id {
>   *                            Usually these will power-up in a write-protected
>   *                            state.
>   *   SPI_NOR_NO_ERASE:        no erase command needed.
> - *   SPI_NOR_NO_FR:           can't do fastread.
>   *   SPI_NOR_QUAD_PP:         flash supports Quad Input Page Program.
>   *   SPI_NOR_RWW:             flash supports reads while write.
>   *
> @@ -528,7 +527,6 @@ struct flash_info {
>  #define SPI_NOR_BP3_SR_BIT6		BIT(4)
>  #define SPI_NOR_SWP_IS_VOLATILE		BIT(5)
>  #define SPI_NOR_NO_ERASE		BIT(6)
> -#define SPI_NOR_NO_FR			BIT(7)
>  #define SPI_NOR_QUAD_PP			BIT(8)
>  #define SPI_NOR_RWW			BIT(9)

Move the other bits up since the slot is now free.

>  
> diff --git a/drivers/mtd/spi-nor/everspin.c b/drivers/mtd/spi-nor/everspin.c
> index 5f321e24ae7d..0720a61947e7 100644
> --- a/drivers/mtd/spi-nor/everspin.c
> +++ b/drivers/mtd/spi-nor/everspin.c
> @@ -14,28 +14,39 @@ static const struct flash_info everspin_nor_parts[] = {
>  		.size = SZ_16K,
>  		.sector_size = SZ_16K,
>  		.addr_nbytes = 2,
> -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> +		.flags = SPI_NOR_NO_ERASE,
>  	}, {
>  		.name = "mr25h256",
>  		.size = SZ_32K,
>  		.sector_size = SZ_32K,
>  		.addr_nbytes = 2,
> -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> +		.flags = SPI_NOR_NO_ERASE,
>  	}, {
>  		.name = "mr25h10",
>  		.size = SZ_128K,
>  		.sector_size = SZ_128K,
> -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> +		.flags = SPI_NOR_NO_ERASE,
>  	}, {
>  		.name = "mr25h40",
>  		.size = SZ_512K,
>  		.sector_size = SZ_512K,
> -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> +		.flags = SPI_NOR_NO_ERASE,
>  	}
>  };
>  
> +static void evervision_nor_default_init(struct spi_nor *nor)
> +{
> +	/* Everspin FRAMs don't support the fast read opcode. */
> +	nor->params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
> +}
> +
> +static const struct spi_nor_fixups evervision_nor_fixups = {
> +	.default_init = evervision_nor_default_init,
> +};
> +
>  const struct spi_nor_manufacturer spi_nor_everspin = {
>  	.name = "everspin",
>  	.parts = everspin_nor_parts,
>  	.nparts = ARRAY_SIZE(everspin_nor_parts),
> +	.fixups = &evervision_nor_fixups,
>  };
Michael Walle April 17, 2024, 2:43 p.m. UTC | #5
Hi,

On Wed Apr 17, 2024 at 3:39 PM CEST, Pratyush Yadav wrote:
> On Fri, Apr 12 2024, Michael Walle wrote:
>
> > The evervision FRAM devices are the only user of the NO_FR flag. Drop
> > the global flag and instead use a manufacturer fixup for the evervision
> > flashes to drop the fast read support.
> >
> > Signed-off-by: Michael Walle <mwalle@kernel.org>
> > ---
> > Please note, that the fast read opcode will still be set in
> > spi_nor_init_default_params(), but the selection of the read opcodes
> > just depends on the mask.
>
> Since that is the case now, might as well drop the
>
>     if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>
> in spi_nor_init_default_params().

I want to address that in another patch where I'll do that for all
the opcodes. Just doing it for the fast read looks odd.

> > That is also something I want to fix soon: the opcodes can always
> > be set and the drivers/SFDP will only set the mask. Opcodes then can be
> > switched between 3b and 4b ones if necessary.
> > ---
> >  drivers/mtd/spi-nor/core.c     | 12 +++++-------
> >  drivers/mtd/spi-nor/core.h     |  2 --
> >  drivers/mtd/spi-nor/everspin.c | 19 +++++++++++++++----
> >  3 files changed, 20 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> > index fb76e0522665..65e6531ada0a 100644
> > --- a/drivers/mtd/spi-nor/core.c
> > +++ b/drivers/mtd/spi-nor/core.c
> > @@ -2952,14 +2952,12 @@ static void spi_nor_init_default_params(struct spi_nor *nor)
> >  	params->page_size = info->page_size ?: SPI_NOR_DEFAULT_PAGE_SIZE;
> >  	params->n_banks = info->n_banks ?: SPI_NOR_DEFAULT_N_BANKS;
> >  
> > -	if (!(info->flags & SPI_NOR_NO_FR)) {
> > -		/* Default to Fast Read for DT and non-DT platform devices. */
> > -		params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
> > +	/* Default to Fast Read for DT and non-DT platform devices. */
> > +	params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
> >  
> > -		/* Mask out Fast Read if not requested at DT instantiation. */
> > -		if (np && !of_property_read_bool(np, "m25p,fast-read"))
> > -			params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
> > -	}
> > +	/* Mask out Fast Read if not requested at DT instantiation. */
> > +	if (np && !of_property_read_bool(np, "m25p,fast-read"))
> > +		params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
>
> Nit: move this above where SNOR_CMD_READ_FAST is set up.
>
> Also, I think this is a bit clearer:
>
> 	/* Default to Fast Read for non-DT and enable it if requested by DT. */
> 	if (!np || of_property_read_bool(np, "m25p,fast-read"))
> 		params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;

Will do.

> >  	/* (Fast) Read settings. */
> >  	params->hwcaps.mask |= SNOR_HWCAPS_READ;
> > diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> > index 072c69b0d06c..9aa7d6399c8a 100644
> > --- a/drivers/mtd/spi-nor/core.h
> > +++ b/drivers/mtd/spi-nor/core.h
> > @@ -479,7 +479,6 @@ struct spi_nor_id {
> >   *                            Usually these will power-up in a write-protected
> >   *                            state.
> >   *   SPI_NOR_NO_ERASE:        no erase command needed.
> > - *   SPI_NOR_NO_FR:           can't do fastread.
> >   *   SPI_NOR_QUAD_PP:         flash supports Quad Input Page Program.
> >   *   SPI_NOR_RWW:             flash supports reads while write.
> >   *
> > @@ -528,7 +527,6 @@ struct flash_info {
> >  #define SPI_NOR_BP3_SR_BIT6		BIT(4)
> >  #define SPI_NOR_SWP_IS_VOLATILE		BIT(5)
> >  #define SPI_NOR_NO_ERASE		BIT(6)
> > -#define SPI_NOR_NO_FR			BIT(7)
> >  #define SPI_NOR_QUAD_PP			BIT(8)
> >  #define SPI_NOR_RWW			BIT(9)
>
> Move the other bits up since the slot is now free.

Mhh can't decide what's better here. On one hand I'd really like to
avoid too much code churn because it's already hard enough to follow
the development using git blame. OTOH, a new flag would need to be
added in between the existing flags. Not sure.. Or we if we run out
of free spots at the end we might get rid of the free slots.

-michael

> > diff --git a/drivers/mtd/spi-nor/everspin.c b/drivers/mtd/spi-nor/everspin.c
> > index 5f321e24ae7d..0720a61947e7 100644
> > --- a/drivers/mtd/spi-nor/everspin.c
> > +++ b/drivers/mtd/spi-nor/everspin.c
> > @@ -14,28 +14,39 @@ static const struct flash_info everspin_nor_parts[] = {
> >  		.size = SZ_16K,
> >  		.sector_size = SZ_16K,
> >  		.addr_nbytes = 2,
> > -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> > +		.flags = SPI_NOR_NO_ERASE,
> >  	}, {
> >  		.name = "mr25h256",
> >  		.size = SZ_32K,
> >  		.sector_size = SZ_32K,
> >  		.addr_nbytes = 2,
> > -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> > +		.flags = SPI_NOR_NO_ERASE,
> >  	}, {
> >  		.name = "mr25h10",
> >  		.size = SZ_128K,
> >  		.sector_size = SZ_128K,
> > -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> > +		.flags = SPI_NOR_NO_ERASE,
> >  	}, {
> >  		.name = "mr25h40",
> >  		.size = SZ_512K,
> >  		.sector_size = SZ_512K,
> > -		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
> > +		.flags = SPI_NOR_NO_ERASE,
> >  	}
> >  };
> >  
> > +static void evervision_nor_default_init(struct spi_nor *nor)
> > +{
> > +	/* Everspin FRAMs don't support the fast read opcode. */
> > +	nor->params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
> > +}
> > +
> > +static const struct spi_nor_fixups evervision_nor_fixups = {
> > +	.default_init = evervision_nor_default_init,
> > +};
> > +
> >  const struct spi_nor_manufacturer spi_nor_everspin = {
> >  	.name = "everspin",
> >  	.parts = everspin_nor_parts,
> >  	.nparts = ARRAY_SIZE(everspin_nor_parts),
> > +	.fixups = &evervision_nor_fixups,
> >  };
Pratyush Yadav April 17, 2024, 3:37 p.m. UTC | #6
On Wed, Apr 17 2024, Michael Walle wrote:

> Hi,
>
> On Wed Apr 17, 2024 at 3:39 PM CEST, Pratyush Yadav wrote:
>> On Fri, Apr 12 2024, Michael Walle wrote:
>>
>> > The evervision FRAM devices are the only user of the NO_FR flag. Drop
>> > the global flag and instead use a manufacturer fixup for the evervision
>> > flashes to drop the fast read support.
>> >
>> > Signed-off-by: Michael Walle <mwalle@kernel.org>
>> > ---
>> > Please note, that the fast read opcode will still be set in
>> > spi_nor_init_default_params(), but the selection of the read opcodes
>> > just depends on the mask.
>>
>> Since that is the case now, might as well drop the
>>
>>     if (params->hwcaps.mask & SNOR_HWCAPS_READ_FAST)
>>
>> in spi_nor_init_default_params().
>
> I want to address that in another patch where I'll do that for all
> the opcodes. Just doing it for the fast read looks odd.

Okay.

[...]
>> > diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> > index 072c69b0d06c..9aa7d6399c8a 100644
>> > --- a/drivers/mtd/spi-nor/core.h
>> > +++ b/drivers/mtd/spi-nor/core.h
>> > @@ -479,7 +479,6 @@ struct spi_nor_id {
>> >   *                            Usually these will power-up in a write-protected
>> >   *                            state.
>> >   *   SPI_NOR_NO_ERASE:        no erase command needed.
>> > - *   SPI_NOR_NO_FR:           can't do fastread.
>> >   *   SPI_NOR_QUAD_PP:         flash supports Quad Input Page Program.
>> >   *   SPI_NOR_RWW:             flash supports reads while write.
>> >   *
>> > @@ -528,7 +527,6 @@ struct flash_info {
>> >  #define SPI_NOR_BP3_SR_BIT6		BIT(4)
>> >  #define SPI_NOR_SWP_IS_VOLATILE		BIT(5)
>> >  #define SPI_NOR_NO_ERASE		BIT(6)
>> > -#define SPI_NOR_NO_FR			BIT(7)
>> >  #define SPI_NOR_QUAD_PP			BIT(8)
>> >  #define SPI_NOR_RWW			BIT(9)
>>
>> Move the other bits up since the slot is now free.
>
> Mhh can't decide what's better here. On one hand I'd really like to
> avoid too much code churn because it's already hard enough to follow
> the development using git blame. OTOH, a new flag would need to be
> added in between the existing flags. Not sure.. Or we if we run out
> of free spots at the end we might get rid of the free slots.

Filling this slot with the new deprecated flag should do the trick then.

BTW, -M and -C options for git-blame can help you a bit. They can detect
moved and copied lines, and look for the original one to blame. From man
git-blame:

        -M[<num>]
           Detect moved or copied lines within a file. When a commit
           moves or copies a block of lines (e.g. the original file has
           A and then B, and the commit changes it to B and then A), the
           traditional blame algorithm notices only half of the movement
           and typically blames the lines that were moved up (i.e. B) to
           the parent and assigns blame to the lines that were moved
           down (i.e. A) to the child commit. With this option, both
           groups of lines are blamed on the parent by running extra
           passes of inspection.

           <num> is optional but it is the lower bound on the number of
           alphanumeric characters that Git must detect as
           moving/copying within a file for it to associate those lines
           with the parent commit. The default value is 20.

       -C[<num>]
           In addition to -M, detect lines moved or copied from other
           files that were modified in the same commit. This is useful
           when you reorganize your program and move code around across
           files. When this option is given twice, the command
           additionally looks for copies from other files in the commit
           that creates the file. When this option is given three times,
           the command additionally looks for copies from other files in
           any commit.

           <num> is optional but it is the lower bound on the number of
           alphanumeric characters that Git must detect as
           moving/copying between files for it to associate those lines
           with the parent commit. And the default value is 40. If there
           are more than one -C options given, the <num> argument of the
           last -C will take effect.

[...]
Michael Walle April 17, 2024, 3:45 p.m. UTC | #7
Hi,

On Wed Apr 17, 2024 at 5:37 PM CEST, Pratyush Yadav wrote:
> BTW, -M and -C options for git-blame can help you a bit. They can detect
> moved and copied lines, and look for the original one to blame. From man
> git-blame:

I know, did you saw "So You Think You Know Git - FOSDEM 2024", too? ;)
Anyway, at least in netdev unnecessary code churn is frowned upon ;)

-michael
Pratyush Yadav April 17, 2024, 3:54 p.m. UTC | #8
On Wed, Apr 17 2024, Michael Walle wrote:

> Hi,
>
> On Wed Apr 17, 2024 at 5:37 PM CEST, Pratyush Yadav wrote:
>> BTW, -M and -C options for git-blame can help you a bit. They can detect
>> moved and copied lines, and look for the original one to blame. From man
>> git-blame:
>
> I know, did you saw "So You Think You Know Git - FOSDEM 2024", too? ;)

Hahaha, yes :-)

> Anyway, at least in netdev unnecessary code churn is frowned upon ;)
>
> -michael
>
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index fb76e0522665..65e6531ada0a 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2952,14 +2952,12 @@  static void spi_nor_init_default_params(struct spi_nor *nor)
 	params->page_size = info->page_size ?: SPI_NOR_DEFAULT_PAGE_SIZE;
 	params->n_banks = info->n_banks ?: SPI_NOR_DEFAULT_N_BANKS;
 
-	if (!(info->flags & SPI_NOR_NO_FR)) {
-		/* Default to Fast Read for DT and non-DT platform devices. */
-		params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
+	/* Default to Fast Read for DT and non-DT platform devices. */
+	params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;
 
-		/* Mask out Fast Read if not requested at DT instantiation. */
-		if (np && !of_property_read_bool(np, "m25p,fast-read"))
-			params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
-	}
+	/* Mask out Fast Read if not requested at DT instantiation. */
+	if (np && !of_property_read_bool(np, "m25p,fast-read"))
+		params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
 
 	/* (Fast) Read settings. */
 	params->hwcaps.mask |= SNOR_HWCAPS_READ;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 072c69b0d06c..9aa7d6399c8a 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -479,7 +479,6 @@  struct spi_nor_id {
  *                            Usually these will power-up in a write-protected
  *                            state.
  *   SPI_NOR_NO_ERASE:        no erase command needed.
- *   SPI_NOR_NO_FR:           can't do fastread.
  *   SPI_NOR_QUAD_PP:         flash supports Quad Input Page Program.
  *   SPI_NOR_RWW:             flash supports reads while write.
  *
@@ -528,7 +527,6 @@  struct flash_info {
 #define SPI_NOR_BP3_SR_BIT6		BIT(4)
 #define SPI_NOR_SWP_IS_VOLATILE		BIT(5)
 #define SPI_NOR_NO_ERASE		BIT(6)
-#define SPI_NOR_NO_FR			BIT(7)
 #define SPI_NOR_QUAD_PP			BIT(8)
 #define SPI_NOR_RWW			BIT(9)
 
diff --git a/drivers/mtd/spi-nor/everspin.c b/drivers/mtd/spi-nor/everspin.c
index 5f321e24ae7d..0720a61947e7 100644
--- a/drivers/mtd/spi-nor/everspin.c
+++ b/drivers/mtd/spi-nor/everspin.c
@@ -14,28 +14,39 @@  static const struct flash_info everspin_nor_parts[] = {
 		.size = SZ_16K,
 		.sector_size = SZ_16K,
 		.addr_nbytes = 2,
-		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
+		.flags = SPI_NOR_NO_ERASE,
 	}, {
 		.name = "mr25h256",
 		.size = SZ_32K,
 		.sector_size = SZ_32K,
 		.addr_nbytes = 2,
-		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
+		.flags = SPI_NOR_NO_ERASE,
 	}, {
 		.name = "mr25h10",
 		.size = SZ_128K,
 		.sector_size = SZ_128K,
-		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
+		.flags = SPI_NOR_NO_ERASE,
 	}, {
 		.name = "mr25h40",
 		.size = SZ_512K,
 		.sector_size = SZ_512K,
-		.flags = SPI_NOR_NO_ERASE | SPI_NOR_NO_FR,
+		.flags = SPI_NOR_NO_ERASE,
 	}
 };
 
+static void evervision_nor_default_init(struct spi_nor *nor)
+{
+	/* Everspin FRAMs don't support the fast read opcode. */
+	nor->params->hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;
+}
+
+static const struct spi_nor_fixups evervision_nor_fixups = {
+	.default_init = evervision_nor_default_init,
+};
+
 const struct spi_nor_manufacturer spi_nor_everspin = {
 	.name = "everspin",
 	.parts = everspin_nor_parts,
 	.nparts = ARRAY_SIZE(everspin_nor_parts),
+	.fixups = &evervision_nor_fixups,
 };