[PATCH linux dev-5.7 3/6] spi: fsi: Fix use of the bneq+ sequencer instruction

Joel Stanley joel at jms.id.au
Thu Jul 30 09:27:14 AEST 2020


On Wed, 29 Jul 2020 at 20:45, Eddie James <eajames at linux.ibm.com> wrote:
>
> From: Brad Bishop <bradleyb at fuzziesquirrel.com>
>
> All of the switches in N2_count_control in the counter configuration are
> required to make the branch if not equal and increment command work.
> Set them when using bneq+.
>
> A side effect of this mode requires a dummy write to TDR when both
> transmitting and receiving otherwise the controller won't start shifting
> receive data.
>
> It is likely not possible to avoid TDR underrun errors in this mode and
> they are harmless, so do not check for them.
>
> Signed-off-by: Eddie James <eajames at linux.ibm.com>
> Signed-off-by: Brad Bishop <bradleyb at fuzziesquirrel.com>

Fixes: bbb6b2f9865b ("spi: Add FSI-attached SPI controller driver")
Reviewed-by: Joel Stanley <joel at jms.id.au>

> ---
>  drivers/spi/spi-fsi.c | 28 +++++++++++++++++++++++++---
>  1 file changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
> index 559d0ff981f3..c31a852b6a3e 100644
> --- a/drivers/spi/spi-fsi.c
> +++ b/drivers/spi/spi-fsi.c
> @@ -29,6 +29,10 @@
>  #define SPI_FSI_ERROR                  0x0
>  #define SPI_FSI_COUNTER_CFG            0x1
>  #define  SPI_FSI_COUNTER_CFG_LOOPS(x)   (((u64)(x) & 0xffULL) << 32)
> +#define  SPI_FSI_COUNTER_CFG_N2_RX      BIT_ULL(8)
> +#define  SPI_FSI_COUNTER_CFG_N2_TX      BIT_ULL(9)
> +#define  SPI_FSI_COUNTER_CFG_N2_IMPLICIT BIT_ULL(10)
> +#define  SPI_FSI_COUNTER_CFG_N2_RELOAD  BIT_ULL(11)
>  #define SPI_FSI_CFG1                   0x2
>  #define SPI_FSI_CLOCK_CFG              0x3
>  #define  SPI_FSI_CLOCK_CFG_MM_ENABLE    BIT_ULL(32)
> @@ -61,7 +65,7 @@
>  #define  SPI_FSI_STATUS_RDR_OVERRUN     BIT_ULL(62)
>  #define  SPI_FSI_STATUS_RDR_FULL        BIT_ULL(63)
>  #define  SPI_FSI_STATUS_ANY_ERROR       \
> -       (SPI_FSI_STATUS_ERROR | SPI_FSI_STATUS_TDR_UNDERRUN | \
> +       (SPI_FSI_STATUS_ERROR | \
>          SPI_FSI_STATUS_TDR_OVERRUN | SPI_FSI_STATUS_RDR_UNDERRUN | \
>          SPI_FSI_STATUS_RDR_OVERRUN)
>  #define SPI_FSI_PORT_CTRL              0x9
> @@ -238,6 +242,7 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
>         int rc;
>         u8 len = min(transfer->len, 8U);
>         u8 rem = transfer->len % len;
> +       u64 cfg = 0ULL;
>
>         loops = transfer->len / len;
>
> @@ -258,8 +263,14 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
>         if (loops > 1) {
>                 fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
>
> -               rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG,
> -                                      SPI_FSI_COUNTER_CFG_LOOPS(loops - 1));
> +               cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
> +               if (transfer->rx_buf)
> +                       cfg |= SPI_FSI_COUNTER_CFG_N2_RX |
> +                               SPI_FSI_COUNTER_CFG_N2_TX |
> +                               SPI_FSI_COUNTER_CFG_N2_IMPLICIT |
> +                               SPI_FSI_COUNTER_CFG_N2_RELOAD;
> +
> +               rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, cfg);
>                 if (rc)
>                         return rc;
>         }
> @@ -275,6 +286,7 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
>  {
>         int rc = 0;
>         u64 status = 0ULL;
> +       u64 cfg = 0ULL;
>
>         if (transfer->tx_buf) {
>                 int nb;
> @@ -312,6 +324,16 @@ static int fsi_spi_transfer_data(struct fsi_spi *ctx,
>                 u64 in = 0ULL;
>                 u8 *rx = transfer->rx_buf;
>
> +               rc = fsi_spi_read_reg(ctx, SPI_FSI_COUNTER_CFG, &cfg);
> +               if (rc)
> +                       return rc;
> +
> +               if (cfg & SPI_FSI_COUNTER_CFG_N2_IMPLICIT) {
> +                       rc = fsi_spi_write_reg(ctx, SPI_FSI_DATA_TX, 0);
> +                       if (rc)
> +                               return rc;
> +               }
> +
>                 while (transfer->len > recv) {
>                         do {
>                                 rc = fsi_spi_read_reg(ctx, SPI_FSI_STATUS,
> --
> 2.24.0
>


More information about the openbmc mailing list