Re: [Qemu-devel] [PATCH v4 24/28] riscv: sifive: Implement a model for SiFive FU540 OTP

2019-08-22 Thread Alistair Francis
On Sun, Aug 18, 2019 at 10:19 PM Bin Meng  wrote:
>
> This implements a simple model for SiFive FU540 OTP (One-Time
> Programmable) Memory interface, primarily for reading out the
> stored serial number from the first 1 KiB of the 16 KiB OTP
> memory reserved by SiFive for internal use.
>
> Signed-off-by: Bin Meng 
>
> ---
>
> Changes in v4:
> - prefix all macros/variables/functions with SIFIVE_U/sifive_u
>   in the sifive_u_otp driver
>
> Changes in v3: None
> Changes in v2: None
>
>  hw/riscv/Makefile.objs  |   1 +
>  hw/riscv/sifive_u_otp.c | 194 
> 
>  include/hw/riscv/sifive_u_otp.h |  90 +++
>  3 files changed, 285 insertions(+)
>  create mode 100644 hw/riscv/sifive_u_otp.c
>  create mode 100644 include/hw/riscv/sifive_u_otp.h
>
> diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs
> index b95bbd5..fc3c6dd 100644
> --- a/hw/riscv/Makefile.objs
> +++ b/hw/riscv/Makefile.objs
> @@ -8,6 +8,7 @@ obj-$(CONFIG_SIFIVE) += sifive_gpio.o
>  obj-$(CONFIG_SIFIVE) += sifive_plic.o
>  obj-$(CONFIG_SIFIVE) += sifive_test.o
>  obj-$(CONFIG_SIFIVE_U) += sifive_u.o
> +obj-$(CONFIG_SIFIVE_U) += sifive_u_otp.o
>  obj-$(CONFIG_SIFIVE_U) += sifive_u_prci.o
>  obj-$(CONFIG_SIFIVE) += sifive_uart.o
>  obj-$(CONFIG_SPIKE) += spike.o
> diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
> new file mode 100644
> index 000..de8801c
> --- /dev/null
> +++ b/hw/riscv/sifive_u_otp.c
> @@ -0,0 +1,194 @@
> +/*
> + * QEMU SiFive U OTP (One-Time Programmable) Memory interface
> + *
> + * Copyright (c) 2019 Bin Meng 
> + *
> + * Simple model of the OTP to emulate register reads made by the SDK BSP
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along 
> with
> + * this program.  If not, see .
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "qemu/module.h"
> +#include "target/riscv/cpu.h"
> +#include "hw/riscv/sifive_u_otp.h"
> +
> +static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int 
> size)
> +{
> +SiFiveUOTPState *s = opaque;
> +
> +switch (addr) {
> +case SIFIVE_U_OTP_PA:
> +return s->pa;
> +case SIFIVE_U_OTP_PAIO:
> +return s->paio;
> +case SIFIVE_U_OTP_PAS:
> +return s->pas;
> +case SIFIVE_U_OTP_PCE:
> +return s->pce;
> +case SIFIVE_U_OTP_PCLK:
> +return s->pclk;
> +case SIFIVE_U_OTP_PDIN:
> +return s->pdin;
> +case SIFIVE_U_OTP_PDOUT:
> +if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
> +(s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
> +(s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
> +return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
> +} else {
> +return 0xff;
> +}
> +case SIFIVE_U_OTP_PDSTB:
> +return s->pdstb;
> +case SIFIVE_U_OTP_PPROG:
> +return s->pprog;
> +case SIFIVE_U_OTP_PTC:
> +return s->ptc;
> +case SIFIVE_U_OTP_PTM:
> +return s->ptm;
> +case SIFIVE_U_OTP_PTM_REP:
> +return s->ptm_rep;
> +case SIFIVE_U_OTP_PTR:
> +return s->ptr;
> +case SIFIVE_U_OTP_PTRIM:
> +return s->ptrim;
> +case SIFIVE_U_OTP_PWE:
> +return s->pwe;
> +}
> +
> +hw_error("%s: read: addr=0x%x\n", __func__, (int)addr);

This should be qem_log_mask().

> +return 0;
> +}
> +
> +static void sifive_u_otp_write(void *opaque, hwaddr addr,
> +   uint64_t val64, unsigned int size)
> +{
> +SiFiveUOTPState *s = opaque;
> +
> +switch (addr) {
> +case SIFIVE_U_OTP_PA:
> +s->pa = (uint32_t) val64 & SIFIVE_U_OTP_PA_MASK;
> +break;
> +case SIFIVE_U_OTP_PAIO:
> +s->paio = (uint32_t) val64;
> +break;
> +case SIFIVE_U_OTP_PAS:
> +s->pas = (uint32_t) val64;
> +break;
> +case SIFIVE_U_OTP_PCE:
> +s->pce = (uint32_t) val64;
> +break;
> +case SIFIVE_U_OTP_PCLK:
> +s->pclk = (uint32_t) val64;
> +break;
> +case SIFIVE_U_OTP_PDIN:
> +s->pdin = (uint32_t) val64;
> +break;
> +case SIFIVE_U_OTP_PDOUT:
> +/* read-only */
> +break;
> +case SIFIVE_U_OTP_PDSTB:
> +s->pdstb = (uint32_t) val64;
> +break;
> +case SIFIVE_U_OTP_PPROG:
> +s->pprog = (uint32_t) val64;
> +break;
> +case SIFIVE_U_OTP_PTC:
> +s->ptc = (uint32_t) val64;
> +break;
> +

