From 89ece6f76f089bc415fc4b8c78f7dbe74113380c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 3 Sep 2020 18:40:12 +0800 Subject: hw/riscv: Move sifive_e_prci 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_e_prci model to hw/misc directory. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <1599129623-68957-2-git-send-email-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- hw/misc/sifive_e_prci.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 hw/misc/sifive_e_prci.c (limited to 'hw/misc/sifive_e_prci.c') diff --git a/hw/misc/sifive_e_prci.c b/hw/misc/sifive_e_prci.c new file mode 100644 index 0000000000..8ec4ee4b41 --- /dev/null +++ b/hw/misc/sifive_e_prci.c @@ -0,0 +1,125 @@ +/* + * QEMU SiFive E PRCI (Power, Reset, Clock, Interrupt) + * + * Copyright (c) 2017 SiFive, Inc. + * + * Simple model of the PRCI 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 "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/hw.h" +#include "hw/misc/sifive_e_prci.h" + +static uint64_t sifive_e_prci_read(void *opaque, hwaddr addr, unsigned int size) +{ + SiFiveEPRCIState *s = opaque; + switch (addr) { + case SIFIVE_E_PRCI_HFROSCCFG: + return s->hfrosccfg; + case SIFIVE_E_PRCI_HFXOSCCFG: + return s->hfxosccfg; + case SIFIVE_E_PRCI_PLLCFG: + return s->pllcfg; + case SIFIVE_E_PRCI_PLLOUTDIV: + return s->plloutdiv; + } + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%x\n", + __func__, (int)addr); + return 0; +} + +static void sifive_e_prci_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + SiFiveEPRCIState *s = opaque; + switch (addr) { + case SIFIVE_E_PRCI_HFROSCCFG: + s->hfrosccfg = (uint32_t) val64; + /* OSC stays ready */ + s->hfrosccfg |= SIFIVE_E_PRCI_HFROSCCFG_RDY; + break; + case SIFIVE_E_PRCI_HFXOSCCFG: + s->hfxosccfg = (uint32_t) val64; + /* OSC stays ready */ + s->hfxosccfg |= SIFIVE_E_PRCI_HFXOSCCFG_RDY; + break; + case SIFIVE_E_PRCI_PLLCFG: + s->pllcfg = (uint32_t) val64; + /* PLL stays locked */ + s->pllcfg |= SIFIVE_E_PRCI_PLLCFG_LOCK; + break; + case SIFIVE_E_PRCI_PLLOUTDIV: + s->plloutdiv = (uint32_t) val64; + break; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x v=0x%x\n", + __func__, (int)addr, (int)val64); + } +} + +static const MemoryRegionOps sifive_e_prci_ops = { + .read = sifive_e_prci_read, + .write = sifive_e_prci_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static void sifive_e_prci_init(Object *obj) +{ + SiFiveEPRCIState *s = SIFIVE_E_PRCI(obj); + + memory_region_init_io(&s->mmio, obj, &sifive_e_prci_ops, s, + TYPE_SIFIVE_E_PRCI, SIFIVE_E_PRCI_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); + + s->hfrosccfg = (SIFIVE_E_PRCI_HFROSCCFG_RDY | SIFIVE_E_PRCI_HFROSCCFG_EN); + s->hfxosccfg = (SIFIVE_E_PRCI_HFXOSCCFG_RDY | SIFIVE_E_PRCI_HFXOSCCFG_EN); + s->pllcfg = (SIFIVE_E_PRCI_PLLCFG_REFSEL | SIFIVE_E_PRCI_PLLCFG_BYPASS | + SIFIVE_E_PRCI_PLLCFG_LOCK); + s->plloutdiv = SIFIVE_E_PRCI_PLLOUTDIV_DIV1; +} + +static const TypeInfo sifive_e_prci_info = { + .name = TYPE_SIFIVE_E_PRCI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveEPRCIState), + .instance_init = sifive_e_prci_init, +}; + +static void sifive_e_prci_register_types(void) +{ + type_register_static(&sifive_e_prci_info); +} + +type_init(sifive_e_prci_register_types) + + +/* + * Create PRCI device. + */ +DeviceState *sifive_e_prci_create(hwaddr addr) +{ + DeviceState *dev = qdev_new(TYPE_SIFIVE_E_PRCI); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); + return dev; +} -- cgit v1.2.3-55-g7522