qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [RFC PATCH v5 1/2] hw/riscv: sifive_u: Add write operation and write


From: Alistair Francis
Subject: Re: [RFC PATCH v5 1/2] hw/riscv: sifive_u: Add write operation and write-once protection
Date: Fri, 25 Sep 2020 14:34:56 -0700

On Tue, Sep 1, 2020 at 9:09 AM Green Wan <green.wan@sifive.com> wrote:
>
>  - Add write operation to update fuse data bit when PWE bit is on.
>  - Add array, fuse_wo, to store the 'written' status for all bits
>    of OTP to block the write operation.
>
> Signed-off-by: Green Wan <green.wan@sifive.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/riscv/sifive_u_otp.c         | 30 +++++++++++++++++++++++++++++-
>  include/hw/riscv/sifive_u_otp.h |  3 +++
>  2 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
> index f6ecbaa2ca..b8369e9035 100644
> --- a/hw/riscv/sifive_u_otp.c
> +++ b/hw/riscv/sifive_u_otp.c
> @@ -25,6 +25,14 @@
>  #include "qemu/module.h"
>  #include "hw/riscv/sifive_u_otp.h"
>
> +#define WRITTEN_BIT_ON 0x1
> +
> +#define SET_FUSEARRAY_BIT(map, i, off, bit)    \
> +    map[i] = bit ? (map[i] | bit << off) : (map[i] & ~(bit << off))
> +
> +#define GET_FUSEARRAY_BIT(map, i, off)    \
> +    ((map[i] >> off) & 0x1)
> +
>  static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int 
> size)
>  {
>      SiFiveUOTPState *s = opaque;
> @@ -123,7 +131,24 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
>          s->ptrim = val32;
>          break;
>      case SIFIVE_U_OTP_PWE:
> -        s->pwe = val32;
> +        s->pwe = val32 & SIFIVE_U_OTP_PWE_EN;
> +
> +        /* PWE is enabled. Ignore PAS=1 (no redundancy cell) */
> +        if (s->pwe && !s->pas) {
> +            if (GET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio)) {
> +                qemu_log_mask(LOG_GUEST_ERROR,
> +                              "Error: write idx<%u>, bit<%u>\n",
> +                              s->pa, s->paio);
> +                break;
> +            }
> +
> +            /* write bit data */
> +            SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin);
> +
> +            /* update written bit */
> +            SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON);
> +        }
> +
>          break;
>      default:
>          qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx
> @@ -165,6 +190,9 @@ static void sifive_u_otp_reset(DeviceState *dev)
>      /* Make a valid content of serial number */
>      s->fuse[SIFIVE_U_OTP_SERIAL_ADDR] = s->serial;
>      s->fuse[SIFIVE_U_OTP_SERIAL_ADDR + 1] = ~(s->serial);
> +
> +    /* Initialize write-once map */
> +    memset(s->fuse_wo, 0x00, sizeof(s->fuse_wo));
>  }
>
>  static void sifive_u_otp_class_init(ObjectClass *klass, void *data)
> diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/riscv/sifive_u_otp.h
> index 639297564a..4a5a0acf48 100644
> --- a/include/hw/riscv/sifive_u_otp.h
> +++ b/include/hw/riscv/sifive_u_otp.h
> @@ -35,6 +35,8 @@
>  #define SIFIVE_U_OTP_PTRIM      0x34
>  #define SIFIVE_U_OTP_PWE        0x38
>
> +#define SIFIVE_U_OTP_PWE_EN     (1 << 0)
> +
>  #define SIFIVE_U_OTP_PCE_EN     (1 << 0)
>
>  #define SIFIVE_U_OTP_PDSTB_EN   (1 << 0)
> @@ -73,6 +75,7 @@ typedef struct SiFiveUOTPState {
>      uint32_t ptrim;
>      uint32_t pwe;
>      uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
> +    uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES];
>      /* config */
>      uint32_t serial;
>  } SiFiveUOTPState;
> --
> 2.17.1
>
>



reply via email to

[Prev in Thread] Current Thread [Next in Thread]