[RFC PATCH v6 1/2] hw/misc/sifive_u_otp: Add write function and write-once protection

Green Wan posted 2 patches 5 years, 4 months ago
There is a newer version of this series
[RFC PATCH v6 1/2] hw/misc/sifive_u_otp: Add write function and write-once protection
Posted by Green Wan 5 years, 4 months ago
 - 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>
---
 hw/misc/sifive_u_otp.c         | 30 +++++++++++++++++++++++++++++-
 include/hw/misc/sifive_u_otp.h |  3 +++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c
index c2f3c8e129..685c1f8e07 100644
--- a/hw/misc/sifive_u_otp.c
+++ b/hw/misc/sifive_u_otp.c
@@ -25,6 +25,14 @@
 #include "qemu/module.h"
 #include "hw/misc/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/misc/sifive_u_otp.h b/include/hw/misc/sifive_u_otp.h
index 82c9176c8f..ebffbc1fa5 100644
--- a/include/hw/misc/sifive_u_otp.h
+++ b/include/hw/misc/sifive_u_otp.h
@@ -36,6 +36,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)
@@ -75,6 +77,7 @@ 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;
 };
-- 
2.17.1


Re: [RFC PATCH v6 1/2] hw/misc/sifive_u_otp: Add write function and write-once protection
Posted by Bin Meng 5 years, 3 months ago
Hi Green,

On Mon, Sep 28, 2020 at 6:12 PM 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>
> ---
>  hw/misc/sifive_u_otp.c         | 30 +++++++++++++++++++++++++++++-
>  include/hw/misc/sifive_u_otp.h |  3 +++
>  2 files changed, 32 insertions(+), 1 deletion(-)
>

I am not sure how you tested this. I wrote a simple U-Boot command to
call U-Boot sifive-otp driver to test the write functionality, but it
failed.

=> misc write otp@10070000 0 80200000 10
=> misc read  otp@10070000 0 80400000 10
=> md 80400000
80400000: ffffffff ffffffff ffffffff ffffffff    ................
80400010: 00000000 00000000 00000000 00000000    ................
80400020: 00000000 00000000 00000000 00000000    ................
80400030: 00000000 00000000 00000000 00000000    ................
80400040: 00000000 00000000 00000000 00000000    ................
80400050: 00000000 00000000 00000000 00000000    ................
80400060: 00000000 00000000 00000000 00000000    ................
80400070: 00000000 00000000 00000000 00000000    ................
80400080: 00000000 00000000 00000000 00000000    ................
80400090: 00000000 00000000 00000000 00000000    ................
804000a0: 00000000 00000000 00000000 00000000    ................
804000b0: 00000000 00000000 00000000 00000000    ................
804000c0: 00000000 00000000 00000000 00000000    ................
804000d0: 00000000 00000000 00000000 00000000    ................
804000e0: 00000000 00000000 00000000 00000000    ................
804000f0: 00000000 00000000 00000000 00000000    ................
=> misc write otp@10070000 0 80200010 10
=> misc read  otp@10070000 0 80400010 10
=> md 80400000
80400000: ffffffff ffffffff ffffffff ffffffff    ................
80400010: ffffffff ffffffff ffffffff ffffffff    ................
80400020: 00000000 00000000 00000000 00000000    ................
80400030: 00000000 00000000 00000000 00000000    ................
80400040: 00000000 00000000 00000000 00000000    ................
80400050: 00000000 00000000 00000000 00000000    ................
80400060: 00000000 00000000 00000000 00000000    ................
80400070: 00000000 00000000 00000000 00000000    ................
80400080: 00000000 00000000 00000000 00000000    ................
80400090: 00000000 00000000 00000000 00000000    ................
804000a0: 00000000 00000000 00000000 00000000    ................
804000b0: 00000000 00000000 00000000 00000000    ................
804000c0: 00000000 00000000 00000000 00000000    ................
804000d0: 00000000 00000000 00000000 00000000    ................
804000e0: 00000000 00000000 00000000 00000000    ................
804000f0: 00000000 00000000 00000000 00000000    ................