[Qemu-devel] [PATCH v4 24/28] riscv: sifive: Implement a model for SiFive FU540 OTP

2019-08-18 Thread Bin Meng
This implements a simple model for SiFive FU540 OTP (One-Time
Programmable) Memory interface, primarily for reading out the
stored serial number from the first 1 KiB of the 16 KiB OTP
memory reserved by SiFive for internal use.

Signed-off-by: Bin Meng 

---

Changes in v4:
- prefix all macros/variables/functions with SIFIVE_U/sifive_u
  in the sifive_u_otp driver

Changes in v3: None
Changes in v2: None

 hw/riscv/Makefile.objs  |   1 +
 hw/riscv/sifive_u_otp.c | 194 
 include/hw/riscv/sifive_u_otp.h |  90 +++
 3 files changed, 285 insertions(+)
 create mode 100644 hw/riscv/sifive_u_otp.c
 create mode 100644 include/hw/riscv/sifive_u_otp.h

diff --git a/hw/riscv/Makefile.objs b/hw/riscv/Makefile.objs
index b95bbd5..fc3c6dd 100644
--- a/hw/riscv/Makefile.objs
+++ b/hw/riscv/Makefile.objs
@@ -8,6 +8,7 @@ obj-$(CONFIG_SIFIVE) += sifive_gpio.o
 obj-$(CONFIG_SIFIVE) += sifive_plic.o
 obj-$(CONFIG_SIFIVE) += sifive_test.o
 obj-$(CONFIG_SIFIVE_U) += sifive_u.o
+obj-$(CONFIG_SIFIVE_U) += sifive_u_otp.o
 obj-$(CONFIG_SIFIVE_U) += sifive_u_prci.o
 obj-$(CONFIG_SIFIVE) += sifive_uart.o
 obj-$(CONFIG_SPIKE) += spike.o
diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c
new file mode 100644
index 000..de8801c
--- /dev/null
+++ b/hw/riscv/sifive_u_otp.c
@@ -0,0 +1,194 @@
+/*
+ * QEMU SiFive U OTP (One-Time Programmable) Memory interface
+ *
+ * Copyright (c) 2019 Bin Meng 
+ *
+ * Simple model of the OTP to emulate register reads made by the SDK BSP
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qemu/module.h"
+#include "target/riscv/cpu.h"
+#include "hw/riscv/sifive_u_otp.h"
+
+static uint64_t sifive_u_otp_read(void *opaque, hwaddr addr, unsigned int size)
+{
+SiFiveUOTPState *s = opaque;
+
+switch (addr) {
+case SIFIVE_U_OTP_PA:
+return s->pa;
+case SIFIVE_U_OTP_PAIO:
+return s->paio;
+case SIFIVE_U_OTP_PAS:
+return s->pas;
+case SIFIVE_U_OTP_PCE:
+return s->pce;
+case SIFIVE_U_OTP_PCLK:
+return s->pclk;
+case SIFIVE_U_OTP_PDIN:
+return s->pdin;
+case SIFIVE_U_OTP_PDOUT:
+if ((s->pce & SIFIVE_U_OTP_PCE_EN) &&
+(s->pdstb & SIFIVE_U_OTP_PDSTB_EN) &&
+(s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) {
+return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK];
+} else {
+return 0xff;
+}
+case SIFIVE_U_OTP_PDSTB:
+return s->pdstb;
+case SIFIVE_U_OTP_PPROG:
+return s->pprog;
+case SIFIVE_U_OTP_PTC:
+return s->ptc;
+case SIFIVE_U_OTP_PTM:
+return s->ptm;
+case SIFIVE_U_OTP_PTM_REP:
+return s->ptm_rep;
+case SIFIVE_U_OTP_PTR:
+return s->ptr;
+case SIFIVE_U_OTP_PTRIM:
+return s->ptrim;
+case SIFIVE_U_OTP_PWE:
+return s->pwe;
+}
+
+hw_error("%s: read: addr=0x%x\n", __func__, (int)addr);
+return 0;
+}
+
+static void sifive_u_otp_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+SiFiveUOTPState *s = opaque;
+
+switch (addr) {
+case SIFIVE_U_OTP_PA:
+s->pa = (uint32_t) val64 & SIFIVE_U_OTP_PA_MASK;
+break;
+case SIFIVE_U_OTP_PAIO:
+s->paio = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PAS:
+s->pas = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PCE:
+s->pce = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PCLK:
+s->pclk = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PDIN:
+s->pdin = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PDOUT:
+/* read-only */
+break;
+case SIFIVE_U_OTP_PDSTB:
+s->pdstb = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PPROG:
+s->pprog = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PTC:
+s->ptc = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PTM:
+s->ptm = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PTM_REP:
+s->ptm_rep = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PTR:
+s->ptr = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PTRIM:
+s->ptrim = (uint32_t) val64;
+break;
+case SIFIVE_U_OTP_PWE:
+s->pwe = (uint32_t)