* [RFC PATCH v4 0/2] Add file-backed and write-once features to OTP
@ 2020-08-27 7:46 Green Wan
2020-08-27 7:46 ` [RFC PATCH v4 1/2] hw/riscv: sifive_u: Add backend drive support Green Wan
2020-08-27 7:46 ` [RFC PATCH v4 2/2] hw/riscv: sifive_u: Add write-once protection Green Wan
0 siblings, 2 replies; 6+ messages in thread
From: Green Wan @ 2020-08-27 7:46 UTC (permalink / raw)
Cc: qemu-riscv, Sagar Karandikar, Bastian Koppelmann, qemu-devel,
Green Wan, Alistair Francis, Palmer Dabbelt, bmeng.cn
Based RFC v3 to fix:
- Fix all nits-related
- Use blk for blk_by_legacy_dinfo(dinfo)
- Move SET_WRITTEN_BIT out from else branch
Summary of Patches
- First patch is to add file-backed implementation to allow users to use
'-drive' to assign an OTP raw image file. OTP image file must be bigger
than 16K.
For example, '-drive if=none,format=raw,file=otp.img'
- Second patch is to add 'write-once' feature to block second write to
the OTP memory. Only keep the 'written' state for non-control register
range from 0x38 to 16KB.
Testing
- Tested on sifive_u for both qemu and u-boot.
Green Wan (2):
hw/riscv: sifive_u: Add backend drive support
hw/riscv: sifive_u: Add write-once protection
hw/riscv/sifive_u_otp.c | 71 +++++++++++++++++++++++++++++++++
include/hw/riscv/sifive_u_otp.h | 3 ++
2 files changed, 74 insertions(+)
--
2.17.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [RFC PATCH v4 1/2] hw/riscv: sifive_u: Add backend drive support
2020-08-27 7:46 [RFC PATCH v4 0/2] Add file-backed and write-once features to OTP Green Wan
@ 2020-08-27 7:46 ` Green Wan
2020-08-28 12:54 ` Bin Meng
2020-08-27 7:46 ` [RFC PATCH v4 2/2] hw/riscv: sifive_u: Add write-once protection Green Wan
1 sibling, 1 reply; 6+ messages in thread
From: Green Wan @ 2020-08-27 7:46 UTC (permalink / raw)
Cc: qemu-riscv, Sagar Karandikar, Bastian Koppelmann, qemu-devel,
Green Wan, Alistair Francis, Palmer Dabbelt, bmeng.cn
Add '-drive' support to OTP device. Allow users to assign a raw file
as OTP image.
Signed-off-by: Green Wan <green.wan@sifive.com>
---
hw/riscv/sifive_u_otp.c | 50 +++++++++++++++++++++++++++++++++
include/hw/riscv/sifive_u_otp.h | 2 ++
2 files changed, 52 insertions(+)
diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
index f6ecbaa2ca..aab2220494 100644
--- a/hw/riscv/sifive_u_otp.c
+++ b/hw/riscv/sifive_u_otp.c
@@ -24,6 +24,8 @@
#include "qemu/log.h"
#include "qemu/module.h"
#include "hw/riscv/sifive_u_otp.h"
+#include "sysemu/blockdev.h"
+#include "sysemu/block-backend.h"
static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
{
@@ -46,6 +48,16 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
(s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
(s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
+
+ /* read from backend */
+ if (s->blk) {
+ int32_t buf;
+
+ blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf,
+ SIFIVE_U_OTP_FUSE_WORD);
+ return buf;
+ }
+
return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
} else {
return 0xff;
@@ -123,6 +135,12 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
s->ptrim = val32;
break;
case SIFIVE_U_OTP_PWE:
+ /* write to backend */
+ if (s->blk) {
+ blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &val32,
+ SIFIVE_U_OTP_FUSE_WORD, 0);
+ }
+
s->pwe = val32;
break;
default:
@@ -143,16 +161,48 @@ static const MemoryRegionOps sifive_u_otp_ops = {
static Property sifive_u_otp_properties[] = {
DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0),
+ DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk),
DEFINE_PROP_END_OF_LIST(),
};
static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
{
SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
+ DriveInfo *dinfo;
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s,
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+
+ dinfo = drive_get_next(IF_NONE);
+ if (dinfo) {
+ int ret;
+ uint64_t perm;
+ int filesize;
+ BlockBackend *blk;
+
+ blk = blk_by_legacy_dinfo(dinfo);
+ filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD;
+ if (blk_getlength(blk) < filesize) {
+ qemu_log_mask(LOG_GUEST_ERROR, "OTP drive size < 16K\n");
+ return;
+ }
+
+ qdev_prop_set_drive(dev, "drive", blk);
+
+ perm = BLK_PERM_CONSISTENT_READ |
+ (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
+ ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
+ if (ret < 0) {
+ qemu_log_mask(LOG_GUEST_ERROR, "set perm error.");
+ }
+
+ if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "failed to read the initial flash content");
+ return;
+ }
+ }
}
static void sifive_u_otp_reset(DeviceState *dev)
diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/riscv/sifive_u_otp.h
index 639297564a..13d2552e43 100644
--- a/include/hw/riscv/sifive_u_otp.h
+++ b/include/hw/riscv/sifive_u_otp.h
@@ -43,6 +43,7 @@
#define SIFIVE_U_OTP_PA_MASK 0xfff
#define SIFIVE_U_OTP_NUM_FUSES 0x1000
+#define SIFIVE_U_OTP_FUSE_WORD 4
#define SIFIVE_U_OTP_SERIAL_ADDR 0xfc
#define SIFIVE_U_OTP_REG_SIZE 0x1000
@@ -75,6 +76,7 @@ typedef struct SiFiveUOTPState {
uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
/* config */
uint32_t serial;
+ BlockBackend *blk;
} SiFiveUOTPState;
#endif /* HW_SIFIVE_U_OTP_H */
--
2.17.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [RFC PATCH v4 2/2] hw/riscv: sifive_u: Add write-once protection
2020-08-27 7:46 [RFC PATCH v4 0/2] Add file-backed and write-once features to OTP Green Wan
2020-08-27 7:46 ` [RFC PATCH v4 1/2] hw/riscv: sifive_u: Add backend drive support Green Wan
@ 2020-08-27 7:46 ` Green Wan
2020-08-28 13:08 ` Bin Meng
1 sibling, 1 reply; 6+ messages in thread
From: Green Wan @ 2020-08-27 7:46 UTC (permalink / raw)
Cc: qemu-riscv, Sagar Karandikar, Bastian Koppelmann, qemu-devel,
Green Wan, Alistair Francis, Palmer Dabbelt, bmeng.cn
Add array to store the 'written' status for all bit of OTP to block
the write operation to the same bit. Ignore the control register
offset from 0x0 to 0x38 of OTP memory mapping.
Signed-off-by: Green Wan <green.wan@sifive.com>
---
hw/riscv/sifive_u_otp.c | 21 +++++++++++++++++++++
include/hw/riscv/sifive_u_otp.h | 1 +
2 files changed, 22 insertions(+)
diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
index aab2220494..e9605b9ae9 100644
--- a/hw/riscv/sifive_u_otp.c
+++ b/hw/riscv/sifive_u_otp.c
@@ -27,6 +27,12 @@
#include "sysemu/blockdev.h"
#include "sysemu/block-backend.h"
+#define SET_WRITTEN_BIT(map, idx, bit) \
+ (map[idx] |= (0x1 << bit))
+
+#define GET_WRITTEN_BIT(map, idx, bit) \
+ ((map[idx] >> bit) & 0x1)
+
static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
{
SiFiveUOTPState *s = opaque;
@@ -135,6 +141,18 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
s->ptrim = val32;
break;
case SIFIVE_U_OTP_PWE:
+ /* Keep written state for data only and PWE is enabled. Ignore PAS=1 */
+ if ((s->pa > SIFIVE_U_OTP_PWE) && (val32 & 0x1) && !s->pas) {
+ if (GET_WRITTEN_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;
+ }
+
+ SET_WRITTEN_BIT(s->fuse_wo, s->pa, s->paio);
+ }
+
/* write to backend */
if (s->blk) {
blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &val32,
@@ -215,6 +233,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 13d2552e43..49d40a6430 100644
--- a/include/hw/riscv/sifive_u_otp.h
+++ b/include/hw/riscv/sifive_u_otp.h
@@ -74,6 +74,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;
BlockBackend *blk;
--
2.17.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [RFC PATCH v4 1/2] hw/riscv: sifive_u: Add backend drive support
2020-08-27 7:46 ` [RFC PATCH v4 1/2] hw/riscv: sifive_u: Add backend drive support Green Wan
@ 2020-08-28 12:54 ` Bin Meng
2020-09-01 7:22 ` Green Wan
0 siblings, 1 reply; 6+ messages in thread
From: Bin Meng @ 2020-08-28 12:54 UTC (permalink / raw)
To: Green Wan
Cc: open list:RISC-V, Sagar Karandikar, Bastian Koppelmann,
qemu-devel@nongnu.org Developers, Alistair Francis,
Palmer Dabbelt
Hi Green,
On Thu, Aug 27, 2020 at 3:47 PM Green Wan <green.wan@sifive.com> wrote:
>
> Add '-drive' support to OTP device. Allow users to assign a raw file
> as OTP image.
>
> Signed-off-by: Green Wan <green.wan@sifive.com>
> ---
> hw/riscv/sifive_u_otp.c | 50 +++++++++++++++++++++++++++++++++
> include/hw/riscv/sifive_u_otp.h | 2 ++
> 2 files changed, 52 insertions(+)
>
> diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
> index f6ecbaa2ca..aab2220494 100644
> --- a/hw/riscv/sifive_u_otp.c
> +++ b/hw/riscv/sifive_u_otp.c
> @@ -24,6 +24,8 @@
> #include "qemu/log.h"
> #include "qemu/module.h"
> #include "hw/riscv/sifive_u_otp.h"
> +#include "sysemu/blockdev.h"
> +#include "sysemu/block-backend.h"
>
> static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
> {
> @@ -46,6 +48,16 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
> if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
> (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
> (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
> +
> + /* read from backend */
> + if (s->blk) {
> + int32_t buf;
> +
> + blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf,
> + SIFIVE_U_OTP_FUSE_WORD);
> + return buf;
> + }
> +
> return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
> } else {
> return 0xff;
> @@ -123,6 +135,12 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
> s->ptrim = val32;
> break;
> case SIFIVE_U_OTP_PWE:
> + /* write to backend */
> + if (s->blk) {
> + blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &val32,
The logic looks wrong to me. According to the U-Boot driver
(sifive-otp.c) the content to be written to the OTP memory comes from
s->pdin bit by bit. Here val32 represents whether to disable write or
enable write.
I think we should arrange patches like this:
patch 1 to add OTP write functionality, to the existing s->fuse[] mechanism
patch 2 to add file based backend write support
> + SIFIVE_U_OTP_FUSE_WORD, 0);
> + }
> +
> s->pwe = val32;
> break;
> default:
> @@ -143,16 +161,48 @@ static const MemoryRegionOps sifive_u_otp_ops = {
>
> static Property sifive_u_otp_properties[] = {
> DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0),
> + DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk),
> DEFINE_PROP_END_OF_LIST(),
> };
>
> static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
> {
> SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
> + DriveInfo *dinfo;
>
> memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s,
> TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
> sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
> +
> + dinfo = drive_get_next(IF_NONE);
> + if (dinfo) {
> + int ret;
> + uint64_t perm;
> + int filesize;
> + BlockBackend *blk;
> +
> + blk = blk_by_legacy_dinfo(dinfo);
> + filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD;
> + if (blk_getlength(blk) < filesize) {
> + qemu_log_mask(LOG_GUEST_ERROR, "OTP drive size < 16K\n");
> + return;
> + }
> +
> + qdev_prop_set_drive(dev, "drive", blk);
> +
> + perm = BLK_PERM_CONSISTENT_READ |
> + (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
> + ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
> + if (ret < 0) {
> + qemu_log_mask(LOG_GUEST_ERROR, "set perm error.");
> + }
> +
> + if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "failed to read the initial flash content");
> + return;
> + }
> + }
> }
>
> static void sifive_u_otp_reset(DeviceState *dev)
> diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/riscv/sifive_u_otp.h
> index 639297564a..13d2552e43 100644
> --- a/include/hw/riscv/sifive_u_otp.h
> +++ b/include/hw/riscv/sifive_u_otp.h
> @@ -43,6 +43,7 @@
>
> #define SIFIVE_U_OTP_PA_MASK 0xfff
> #define SIFIVE_U_OTP_NUM_FUSES 0x1000
> +#define SIFIVE_U_OTP_FUSE_WORD 4
> #define SIFIVE_U_OTP_SERIAL_ADDR 0xfc
>
> #define SIFIVE_U_OTP_REG_SIZE 0x1000
> @@ -75,6 +76,7 @@ typedef struct SiFiveUOTPState {
> uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
> /* config */
> uint32_t serial;
> + BlockBackend *blk;
> } SiFiveUOTPState;
>
> #endif /* HW_SIFIVE_U_OTP_H */
> --
Regards,
Bin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH v4 2/2] hw/riscv: sifive_u: Add write-once protection
2020-08-27 7:46 ` [RFC PATCH v4 2/2] hw/riscv: sifive_u: Add write-once protection Green Wan
@ 2020-08-28 13:08 ` Bin Meng
0 siblings, 0 replies; 6+ messages in thread
From: Bin Meng @ 2020-08-28 13:08 UTC (permalink / raw)
To: Green Wan
Cc: open list:RISC-V, Sagar Karandikar, Bastian Koppelmann,
qemu-devel@nongnu.org Developers, Alistair Francis,
Palmer Dabbelt
Hi Green,
On Thu, Aug 27, 2020 at 3:47 PM Green Wan <green.wan@sifive.com> wrote:
>
> Add array to store the 'written' status for all bit of OTP to block
> the write operation to the same bit. Ignore the control register
> offset from 0x0 to 0x38 of OTP memory mapping.
>
> Signed-off-by: Green Wan <green.wan@sifive.com>
> ---
> hw/riscv/sifive_u_otp.c | 21 +++++++++++++++++++++
> include/hw/riscv/sifive_u_otp.h | 1 +
> 2 files changed, 22 insertions(+)
>
> diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
> index aab2220494..e9605b9ae9 100644
> --- a/hw/riscv/sifive_u_otp.c
> +++ b/hw/riscv/sifive_u_otp.c
> @@ -27,6 +27,12 @@
> #include "sysemu/blockdev.h"
> #include "sysemu/block-backend.h"
>
> +#define SET_WRITTEN_BIT(map, idx, bit) \
> + (map[idx] |= (0x1 << bit))
> +
> +#define GET_WRITTEN_BIT(map, idx, bit) \
> + ((map[idx] >> bit) & 0x1)
> +
> static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
> {
> SiFiveUOTPState *s = opaque;
> @@ -135,6 +141,18 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
> s->ptrim = val32;
> break;
> case SIFIVE_U_OTP_PWE:
> + /* Keep written state for data only and PWE is enabled. Ignore PAS=1 */
> + if ((s->pa > SIFIVE_U_OTP_PWE) && (val32 & 0x1) && !s->pas) {
s->pa represents the OTP memory address, and it has nothing to do with
the OTP controller register SIFIVE_U_OTP_PWE.
Please replace 0x1 with a macro like SIFIVE_U_OTP_PWE_EN.
> + if (GET_WRITTEN_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;
> + }
> +
> + SET_WRITTEN_BIT(s->fuse_wo, s->pa, s->paio);
Note this only protects 1 bit, so you should probably change the write
operation to operate on a bit basis instead of 4 bytes
(SIFIVE_U_OTP_FUSE_WORD).
> + }
> +
> /* write to backend */
> if (s->blk) {
> blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &val32,
> @@ -215,6 +233,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 13d2552e43..49d40a6430 100644
> --- a/include/hw/riscv/sifive_u_otp.h
> +++ b/include/hw/riscv/sifive_u_otp.h
> @@ -74,6 +74,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;
> BlockBackend *blk;
> --
Regards,
Bin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH v4 1/2] hw/riscv: sifive_u: Add backend drive support
2020-08-28 12:54 ` Bin Meng
@ 2020-09-01 7:22 ` Green Wan
0 siblings, 0 replies; 6+ messages in thread
From: Green Wan @ 2020-09-01 7:22 UTC (permalink / raw)
To: Bin Meng
Cc: open list:RISC-V, Sagar Karandikar, Bastian Koppelmann,
qemu-devel@nongnu.org Developers, Alistair Francis,
Palmer Dabbelt
Hi Bin,
Thanks for the remindings. I didn't notice the write operation and
will add the write functionality based on bit by bit mechanism.
Regards,
Green
On Fri, Aug 28, 2020 at 8:54 PM Bin Meng <bmeng.cn@gmail.com> wrote:
>
> Hi Green,
>
> On Thu, Aug 27, 2020 at 3:47 PM Green Wan <green.wan@sifive.com> wrote:
> >
> > Add '-drive' support to OTP device. Allow users to assign a raw file
> > as OTP image.
> >
> > Signed-off-by: Green Wan <green.wan@sifive.com>
> > ---
> > hw/riscv/sifive_u_otp.c | 50 +++++++++++++++++++++++++++++++++
> > include/hw/riscv/sifive_u_otp.h | 2 ++
> > 2 files changed, 52 insertions(+)
> >
> > diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
> > index f6ecbaa2ca..aab2220494 100644
> > --- a/hw/riscv/sifive_u_otp.c
> > +++ b/hw/riscv/sifive_u_otp.c
> > @@ -24,6 +24,8 @@
> > #include "qemu/log.h"
> > #include "qemu/module.h"
> > #include "hw/riscv/sifive_u_otp.h"
> > +#include "sysemu/blockdev.h"
> > +#include "sysemu/block-backend.h"
> >
> > static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
> > {
> > @@ -46,6 +48,16 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
> > if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
> > (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
> > (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
> > +
> > + /* read from backend */
> > + if (s->blk) {
> > + int32_t buf;
> > +
> > + blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf,
> > + SIFIVE_U_OTP_FUSE_WORD);
> > + return buf;
> > + }
> > +
> > return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
> > } else {
> > return 0xff;
> > @@ -123,6 +135,12 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr,
> > s->ptrim = val32;
> > break;
> > case SIFIVE_U_OTP_PWE:
> > + /* write to backend */
> > + if (s->blk) {
> > + blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &val32,
>
> The logic looks wrong to me. According to the U-Boot driver
> (sifive-otp.c) the content to be written to the OTP memory comes from
> s->pdin bit by bit. Here val32 represents whether to disable write or
> enable write.
>
> I think we should arrange patches like this:
>
> patch 1 to add OTP write functionality, to the existing s->fuse[] mechanism
> patch 2 to add file based backend write support
>
> > + SIFIVE_U_OTP_FUSE_WORD, 0);
> > + }
> > +
> > s->pwe = val32;
> > break;
> > default:
> > @@ -143,16 +161,48 @@ static const MemoryRegionOps sifive_u_otp_ops = {
> >
> > static Property sifive_u_otp_properties[] = {
> > DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0),
> > + DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk),
> > DEFINE_PROP_END_OF_LIST(),
> > };
> >
> > static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
> > {
> > SiFiveUOTPState *s = SIFIVE_U_OTP(dev);
> > + DriveInfo *dinfo;
> >
> > memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s,
> > TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
> > sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
> > +
> > + dinfo = drive_get_next(IF_NONE);
> > + if (dinfo) {
> > + int ret;
> > + uint64_t perm;
> > + int filesize;
> > + BlockBackend *blk;
> > +
> > + blk = blk_by_legacy_dinfo(dinfo);
> > + filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD;
> > + if (blk_getlength(blk) < filesize) {
> > + qemu_log_mask(LOG_GUEST_ERROR, "OTP drive size < 16K\n");
> > + return;
> > + }
> > +
> > + qdev_prop_set_drive(dev, "drive", blk);
> > +
> > + perm = BLK_PERM_CONSISTENT_READ |
> > + (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE);
> > + ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp);
> > + if (ret < 0) {
> > + qemu_log_mask(LOG_GUEST_ERROR, "set perm error.");
> > + }
> > +
> > + if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "failed to read the initial flash content");
> > + return;
> > + }
> > + }
> > }
> >
> > static void sifive_u_otp_reset(DeviceState *dev)
> > diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/riscv/sifive_u_otp.h
> > index 639297564a..13d2552e43 100644
> > --- a/include/hw/riscv/sifive_u_otp.h
> > +++ b/include/hw/riscv/sifive_u_otp.h
> > @@ -43,6 +43,7 @@
> >
> > #define SIFIVE_U_OTP_PA_MASK 0xfff
> > #define SIFIVE_U_OTP_NUM_FUSES 0x1000
> > +#define SIFIVE_U_OTP_FUSE_WORD 4
> > #define SIFIVE_U_OTP_SERIAL_ADDR 0xfc
> >
> > #define SIFIVE_U_OTP_REG_SIZE 0x1000
> > @@ -75,6 +76,7 @@ typedef struct SiFiveUOTPState {
> > uint32_t fuse[SIFIVE_U_OTP_NUM_FUSES];
> > /* config */
> > uint32_t serial;
> > + BlockBackend *blk;
> > } SiFiveUOTPState;
> >
> > #endif /* HW_SIFIVE_U_OTP_H */
> > --
>
> Regards,
> Bin
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2020-09-01 7:23 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-08-27 7:46 [RFC PATCH v4 0/2] Add file-backed and write-once features to OTP Green Wan
2020-08-27 7:46 ` [RFC PATCH v4 1/2] hw/riscv: sifive_u: Add backend drive support Green Wan
2020-08-28 12:54 ` Bin Meng
2020-09-01 7:22 ` Green Wan
2020-08-27 7:46 ` [RFC PATCH v4 2/2] hw/riscv: sifive_u: Add write-once protection Green Wan
2020-08-28 13:08 ` Bin Meng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).