But it can read the serial number at offset 0x3f0

=> misc read  otp@10070000 3f0 80400010 10
=> md 80400000
80400000: ffffffff ffffffff ffffffff ffffffff    ................
80400010: 00000001 fffffffe ffffffff ffffffff    ................
80400020: 00000000 00000000 00000000 00000000    ................
80400030: 00000000 00000000 00000000 00000000    ................
80400040: 00000000 00000000 00000000 00000000    ................
80400050: 00000000 00000000 00000000 00000000    ................
80400060: 00000000 00000000 00000000 00000000    ................
80400070: 00000000 00000000 00000000 00000000    ................
80400080: 00000000 00000000 00000000 00000000    ................
80400090: 00000000 00000000 00000000 00000000    ................
804000a0: 00000000 00000000 00000000 00000000    ................
804000b0: 00000000 00000000 00000000 00000000    ................
804000c0: 00000000 00000000 00000000 00000000    ................
804000d0: 00000000 00000000 00000000 00000000    ................
804000e0: 00000000 00000000 00000000 00000000    ................
804000f0: 00000000 00000000 00000000 00000000    ................

Regards,
Bin

Re: [RFC PATCH v6 1/2] hw/misc/sifive_u_otp: Add write function and write-once protection
Posted by Green Wan 5 years, 3 months ago
On Wed, Oct 14, 2020 at 1:37 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Green,
>
> On Mon, Sep 28, 2020 at 6:12 PM 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>
> > ---
> >  hw/misc/sifive_u_otp.c         | 30 +++++++++++++++++++++++++++++-
> >  include/hw/misc/sifive_u_otp.h |  3 +++
> >  2 files changed, 32 insertions(+), 1 deletion(-)
> >
>
> I am not sure how you tested this. I wrote a simple U-Boot command to
> call U-Boot sifive-otp driver to test the write functionality, but it
> failed.
>
> => misc write otp@10070000 0 80200000 10
                                                      ^^^^^^^^^
Quick ask, how about 'md 80200000'?

I didn't use 'misc write' command. I can check afterward.

> => misc read  otp@10070000 0 80400000 10
> => md 80400000
> 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> 80400010: 00000000 00000000 00000000 00000000    ................
> 80400020: 00000000 00000000 00000000 00000000    ................
> 80400030: 00000000 00000000 00000000 00000000    ................
> 80400040: 00000000 00000000 00000000 00000000    ................
> 80400050: 00000000 00000000 00000000 00000000    ................
> 80400060: 00000000 00000000 00000000 00000000    ................
> 80400070: 00000000 00000000 00000000 00000000    ................
> 80400080: 00000000 00000000 00000000 00000000    ................
> 80400090: 00000000 00000000 00000000 00000000    ................
> 804000a0: 00000000 00000000 00000000 00000000    ................
> 804000b0: 00000000 00000000 00000000 00000000    ................
> 804000c0: 00000000 00000000 00000000 00000000    ................
> 804000d0: 00000000 00000000 00000000 00000000    ................
> 804000e0: 00000000 00000000 00000000 00000000    ................
> 804000f0: 00000000 00000000 00000000 00000000    ................
> => misc write otp@10070000 0 80200010 10
> => misc read  otp@10070000 0 80400010 10
> => md 80400000
> 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> 80400010: ffffffff ffffffff ffffffff ffffffff    ................
> 80400020: 00000000 00000000 00000000 00000000    ................
> 80400030: 00000000 00000000 00000000 00000000    ................
> 80400040: 00000000 00000000 00000000 00000000    ................
> 80400050: 00000000 00000000 00000000 00000000    ................
> 80400060: 00000000 00000000 00000000 00000000    ................
> 80400070: 00000000 00000000 00000000 00000000    ................
> 80400080: 00000000 00000000 00000000 00000000    ................
> 80400090: 00000000 00000000 00000000 00000000    ................
> 804000a0: 00000000 00000000 00000000 00000000    ................
> 804000b0: 00000000 00000000 00000000 00000000    ................
> 804000c0: 00000000 00000000 00000000 00000000    ................
> 804000d0: 00000000 00000000 00000000 00000000    ................
> 804000e0: 00000000 00000000 00000000 00000000    ................
> 804000f0: 00000000 00000000 00000000 00000000    ................
>
> But it can read the serial number at offset 0x3f0
>
> => misc read  otp@10070000 3f0 80400010 10
> => md 80400000
> 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> 80400010: 00000001 fffffffe ffffffff ffffffff    ................
> 80400020: 00000000 00000000 00000000 00000000    ................
> 80400030: 00000000 00000000 00000000 00000000    ................
> 80400040: 00000000 00000000 00000000 00000000    ................
> 80400050: 00000000 00000000 00000000 00000000    ................
> 80400060: 00000000 00000000 00000000 00000000    ................
> 80400070: 00000000 00000000 00000000 00000000    ................
> 80400080: 00000000 00000000 00000000 00000000    ................
> 80400090: 00000000 00000000 00000000 00000000    ................
> 804000a0: 00000000 00000000 00000000 00000000    ................
> 804000b0: 00000000 00000000 00000000 00000000    ................
> 804000c0: 00000000 00000000 00000000 00000000    ................
> 804000d0: 00000000 00000000 00000000 00000000    ................
> 804000e0: 00000000 00000000 00000000 00000000    ................
> 804000f0: 00000000 00000000 00000000 00000000    ................
>
> Regards,
> Bin

