From 0fa9e329454aaccc6dbb6a4f52ad0c88a060a3b6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 3 Sep 2020 18:40:14 +0800 Subject: hw/riscv: Move sifive_u_otp model to hw/misc This is an effort to clean up the hw/riscv directory. Ideally it should only contain the RISC-V SoC / machine codes plus generic codes. Let's move sifive_u_otp model to hw/misc directory. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <1599129623-68957-4-git-send-email-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- hw/misc/Kconfig | 3 + hw/misc/meson.build | 1 + hw/misc/sifive_u_otp.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ hw/riscv/Kconfig | 1 + hw/riscv/meson.build | 1 - hw/riscv/sifive_u_otp.c | 191 ------------------------------------------------ 6 files changed, 196 insertions(+), 192 deletions(-) create mode 100644 hw/misc/sifive_u_otp.c delete mode 100644 hw/riscv/sifive_u_otp.c (limited to 'hw') diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 65f3fdd..fa3d0f4 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -137,6 +137,9 @@ config AVR_POWER config SIFIVE_E_PRCI bool +config SIFIVE_U_OTP + bool + config SIFIVE_U_PRCI bool diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 9e9550e..018a88c 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -23,6 +23,7 @@ softmmu_ss.add(when: 'CONFIG_MOS6522', if_true: files('mos6522.c')) # RISC-V devices softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c')) +softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c')) # PKUnity SoC devices diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c new file mode 100644 index 0000000..c2f3c8e --- /dev/null +++ b/hw/misc/sifive_u_otp.c @@ -0,0 +1,191 @@ +/* + * 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/qdev-properties.h" +#include "hw/sysbus.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/misc/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; + } + + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", + __func__, addr); + return 0; +} + +static void sifive_u_otp_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + SiFiveUOTPState *s = opaque; + uint32_t val32 = (uint32_t)val64; + + switch (addr) { + case SIFIVE_U_OTP_PA: + s->pa = val32 & SIFIVE_U_OTP_PA_MASK; + break; + case SIFIVE_U_OTP_PAIO: + s->paio = val32; + break; + case SIFIVE_U_OTP_PAS: + s->pas = val32; + break; + case SIFIVE_U_OTP_PCE: + s->pce = val32; + break; + case SIFIVE_U_OTP_PCLK: + s->pclk = val32; + break; + case SIFIVE_U_OTP_PDIN: + s->pdin = val32; + break; + case SIFIVE_U_OTP_PDOUT: + /* read-only */ + break; + case SIFIVE_U_OTP_PDSTB: + s->pdstb = val32; + break; + case SIFIVE_U_OTP_PPROG: + s->pprog = val32; + break; + case SIFIVE_U_OTP_PTC: + s->ptc = val32; + break; + case SIFIVE_U_OTP_PTM: + s->ptm = val32; + break; + case SIFIVE_U_OTP_PTM_REP: + s->ptm_rep = val32; + break; + case SIFIVE_U_OTP_PTR: + s->ptr = val32; + break; + case SIFIVE_U_OTP_PTRIM: + s->ptrim = val32; + break; + case SIFIVE_U_OTP_PWE: + s->pwe = val32; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx + " v=0x%x\n", __func__, addr, val32); + } +} + +static const MemoryRegionOps sifive_u_otp_ops = { + .read = sifive_u_otp_read, + .write = sifive_u_otp_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static Property sifive_u_otp_properties[] = { + DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void sifive_u_otp_realize(DeviceState *dev, Error **errp) +{ + SiFiveUOTPState *s = SIFIVE_U_OTP(dev); + + 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); +} + +static void sifive_u_otp_reset(DeviceState *dev) +{ + SiFiveUOTPState *s = SIFIVE_U_OTP(dev); + + /* Initialize all fuses' initial value to 0xFFs */ + memset(s->fuse, 0xff, sizeof(s->fuse)); + + /* 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); +} + +static void sifive_u_otp_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + device_class_set_props(dc, sifive_u_otp_properties); + dc->realize = sifive_u_otp_realize; + dc->reset = sifive_u_otp_reset; +} + +static const TypeInfo sifive_u_otp_info = { + .name = TYPE_SIFIVE_U_OTP, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveUOTPState), + .class_init = sifive_u_otp_class_init, +}; + +static void sifive_u_otp_register_types(void) +{ + type_register_static(&sifive_u_otp_info); +} + +type_init(sifive_u_otp_register_types) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 109364b..76eaf77 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -24,6 +24,7 @@ config SIFIVE_U select HART select SIFIVE select SIFIVE_PDMA + select SIFIVE_U_OTP select SIFIVE_U_PRCI select UNIMP diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 3462cb5..74a73b2 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -11,7 +11,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_test.c')) riscv_ss.add(when: 'CONFIG_SIFIVE', if_true: files('sifive_uart.c')) riscv_ss.add(when: 'CONFIG_SIFIVE_E', if_true: files('sifive_e.c')) riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u.c')) -riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: files('sifive_u_otp.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('riscv_htif.c')) riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c')) riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: files('microchip_pfsoc.c')) diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c deleted file mode 100644 index f6ecbaa..0000000 --- a/hw/riscv/sifive_u_otp.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * 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/qdev-properties.h" -#include "hw/sysbus.h" -#include "qemu/log.h" -#include "qemu/module.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; - } - - qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", - __func__, addr); - return 0; -} - -static void sifive_u_otp_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned int size) -{ - SiFiveUOTPState *s = opaque; - uint32_t val32 = (uint32_t)val64; - - switch (addr) { - case SIFIVE_U_OTP_PA: - s->pa = val32 & SIFIVE_U_OTP_PA_MASK; - break; - case SIFIVE_U_OTP_PAIO: - s->paio = val32; - break; - case SIFIVE_U_OTP_PAS: - s->pas = val32; - break; - case SIFIVE_U_OTP_PCE: - s->pce = val32; - break; - case SIFIVE_U_OTP_PCLK: - s->pclk = val32; - break; - case SIFIVE_U_OTP_PDIN: - s->pdin = val32; - break; - case SIFIVE_U_OTP_PDOUT: - /* read-only */ - break; - case SIFIVE_U_OTP_PDSTB: - s->pdstb = val32; - break; - case SIFIVE_U_OTP_PPROG: - s->pprog = val32; - break; - case SIFIVE_U_OTP_PTC: - s->ptc = val32; - break; - case SIFIVE_U_OTP_PTM: - s->ptm = val32; - break; - case SIFIVE_U_OTP_PTM_REP: - s->ptm_rep = val32; - break; - case SIFIVE_U_OTP_PTR: - s->ptr = val32; - break; - case SIFIVE_U_OTP_PTRIM: - s->ptrim = val32; - break; - case SIFIVE_U_OTP_PWE: - s->pwe = val32; - break; - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%" HWADDR_PRIx - " v=0x%x\n", __func__, addr, val32); - } -} - -static const MemoryRegionOps sifive_u_otp_ops = { - .read = sifive_u_otp_read, - .write = sifive_u_otp_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4 - } -}; - -static Property sifive_u_otp_properties[] = { - DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static void sifive_u_otp_realize(DeviceState *dev, Error **errp) -{ - SiFiveUOTPState *s = SIFIVE_U_OTP(dev); - - 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); -} - -static void sifive_u_otp_reset(DeviceState *dev) -{ - SiFiveUOTPState *s = SIFIVE_U_OTP(dev); - - /* Initialize all fuses' initial value to 0xFFs */ - memset(s->fuse, 0xff, sizeof(s->fuse)); - - /* 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); -} - -static void sifive_u_otp_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - device_class_set_props(dc, sifive_u_otp_properties); - dc->realize = sifive_u_otp_realize; - dc->reset = sifive_u_otp_reset; -} - -static const TypeInfo sifive_u_otp_info = { - .name = TYPE_SIFIVE_U_OTP, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SiFiveUOTPState), - .class_init = sifive_u_otp_class_init, -}; - -static void sifive_u_otp_register_types(void) -{ - type_register_static(&sifive_u_otp_info); -} - -type_init(sifive_u_otp_register_types) -- cgit v1.1