aboutsummaryrefslogtreecommitdiff
path: root/hw/arm/npcm7xx.c
diff options
context:
space:
mode:
authorHavard Skinnemoen <hskinnemoen@google.com>2020-09-10 22:20:55 -0700
committerPeter Maydell <peter.maydell@linaro.org>2020-09-14 14:24:59 +0100
commitc752bb079beb57a8527e55859ce4c416fb1663c3 (patch)
tree46149cb1a7a73df44d6c3e1a4e73e10a3864ffc7 /hw/arm/npcm7xx.c
parent4e89ccd685a381981c9b295888eb269b67c3320b (diff)
hw/nvram: NPCM7xx OTP device model
This supports reading and writing OTP fuses and keys. Only fuse reading has been tested. Protection is not implemented. Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Tested-by: Alexander Bulekov <alxndr@bu.edu> Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com> Message-id: 20200911052101.2602693-9-hskinnemoen@google.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/arm/npcm7xx.c')
-rw-r--r--hw/arm/npcm7xx.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
index 9669ac5fa0..9166002598 100644
--- a/hw/arm/npcm7xx.c
+++ b/hw/arm/npcm7xx.c
@@ -34,6 +34,10 @@
#define NPCM7XX_MMIO_BA (0x80000000)
#define NPCM7XX_MMIO_SZ (0x7ffd0000)
+/* OTP key storage and fuse strap array */
+#define NPCM7XX_OTP1_BA (0xf0189000)
+#define NPCM7XX_OTP2_BA (0xf018a000)
+
/* Core system modules. */
#define NPCM7XX_L2C_BA (0xf03fc000)
#define NPCM7XX_CPUP_BA (0xf03fe000)
@@ -144,6 +148,20 @@ void npcm7xx_load_kernel(MachineState *machine, NPCM7xxState *soc)
arm_load_kernel(&soc->cpu[0], machine, &npcm7xx_binfo);
}
+static void npcm7xx_init_fuses(NPCM7xxState *s)
+{
+ NPCM7xxClass *nc = NPCM7XX_GET_CLASS(s);
+ uint32_t value;
+
+ /*
+ * The initial mask of disabled modules indicates the chip derivative (e.g.
+ * NPCM750 or NPCM730).
+ */
+ value = tswap32(nc->disabled_modules);
+ npcm7xx_otp_array_write(&s->fuse_array, &value, NPCM7XX_FUSE_DERIVATIVE,
+ sizeof(value));
+}
+
static qemu_irq npcm7xx_irq(NPCM7xxState *s, int n)
{
return qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
@@ -164,6 +182,10 @@ static void npcm7xx_init(Object *obj)
object_property_add_alias(obj, "power-on-straps", OBJECT(&s->gcr),
"power-on-straps");
object_initialize_child(obj, "clk", &s->clk, TYPE_NPCM7XX_CLK);
+ object_initialize_child(obj, "otp1", &s->key_storage,
+ TYPE_NPCM7XX_KEY_STORAGE);
+ object_initialize_child(obj, "otp2", &s->fuse_array,
+ TYPE_NPCM7XX_FUSE_ARRAY);
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {
object_initialize_child(obj, "tim[*]", &s->tim[i], TYPE_NPCM7XX_TIMER);
@@ -232,6 +254,13 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->clk), &error_abort);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->clk), 0, NPCM7XX_CLK_BA);
+ /* OTP key storage and fuse strap array. Cannot fail. */
+ sysbus_realize(SYS_BUS_DEVICE(&s->key_storage), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->key_storage), 0, NPCM7XX_OTP1_BA);
+ sysbus_realize(SYS_BUS_DEVICE(&s->fuse_array), &error_abort);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->fuse_array), 0, NPCM7XX_OTP2_BA);
+ npcm7xx_init_fuses(s);
+
/* Timer Modules (TIM). Cannot fail. */
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_tim_addr) != ARRAY_SIZE(s->tim));
for (i = 0; i < ARRAY_SIZE(s->tim); i++) {