Re: [RFC PATCH v6 1/2] hw/misc/sifive_u_otp: Add write function and write-once protection
Posted by Bin Meng 5 years, 3 months ago
Hi Green,

On Wed, Oct 14, 2020 at 3:02 PM Green Wan <green.wan@sifive.com> wrote:
>
> On Wed, Oct 14, 2020 at 1:37 PM Bin Meng <bmeng.cn@gmail.com> wrote:
> >
> > Hi Green,
> >
> > On Mon, Sep 28, 2020 at 6:12 PM 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>
> > > ---
> > >  hw/misc/sifive_u_otp.c         | 30 +++++++++++++++++++++++++++++-
> > >  include/hw/misc/sifive_u_otp.h |  3 +++
> > >  2 files changed, 32 insertions(+), 1 deletion(-)
> > >
> >
> > I am not sure how you tested this. I wrote a simple U-Boot command to
> > call U-Boot sifive-otp driver to test the write functionality, but it
> > failed.
> >
> > => misc write otp@10070000 0 80200000 10
>                                                       ^^^^^^^^^
> Quick ask, how about 'md 80200000'?
>
> I didn't use 'misc write' command. I can check afterward.

Note 'misc write' is a new U-Boot command I just added for testing
this QEMU functionality. Please use the U-Boot patch below:
http://patchwork.ozlabs.org/project/uboot/patch/1602657292-82815-1-git-send-email-bmeng.cn@gmail.com/

