Raspberry Pi spidev failure

Message ID em9bf40c86-539e-4201-954b-fa819f9193c3@pazuzu
State New
Headers show
Series
  • Raspberry Pi spidev failure
Related show

Commit Message

Sean Cross Nov. 21, 2018, 7:49 a.m.
Hi,

I got this email from a mailing list somewhere.  I'm experiencing an 
issue where I'm unable to flash using spidev on a Raspberry Pi.

I'm running "4.14.79-1.rpi.fc27.armv7hl", which is based on Fedberry.  
I'm experiencing two issues:

1) I'm completely unable to access any SPI chips.  This appears to be 
due to a bug in the kernel driver, which always yanks the CS line high 
despite the cs_change set to 0.  A workaround I've come up with is to do 
everything as a single transaction, which seems to fix the problem on my 
device:


@@ -203,15 +201,14 @@ static int linux_spi_send_command(struct flashctx 
*flash, unsigned int writecnt,

         /* Just submit the first (write) request in case there is 
nothing
            to read. Otherwise submit both requests. */
- if (readcnt == 0)
- iocontrol_code = SPI_IOC_MESSAGE(1);
- else
- iocontrol_code = SPI_IOC_MESSAGE(2);
+ iocontrol_code = SPI_IOC_MESSAGE(1);

         if (ioctl(fd, iocontrol_code, msg) == -1) {
                 msg_cerr("%s: ioctl: %s\n", __func__, strerror(errno));
                 return -1;
         }
+
+ memcpy(rxbuf, tmp_buf + writecnt, readcnt);
         return 0;
  }

-------------------

2) The other issue is that my device appears to want SPI_MODE_1.  When I 
set SPI_MODE_1, it is able to detect and program the board, but fails to 
verify.  The image that gets loaded still works, but I'm unsure of 
what's causing the issue.

I can do some more debugging, but changing SPI_MODE_1 and applying the 
above-mentioned patch solves the issue for me.


Sean

Comments

Nico Huber Nov. 22, 2018, 9:28 a.m. | #1
Hi Sean,

> 1) I'm completely unable to access any SPI chips.  This appears to be
> due to a bug in the kernel driver, which always yanks the CS line high
> despite the cs_change set to 0.  A workaround I've come up with is to do
> everything as a single transaction, which seems to fix the problem on my
> device:

what you describe should be impossible, theoretically. CS high means do
nothing. If it stays that way it wouldn't matter if you do everything in
a single long "do nothing" or in separate shorter ones.

So... how do you sample the CS line?

And at which speed do you run the SPI bus? i.e. the `spispeed` parameter
to flashrom's linux_spi driver. If you didn't set any, it might just be
too fast.

> 2) The other issue is that my device appears to want SPI_MODE_1.  When I
> set SPI_MODE_1, it is able to detect and program the board, but fails to
> verify.  The image that gets loaded still works, but I'm unsure of
> what's causing the issue.

What device is it?

Nico
Sean Cross Nov. 22, 2018, 9:46 a.m. | #2
------ Original Message ------
From: "Nico Huber" <nico.h@gmx.de>
To: "Sean Cross" <sean@xobs.io>; flashrom@flashrom.org
Sent: 22/11/2018 5:28:37 PM
Subject: Re: [flashrom] Raspberry Pi spidev failure

>Hi Sean,
>
>>1) I'm completely unable to access any SPI chips.  This appears to be
>>due to a bug in the kernel driver, which always yanks the CS line high
>>despite the cs_change set to 0.  A workaround I've come up with is to 
>>do
>>everything as a single transaction, which seems to fix the problem on 
>>my
>>device:
>
>what you describe should be impossible, theoretically. CS high means do
>nothing. If it stays that way it wouldn't matter if you do everything 
>in
>a single long "do nothing" or in separate shorter ones.
>
>So... how do you sample the CS line?
>
>And at which speed do you run the SPI bus? i.e. the `spispeed` 
>parameter
>to flashrom's linux_spi driver. If you didn't set any, it might just be
>too fast.
I've attached a png where I measure both the clock and the CS line.  
This is the result of running the command:

  ./flashrom -c W25Q128.V..M --programmer 
