diff mbox series

[v4,2/3] spi-nor: s25fl512s supports region locking

Message ID 20190320071605.4289-3-jonas@norrbonn.se
State Accepted
Delegated to: Ambarus Tudor
Headers show
Series spi-nor block protection | expand

Commit Message

Jonas Bonn March 20, 2019, 7:16 a.m. UTC
Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
Tested and verified on a Cypress s25fl512s.

Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
---
 drivers/mtd/spi-nor/spi-nor.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Comments

Tudor Ambarus March 20, 2019, 7:39 a.m. UTC | #1
On 03/20/2019 09:16 AM, Jonas Bonn wrote:
> External E-Mail
> 
> 
> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
> Tested and verified on a Cypress s25fl512s.
> 
> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>

Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>

> ---
>  drivers/mtd/spi-nor/spi-nor.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 0cc0ef4fbf3a..9abac9e326a1 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
>  			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>  	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
>  	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> -	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> +	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
> +			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> +			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
>  	{ "s25fs512s",  INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>  	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
>  	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
>
Tudor Ambarus March 21, 2019, 4:48 p.m. UTC | #2
On 03/20/2019 09:16 AM, Jonas Bonn wrote:
> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
> Tested and verified on a Cypress s25fl512s.
> 
> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
> ---
>  drivers/mtd/spi-nor/spi-nor.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)

Applied to http://git.infradead.org/linux-mtd.git, spi-nor/next. Thanks.
Geert Uytterhoeven May 7, 2019, 9:53 a.m. UTC | #3
Hi Jonas,

On Wed, Mar 20, 2019 at 8:16 AM Jonas Bonn <jonas@norrbonn.se> wrote:
> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
> Tested and verified on a Cypress s25fl512s.
>
> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>