>
> > => misc read  otp@10070000 0 80400000 10
> > => md 80400000
> > 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> > 80400010: 00000000 00000000 00000000 00000000    ................
> > 80400020: 00000000 00000000 00000000 00000000    ................
> > 80400030: 00000000 00000000 00000000 00000000    ................
> > 80400040: 00000000 00000000 00000000 00000000    ................
> > 80400050: 00000000 00000000 00000000 00000000    ................
> > 80400060: 00000000 00000000 00000000 00000000    ................
> > 80400070: 00000000 00000000 00000000 00000000    ................
> > 80400080: 00000000 00000000 00000000 00000000    ................
> > 80400090: 00000000 00000000 00000000 00000000    ................
> > 804000a0: 00000000 00000000 00000000 00000000    ................
> > 804000b0: 00000000 00000000 00000000 00000000    ................
> > 804000c0: 00000000 00000000 00000000 00000000    ................
> > 804000d0: 00000000 00000000 00000000 00000000    ................
> > 804000e0: 00000000 00000000 00000000 00000000    ................
> > 804000f0: 00000000 00000000 00000000 00000000    ................
> > => misc write otp@10070000 0 80200010 10
> > => misc read  otp@10070000 0 80400010 10
> > => md 80400000
> > 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> > 80400010: ffffffff ffffffff ffffffff ffffffff    ................
> > 80400020: 00000000 00000000 00000000 00000000    ................
> > 80400030: 00000000 00000000 00000000 00000000    ................
> > 80400040: 00000000 00000000 00000000 00000000    ................
> > 80400050: 00000000 00000000 00000000 00000000    ................
> > 80400060: 00000000 00000000 00000000 00000000    ................
> > 80400070: 00000000 00000000 00000000 00000000    ................
> > 80400080: 00000000 00000000 00000000 00000000    ................
> > 80400090: 00000000 00000000 00000000 00000000    ................
> > 804000a0: 00000000 00000000 00000000 00000000    ................
> > 804000b0: 00000000 00000000 00000000 00000000    ................
> > 804000c0: 00000000 00000000 00000000 00000000    ................
> > 804000d0: 00000000 00000000 00000000 00000000    ................
> > 804000e0: 00000000 00000000 00000000 00000000    ................
> > 804000f0: 00000000 00000000 00000000 00000000    ................
> >
> > But it can read the serial number at offset 0x3f0
> >
> > => misc read  otp@10070000 3f0 80400010 10
> > => md 80400000
> > 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> > 80400010: 00000001 fffffffe ffffffff ffffffff    ................
> > 80400020: 00000000 00000000 00000000 00000000    ................
> > 80400030: 00000000 00000000 00000000 00000000    ................
> > 80400040: 00000000 00000000 00000000 00000000    ................
> > 80400050: 00000000 00000000 00000000 00000000    ................
> > 80400060: 00000000 00000000 00000000 00000000    ................
> > 80400070: 00000000 00000000 00000000 00000000    ................
> > 80400080: 00000000 00000000 00000000 00000000    ................
> > 80400090: 00000000 00000000 00000000 00000000    ................
> > 804000a0: 00000000 00000000 00000000 00000000    ................
> > 804000b0: 00000000 00000000 00000000 00000000    ................
> > 804000c0: 00000000 00000000 00000000 00000000    ................
> > 804000d0: 00000000 00000000 00000000 00000000    ................
> > 804000e0: 00000000 00000000 00000000 00000000    ................
> > 804000f0: 00000000 00000000 00000000 00000000    ................

Regards,
Bin

Re: [RFC PATCH v6 1/2] hw/misc/sifive_u_otp: Add write function and write-once protection
Posted by Green Wan 5 years, 3 months ago
On Wed, Oct 14, 2020 at 3:17 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Green,
>
> On Wed, Oct 14, 2020 at 3:02 PM Green Wan <green.wan@sifive.com> wrote:
> >
> > On Wed, Oct 14, 2020 at 1:37 PM Bin Meng <bmeng.cn@gmail.com> wrote:
> > >
> > > Hi Green,
> > >
> > > On Mon, Sep 28, 2020 at 6:12 PM 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>
> > > > ---
> > > >  hw/misc/sifive_u_otp.c         | 30 +++++++++++++++++++++++++++++-
> > > >  include/hw/misc/sifive_u_otp.h |  3 +++
> > > >  2 files changed, 32 insertions(+), 1 deletion(-)
> > > >
> > >
> > > I am not sure how you tested this. I wrote a simple U-Boot command to
> > > call U-Boot sifive-otp driver to test the write functionality, but it
> > > failed.
> > >
> > > => misc write otp@10070000 0 80200000 10
> >                                                       ^^^^^^^^^
> > Quick ask, how about 'md 80200000'?
> >
> > I didn't use 'misc write' command. I can check afterward.
>
> Note 'misc write' is a new U-Boot command I just added for testing
> this QEMU functionality. Please use the U-Boot patch below:
> http://patchwork.ozlabs.org/project/uboot/patch/1602657292-82815-1-git-send-email-bmeng.cn@gmail.com/
>
Thanks for pointing it out.