linux_spi:dev=/dev/spidev0.0,spispeed=1000

You can see the first 8-bit command gets sent, followed by CS getting 
driven high, and then low again when it clocks in the 24-bit response.  
Because CS went high, the response came back as all 1s.

With the patch I sent CS does not go high, and so flashrom is able to 
work.

>
>>2) The other issue is that my device appears to want SPI_MODE_1.  When 
>>I
>>set SPI_MODE_1, it is able to detect and program the board, but fails 
>>to
>>verify.  The image that gets loaded still works, but I'm unsure of
>>what's causing the issue.
>
>What device is it?
This is a W25Q128JV.  The reference manual reports that it should work 
with SPI_MODE_0 or SPI_MODE_3, so it's odd that it works only in MODE_1. 
  I suspect there is something seriously wrong with the Raspberry Pi 
kernel here.


Sean
Nico Huber Nov. 22, 2018, 10:50 a.m. | #3
Hi,

Am 22.11.18 um 10:46 schrieb Sean Cross:
>>> 1) I'm completely unable to access any SPI chips.  This appears to be
>>> due to a bug in the kernel driver, which always yanks the CS line high
>>> despite the cs_change set to 0.  A workaround I've come up with is to do
>>> everything as a single transaction, which seems to fix the problem on my
>>> device:
>>
>> what you describe should be impossible, theoretically. CS high means do
>> nothing. If it stays that way it wouldn't matter if you do everything in
>> a single long "do nothing" or in separate shorter ones.
>>
>> So... how do you sample the CS line?
>>
>> And at which speed do you run the SPI bus? i.e. the `spispeed` parameter
>> to flashrom's linux_spi driver. If you didn't set any, it might just be
>> too fast.
> I've attached a png where I measure both the clock and the CS line.

thanks. Turns out I completely misunderstood you the first time (my bad,
my English failed at "yanks [...] high").

>>> 2) The other issue is that my device appears to want SPI_MODE_1.  When I
>>> set SPI_MODE_1, it is able to detect and program the board, but fails to
>>> verify.  The image that gets loaded still works, but I'm unsure of
>>> what's causing the issue.
>>
>> What device is it?
> This is a W25Q128JV.  The reference manual reports that it should work
> with SPI_MODE_0 or SPI_MODE_3, so it's odd that it works only in MODE_1.
>  I suspect there is something seriously wrong with the Raspberry Pi
> kernel here.

I agree, ignoring `.cs_change = 0` is a clear violation of the inter-
face.

IIRC, choosing MODE_1 over MODE_0 would shift MISO/MOSI half a clock,
right? That it works in the wrong mode, could be a physical issue. If
you'd sample MOSI and clock together without anything else connected
(i.e. not even the flash chip) that might show us if the driver works
correctly.

If you happen to find the code for that kernel, or can reproduce the
problem with a vanilla kernel, I'd like to have a look at the code
(wouldn't be the first time I have to check what they broke). Though,
I'd have expected 4.14 to work (just by its age). But maybe other
distributions just include fixes that Fedora lacks.

Nico

Patch

diff --git a/linux_spi.c b/linux_spi.c
index 3e60492..50f8220 100644
--- a/linux_spi.c
+++ b/linux_spi.c
@@ -183,14 +183,12 @@  static int linux_spi_send_command(struct flashctx 
*flash, unsigned int writecnt,
                                   unsigned char *rxbuf)
  {
         int iocontrol_code;
+ char tmp_buf[readcnt + writecnt];
         struct spi_ioc_transfer msg[2] = {
                 {
                         .tx_buf = (uint64_t)(uintptr_t)txbuf,
- .len = writecnt,
- },
- {
- .rx_buf = (uint64_t)(uintptr_t)rxbuf,
- .len = readcnt,
+ .rx_buf = (uint64_t)(uintptr_t)tmp_buf,
+ .len = writecnt+readcnt,
                 },
         };