This is now commit dcb4b22eeaf44f91 ("spi-nor: s25fl512s supports region
locking") in mtd/next.

> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
>                         SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>         { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
>         { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> -       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> +       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
> +                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> +                       SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },

Setting SPI_NOR_HAS_LOCK causes the QSPI FLASH on r8a7791/koelsch to fail
probing.

Before/after:

    -m25p80 spi0.0: s25fl512s (65536 Kbytes)
    -3 fixed-partitions partitions found on MTD device spi0.0
    -Creating 3 MTD partitions on "spi0.0":
    -0x000000000000-0x000000080000 : "loader"
    -0x000000080000-0x000000600000 : "user"
    -0x000000600000-0x000004000000 : "flash"
    +m25p80 spi0.0: Erase Error occurred
    +m25p80 spi0.0: Erase Error occurred
    +m25p80 spi0.0: timeout while writing configuration register
    +m25p80 spi0.0: quad mode not supported
    +m25p80: probe of spi0.0 failed with error -5

FLASH chip is SPANSION FL512SAIFG1 311QQ063 A ©11 SPANSION
JEDEC id bytes: 01 02 20 4d 00 80

Gr{oetje,eeting}s,

                        Geert
Tudor Ambarus May 7, 2019, 10:42 a.m. UTC | #4
Hi, Geert,

On 05/07/2019 12:53 PM, Geert Uytterhoeven wrote:
> External E-Mail
> 
> 
> Hi Jonas,
> 
> On Wed, Mar 20, 2019 at 8:16 AM Jonas Bonn <jonas@norrbonn.se> wrote:
>> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
>> Tested and verified on a Cypress s25fl512s.
>>
>> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
> 
> This is now commit dcb4b22eeaf44f91 ("spi-nor: s25fl512s supports region
> locking") in mtd/next.
> 
>> --- a/drivers/mtd/spi-nor/spi-nor.c
>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
>>                         SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>         { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
>>         { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>> -       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>> +       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
>> +                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>> +                       SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
> 
> Setting SPI_NOR_HAS_LOCK causes the QSPI FLASH on r8a7791/koelsch to fail
> probing.
> 
> Before/after:
> 
>     -m25p80 spi0.0: s25fl512s (65536 Kbytes)
>     -3 fixed-partitions partitions found on MTD device spi0.0
>     -Creating 3 MTD partitions on "spi0.0":
>     -0x000000000000-0x000000080000 : "loader"
>     -0x000000080000-0x000000600000 : "user"
>     -0x000000600000-0x000004000000 : "flash"
>     +m25p80 spi0.0: Erase Error occurred
>     +m25p80 spi0.0: Erase Error occurred
>     +m25p80 spi0.0: timeout while writing configuration register
>     +m25p80 spi0.0: quad mode not supported
>     +m25p80: probe of spi0.0 failed with error -5
> 
> FLASH chip is SPANSION FL512SAIFG1 311QQ063 A ©11 SPANSION
> JEDEC id bytes: 01 02 20 4d 00 80

That's curious. Did you revert this patch and probe was ok? Are you sure it is
not related to the recent changes on spi-rspi.c?

Cheers,
ta
Geert Uytterhoeven May 7, 2019, 10:50 a.m. UTC | #5
Hi Tudor,

On Tue, May 7, 2019 at 12:42 PM <Tudor.Ambarus@microchip.com> wrote:
> On 05/07/2019 12:53 PM, Geert Uytterhoeven wrote:
> > On Wed, Mar 20, 2019 at 8:16 AM Jonas Bonn <jonas@norrbonn.se> wrote:
> >> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
> >> Tested and verified on a Cypress s25fl512s.
> >>
> >> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
> >
> > This is now commit dcb4b22eeaf44f91 ("spi-nor: s25fl512s supports region
> > locking") in mtd/next.
> >
> >> --- a/drivers/mtd/spi-nor/spi-nor.c
> >> +++ b/drivers/mtd/spi-nor/spi-nor.c
> >> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
> >>                         SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> >>         { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
> >>         { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> >> -       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> >> +       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
> >> +                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >> +                       SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
> >
> > Setting SPI_NOR_HAS_LOCK causes the QSPI FLASH on r8a7791/koelsch to fail
> > probing.
> >
> > Before/after:
> >
> >     -m25p80 spi0.0: s25fl512s (65536 Kbytes)
> >     -3 fixed-partitions partitions found on MTD device spi0.0
> >     -Creating 3 MTD partitions on "spi0.0":
> >     -0x000000000000-0x000000080000 : "loader"
> >     -0x000000080000-0x000000600000 : "user"
> >     -0x000000600000-0x000004000000 : "flash"
> >     +m25p80 spi0.0: Erase Error occurred
> >     +m25p80 spi0.0: Erase Error occurred
> >     +m25p80 spi0.0: timeout while writing configuration register
> >     +m25p80 spi0.0: quad mode not supported
> >     +m25p80: probe of spi0.0 failed with error -5
> >
> > FLASH chip is SPANSION FL512SAIFG1 311QQ063 A ©11 SPANSION
> > JEDEC id bytes: 01 02 20 4d 00 80
>
> That's curious. Did you revert this patch and probe was ok? Are you sure it is

Yes, a revert fixes the the probe.
I had tried all combinations of the 2 newly set flags, and only
SPI_NOR_HAS_LOCK is a problem.

> not related to the recent changes on spi-rspi.c?

These changes affect QSPI transfers only.

Gr{oetje,eeting}s,

                        Geert
Jonas Bonn May 7, 2019, 11:13 a.m. UTC | #6
Hi Geert,

On 07/05/2019 12:50, Geert Uytterhoeven wrote:
> Hi Tudor,
> 
> On Tue, May 7, 2019 at 12:42 PM <Tudor.Ambarus@microchip.com> wrote:
>> On 05/07/2019 12:53 PM, Geert Uytterhoeven wrote:
>>> On Wed, Mar 20, 2019 at 8:16 AM Jonas Bonn <jonas@norrbonn.se> wrote:
>>>> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
>>>> Tested and verified on a Cypress s25fl512s.
>>>>
>>>> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
>>>
>>> This is now commit dcb4b22eeaf44f91 ("spi-nor: s25fl512s supports region
>>> locking") in mtd/next.
>>>
>>>> --- a/drivers/mtd/spi-nor/spi-nor.c
>>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>>>> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
>>>>                          SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>>          { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
>>>>          { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>> -       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>> +       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
>>>> +                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>>>> +                       SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
>>>
>>> Setting SPI_NOR_HAS_LOCK causes the QSPI FLASH on r8a7791/koelsch to fail
>>> probing.
>>>
>>> Before/after:
>>>
>>>      -m25p80 spi0.0: s25fl512s (65536 Kbytes)
>>>      -3 fixed-partitions partitions found on MTD device spi0.0
>>>      -Creating 3 MTD partitions on "spi0.0":
>>>      -0x000000000000-0x000000080000 : "loader"
>>>      -0x000000080000-0x000000600000 : "user"
>>>      -0x000000600000-0x000004000000 : "flash"
>>>      +m25p80 spi0.0: Erase Error occurred
>>>      +m25p80 spi0.0: Erase Error occurred
>>>      +m25p80 spi0.0: timeout while writing configuration register
>>>      +m25p80 spi0.0: quad mode not supported
>>>      +m25p80: probe of spi0.0 failed with error -5
>>>

In drivers/mtd/spi-nor/spi-nor.c you have:

static int spi_nor_init(struct spi_nor *nor)
{
         int err;

         /*
          * Atmel, SST, Intel/Numonyx, and others serial NOR tend to 
power up
          * with the software protection bits set
          */
         if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
             JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
             JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
             nor->info->flags & SPI_NOR_HAS_LOCK) {
                 write_enable(nor);
                 write_sr(nor, 0);
                 spi_nor_wait_till_ready(nor);
         }

         if (nor->quad_enable) {
                 err = nor->quad_enable(nor);
                 if (err) {
                         dev_err(nor->dev, "quad mode not supported\n");
                         return err;
                 }
         }

This is the only meaningful thing that I can see may have changed with 
this flag.  We now have an additional write_enable before quad_enable. 
What happens if you swap those two blocks above so that quad_enable is 
called first?

If it's not that, I can't see how the extra flags can have any effect.

Regards,
Jonas
Geert Uytterhoeven May 7, 2019, 12:52 p.m. UTC | #7
Hi Jonas,

On Tue, May 7, 2019 at 1:14 PM Jonas Bonn <jonas@norrbonn.se> wrote:
> On 07/05/2019 12:50, Geert Uytterhoeven wrote:
> > On Tue, May 7, 2019 at 12:42 PM <Tudor.Ambarus@microchip.com> wrote:
> >> On 05/07/2019 12:53 PM, Geert Uytterhoeven wrote:
> >>> On Wed, Mar 20, 2019 at 8:16 AM Jonas Bonn <jonas@norrbonn.se> wrote:
> >>>> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
> >>>> Tested and verified on a Cypress s25fl512s.
> >>>>
> >>>> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
> >>>
> >>> This is now commit dcb4b22eeaf44f91 ("spi-nor: s25fl512s supports region
> >>> locking") in mtd/next.
> >>>
> >>>> --- a/drivers/mtd/spi-nor/spi-nor.c
> >>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
> >>>> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
> >>>>                          SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> >>>>          { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
> >>>>          { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> >>>> -       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
> >>>> +       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
> >>>> +                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> >>>> +                       SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
> >>>
> >>> Setting SPI_NOR_HAS_LOCK causes the QSPI FLASH on r8a7791/koelsch to fail
> >>> probing.
> >>>
> >>> Before/after:
> >>>
> >>>      -m25p80 spi0.0: s25fl512s (65536 Kbytes)
> >>>      -3 fixed-partitions partitions found on MTD device spi0.0
> >>>      -Creating 3 MTD partitions on "spi0.0":
> >>>      -0x000000000000-0x000000080000 : "loader"
> >>>      -0x000000080000-0x000000600000 : "user"
> >>>      -0x000000600000-0x000004000000 : "flash"
> >>>      +m25p80 spi0.0: Erase Error occurred
> >>>      +m25p80 spi0.0: Erase Error occurred
> >>>      +m25p80 spi0.0: timeout while writing configuration register
> >>>      +m25p80 spi0.0: quad mode not supported
> >>>      +m25p80: probe of spi0.0 failed with error -5
> >>>
>
> In drivers/mtd/spi-nor/spi-nor.c you have:
>
> static int spi_nor_init(struct spi_nor *nor)
> {
>          int err;
>
>          /*
>           * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
>           * with the software protection bits set
>           */
>          if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
>              JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
>              JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
>              nor->info->flags & SPI_NOR_HAS_LOCK) {
>                  write_enable(nor);

With more debug prints:

    m25p80 spi0.0: spi_nor_init:3925: write_enable() returned 0

>                  write_sr(nor, 0);

    m25p80 spi0.0: spi_nor_init:3927: write_sr() returned 0

>                  spi_nor_wait_till_ready(nor);

    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
                                     ...
    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
    m25p80 spi0.0: Erase Error occurred
    m25p80 spi0.0: spi_nor_init:3929: spi_nor_wait_till_ready() returned -5

>          }
>
>          if (nor->quad_enable) {
>                  err = nor->quad_enable(nor);

    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
    m25p80 spi0.0: Erase Error occurred
    m25p80 spi0.0: timeout while writing configuration register
    m25p80 spi0.0: spi_nor_init:3937: spansion_quad_enable() returned -5

>                  if (err) {
>                          dev_err(nor->dev, "quad mode not supported\n");
>                          return err;
>                  }
>          }
>
> This is the only meaningful thing that I can see may have changed with
> this flag.  We now have an additional write_enable before quad_enable.
> What happens if you swap those two blocks above so that quad_enable is
> called first?

With the two blocks swapped:

    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x0
    m25p80 spi0.0: spi_nor_init:3919: spansion_quad_enable() returned 0
    m25p80 spi0.0: spi_nor_init:3937: write_enable() returned 0
    m25p80 spi0.0: spi_nor_init:3939: write_sr() returned 0
    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
                                                                  ...
    m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
    m25p80 spi0.0: Erase Error occurred
    m25p80 spi0.0: spi_nor_init:3941: spi_nor_wait_till_ready() returned -5
    m25p80 spi0.0: s25fl512s (65536 Kbytes)
    3 fixed-partitions partitions found on MTD device spi0.0
    Creating 3 MTD partitions on "spi0.0":
    0x000000000000-0x000000080000 : "loader"
    0x000000080000-0x000000600000 : "user"
    0x000000600000-0x000004000000 : "flash"

Note that spi_nor_wait_till_ready() still fails.

While the device (which contains the boot loader) now appears to be
detected fine, reading returns bogus repetitive data, for all partitions:

    # hd /dev/mtd0 | head
    00000000  33 33 33 33 33 33 33 33  33 33 3b bb ff ff ff ff
|3333333333;.....|
    00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
|................|
    *
    00001000  33 33 33 33 33 33 33 33  33 33 3b bb ff ff ff ff
|3333333333;.....|
    00001010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
|................|
    *

If I remove the call to "write_sr(nor, 0)", everything works as
before, regardless
of swapping the blocks.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Tudor Ambarus May 7, 2019, 1:15 p.m. UTC | #8
Geert,

On 05/07/2019 03:52 PM, Geert Uytterhoeven wrote:
> External E-Mail
> 
> 
> Hi Jonas,
> 
> On Tue, May 7, 2019 at 1:14 PM Jonas Bonn <jonas@norrbonn.se> wrote:
>> On 07/05/2019 12:50, Geert Uytterhoeven wrote:
>>> On Tue, May 7, 2019 at 12:42 PM <Tudor.Ambarus@microchip.com> wrote:
>>>> On 05/07/2019 12:53 PM, Geert Uytterhoeven wrote:
>>>>> On Wed, Mar 20, 2019 at 8:16 AM Jonas Bonn <jonas@norrbonn.se> wrote:
>>>>>> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
>>>>>> Tested and verified on a Cypress s25fl512s.
>>>>>>
>>>>>> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
>>>>>
>>>>> This is now commit dcb4b22eeaf44f91 ("spi-nor: s25fl512s supports region
>>>>> locking") in mtd/next.
>>>>>
>>>>>> --- a/drivers/mtd/spi-nor/spi-nor.c
>>>>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>>>>>> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
>>>>>>                          SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>>>>          { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
>>>>>>          { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>>>> -       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>>>> +       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
>>>>>> +                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>>>>>> +                       SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
>>>>>
>>>>> Setting SPI_NOR_HAS_LOCK causes the QSPI FLASH on r8a7791/koelsch to fail
>>>>> probing.
>>>>>
>>>>> Before/after:
>>>>>
>>>>>      -m25p80 spi0.0: s25fl512s (65536 Kbytes)
>>>>>      -3 fixed-partitions partitions found on MTD device spi0.0
>>>>>      -Creating 3 MTD partitions on "spi0.0":
>>>>>      -0x000000000000-0x000000080000 : "loader"
>>>>>      -0x000000080000-0x000000600000 : "user"
>>>>>      -0x000000600000-0x000004000000 : "flash"
>>>>>      +m25p80 spi0.0: Erase Error occurred
>>>>>      +m25p80 spi0.0: Erase Error occurred
>>>>>      +m25p80 spi0.0: timeout while writing configuration register
>>>>>      +m25p80 spi0.0: quad mode not supported
>>>>>      +m25p80: probe of spi0.0 failed with error -5
>>>>>
>>
>> In drivers/mtd/spi-nor/spi-nor.c you have:
>>
>> static int spi_nor_init(struct spi_nor *nor)
>> {
>>          int err;
>>
>>          /*
>>           * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
>>           * with the software protection bits set
>>           */
>>          if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
>>              JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
>>              JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
>>              nor->info->flags & SPI_NOR_HAS_LOCK) {
>>                  write_enable(nor);
> 
> With more debug prints:
> 
>     m25p80 spi0.0: spi_nor_init:3925: write_enable() returned 0
> 
>>                  write_sr(nor, 0);
> 
>     m25p80 spi0.0: spi_nor_init:3927: write_sr() returned 0
> 
>>                  spi_nor_wait_till_ready(nor);
> 
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>                                      ...
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
>     m25p80 spi0.0: Erase Error occurred
>     m25p80 spi0.0: spi_nor_init:3929: spi_nor_wait_till_ready() returned -5
> 
>>          }
>>
>>          if (nor->quad_enable) {
>>                  err = nor->quad_enable(nor);
> 
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
>     m25p80 spi0.0: Erase Error occurred
>     m25p80 spi0.0: timeout while writing configuration register
>     m25p80 spi0.0: spi_nor_init:3937: spansion_quad_enable() returned -5
> 
>>                  if (err) {
>>                          dev_err(nor->dev, "quad mode not supported\n");
>>                          return err;
>>                  }
>>          }
>>
>> This is the only meaningful thing that I can see may have changed with
>> this flag.  We now have an additional write_enable before quad_enable.
>> What happens if you swap those two blocks above so that quad_enable is
>> called first?
> 
> With the two blocks swapped:
> 
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x0
>     m25p80 spi0.0: spi_nor_init:3919: spansion_quad_enable() returned 0
>     m25p80 spi0.0: spi_nor_init:3937: write_enable() returned 0
>     m25p80 spi0.0: spi_nor_init:3939: write_sr() returned 0
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>                                                                   ...
>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
>     m25p80 spi0.0: Erase Error occurred
>     m25p80 spi0.0: spi_nor_init:3941: spi_nor_wait_till_ready() returned -5
>     m25p80 spi0.0: s25fl512s (65536 Kbytes)
>     3 fixed-partitions partitions found on MTD device spi0.0
>     Creating 3 MTD partitions on "spi0.0":
>     0x000000000000-0x000000080000 : "loader"
>     0x000000080000-0x000000600000 : "user"
>     0x000000600000-0x000004000000 : "flash"
> 
> Note that spi_nor_wait_till_ready() still fails.
> 
> While the device (which contains the boot loader) now appears to be
> detected fine, reading returns bogus repetitive data, for all partitions:
> 
>     # hd /dev/mtd0 | head
>     00000000  33 33 33 33 33 33 33 33  33 33 3b bb ff ff ff ff
> |3333333333;.....|
>     00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
> |................|
>     *
>     00001000  33 33 33 33 33 33 33 33  33 33 3b bb ff ff ff ff
> |3333333333;.....|
>     00001010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
> |................|
>     *
> 
> If I remove the call to "write_sr(nor, 0)", everything works as
> before, regardless
> of swapping the blocks.
> 

Can you try this one?

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 73172d7f512b..b94a6eaaaca5 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1551,6 +1551,7 @@ static int spansion_read_cr_quad_enable(struct spi_nor *nor)
        u8 sr_cr[2];
        int ret;
 
+       dev_err(dev, "%s\n", __FUNCTION__);
        /* Check current Quad Enable bit value. */
        ret = read_cr(nor);
        if (ret < 0) {
@@ -3911,6 +3912,12 @@ static int spi_nor_setup(struct spi_nor *nor,
 static int spi_nor_init(struct spi_nor *nor)
 {
        int err;
+       u8 val;
+       u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+
+       /* Check current Quad Enable bit value. */
+       val = read_cr(nor);
+       dev_err(nor->dev, "%s val = %02x\n", val);
 
        /*
         * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
@@ -3921,7 +3928,7 @@ static int spi_nor_init(struct spi_nor *nor)
            JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
            nor->info->flags & SPI_NOR_HAS_LOCK) {
                write_enable(nor);
-               write_sr(nor, 0);
+               write_sr(nor, val & ~mask);
                spi_nor_wait_till_ready(nor);
        }
Tudor Ambarus May 7, 2019, 1:18 p.m. UTC | #9
On 05/07/2019 04:15 PM, Tudor Ambarus wrote:
> Geert,
> 
> On 05/07/2019 03:52 PM, Geert Uytterhoeven wrote:
>> External E-Mail
>>
>>
>> Hi Jonas,
>>
>> On Tue, May 7, 2019 at 1:14 PM Jonas Bonn <jonas@norrbonn.se> wrote:
>>> On 07/05/2019 12:50, Geert Uytterhoeven wrote:
>>>> On Tue, May 7, 2019 at 12:42 PM <Tudor.Ambarus@microchip.com> wrote:
>>>>> On 05/07/2019 12:53 PM, Geert Uytterhoeven wrote:
>>>>>> On Wed, Mar 20, 2019 at 8:16 AM Jonas Bonn <jonas@norrbonn.se> wrote:
>>>>>>> Both the BP[0-2] bits and the TBPROT bit are supported on this chip.
>>>>>>> Tested and verified on a Cypress s25fl512s.
>>>>>>>
>>>>>>> Signed-off-by: Jonas Bonn <jonas@norrbonn.se>
>>>>>>
>>>>>> This is now commit dcb4b22eeaf44f91 ("spi-nor: s25fl512s supports region
>>>>>> locking") in mtd/next.
>>>>>>
>>>>>>> --- a/drivers/mtd/spi-nor/spi-nor.c
>>>>>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>>>>>>> @@ -1898,7 +1898,9 @@ static const struct flash_info spi_nor_ids[] = {
>>>>>>>                          SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>>>>>          { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
>>>>>>>          { "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>>>>> -       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
>>>>>>> +       { "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
>>>>>>> +                       SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
>>>>>>> +                       SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
>>>>>>
>>>>>> Setting SPI_NOR_HAS_LOCK causes the QSPI FLASH on r8a7791/koelsch to fail
>>>>>> probing.
>>>>>>
>>>>>> Before/after:
>>>>>>
>>>>>>      -m25p80 spi0.0: s25fl512s (65536 Kbytes)
>>>>>>      -3 fixed-partitions partitions found on MTD device spi0.0
>>>>>>      -Creating 3 MTD partitions on "spi0.0":
>>>>>>      -0x000000000000-0x000000080000 : "loader"
>>>>>>      -0x000000080000-0x000000600000 : "user"
>>>>>>      -0x000000600000-0x000004000000 : "flash"
>>>>>>      +m25p80 spi0.0: Erase Error occurred
>>>>>>      +m25p80 spi0.0: Erase Error occurred
>>>>>>      +m25p80 spi0.0: timeout while writing configuration register
>>>>>>      +m25p80 spi0.0: quad mode not supported
>>>>>>      +m25p80: probe of spi0.0 failed with error -5
>>>>>>
>>>
>>> In drivers/mtd/spi-nor/spi-nor.c you have:
>>>
>>> static int spi_nor_init(struct spi_nor *nor)
>>> {
>>>          int err;
>>>
>>>          /*
>>>           * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
>>>           * with the software protection bits set
>>>           */
>>>          if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
>>>              JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
>>>              JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
>>>              nor->info->flags & SPI_NOR_HAS_LOCK) {
>>>                  write_enable(nor);
>>
>> With more debug prints:
>>
>>     m25p80 spi0.0: spi_nor_init:3925: write_enable() returned 0
>>
>>>                  write_sr(nor, 0);
>>
>>     m25p80 spi0.0: spi_nor_init:3927: write_sr() returned 0
>>
>>>                  spi_nor_wait_till_ready(nor);
>>
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>>                                      ...
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
>>     m25p80 spi0.0: Erase Error occurred
>>     m25p80 spi0.0: spi_nor_init:3929: spi_nor_wait_till_ready() returned -5
>>
>>>          }
>>>
>>>          if (nor->quad_enable) {
>>>                  err = nor->quad_enable(nor);
>>
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
>>     m25p80 spi0.0: Erase Error occurred
>>     m25p80 spi0.0: timeout while writing configuration register
>>     m25p80 spi0.0: spi_nor_init:3937: spansion_quad_enable() returned -5
>>
>>>                  if (err) {
>>>                          dev_err(nor->dev, "quad mode not supported\n");
>>>                          return err;
>>>                  }
>>>          }
>>>
>>> This is the only meaningful thing that I can see may have changed with
>>> this flag.  We now have an additional write_enable before quad_enable.
>>> What happens if you swap those two blocks above so that quad_enable is
>>> called first?
>>
>> With the two blocks swapped:
>>
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x0
>>     m25p80 spi0.0: spi_nor_init:3919: spansion_quad_enable() returned 0
>>     m25p80 spi0.0: spi_nor_init:3937: write_enable() returned 0
>>     m25p80 spi0.0: spi_nor_init:3939: write_sr() returned 0
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0x3
>>                                                                   ...
>>     m25p80 spi0.0: spi_nor_sr_ready:533: sr = 0xff
>>     m25p80 spi0.0: Erase Error occurred
>>     m25p80 spi0.0: spi_nor_init:3941: spi_nor_wait_till_ready() returned -5
>>     m25p80 spi0.0: s25fl512s (65536 Kbytes)
>>     3 fixed-partitions partitions found on MTD device spi0.0
>>     Creating 3 MTD partitions on "spi0.0":
>>     0x000000000000-0x000000080000 : "loader"
>>     0x000000080000-0x000000600000 : "user"
>>     0x000000600000-0x000004000000 : "flash"
>>
>> Note that spi_nor_wait_till_ready() still fails.
>>
>> While the device (which contains the boot loader) now appears to be
>> detected fine, reading returns bogus repetitive data, for all partitions:
>>
>>     # hd /dev/mtd0 | head
>>     00000000  33 33 33 33 33 33 33 33  33 33 3b bb ff ff ff ff
>> |3333333333;.....|
>>     00000010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
>> |................|
>>     *
>>     00001000  33 33 33 33 33 33 33 33  33 33 3b bb ff ff ff ff
>> |3333333333;.....|
>>     00001010  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff
>> |................|
>>     *
>>
>> If I remove the call to "write_sr(nor, 0)", everything works as
>> before, regardless
>> of swapping the blocks.
>>
> 
> Can you try this one?
> 
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 73172d7f512b..b94a6eaaaca5 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -1551,6 +1551,7 @@ static int spansion_read_cr_quad_enable(struct spi_nor *nor)
>         u8 sr_cr[2];
>         int ret;
>  
> +       dev_err(dev, "%s\n", __FUNCTION__);
>         /* Check current Quad Enable bit value. */
>         ret = read_cr(nor);
>         if (ret < 0) {
> @@ -3911,6 +3912,12 @@ static int spi_nor_setup(struct spi_nor *nor,
>  static int spi_nor_init(struct spi_nor *nor)
>  {
>         int err;
> +       u8 val;
> +       u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
> +
> +       /* Check current Quad Enable bit value. */
> +       val = read_cr(nor);
> +       dev_err(nor->dev, "%s val = %02x\n", val);

        dev_err(nor->dev, "%s val = %02x\n", __FUNCTION__, val);

>  
>         /*
>          * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
> @@ -3921,7 +3928,7 @@ static int spi_nor_init(struct spi_nor *nor)
>             JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
>             nor->info->flags & SPI_NOR_HAS_LOCK) {
>                 write_enable(nor);
> -               write_sr(nor, 0);
> +               write_sr(nor, val & ~mask);
>                 spi_nor_wait_till_ready(nor);
>         }
>  
>
Tudor Ambarus May 7, 2019, 1:25 p.m. UTC | #10
On 05/07/2019 04:15 PM, Tudor Ambarus wrote:
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 73172d7f512b..b94a6eaaaca5 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -1551,6 +1551,7 @@ static int spansion_read_cr_quad_enable(struct spi_nor *nor)
>         u8 sr_cr[2];
>         int ret;
>  
> +       dev_err(dev, "%s\n", __FUNCTION__);
>         /* Check current Quad Enable bit value. */
>         ret = read_cr(nor);
>         if (ret < 0) {
> @@ -3911,6 +3912,12 @@ static int spi_nor_setup(struct spi_nor *nor,
>  static int spi_nor_init(struct spi_nor *nor)
>  {
>         int err;
> +       u8 val;
> +       u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
> +
> +       /* Check current Quad Enable bit value. */
> +       val = read_cr(nor);
this should have been:
	val = read_sr(nor);
sorry.

> +       dev_err(nor->dev, "%s val = %02x\n", val);
and here 
	dev_err(nor->dev, "%s val = %02x\n", __FUNCTION__, val);
>  
>         /*
>          * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
> @@ -3921,7 +3928,7 @@ static int spi_nor_init(struct spi_nor *nor)
>             JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
>             nor->info->flags & SPI_NOR_HAS_LOCK) {
>                 write_enable(nor);
> -               write_sr(nor, 0);
> +               write_sr(nor, val & ~mask);
>                 spi_nor_wait_till_ready(nor);
>         }
>
Geert Uytterhoeven May 7, 2019, 2:33 p.m. UTC | #11
Hi Tudor,

On Tue, May 7, 2019 at 3:25 PM <Tudor.Ambarus@microchip.com> wrote:
> On 05/07/2019 04:15 PM, Tudor Ambarus wrote:
> > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> > index 73172d7f512b..b94a6eaaaca5 100644
> > --- a/drivers/mtd/spi-nor/spi-nor.c
> > +++ b/drivers/mtd/spi-nor/spi-nor.c
> > @@ -1551,6 +1551,7 @@ static int spansion_read_cr_quad_enable(struct spi_nor *nor)
> >         u8 sr_cr[2];
> >         int ret;
> >
> > +       dev_err(dev, "%s\n", __FUNCTION__);

This one isn't triggered.

> >         /* Check current Quad Enable bit value. */
> >         ret = read_cr(nor);
> >         if (ret < 0) {
> > @@ -3911,6 +3912,12 @@ static int spi_nor_setup(struct spi_nor *nor,
> >  static int spi_nor_init(struct spi_nor *nor)
> >  {
> >         int err;
> > +       u8 val;
> > +       u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
> > +
> > +       /* Check current Quad Enable bit value. */
> > +       val = read_cr(nor);
> this should have been:
>         val = read_sr(nor);
> sorry.
>
> > +       dev_err(nor->dev, "%s val = %02x\n", val);
> and here
>         dev_err(nor->dev, "%s val = %02x\n", __FUNCTION__, val);

m25p80 spi0.0: spi_nor_init val = 00

so the masking trick doesn't help :-(

Gr{oetje,eeting}s,

                        Geert
Tudor Ambarus May 8, 2019, 10:44 a.m. UTC | #12
Geert,

Would you run this debug patch on top of mtd/next? I dumped the SR and CR before
and after the operations in cause.

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 73172d7f512b..20d0fdb1dc92 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -22,6 +22,8 @@
 #include <linux/spi/flash.h>
 #include <linux/mtd/spi-nor.h>

+#define DEBUG
+
 /* Define max times to check status register before we give up. */

 /*
@@ -200,7 +202,7 @@ struct sfdp_header {
  *         register does not modify status register 2.
  * - 101b: QE is bit 1 of status register 2. Status register 1 is read using
  *         Read Status instruction 05h. Status register2 is read using
- *         instruction 35h. QE is set via Writ Status instruction 01h with
+ *         instruction 35h. QE is set via Write Status instruction 01h with
  *         two data bytes where bit 1 of the second byte is one.
  *         [...]
  */
@@ -2795,8 +2797,11 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 		return err;

 	/* Fix endianness of the BFPT DWORDs. */
-	for (i = 0; i < BFPT_DWORD_MAX; i++)
+	for (i = 0; i < BFPT_DWORD_MAX; i++) {
 		bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]);
+		dev_dbg(nor->dev, "bfpt.dwords[%d] = %08x\n", i + 1,
+			bfpt.dwords[i]);
+	}

 	/* Number of address bytes. */
 	switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
@@ -3532,8 +3537,10 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
 	}

 	err = spi_nor_parse_bfpt(nor, bfpt_header, params);
-	if (err)
+	if (err) {
+		dev_dbg(dev, "failed to parse BFPT: err = %d\n", err);
 		goto exit;
+	}

 	/* Parse optional parameter tables. */
 	for (i = 0; i < header.nph; i++) {
@@ -3576,6 +3583,7 @@ static int spi_nor_init_params(struct spi_nor *nor,
 	struct spi_nor_erase_map *map = &nor->erase_map;
 	const struct flash_info *info = nor->info;
 	u8 i, erase_mask;
+	int ret;

 	/* Set legacy flash parameters as default. */
 	memset(params, 0, sizeof(*params));
@@ -3681,12 +3689,15 @@ static int spi_nor_init_params(struct spi_nor *nor,
 		memcpy(&sfdp_params, params, sizeof(sfdp_params));
 		memcpy(&prev_map, &nor->erase_map, sizeof(prev_map));

-		if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
+		ret = spi_nor_parse_sfdp(nor, &sfdp_params);
+		if (ret) {
 			nor->addr_width = 0;
 			nor->flags &= ~SNOR_F_4B_OPCODES;
 			/* restore previous erase map */
 			memcpy(&nor->erase_map, &prev_map,
 			       sizeof(nor->erase_map));
+			dev_dbg(nor->dev, "%s sfdp parse failed, ret =%d\n",
+				__FUNCTION__, ret);
 		} else {
 			memcpy(params, &sfdp_params, sizeof(*params));
 		}
@@ -3908,9 +3919,67 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return 0;
 }

+static int spi_nor_dump_sr_cr(struct spi_nor *nor)
+{
+	int ret = read_sr(nor);
+
+	dev_dbg(nor->dev, "SR = %08x\n", ret);
+        if (ret < 0) {
+                dev_err(nor->dev, "error while reading status register\n");
+                return ret;
+        }
+
+	ret = read_cr(nor);
+	dev_dbg(nor->dev, "CR = %08x\n", ret);
+        if (ret < 0) {
+                dev_err(nor->dev, "error while reading configuration register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int spi_nor_clear_block_protection(struct spi_nor *nor)
+{
+	int ret;
+	u8 val, mask = SR_BP2 | SR_BP1 | SR_BP0;
+
+	ret = spi_nor_dump_sr_cr(nor);
+	if (ret)
+		return ret;
+
+	/* clear just the BP bits */
+	ret = read_sr(nor);
+        if (ret < 0) {
+                dev_err(nor->dev, "error while reading status register\n");
+                return ret;
+        }
+	val = ret;
+
+	ret = write_enable(nor);
+        if (ret < 0) {
+                dev_err(nor->dev, "error on write enable, err = %d\n", ret);
+                return ret;
+	}
+
+	ret = write_sr(nor, val & ~mask);
+        if (ret < 0) {
+                dev_err(nor->dev, "error on write_sr, err = %d\n", ret);
+                return ret;
+	}
+
+	ret = spi_nor_wait_till_ready(nor);
+        if (ret) {
+                dev_err(nor->dev, "timeout while writing SR, ret = %d\n", ret);
+		return spi_nor_dump_sr_cr(nor);
+        }
+
+	return 0;
+}
+
 static int spi_nor_init(struct spi_nor *nor)
 {
-	int err;
+	int err = 0, quad_err;

 	/*
 	 * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
@@ -3919,18 +3988,38 @@ static int spi_nor_init(struct spi_nor *nor)
 	if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
 	    JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
 	    JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
-	    nor->info->flags & SPI_NOR_HAS_LOCK) {
-		write_enable(nor);
-		write_sr(nor, 0);
-		spi_nor_wait_till_ready(nor);
+	    nor->info->flags & SPI_NOR_HAS_LOCK)
+		/*
+		 * this should be done only on demand, not for every flash that
+		 * has SPI_NOR_HAS_LOCK set
+		 */
+		err = spi_nor_clear_block_protection(nor);
+	if (err) {
+		dev_err(nor->dev, "clearing BP bits failed, err = %d\n", err);
+		return err;
 	}

 	if (nor->quad_enable) {
-		err = nor->quad_enable(nor);
+		dev_dbg(nor->dev, "SR and CR before quad_enable:\n");
+
+		err = spi_nor_dump_sr_cr(nor);
 		if (err) {
-			dev_err(nor->dev, "quad mode not supported\n");
+			dev_err(nor->dev, "dump_sr_cr before quad enable fail, err = %d\n", err);
 			return err;
 		}
+
+		quad_err = nor->quad_enable(nor);
+		dev_dbg(nor->dev, "SR and CR after quad_enable:\n");
+		err = spi_nor_dump_sr_cr(nor);
+		if (err) {
+			dev_err(nor->dev, "dump_sr_cr after quad enable fail, err = %d\n", err);
+			return err;
+		}
+
+		if (quad_err) {
+			dev_err(nor->dev, "quad mode not supported, err = %d\n", quad_err);
+			return quad_err;
+		}
 	}

 	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES)) {
Geert Uytterhoeven May 8, 2019, 1:11 p.m. UTC | #13
Hi Tudor,

On Wed, May 8, 2019 at 12:44 PM <Tudor.Ambarus@microchip.com> wrote:
> Would you run this debug patch on top of mtd/next? I dumped the SR and CR before
> and after the operations in cause.

Thanks, giving it a try...

> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index 73172d7f512b..20d0fdb1dc92 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -22,6 +22,8 @@
>  #include <linux/spi/flash.h>
>  #include <linux/mtd/spi-nor.h>
>
> +#define DEBUG

Should be moved to the top of the file, before dev_dbg() is defined.

Result is:

m25p80 spi0.0: bfpt.dwords[1] = ffffffff
m25p80 spi0.0: bfpt.dwords[2] = ffffffff
m25p80 spi0.0: bfpt.dwords[3] = ffffffff
m25p80 spi0.0: bfpt.dwords[4] = ffffffff
m25p80 spi0.0: bfpt.dwords[5] = ffffffff
m25p80 spi0.0: bfpt.dwords[6] = ffffffff
m25p80 spi0.0: bfpt.dwords[7] = ffffffff
m25p80 spi0.0: bfpt.dwords[8] = ffffffff
m25p80 spi0.0: bfpt.dwords[9] = ffffffff
m25p80 spi0.0: bfpt.dwords[10] = 00000000
m25p80 spi0.0: bfpt.dwords[11] = 00000000
m25p80 spi0.0: bfpt.dwords[12] = 00000000
m25p80 spi0.0: bfpt.dwords[13] = 00000000
m25p80 spi0.0: bfpt.dwords[14] = 00000000
m25p80 spi0.0: bfpt.dwords[15] = 00000000
m25p80 spi0.0: bfpt.dwords[16] = 00000000
m25p80 spi0.0: failed to parse BFPT: err = -22
m25p80 spi0.0: spi_nor_init_params sfdp parse failed, ret =-22
m25p80 spi0.0: SR = 00000000
m25p80 spi0.0: CR = 00000002
m25p80 spi0.0: Erase Error occurred
m25p80 spi0.0: timeout while writing SR, ret = -5
m25p80 spi0.0: SR = 000000ff
m25p80 spi0.0: CR = 000000ff
m25p80 spi0.0: SR and CR before quad_enable:
m25p80 spi0.0: SR = 000000ff
m25p80 spi0.0: CR = 000000ff
m25p80 spi0.0: Erase Error occurred
m25p80 spi0.0: timeout while writing configuration register
m25p80 spi0.0: SR and CR after quad_enable:
m25p80 spi0.0: SR = 000000ff
m25p80 spi0.0: CR = 000000ff
m25p80 spi0.0: quad mode not supported, err = -5
m25p80: probe of spi0.0 failed with error -5

Gr{oetje,eeting}s,

                        Geert
Tudor Ambarus May 8, 2019, 2:23 p.m. UTC | #14
Hi, Geert,

On 05/08/2019 04:11 PM, Geert Uytterhoeven wrote:
> External E-Mail
> 
> 
> Hi Tudor,
> 
> On Wed, May 8, 2019 at 12:44 PM <Tudor.Ambarus@microchip.com> wrote:
>> Would you run this debug patch on top of mtd/next? I dumped the SR and CR before
>> and after the operations in cause.
> 
> Thanks, giving it a try...
> 
>> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
>> index 73172d7f512b..20d0fdb1dc92 100644
>> --- a/drivers/mtd/spi-nor/spi-nor.c
>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>> @@ -22,6 +22,8 @@
>>  #include <linux/spi/flash.h>
>>  #include <linux/mtd/spi-nor.h>
>>
>> +#define DEBUG
> 
> Should be moved to the top of the file, before dev_dbg() is defined.
> 
> Result is:
> 
> m25p80 spi0.0: bfpt.dwords[1] = ffffffff
> m25p80 spi0.0: bfpt.dwords[2] = ffffffff
> m25p80 spi0.0: bfpt.dwords[3] = ffffffff
> m25p80 spi0.0: bfpt.dwords[4] = ffffffff
> m25p80 spi0.0: bfpt.dwords[5] = ffffffff
> m25p80 spi0.0: bfpt.dwords[6] = ffffffff
> m25p80 spi0.0: bfpt.dwords[7] = ffffffff
> m25p80 spi0.0: bfpt.dwords[8] = ffffffff
> m25p80 spi0.0: bfpt.dwords[9] = ffffffff
> m25p80 spi0.0: bfpt.dwords[10] = 00000000
> m25p80 spi0.0: bfpt.dwords[11] = 00000000
> m25p80 spi0.0: bfpt.dwords[12] = 00000000
> m25p80 spi0.0: bfpt.dwords[13] = 00000000
> m25p80 spi0.0: bfpt.dwords[14] = 00000000
> m25p80 spi0.0: bfpt.dwords[15] = 00000000
> m25p80 spi0.0: bfpt.dwords[16] = 00000000
> m25p80 spi0.0: failed to parse BFPT: err = -22
> m25p80 spi0.0: spi_nor_init_params sfdp parse failed, ret =-22
> m25p80 spi0.0: SR = 00000000
> m25p80 spi0.0: CR = 00000002
> m25p80 spi0.0: Erase Error occurred
> m25p80 spi0.0: timeout while writing SR, ret = -5
> m25p80 spi0.0: SR = 000000ff
> m25p80 spi0.0: CR = 000000ff

ff can mean that the lines are "in air", maybe the flash resets when we
write_sr(nor, 0)? How about adding a delay here to let the flash reset?

SR=0 and CR=2 after reset, both write_sr(nor, 0) and quad_enable can be avoided
-> read SR, clear BP bits only if they are set to 1, read CR -> set Quad Enable
bit only when it's zero.

Cheers,
ta

> m25p80 spi0.0: SR and CR before quad_enable:
> m25p80 spi0.0: SR = 000000ff
> m25p80 spi0.0: CR = 000000ff
> m25p80 spi0.0: Erase Error occurred
> m25p80 spi0.0: timeout while writing configuration register
> m25p80 spi0.0: SR and CR after quad_enable:
> m25p80 spi0.0: SR = 000000ff
> m25p80 spi0.0: CR = 000000ff
> m25p80 spi0.0: quad mode not supported, err = -5
> m25p80: probe of spi0.0 failed with error -5
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
>
Geert Uytterhoeven May 8, 2019, 5 p.m. UTC | #15
Hi Tudor,

On Wed, May 8, 2019 at 4:23 PM <Tudor.Ambarus@microchip.com> wrote:
> On 05/08/2019 04:11 PM, Geert Uytterhoeven wrote:
> > On Wed, May 8, 2019 at 12:44 PM <Tudor.Ambarus@microchip.com> wrote:
> >> Would you run this debug patch on top of mtd/next? I dumped the SR and CR before
> >> and after the operations in cause.
> >
> > Thanks, giving it a try...
> >
> >> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> >> index 73172d7f512b..20d0fdb1dc92 100644
> >> --- a/drivers/mtd/spi-nor/spi-nor.c
> >> +++ b/drivers/mtd/spi-nor/spi-nor.c
> >> @@ -22,6 +22,8 @@
> >>  #include <linux/spi/flash.h>
> >>  #include <linux/mtd/spi-nor.h>
> >>
> >> +#define DEBUG
> >
> > Should be moved to the top of the file, before dev_dbg() is defined.
> >
> > Result is:
> >
> > m25p80 spi0.0: bfpt.dwords[1] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[2] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[3] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[4] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[5] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[6] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[7] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[8] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[9] = ffffffff
> > m25p80 spi0.0: bfpt.dwords[10] = 00000000
> > m25p80 spi0.0: bfpt.dwords[11] = 00000000
> > m25p80 spi0.0: bfpt.dwords[12] = 00000000
> > m25p80 spi0.0: bfpt.dwords[13] = 00000000
> > m25p80 spi0.0: bfpt.dwords[14] = 00000000
> > m25p80 spi0.0: bfpt.dwords[15] = 00000000
> > m25p80 spi0.0: bfpt.dwords[16] = 00000000
> > m25p80 spi0.0: failed to parse BFPT: err = -22
> > m25p80 spi0.0: spi_nor_init_params sfdp parse failed, ret =-22
> > m25p80 spi0.0: SR = 00000000
> > m25p80 spi0.0: CR = 00000002
> > m25p80 spi0.0: Erase Error occurred
> > m25p80 spi0.0: timeout while writing SR, ret = -5
> > m25p80 spi0.0: SR = 000000ff
> > m25p80 spi0.0: CR = 000000ff
>
> ff can mean that the lines are "in air", maybe the flash resets when we
> write_sr(nor, 0)? How about adding a delay here to let the flash reset?

No difference after adding msleep(1000).

Gr{oetje,eeting}s,

                        Geert
Tudor Ambarus May 9, 2019, 6:55 a.m. UTC | #16
Hi, Geert,

On 05/08/2019 08:00 PM, Geert Uytterhoeven wrote:
> External E-Mail
> 
> 
> Hi Tudor,>
> On Wed, May 8, 2019 at 4:23 PM <Tudor.Ambarus@microchip.com> wrote:
>> On 05/08/2019 04:11 PM, Geert Uytterhoeven wrote:
>>> On Wed, May 8, 2019 at 12:44 PM <Tudor.Ambarus@microchip.com> wrote:
>>>> Would you run this debug patch on top of mtd/next? I dumped the SR and CR before
>>>> and after the operations in cause.
>>>
>>> Thanks, giving it a try...
>>>
>>>> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
>>>> index 73172d7f512b..20d0fdb1dc92 100644
>>>> --- a/drivers/mtd/spi-nor/spi-nor.c
>>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>>>> @@ -22,6 +22,8 @@
>>>>  #include <linux/spi/flash.h>
>>>>  #include <linux/mtd/spi-nor.h>
>>>>
>>>> +#define DEBUG
>>>
>>> Should be moved to the top of the file, before dev_dbg() is defined.
>>>
>>> Result is:
>>>
>>> m25p80 spi0.0: bfpt.dwords[1] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[2] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[3] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[4] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[5] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[6] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[7] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[8] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[9] = ffffffff
>>> m25p80 spi0.0: bfpt.dwords[10] = 00000000
>>> m25p80 spi0.0: bfpt.dwords[11] = 00000000
>>> m25p80 spi0.0: bfpt.dwords[12] = 00000000
>>> m25p80 spi0.0: bfpt.dwords[13] = 00000000
>>> m25p80 spi0.0: bfpt.dwords[14] = 00000000
>>> m25p80 spi0.0: bfpt.dwords[15] = 00000000
>>> m25p80 spi0.0: bfpt.dwords[16] = 00000000
>>> m25p80 spi0.0: failed to parse BFPT: err = -22
>>> m25p80 spi0.0: spi_nor_init_params sfdp parse failed, ret =-22
>>> m25p80 spi0.0: SR = 00000000
>>> m25p80 spi0.0: CR = 00000002
>>> m25p80 spi0.0: Erase Error occurred
>>> m25p80 spi0.0: timeout while writing SR, ret = -5
>>> m25p80 spi0.0: SR = 000000ff
>>> m25p80 spi0.0: CR = 000000ff
>>
>> ff can mean that the lines are "in air", maybe the flash resets when we
>> write_sr(nor, 0)? How about adding a delay here to let the flash reset?
> 
> No difference after adding msleep(1000).
> 

When the configuration register QUAD bit CR[1] is 1, only the WRR command format
with 16 data bits may be used, WRR with 8 bits is not recognized and hence the
FFs. You probably set quad bit in u-boot, while others don't. We can verify this
assumption with the patch form below. Can you try it?

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 73172d7f512b..0d636eab3ebf 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2005, Intec Automation Inc.
  * Copyright (C) 2014, Freescale Semiconductor, Inc.
  */
+#define DEBUG

 #include <linux/err.h>
 #include <linux/errno.h>
@@ -200,7 +201,7 @@ struct sfdp_header {
  *         register does not modify status register 2.
  * - 101b: QE is bit 1 of status register 2. Status register 1 is read using
  *         Read Status instruction 05h. Status register2 is read using
- *         instruction 35h. QE is set via Writ Status instruction 01h with
+ *         instruction 35h. QE is set via Write Status instruction 01h with
  *         two data bytes where bit 1 of the second byte is one.
  *         [...]
  */
@@ -2795,8 +2796,11 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor,
 		return err;

 	/* Fix endianness of the BFPT DWORDs. */
-	for (i = 0; i < BFPT_DWORD_MAX; i++)
+	for (i = 0; i < BFPT_DWORD_MAX; i++) {
 		bfpt.dwords[i] = le32_to_cpu(bfpt.dwords[i]);
+		dev_dbg(nor->dev, "bfpt.dwords[%d] = %08x\n", i + 1,
+			bfpt.dwords[i]);
+	}

 	/* Number of address bytes. */
 	switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
@@ -3532,8 +3536,10 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,
 	}

 	err = spi_nor_parse_bfpt(nor, bfpt_header, params);
-	if (err)
+	if (err) {
+		dev_dbg(dev, "failed to parse BFPT: err = %d\n", err);
 		goto exit;
+	}

 	/* Parse optional parameter tables. */
 	for (i = 0; i < header.nph; i++) {
@@ -3576,6 +3582,7 @@ static int spi_nor_init_params(struct spi_nor *nor,
 	struct spi_nor_erase_map *map = &nor->erase_map;
 	const struct flash_info *info = nor->info;
 	u8 i, erase_mask;
+	int ret;

 	/* Set legacy flash parameters as default. */
 	memset(params, 0, sizeof(*params));
@@ -3681,12 +3688,15 @@ static int spi_nor_init_params(struct spi_nor *nor,
 		memcpy(&sfdp_params, params, sizeof(sfdp_params));
 		memcpy(&prev_map, &nor->erase_map, sizeof(prev_map));

-		if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
+		ret = spi_nor_parse_sfdp(nor, &sfdp_params);
+		if (ret) {
 			nor->addr_width = 0;
 			nor->flags &= ~SNOR_F_4B_OPCODES;
 			/* restore previous erase map */
 			memcpy(&nor->erase_map, &prev_map,
 			       sizeof(nor->erase_map));
+			dev_dbg(nor->dev, "%s sfdp parse failed, ret =%d\n",
+				__FUNCTION__, ret);
 		} else {
 			memcpy(params, &sfdp_params, sizeof(*params));
 		}
@@ -3908,9 +3918,86 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return 0;
 }

+static int spi_nor_dump_sr_cr(struct spi_nor *nor)
+{
+	int ret = read_sr(nor);
+
+	dev_dbg(nor->dev, "SR = %08x\n", ret);
+        if (ret < 0) {
+                dev_err(nor->dev, "error while reading status register\n");
+                return ret;
+        }
+
+	ret = read_cr(nor);
+	dev_dbg(nor->dev, "CR = %08x\n", ret);
+        if (ret < 0) {
+                dev_err(nor->dev, "error while reading configuration register\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int spi_nor_clear_block_protection(struct spi_nor *nor)
+{
+	int ret;
+	u8 sr, cr, sr_cr[2] = {0};
+	u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+
+	ret = read_cr(nor);
+	dev_dbg(nor->dev, "CR = %08x\n", ret);
+        if (ret < 0) {
+                dev_err(nor->dev, "error while reading CR\n");
+		return ret;
+	}
+	cr = ret;
+
+	if (cr & CR_QUAD_EN_SPAN) {
+		/* disable quad if already set, must do it with 16-bit WRR */
+		ret = write_sr_cr(nor, sr_cr);
+		if (ret) {
+			dev_err(nor->dev, "error diasbling quad mode\n");
+			return ret;
+		}
+
+		/* read back and check it */
+		ret = read_cr(nor);
+		if (ret >= 0 && (ret & CR_QUAD_EN_SPAN)) {
+			dev_err(nor->dev, "Spansion Quad bit not cleared\n");
+			return -EINVAL;
+		}
+	}
+
+	/* Clear BP bits with 8-bit WRR */
+	ret = read_sr(nor);
+	dev_dbg(nor->dev, "SR = %08x\n", ret);
+	if (ret < 0) {
+		dev_err(nor->dev, "error while reading SR\n");
+                return ret;
+	}
+	sr = ret;
+
+	ret = write_enable(nor);
+        if (ret < 0) {
+                dev_err(nor->dev, "error on write enable, err = %d\n", ret);
+                return ret;
+	}
+
+	ret = write_sr(nor, sr & ~mask);
+        if (ret < 0) {
+                dev_err(nor->dev, "error on write_sr, err = %d\n", ret);
+                return ret;
+	}
+
+	ret = spi_nor_wait_till_ready(nor);
+        if (ret)
+                dev_err(nor->dev, "timeout while writing SR, ret = %d\n", ret);
+	return spi_nor_dump_sr_cr(nor);
+}
+
 static int spi_nor_init(struct spi_nor *nor)
 {
-	int err;
+	int err = 0, quad_err;

 	/*
 	 * Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up
@@ -3919,18 +4006,38 @@ static int spi_nor_init(struct spi_nor *nor)
 	if (JEDEC_MFR(nor->info) == SNOR_MFR_ATMEL ||
 	    JEDEC_MFR(nor->info) == SNOR_MFR_INTEL ||
 	    JEDEC_MFR(nor->info) == SNOR_MFR_SST ||
-	    nor->info->flags & SPI_NOR_HAS_LOCK) {
-		write_enable(nor);
-		write_sr(nor, 0);
-		spi_nor_wait_till_ready(nor);
+	    nor->info->flags & SPI_NOR_HAS_LOCK)
+		/*
+		 * this should be done only on demand, not for every flash that
+		 * has SPI_NOR_HAS_LOCK set
+		 */
+		err = spi_nor_clear_block_protection(nor);
+	if (err) {
+		dev_err(nor->dev, "clearing BP bits failed, err = %d\n", err);
+		return err;
 	}

 	if (nor->quad_enable) {
-		err = nor->quad_enable(nor);
+		dev_dbg(nor->dev, "SR and CR before quad_enable:\n");
+
+		err = spi_nor_dump_sr_cr(nor);
 		if (err) {
-			dev_err(nor->dev, "quad mode not supported\n");
+			dev_err(nor->dev, "dump_sr_cr before quad enable fail, err = %d\n", err);
 			return err;
 		}
+
+		quad_err = nor->quad_enable(nor);
+		dev_dbg(nor->dev, "SR and CR after quad_enable:\n");
+		err = spi_nor_dump_sr_cr(nor);
+		if (err) {
+			dev_err(nor->dev, "dump_sr_cr after quad enable fail, err = %d\n", err);
+			return err;
+		}
+
+		if (quad_err) {
+			dev_err(nor->dev, "quad mode not supported, err = %d\n", quad_err);
+			return quad_err;
+		}
 	}

 	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES)) {
Geert Uytterhoeven May 9, 2019, 9:11 a.m. UTC | #17
Hi Tudor,

On Thu, May 9, 2019 at 8:56 AM <Tudor.Ambarus@microchip.com> wrote:
> When the configuration register QUAD bit CR[1] is 1, only the WRR command format
> with 16 data bits may be used, WRR with 8 bits is not recognized and hence the
> FFs. You probably set quad bit in u-boot, while others don't. We can verify this
> assumption with the patch form below. Can you try it?

Thanks!

> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c

> +static int spi_nor_clear_block_protection(struct spi_nor *nor)
> +{
> +       int ret;
> +       u8 sr, cr, sr_cr[2] = {0};
> +       u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
> +
> +       ret = read_cr(nor);
> +       dev_dbg(nor->dev, "CR = %08x\n", ret);
> +        if (ret < 0) {
> +                dev_err(nor->dev, "error while reading CR\n");
> +               return ret;
> +       }
> +       cr = ret;
> +
> +       if (cr & CR_QUAD_EN_SPAN) {
> +               /* disable quad if already set, must do it with 16-bit WRR */
> +               ret = write_sr_cr(nor, sr_cr);
> +               if (ret) {
> +                       dev_err(nor->dev, "error diasbling quad mode\n");

disabling

> +                       return ret;
> +               }

renesas_spi e6b10000.spi: DMA available
renesas_spi e6b10000.spi: registered master spi0
spi spi0.0: setup mode 3, 8 bits/w, 30000000 Hz max --> 0
m25p80 spi0.0: bfpt.dwords[1] = ffffffff
m25p80 spi0.0: bfpt.dwords[2] = ffffffff
m25p80 spi0.0: bfpt.dwords[3] = ffffffff
m25p80 spi0.0: bfpt.dwords[4] = ffffffff
m25p80 spi0.0: bfpt.dwords[5] = ffffffff
m25p80 spi0.0: bfpt.dwords[6] = ffffffff
m25p80 spi0.0: bfpt.dwords[7] = ffffffff
m25p80 spi0.0: bfpt.dwords[8] = ffffffff
m25p80 spi0.0: bfpt.dwords[9] = ffffffff
m25p80 spi0.0: bfpt.dwords[10] = 00000000
m25p80 spi0.0: bfpt.dwords[11] = 00000000
m25p80 spi0.0: bfpt.dwords[12] = 00000000
m25p80 spi0.0: bfpt.dwords[13] = 00000000
m25p80 spi0.0: bfpt.dwords[14] = 00000000
m25p80 spi0.0: bfpt.dwords[15] = 00000000
m25p80 spi0.0: bfpt.dwords[16] = 00000000
m25p80 spi0.0: failed to parse BFPT: err = -22
m25p80 spi0.0: spi_nor_init_params sfdp parse failed, ret =-22
m25p80 spi0.0: SR and CR before quad_enable:
m25p80 spi0.0: SR = 00000000
m25p80 spi0.0: CR = 00000002
m25p80 spi0.0: SR and CR after quad_enable:
m25p80 spi0.0: SR = 00000000
m25p80 spi0.0: CR = 00000002
m25p80 spi0.0: s25fl512s (65536 Kbytes)
m25p80 spi0.0: mtd .name = spi0.0, .size = 0x4000000 (64MiB),
.erasesize = 0x00040000 (256KiB) .numeraseregions = 0
3 fixed-partitions partitions found on MTD device spi0.0
Creating 3 MTD partitions on "spi0.0":
0x000000000000-0x000000080000 : "loader"
0x000000080000-0x000000600000 : "user"
0x000000600000-0x000004000000 : "flash"
renesas_spi e6b10000.spi: registered child spi0.0
renesas_spi e6b10000.spi: probed

And /dev/mtd0 reading works fine.
Thanks!

Gr{oetje,eeting}s,

                        Geert
Tudor Ambarus May 9, 2019, 10:31 a.m. UTC | #18
Hi, Geert,

On 05/09/2019 12:11 PM, Geert Uytterhoeven wrote:
> External E-Mail
> 
> 
> Hi Tudor,
> 
> On Thu, May 9, 2019 at 8:56 AM <Tudor.Ambarus@microchip.com> wrote:
>> When the configuration register QUAD bit CR[1] is 1, only the WRR command format
>> with 16 data bits may be used, WRR with 8 bits is not recognized and hence the
>> FFs. You probably set quad bit in u-boot, while others don't. We can verify this
>> assumption with the patch form below. Can you try it?
> 
> Thanks!
> 
>> --- a/drivers/mtd/spi-nor/spi-nor.c
>> +++ b/drivers/mtd/spi-nor/spi-nor.c
> 
>> +static int spi_nor_clear_block_protection(struct spi_nor *nor)
>> +{
>> +       int ret;
>> +       u8 sr, cr, sr_cr[2] = {0};
>> +       u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
>> +
>> +       ret = read_cr(nor);
>> +       dev_dbg(nor->dev, "CR = %08x\n", ret);
>> +        if (ret < 0) {
>> +                dev_err(nor->dev, "error while reading CR\n");
>> +               return ret;
>> +       }
>> +       cr = ret;
>> +
>> +       if (cr & CR_QUAD_EN_SPAN) {
>> +               /* disable quad if already set, must do it with 16-bit WRR */
>> +               ret = write_sr_cr(nor, sr_cr);
>> +               if (ret) {
>> +                       dev_err(nor->dev, "error diasbling quad mode\n");
> 
> disabling
> 
>> +                       return ret;
>> +               }
> 
> renesas_spi e6b10000.spi: DMA available
> renesas_spi e6b10000.spi: registered master spi0
> spi spi0.0: setup mode 3, 8 bits/w, 30000000 Hz max --> 0
> m25p80 spi0.0: bfpt.dwords[1] = ffffffff
> m25p80 spi0.0: bfpt.dwords[2] = ffffffff
> m25p80 spi0.0: bfpt.dwords[3] = ffffffff
> m25p80 spi0.0: bfpt.dwords[4] = ffffffff
> m25p80 spi0.0: bfpt.dwords[5] = ffffffff
> m25p80 spi0.0: bfpt.dwords[6] = ffffffff
> m25p80 spi0.0: bfpt.dwords[7] = ffffffff
> m25p80 spi0.0: bfpt.dwords[8] = ffffffff
> m25p80 spi0.0: bfpt.dwords[9] = ffffffff
> m25p80 spi0.0: bfpt.dwords[10] = 00000000
> m25p80 spi0.0: bfpt.dwords[11] = 00000000
> m25p80 spi0.0: bfpt.dwords[12] = 00000000
> m25p80 spi0.0: bfpt.dwords[13] = 00000000
> m25p80 spi0.0: bfpt.dwords[14] = 00000000
> m25p80 spi0.0: bfpt.dwords[15] = 00000000
> m25p80 spi0.0: bfpt.dwords[16] = 00000000
> m25p80 spi0.0: failed to parse BFPT: err = -22
> m25p80 spi0.0: spi_nor_init_params sfdp parse failed, ret =-22
> m25p80 spi0.0: SR and CR before quad_enable:
> m25p80 spi0.0: SR = 00000000
> m25p80 spi0.0: CR = 00000002
> m25p80 spi0.0: SR and CR after quad_enable:
> m25p80 spi0.0: SR = 00000000
> m25p80 spi0.0: CR = 00000002
> m25p80 spi0.0: s25fl512s (65536 Kbytes)
> m25p80 spi0.0: mtd .name = spi0.0, .size = 0x4000000 (64MiB),
> .erasesize = 0x00040000 (256KiB) .numeraseregions = 0
> 3 fixed-partitions partitions found on MTD device spi0.0
> Creating 3 MTD partitions on "spi0.0":
> 0x000000000000-0x000000080000 : "loader"
> 0x000000080000-0x000000600000 : "user"
> 0x000000600000-0x000004000000 : "flash"
> renesas_spi e6b10000.spi: registered child spi0.0
> renesas_spi e6b10000.spi: probed
> 
> And /dev/mtd0 reading works fine.
> Thanks!
> 

I'm glad that it worked, thanks for the help. I'll do a patch to fix this case,
but probably it will qualify for -next. Is -next ok for you?

Cheers,
ta
Geert Uytterhoeven May 9, 2019, 11:12 a.m. UTC | #19
Hi Tudor,

On Thu, May 9, 2019 at 12:31 PM <Tudor.Ambarus@microchip.com> wrote:
> On 05/09/2019 12:11 PM, Geert Uytterhoeven wrote:
> > On Thu, May 9, 2019 at 8:56 AM <Tudor.Ambarus@microchip.com> wrote:
> >> When the configuration register QUAD bit CR[1] is 1, only the WRR command format
> >> with 16 data bits may be used, WRR with 8 bits is not recognized and hence the
> >> FFs. You probably set quad bit in u-boot, while others don't. We can verify this
> >> assumption with the patch form below. Can you try it?
> >
> > And /dev/mtd0 reading works fine.
> > Thanks!
> >
>
> I'm glad that it worked, thanks for the help. I'll do a patch to fix this case,
> but probably it will qualify for -next. Is -next ok for you?

Given the issue is present only in -next, fixing it in -next is fine for me.
Thanks!

Gr{oetje,eeting}s,

                        Geert
Raghavendra, Vignesh May 9, 2019, 3:57 p.m. UTC | #20
Hi Tudor,

On 09/05/19 4:01 PM, Tudor.Ambarus@microchip.com wrote:
[...]
>>
>>> --- a/drivers/mtd/spi-nor/spi-nor.c
>>> +++ b/drivers/mtd/spi-nor/spi-nor.c
>>
>>> +static int spi_nor_clear_block_protection(struct spi_nor *nor)
>>> +{
>>> +       int ret;
>>> +       u8 sr, cr, sr_cr[2] = {0};
>>> +       u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
>>> +
>>> +       ret = read_cr(nor);
>>> +       dev_dbg(nor->dev, "CR = %08x\n", ret);
>>> +        if (ret < 0) {
>>> +                dev_err(nor->dev, "error while reading CR\n");
>>> +               return ret;
>>> +       }
>>> +       cr = ret;
>>> +
>>> +       if (cr & CR_QUAD_EN_SPAN) {
>>> +               /* disable quad if already set, must do it with 16-bit WRR */
>>> +               ret = write_sr_cr(nor, sr_cr);
>>> +               if (ret) {
>>> +                       dev_err(nor->dev, "error diasbling quad mode\n");
>>
>> disabling
>>
>>> +                       return ret;
>>> +               }
>>
>> renesas_spi e6b10000.spi: DMA available
>> renesas_spi e6b10000.spi: registered master spi0
>> spi spi0.0: setup mode 3, 8 bits/w, 30000000 Hz max --> 0
>> m25p80 spi0.0: bfpt.dwords[1] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[2] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[3] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[4] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[5] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[6] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[7] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[8] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[9] = ffffffff
>> m25p80 spi0.0: bfpt.dwords[10] = 00000000
>> m25p80 spi0.0: bfpt.dwords[11] = 00000000
>> m25p80 spi0.0: bfpt.dwords[12] = 00000000
>> m25p80 spi0.0: bfpt.dwords[13] = 00000000
>> m25p80 spi0.0: bfpt.dwords[14] = 00000000
>> m25p80 spi0.0: bfpt.dwords[15] = 00000000
>> m25p80 spi0.0: bfpt.dwords[16] = 00000000
>> m25p80 spi0.0: failed to parse BFPT: err = -22
>> m25p80 spi0.0: spi_nor_init_params sfdp parse failed, ret =-22
>> m25p80 spi0.0: SR and CR before quad_enable:
>> m25p80 spi0.0: SR = 00000000
>> m25p80 spi0.0: CR = 00000002
>> m25p80 spi0.0: SR and CR after quad_enable:
>> m25p80 spi0.0: SR = 00000000
>> m25p80 spi0.0: CR = 00000002
>> m25p80 spi0.0: s25fl512s (65536 Kbytes)
>> m25p80 spi0.0: mtd .name = spi0.0, .size = 0x4000000 (64MiB),
>> .erasesize = 0x00040000 (256KiB) .numeraseregions = 0
>> 3 fixed-partitions partitions found on MTD device spi0.0
>> Creating 3 MTD partitions on "spi0.0":
>> 0x000000000000-0x000000080000 : "loader"
>> 0x000000080000-0x000000600000 : "user"
>> 0x000000600000-0x000004000000 : "flash"
>> renesas_spi e6b10000.spi: registered child spi0.0
>> renesas_spi e6b10000.spi: probed
>>
>> And /dev/mtd0 reading works fine.
>> Thanks!
>>
> 
> I'm glad that it worked, thanks for the help. I'll do a patch to fix this case,
> but probably it will qualify for -next. Is -next ok for you?

I think this fix should be forwarded to v5.2-rc1 (or -rc2 at least) as
patch in question ("spi-nor: s25fl512s supports region locking") is part
of SPI NOR pull request for v5.2-rc1 and therefore would end up in
mainline v5.2-rc1 during the merge window.
Tudor Ambarus May 22, 2019, 3:49 p.m. UTC | #21
Hi, Geert,

On 05/09/2019 02:12 PM, Geert Uytterhoeven wrote:
> External E-Mail
> 
> 
> Hi Tudor,
> 
> On Thu, May 9, 2019 at 12:31 PM <Tudor.Ambarus@microchip.com> wrote:
>> On 05/09/2019 12:11 PM, Geert Uytterhoeven wrote:
>>> On Thu, May 9, 2019 at 8:56 AM <Tudor.Ambarus@microchip.com> wrote:
>>>> When the configuration register QUAD bit CR[1] is 1, only the WRR command format
>>>> with 16 data bits may be used, WRR with 8 bits is not recognized and hence the
>>>> FFs. You probably set quad bit in u-boot, while others don't. We can verify this
>>>> assumption with the patch form below. Can you try it?
>>>
>>> And /dev/mtd0 reading works fine.
>>> Thanks!
>>>
>>
>> I'm glad that it worked, thanks for the help. I'll do a patch to fix this case,
>> but probably it will qualify for -next. Is -next ok for you?
> 
> Given the issue is present only in -next, fixing it in -next is fine for me.
> Thanks!
> 

I've started working to squash the bug discovered by this patch. spi-nor flashes
from different manufacturers have widely different configurations for status and
configuration registers. I have a work in progress patch, backward compatibility
requirements increased code complexity. I'll be out of office and will return on
3rd of June. Probably I will not finish it today, this is to inform you (and
others) that I'll be inactive next week.

Cheers,
ta
diff mbox series

Patch

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index 0cc0ef4fbf3a..9abac9e326a1 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -1898,7 +1898,9 @@  static const struct flash_info spi_nor_ids[] = {
 			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
 	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
 	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
+	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
+			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | USE_CLSR) },
 	{ "s25fs512s",  INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
 	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
 	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },