[PATCH linux dev-5.7 5/6] spi: fsi: Implement restricted size for certain controllers

Joel Stanley joel at jms.id.au
Thu Jul 30 09:33:06 AEST 2020


On Wed, 29 Jul 2020 at 20:45, Eddie James <eajames at linux.ibm.com> wrote:
>
> Some of the FSI-attached SPI controllers cannot use the loop command in
> programming the sequencer due to security requirements. Add a boolean
> devicetree property that describes this condition and restrict the
> size for these controllers. Also, add more transfers directly in the
> sequence up to the length of the sequence register.
>
> Signed-off-by: Eddie James <eajames at linux.ibm.com>

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

> ---
>  drivers/spi/spi-fsi.c | 65 +++++++++++++++++++++++++++++++++++--------
>  1 file changed, 53 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/spi/spi-fsi.c b/drivers/spi/spi-fsi.c
> index c31a852b6a3e..53cfa201e187 100644
> --- a/drivers/spi/spi-fsi.c
> +++ b/drivers/spi/spi-fsi.c
> @@ -24,7 +24,8 @@
>
>  #define SPI_FSI_BASE                   0x70000
>  #define SPI_FSI_INIT_TIMEOUT_MS                1000
> -#define SPI_FSI_MAX_TRANSFER_SIZE      2048
> +#define SPI_FSI_MAX_XFR_SIZE           2048
> +#define SPI_FSI_MAX_XFR_SIZE_RESTRICTED        32
>
>  #define SPI_FSI_ERROR                  0x0
>  #define SPI_FSI_COUNTER_CFG            0x1
> @@ -74,6 +75,8 @@ struct fsi_spi {
>         struct device *dev;     /* SPI controller device */
>         struct fsi_device *fsi; /* FSI2SPI CFAM engine device */
>         u32 base;
> +       size_t max_xfr_size;
> +       bool restricted;
>  };
>
>  struct fsi_spi_sequence {
> @@ -209,8 +212,12 @@ static int fsi_spi_reset(struct fsi_spi *ctx)
>         if (rc)
>                 return rc;
>
> -       return fsi_spi_write_reg(ctx, SPI_FSI_CLOCK_CFG,
> -                                SPI_FSI_CLOCK_CFG_RESET2);
> +       rc = fsi_spi_write_reg(ctx, SPI_FSI_CLOCK_CFG,
> +                              SPI_FSI_CLOCK_CFG_RESET2);
> +       if (rc)
> +               return rc;
> +
> +       return fsi_spi_write_reg(ctx, SPI_FSI_STATUS, 0ULL);
>  }
>
>  static int fsi_spi_sequence_add(struct fsi_spi_sequence *seq, u8 val)
> @@ -218,8 +225,8 @@ static int fsi_spi_sequence_add(struct fsi_spi_sequence *seq, u8 val)
>         /*
>          * Add the next byte of instruction to the 8-byte sequence register.
>          * Then decrement the counter so that the next instruction will go in
> -        * the right place. Return the number of "slots" left in the sequence
> -        * register.
> +        * the right place. Return the index of the slot we just filled in the
> +        * sequence register.
>          */
>         seq->data |= (u64)val << seq->bit;
>         seq->bit -= 8;
> @@ -237,9 +244,11 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
>                                      struct fsi_spi_sequence *seq,
>                                      struct spi_transfer *transfer)
>  {
> +       bool docfg = false;
>         int loops;
>         int idx;
>         int rc;
> +       u8 val = 0;
>         u8 len = min(transfer->len, 8U);
>         u8 rem = transfer->len % len;
>         u64 cfg = 0ULL;
> @@ -247,22 +256,42 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
>         loops = transfer->len / len;
>
>         if (transfer->tx_buf) {
> -               idx = fsi_spi_sequence_add(seq,
> -                                          SPI_FSI_SEQUENCE_SHIFT_OUT(len));
> +               val = SPI_FSI_SEQUENCE_SHIFT_OUT(len);
> +               idx = fsi_spi_sequence_add(seq, val);
> +
>                 if (rem)
>                         rem = SPI_FSI_SEQUENCE_SHIFT_OUT(rem);
>         } else if (transfer->rx_buf) {
> -               idx = fsi_spi_sequence_add(seq,
> -                                          SPI_FSI_SEQUENCE_SHIFT_IN(len));
> +               val = SPI_FSI_SEQUENCE_SHIFT_IN(len);
> +               idx = fsi_spi_sequence_add(seq, val);
> +
>                 if (rem)
>                         rem = SPI_FSI_SEQUENCE_SHIFT_IN(rem);
>         } else {
>                 return -EINVAL;
>         }
>
> +       if (ctx->restricted) {
> +               const int eidx = rem ? 5 : 6;
> +
> +               while (loops > 1 && idx <= eidx) {
> +                       idx = fsi_spi_sequence_add(seq, val);
> +                       loops--;
> +                       docfg = true;
> +               }
> +
> +               if (loops > 1) {
> +                       dev_warn(ctx->dev, "No sequencer slots; aborting.\n");
> +                       return -EINVAL;
> +               }
> +       }
> +
>         if (loops > 1) {
>                 fsi_spi_sequence_add(seq, SPI_FSI_SEQUENCE_BRANCH(idx));
> +               docfg = true;
> +       }
>
> +       if (docfg) {
>                 cfg = SPI_FSI_COUNTER_CFG_LOOPS(loops - 1);
>                 if (transfer->rx_buf)
>                         cfg |= SPI_FSI_COUNTER_CFG_N2_RX |
> @@ -273,6 +302,8 @@ static int fsi_spi_sequence_transfer(struct fsi_spi *ctx,
>                 rc = fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, cfg);
>                 if (rc)
>                         return rc;
> +       } else {
> +               fsi_spi_write_reg(ctx, SPI_FSI_COUNTER_CFG, 0ULL);
>         }
>
>         if (rem)
> @@ -429,7 +460,7 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
>
>                 /* Sequencer must do shift out (tx) first. */
>                 if (!transfer->tx_buf ||
> -                   transfer->len > SPI_FSI_MAX_TRANSFER_SIZE) {
> +                   transfer->len > (ctx->max_xfr_size + 8)) {
>                         rc = -EINVAL;
>                         goto error;
>                 }
> @@ -453,7 +484,7 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
>
>                         /* Sequencer can only do shift in (rx) after tx. */
>                         if (next->rx_buf) {
> -                               if (next->len > SPI_FSI_MAX_TRANSFER_SIZE) {
> +                               if (next->len > ctx->max_xfr_size) {
>                                         rc = -EINVAL;
>                                         goto error;
>                                 }
> @@ -498,7 +529,9 @@ static int fsi_spi_transfer_one_message(struct spi_controller *ctlr,
>
>  static size_t fsi_spi_max_transfer_size(struct spi_device *spi)
>  {
> -       return SPI_FSI_MAX_TRANSFER_SIZE;
> +       struct fsi_spi *ctx = spi_controller_get_devdata(spi->controller);
> +
> +       return ctx->max_xfr_size;
>  }
>
>  static int fsi_spi_probe(struct device *dev)
> @@ -546,6 +579,14 @@ static int fsi_spi_probe(struct device *dev)
>                 ctx->fsi = fsi;
>                 ctx->base = base + SPI_FSI_BASE;
>
> +               if (of_property_read_bool(np, "fsi2spi,restricted")) {
> +                       ctx->restricted = true;
> +                       ctx->max_xfr_size = SPI_FSI_MAX_XFR_SIZE_RESTRICTED;
> +               } else {
> +                       ctx->restricted = false;
> +                       ctx->max_xfr_size = SPI_FSI_MAX_XFR_SIZE;
> +               }
> +
>                 rc = devm_spi_register_controller(dev, ctlr);
>                 if (rc)
>                         spi_controller_put(ctlr);
> --
> 2.24.0
>


More information about the openbmc mailing list