On Fri, 20 Nov 2020 at 16:16, Cédric Le Goater <c...@kaod.org> wrote:
>
> The controller can be configured to disable or enable address and data
> byte lanes when issuing commands. This is useful in read command mode
> to send SPI NOR commands that don't have an address space, such as
> RDID. It's a good way to have a unified read operation for registers
> and flash contents accesses.
>
> A new SPI driver proposed by Aspeed makes use of this feature. Add
> support for address lanes to start with. We will do the same for the
> data lanes if they are controlled one day.
>
> Cc: Chin-Ting Kuo <chin-ting_...@aspeedtech.com>
> Signed-off-by: Cédric Le Goater <c...@kaod.org>

Reviewed-by: Joel Stanley <j...@jms.id.au>

> ---
>  hw/ssi/aspeed_smc.c | 25 ++++++++++++++++++-------
>  1 file changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 795784e5f364..e3d5e26058c0 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -71,6 +71,16 @@
>  #define   INTR_CTRL_CMD_ABORT_EN          (1 << 2)
>  #define   INTR_CTRL_WRITE_PROTECT_EN      (1 << 1)
>
> +/* Command Control Register */
> +#define R_CE_CMD_CTRL      (0x0C / 4)
> +#define   CTRL_ADDR_BYTE0_DISABLE_SHIFT       4
> +#define   CTRL_DATA_BYTE0_DISABLE_SHIFT       0
> +
> +#define aspeed_smc_addr_byte_enabled(s, i)                               \
> +    (!((s)->regs[R_CE_CMD_CTRL] & (1 << (CTRL_ADDR_BYTE0_DISABLE_SHIFT + 
> (i)))))
> +#define aspeed_smc_data_byte_enabled(s, i)                               \
> +    (!((s)->regs[R_CE_CMD_CTRL] & (1 << (CTRL_DATA_BYTE0_DISABLE_SHIFT + 
> (i)))))
> +
>  /* CEx Control Register */
>  #define R_CTRL0           (0x10 / 4)
>  #define   CTRL_IO_QPI              (1 << 31)
> @@ -702,19 +712,17 @@ static void aspeed_smc_flash_setup(AspeedSMCFlash *fl, 
> uint32_t addr)
>  {
>      const AspeedSMCState *s = fl->controller;
>      uint8_t cmd = aspeed_smc_flash_cmd(fl);
> -    int i;
> +    int i = aspeed_smc_flash_is_4byte(fl) ? 4 : 3;
>
>      /* Flash access can not exceed CS segment */
>      addr = aspeed_smc_check_segment_addr(fl, addr);
>
>      ssi_transfer(s->spi, cmd);
> -
> -    if (aspeed_smc_flash_is_4byte(fl)) {
> -        ssi_transfer(s->spi, (addr >> 24) & 0xff);
> +    while (i--) {
> +        if (aspeed_smc_addr_byte_enabled(s, i)) {
> +            ssi_transfer(s->spi, (addr >> (i * 8)) & 0xff);
> +        }
>      }
> -    ssi_transfer(s->spi, (addr >> 16) & 0xff);
> -    ssi_transfer(s->spi, (addr >> 8) & 0xff);
> -    ssi_transfer(s->spi, (addr & 0xff));
>
>      /*
>       * Use fake transfers to model dummy bytes. The value should
> @@ -988,6 +996,7 @@ static uint64_t aspeed_smc_read(void *opaque, hwaddr 
> addr, unsigned int size)
>          (addr >= s->r_timings &&
>           addr < s->r_timings + s->ctrl->nregs_timings) ||
>          addr == s->r_ce_ctrl ||
> +        addr == R_CE_CMD_CTRL ||
>          addr == R_INTR_CTRL ||
>          addr == R_DUMMY_DATA ||
>          (s->ctrl->has_dma && addr == R_DMA_CTRL) ||
> @@ -1276,6 +1285,8 @@ static void aspeed_smc_write(void *opaque, hwaddr addr, 
> uint64_t data,
>          if (value != s->regs[R_SEG_ADDR0 + cs]) {
>              aspeed_smc_flash_set_segment(s, cs, value);
>          }
> +    } else if (addr == R_CE_CMD_CTRL) {
> +        s->regs[addr] = value & 0xff;
>      } else if (addr == R_DUMMY_DATA) {
>          s->regs[addr] = value & 0xff;
>      } else if (addr == R_INTR_CTRL) {
> --
> 2.26.2
>

Reply via email to