On 03/27/2016 02:10 AM, Iru Cai wrote:
> Thanks for this patch, and I can use flashrom in Cubieboard with the
> patch v6 and mainline kernel.
> 
> However, there's still some problems. I flashed a chip off the board and
> it works well, but when I read a chip on a mainboard twice, the result
> is different. Is there something wrong with the SPI driver, or is it a
> hardware issue?

This worked for both reads and writes a few years back when I wrote it
against 3.1x, but it is possible that regressions have since been
introduced. If you want to rule out hardware issues, try to probe the
chip out-of-circuit (but make sure you pull WP and HOLD pins appropriately).

Personally, I think there's some other device on the board interfering
with the SPI master.

Alex

> 在 2014年3月18日星期二 UTC+8上午9:28:26,mrnuke写道:
> 
>     From c541c363b339d145f326747db5a3b0fabce2780a Mon Sep 17 00:00:00 2001
>     From: Alexandru Gagniuc <[email protected] <javascript:>>
>     Date: Mon, 17 Mar 2014 20:08:05 -0500
>     Subject: [PATCH] NOTFORMERGE: ARM: sun4i: spi: Allow transfers
>     larger than
>      FIFO size
> 
>     SPI transfers were limited to one FIFO depth, which is 64 bytes.
>     This was an artificial limitation, however, as the hardware can handle
>     much larger bursts. To accommodate this, we enable the interrupt when
>     the Rx FIFO is 3/4 full, and drain the FIFO within the interrupt
>     handler. The 3/4 ratio was chosen arbitrarily, with the intention to
>     reduce the potential number of interrupts.
> 
>     Since the SUN4I_CTL_TP bit is set, the hardware will pause
>     transmission whenever the FIFO is full, so there is no risk of losing
>     data if we can't service the interrupt in time.
> 
>     In the long term, we'll be better off handling this as DMA transfers,
>     but for now, this enables some userspace software, such as flashrom,
>     to use the A10 SPI controller via the spidev interfac without receing
>     -EINVAL.
> 
>     This patch should NOT be merged, as it only handles long Rx transfers.
>     Long Tx transfers have not been tested, and they will most likely fail
>     miserably. There is currently no refreshing of Tx FIFOs when they run
>     empty on long transfers.
> 
>     I'm, watching the bus with a logic analyzer, and at low speeds (2 MHz
>     or less), the bursts are continuous. However, on higher speeds, the
>     bursts seem to happen in 64-byte micro-bursts. My assumption is that
>     we aren't servicing the 3/4 FIFO interrupts fast enough, the FIFOs get
>     filled, and the controller pauses communication. At higher speeds,
>     there seem to be weird effects, such as the transmission pausing mid-
>     byte for a long period of time, but I suspect this to be due to my
>     logic analyzer being too slow and/or too much impedance in the
>     connecting wires (logic analyzer missing SCLK transitions).
> 
>     This patch is currently tested on top of sunxi-devel, but should apply
>     cleanly to sunxi-next as well.
> 
>     Signed-off-by: Alexandru Gagniuc <[email protected] <javascript:>>
>     ---
>      drivers/spi/spi-sun4i.c | 20 ++++++++++++++++----
>      1 file changed, 16 insertions(+), 4 deletions(-)
> 
>     diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c
>     index 3f82705..f3d06bb 100644
>     --- a/drivers/spi/spi-sun4i.c
>     +++ b/drivers/spi/spi-sun4i.c
>     @@ -47,6 +47,7 @@
>      #define SUN4I_CTL_TP                                BIT(18)
>      
>      #define SUN4I_INT_CTL_REG                0x0c
>     +#define SUN4I_INT_CTL_RF_F34                        BIT(4)
>      #define SUN4I_INT_CTL_TC                        BIT(16)
>      
>      #define SUN4I_INT_STA_REG                0x10
>     @@ -68,6 +69,8 @@
>      #define SUN4I_XMIT_CNT_REG                0x24
>      #define SUN4I_XMIT_CNT(cnt)                        ((cnt) & 0xffffff)
>      
>     +#define SUN4I_MAX_XFER_SIZE                        0xffffff
>     +
>      #define SUN4I_FIFO_STA_REG                0x28
>      #define SUN4I_FIFO_STA_RF_CNT_MASK                0x7f
>      #define SUN4I_FIFO_STA_RF_CNT_BITS                0
>     @@ -175,8 +178,7 @@ static int sun4i_spi_transfer_one(struct spi_master
>     *master,
>              int ret = 0;
>              u32 reg;
>      
>     -        /* We don't support transfer larger than the FIFO */
>     -        if (tfr->len > SUN4I_FIFO_DEPTH)
>     +        if (tfr->len > SUN4I_MAX_XFER_SIZE)
>                      return -EINVAL;
>      
>              reinit_completion(&sspi->done);
>     @@ -274,7 +276,8 @@ static int sun4i_spi_transfer_one(struct spi_master
>     *master,
>              sun4i_spi_fill_fifo(sspi, SUN4I_FIFO_DEPTH);
>      
>              /* Enable the interrupts */
>     -        sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC);
>     +        sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, SUN4I_INT_CTL_TC |
>     +                                                
>     SUN4I_INT_CTL_RF_F34);
>      
>              /* Start the transfer */
>              reg = sun4i_spi_read(sspi, SUN4I_CTL_REG);
>     @@ -287,7 +290,7 @@ static int sun4i_spi_transfer_one(struct spi_master
>     *master,
>                      goto out;
>              }
>      
>     -        sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
>     +        /* FIFO is drained during the interrupt handler */
>      
>      out:
>              sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0);
>     @@ -300,9 +303,18 @@ static irqreturn_t sun4i_spi_handler(int irq, void
>     *dev_id)
>              struct sun4i_spi *sspi = dev_id;
>              u32 status = sun4i_spi_read(sspi, SUN4I_INT_STA_REG);
>      
>     +        /* Receive FIFO 3/4 full */
>     +        if (status & SUN4I_INT_CTL_RF_F34) {
>     +                sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
>     +                /* Only clear the interrupt _after_ draining the
>     FIFO */
>     +                sun4i_spi_write(sspi, SUN4I_INT_STA_REG,
>     SUN4I_INT_CTL_RF_F34);
>     +                return IRQ_HANDLED;
>     +        }
>     +
>              /* Transfer complete */
>              if (status & SUN4I_INT_CTL_TC) {
>                      sun4i_spi_write(sspi, SUN4I_INT_STA_REG,
>     SUN4I_INT_CTL_TC);
>     +                sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH);
>                      complete(&sspi->done);
>                      return IRQ_HANDLED;
>              }
>     -- 
>     1.8.5.3
> 
> 

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to