I've found one bug when I revise the macro of the write function and
the read is correct. It's my mistake. I will include and rerun this
test as well.

> >
> > > => misc read  otp@10070000 0 80400000 10
> > > => md 80400000
> > > 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> > > 80400010: 00000000 00000000 00000000 00000000    ................
> > > 80400020: 00000000 00000000 00000000 00000000    ................
> > > 80400030: 00000000 00000000 00000000 00000000    ................
> > > 80400040: 00000000 00000000 00000000 00000000    ................
> > > 80400050: 00000000 00000000 00000000 00000000    ................
> > > 80400060: 00000000 00000000 00000000 00000000    ................
> > > 80400070: 00000000 00000000 00000000 00000000    ................
> > > 80400080: 00000000 00000000 00000000 00000000    ................
> > > 80400090: 00000000 00000000 00000000 00000000    ................
> > > 804000a0: 00000000 00000000 00000000 00000000    ................
> > > 804000b0: 00000000 00000000 00000000 00000000    ................
> > > 804000c0: 00000000 00000000 00000000 00000000    ................
> > > 804000d0: 00000000 00000000 00000000 00000000    ................
> > > 804000e0: 00000000 00000000 00000000 00000000    ................
> > > 804000f0: 00000000 00000000 00000000 00000000    ................
> > > => misc write otp@10070000 0 80200010 10
> > > => misc read  otp@10070000 0 80400010 10
> > > => md 80400000
> > > 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> > > 80400010: ffffffff ffffffff ffffffff ffffffff    ................
> > > 80400020: 00000000 00000000 00000000 00000000    ................
> > > 80400030: 00000000 00000000 00000000 00000000    ................
> > > 80400040: 00000000 00000000 00000000 00000000    ................
> > > 80400050: 00000000 00000000 00000000 00000000    ................
> > > 80400060: 00000000 00000000 00000000 00000000    ................
> > > 80400070: 00000000 00000000 00000000 00000000    ................
> > > 80400080: 00000000 00000000 00000000 00000000    ................
> > > 80400090: 00000000 00000000 00000000 00000000    ................
> > > 804000a0: 00000000 00000000 00000000 00000000    ................
> > > 804000b0: 00000000 00000000 00000000 00000000    ................
> > > 804000c0: 00000000 00000000 00000000 00000000    ................
> > > 804000d0: 00000000 00000000 00000000 00000000    ................
> > > 804000e0: 00000000 00000000 00000000 00000000    ................
> > > 804000f0: 00000000 00000000 00000000 00000000    ................
> > >
> > > But it can read the serial number at offset 0x3f0
> > >
> > > => misc read  otp@10070000 3f0 80400010 10
> > > => md 80400000
> > > 80400000: ffffffff ffffffff ffffffff ffffffff    ................
> > > 80400010: 00000001 fffffffe ffffffff ffffffff    ................
> > > 80400020: 00000000 00000000 00000000 00000000    ................
> > > 80400030: 00000000 00000000 00000000 00000000    ................
> > > 80400040: 00000000 00000000 00000000 00000000    ................
> > > 80400050: 00000000 00000000 00000000 00000000    ................
> > > 80400060: 00000000 00000000 00000000 00000000    ................
> > > 80400070: 00000000 00000000 00000000 00000000    ................
> > > 80400080: 00000000 00000000 00000000 00000000    ................
> > > 80400090: 00000000 00000000 00000000 00000000    ................
> > > 804000a0: 00000000 00000000 00000000 00000000    ................
> > > 804000b0: 00000000 00000000 00000000 00000000    ................
> > > 804000c0: 00000000 00000000 00000000 00000000    ................
> > > 804000d0: 00000000 00000000 00000000 00000000    ................
> > > 804000e0: 00000000 00000000 00000000 00000000    ................
> > > 804000f0: 00000000 00000000 00000000 00000000    ................
>
> Regards,
> Bin