From 9fe640a53dd8ef33d32ab6e833fa9b6d1356cfae Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 3 Sep 2020 18:40:13 +0800 Subject: hw/riscv: Move sifive_u_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_u_prci model to hw/misc directory. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <1599129623-68957-3-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_prci.c | 169 +++++++++++++++++++++++++++++++++++++++ hw/riscv/Kconfig | 1 + hw/riscv/meson.build | 1 - hw/riscv/sifive_u_prci.c | 169 --------------------------------------- include/hw/misc/sifive_u_prci.h | 91 +++++++++++++++++++++ include/hw/riscv/sifive_u.h | 2 +- include/hw/riscv/sifive_u_prci.h | 91 --------------------- 9 files changed, 266 insertions(+), 262 deletions(-) create mode 100644 hw/misc/sifive_u_prci.c delete mode 100644 hw/riscv/sifive_u_prci.c create mode 100644 include/hw/misc/sifive_u_prci.h delete mode 100644 include/hw/riscv/sifive_u_prci.h diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig index 5073986..65f3fdd 100644 --- a/hw/misc/Kconfig +++ b/hw/misc/Kconfig @@ -137,4 +137,7 @@ config AVR_POWER config SIFIVE_E_PRCI bool +config SIFIVE_U_PRCI + bool + source macio/Kconfig diff --git a/hw/misc/meson.build b/hw/misc/meson.build index b6b2e57..9e9550e 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_PRCI', if_true: files('sifive_u_prci.c')) # PKUnity SoC devices softmmu_ss.add(when: 'CONFIG_PUV3', if_true: files('puv3_pm.c')) diff --git a/hw/misc/sifive_u_prci.c b/hw/misc/sifive_u_prci.c new file mode 100644 index 0000000..5d9d446 --- /dev/null +++ b/hw/misc/sifive_u_prci.c @@ -0,0 +1,169 @@ +/* + * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt) + * + * Copyright (c) 2019 Bin Meng + * + * 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 "qemu/log.h" +#include "qemu/module.h" +#include "hw/misc/sifive_u_prci.h" + +static uint64_t sifive_u_prci_read(void *opaque, hwaddr addr, unsigned int size) +{ + SiFiveUPRCIState *s = opaque; + + switch (addr) { + case SIFIVE_U_PRCI_HFXOSCCFG: + return s->hfxosccfg; + case SIFIVE_U_PRCI_COREPLLCFG0: + return s->corepllcfg0; + case SIFIVE_U_PRCI_DDRPLLCFG0: + return s->ddrpllcfg0; + case SIFIVE_U_PRCI_DDRPLLCFG1: + return s->ddrpllcfg1; + case SIFIVE_U_PRCI_GEMGXLPLLCFG0: + return s->gemgxlpllcfg0; + case SIFIVE_U_PRCI_GEMGXLPLLCFG1: + return s->gemgxlpllcfg1; + case SIFIVE_U_PRCI_CORECLKSEL: + return s->coreclksel; + case SIFIVE_U_PRCI_DEVICESRESET: + return s->devicesreset; + case SIFIVE_U_PRCI_CLKMUXSTATUS: + return s->clkmuxstatus; + } + + qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", + __func__, addr); + + return 0; +} + +static void sifive_u_prci_write(void *opaque, hwaddr addr, + uint64_t val64, unsigned int size) +{ + SiFiveUPRCIState *s = opaque; + uint32_t val32 = (uint32_t)val64; + + switch (addr) { + case SIFIVE_U_PRCI_HFXOSCCFG: + s->hfxosccfg = val32; + /* OSC stays ready */ + s->hfxosccfg |= SIFIVE_U_PRCI_HFXOSCCFG_RDY; + break; + case SIFIVE_U_PRCI_COREPLLCFG0: + s->corepllcfg0 = val32; + /* internal feedback */ + s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; + /* PLL stays locked */ + s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; + break; + case SIFIVE_U_PRCI_DDRPLLCFG0: + s->ddrpllcfg0 = val32; + /* internal feedback */ + s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; + /* PLL stays locked */ + s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; + break; + case SIFIVE_U_PRCI_DDRPLLCFG1: + s->ddrpllcfg1 = val32; + break; + case SIFIVE_U_PRCI_GEMGXLPLLCFG0: + s->gemgxlpllcfg0 = val32; + /* internal feedback */ + s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; + /* PLL stays locked */ + s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; + break; + case SIFIVE_U_PRCI_GEMGXLPLLCFG1: + s->gemgxlpllcfg1 = val32; + break; + case SIFIVE_U_PRCI_CORECLKSEL: + s->coreclksel = val32; + break; + case SIFIVE_U_PRCI_DEVICESRESET: + s->devicesreset = val32; + break; + case SIFIVE_U_PRCI_CLKMUXSTATUS: + s->clkmuxstatus = 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_prci_ops = { + .read = sifive_u_prci_read, + .write = sifive_u_prci_write, + .endianness = DEVICE_NATIVE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } +}; + +static void sifive_u_prci_realize(DeviceState *dev, Error **errp) +{ + SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev); + + memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_prci_ops, s, + TYPE_SIFIVE_U_PRCI, SIFIVE_U_PRCI_REG_SIZE); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); +} + +static void sifive_u_prci_reset(DeviceState *dev) +{ + SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev); + + /* Initialize register to power-on-reset values */ + s->hfxosccfg = SIFIVE_U_PRCI_HFXOSCCFG_RDY | SIFIVE_U_PRCI_HFXOSCCFG_EN; + s->corepllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | + SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | + SIFIVE_U_PRCI_PLLCFG0_LOCK; + s->ddrpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | + SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | + SIFIVE_U_PRCI_PLLCFG0_LOCK; + s->gemgxlpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | + SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | + SIFIVE_U_PRCI_PLLCFG0_LOCK; + s->coreclksel = SIFIVE_U_PRCI_CORECLKSEL_HFCLK; +} + +static void sifive_u_prci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = sifive_u_prci_realize; + dc->reset = sifive_u_prci_reset; +} + +static const TypeInfo sifive_u_prci_info = { + .name = TYPE_SIFIVE_U_PRCI, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SiFiveUPRCIState), + .class_init = sifive_u_prci_class_init, +}; + +static void sifive_u_prci_register_types(void) +{ + type_register_static(&sifive_u_prci_info); +} + +type_init(sifive_u_prci_register_types) diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index 5855e99..109364b 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_PRCI select UNIMP config SPIKE diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build index 003994d..3462cb5 100644 --- a/hw/riscv/meson.build +++ b/hw/riscv/meson.build @@ -12,7 +12,6 @@ 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_SIFIVE_U', if_true: files('sifive_u_prci.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_prci.c b/hw/riscv/sifive_u_prci.c deleted file mode 100644 index 4fa590c..0000000 --- a/hw/riscv/sifive_u_prci.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt) - * - * Copyright (c) 2019 Bin Meng - * - * 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 "qemu/log.h" -#include "qemu/module.h" -#include "hw/riscv/sifive_u_prci.h" - -static uint64_t sifive_u_prci_read(void *opaque, hwaddr addr, unsigned int size) -{ - SiFiveUPRCIState *s = opaque; - - switch (addr) { - case SIFIVE_U_PRCI_HFXOSCCFG: - return s->hfxosccfg; - case SIFIVE_U_PRCI_COREPLLCFG0: - return s->corepllcfg0; - case SIFIVE_U_PRCI_DDRPLLCFG0: - return s->ddrpllcfg0; - case SIFIVE_U_PRCI_DDRPLLCFG1: - return s->ddrpllcfg1; - case SIFIVE_U_PRCI_GEMGXLPLLCFG0: - return s->gemgxlpllcfg0; - case SIFIVE_U_PRCI_GEMGXLPLLCFG1: - return s->gemgxlpllcfg1; - case SIFIVE_U_PRCI_CORECLKSEL: - return s->coreclksel; - case SIFIVE_U_PRCI_DEVICESRESET: - return s->devicesreset; - case SIFIVE_U_PRCI_CLKMUXSTATUS: - return s->clkmuxstatus; - } - - qemu_log_mask(LOG_GUEST_ERROR, "%s: read: addr=0x%" HWADDR_PRIx "\n", - __func__, addr); - - return 0; -} - -static void sifive_u_prci_write(void *opaque, hwaddr addr, - uint64_t val64, unsigned int size) -{ - SiFiveUPRCIState *s = opaque; - uint32_t val32 = (uint32_t)val64; - - switch (addr) { - case SIFIVE_U_PRCI_HFXOSCCFG: - s->hfxosccfg = val32; - /* OSC stays ready */ - s->hfxosccfg |= SIFIVE_U_PRCI_HFXOSCCFG_RDY; - break; - case SIFIVE_U_PRCI_COREPLLCFG0: - s->corepllcfg0 = val32; - /* internal feedback */ - s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; - /* PLL stays locked */ - s->corepllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; - break; - case SIFIVE_U_PRCI_DDRPLLCFG0: - s->ddrpllcfg0 = val32; - /* internal feedback */ - s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; - /* PLL stays locked */ - s->ddrpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; - break; - case SIFIVE_U_PRCI_DDRPLLCFG1: - s->ddrpllcfg1 = val32; - break; - case SIFIVE_U_PRCI_GEMGXLPLLCFG0: - s->gemgxlpllcfg0 = val32; - /* internal feedback */ - s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_FSE; - /* PLL stays locked */ - s->gemgxlpllcfg0 |= SIFIVE_U_PRCI_PLLCFG0_LOCK; - break; - case SIFIVE_U_PRCI_GEMGXLPLLCFG1: - s->gemgxlpllcfg1 = val32; - break; - case SIFIVE_U_PRCI_CORECLKSEL: - s->coreclksel = val32; - break; - case SIFIVE_U_PRCI_DEVICESRESET: - s->devicesreset = val32; - break; - case SIFIVE_U_PRCI_CLKMUXSTATUS: - s->clkmuxstatus = 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_prci_ops = { - .read = sifive_u_prci_read, - .write = sifive_u_prci_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4 - } -}; - -static void sifive_u_prci_realize(DeviceState *dev, Error **errp) -{ - SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev); - - memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_prci_ops, s, - TYPE_SIFIVE_U_PRCI, SIFIVE_U_PRCI_REG_SIZE); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); -} - -static void sifive_u_prci_reset(DeviceState *dev) -{ - SiFiveUPRCIState *s = SIFIVE_U_PRCI(dev); - - /* Initialize register to power-on-reset values */ - s->hfxosccfg = SIFIVE_U_PRCI_HFXOSCCFG_RDY | SIFIVE_U_PRCI_HFXOSCCFG_EN; - s->corepllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | - SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | - SIFIVE_U_PRCI_PLLCFG0_LOCK; - s->ddrpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | - SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | - SIFIVE_U_PRCI_PLLCFG0_LOCK; - s->gemgxlpllcfg0 = SIFIVE_U_PRCI_PLLCFG0_DIVR | SIFIVE_U_PRCI_PLLCFG0_DIVF | - SIFIVE_U_PRCI_PLLCFG0_DIVQ | SIFIVE_U_PRCI_PLLCFG0_FSE | - SIFIVE_U_PRCI_PLLCFG0_LOCK; - s->coreclksel = SIFIVE_U_PRCI_CORECLKSEL_HFCLK; -} - -static void sifive_u_prci_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->realize = sifive_u_prci_realize; - dc->reset = sifive_u_prci_reset; -} - -static const TypeInfo sifive_u_prci_info = { - .name = TYPE_SIFIVE_U_PRCI, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SiFiveUPRCIState), - .class_init = sifive_u_prci_class_init, -}; - -static void sifive_u_prci_register_types(void) -{ - type_register_static(&sifive_u_prci_info); -} - -type_init(sifive_u_prci_register_types) diff --git a/include/hw/misc/sifive_u_prci.h b/include/hw/misc/sifive_u_prci.h new file mode 100644 index 0000000..0a531fd --- /dev/null +++ b/include/hw/misc/sifive_u_prci.h @@ -0,0 +1,91 @@ +/* + * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt) interface + * + * Copyright (c) 2019 Bin Meng + * + * 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 . + */ + +#ifndef HW_SIFIVE_U_PRCI_H +#define HW_SIFIVE_U_PRCI_H + +#define SIFIVE_U_PRCI_HFXOSCCFG 0x00 +#define SIFIVE_U_PRCI_COREPLLCFG0 0x04 +#define SIFIVE_U_PRCI_DDRPLLCFG0 0x0C +#define SIFIVE_U_PRCI_DDRPLLCFG1 0x10 +#define SIFIVE_U_PRCI_GEMGXLPLLCFG0 0x1C +#define SIFIVE_U_PRCI_GEMGXLPLLCFG1 0x20 +#define SIFIVE_U_PRCI_CORECLKSEL 0x24 +#define SIFIVE_U_PRCI_DEVICESRESET 0x28 +#define SIFIVE_U_PRCI_CLKMUXSTATUS 0x2C + +/* + * Current FU540-C000 manual says ready bit is at bit 29, but + * freedom-u540-c000-bootloader codes (ux00prci.h) says it is at bit 31. + * We have to trust the actual code that works. + * + * see https://github.com/sifive/freedom-u540-c000-bootloader + */ + +#define SIFIVE_U_PRCI_HFXOSCCFG_EN (1 << 30) +#define SIFIVE_U_PRCI_HFXOSCCFG_RDY (1 << 31) + +/* xxxPLLCFG0 register bits */ +#define SIFIVE_U_PRCI_PLLCFG0_DIVR (1 << 0) +#define SIFIVE_U_PRCI_PLLCFG0_DIVF (31 << 6) +#define SIFIVE_U_PRCI_PLLCFG0_DIVQ (3 << 15) +#define SIFIVE_U_PRCI_PLLCFG0_FSE (1 << 25) +#define SIFIVE_U_PRCI_PLLCFG0_LOCK (1 << 31) + +/* xxxPLLCFG1 register bits */ +#define SIFIVE_U_PRCI_PLLCFG1_CKE (1 << 24) + +/* coreclksel register bits */ +#define SIFIVE_U_PRCI_CORECLKSEL_HFCLK (1 << 0) + + +#define SIFIVE_U_PRCI_REG_SIZE 0x1000 + +#define TYPE_SIFIVE_U_PRCI "riscv.sifive.u.prci" + +#define SIFIVE_U_PRCI(obj) \ + OBJECT_CHECK(SiFiveUPRCIState, (obj), TYPE_SIFIVE_U_PRCI) + +typedef struct SiFiveUPRCIState { + /*< private >*/ + SysBusDevice parent_obj; + + /*< public >*/ + MemoryRegion mmio; + uint32_t hfxosccfg; + uint32_t corepllcfg0; + uint32_t ddrpllcfg0; + uint32_t ddrpllcfg1; + uint32_t gemgxlpllcfg0; + uint32_t gemgxlpllcfg1; + uint32_t coreclksel; + uint32_t devicesreset; + uint32_t clkmuxstatus; +} SiFiveUPRCIState; + +/* + * Clock indexes for use by Device Tree data and the PRCI driver. + * + * These values are from sifive-fu540-prci.h in the Linux kernel. + */ +#define PRCI_CLK_COREPLL 0 +#define PRCI_CLK_DDRPLL 1 +#define PRCI_CLK_GEMGXLPLL 2 +#define PRCI_CLK_TLCLK 3 + +#endif /* HW_SIFIVE_U_PRCI_H */ diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h index 793000a..cbeb228 100644 --- a/include/hw/riscv/sifive_u.h +++ b/include/hw/riscv/sifive_u.h @@ -24,8 +24,8 @@ #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_cpu.h" #include "hw/riscv/sifive_gpio.h" -#include "hw/riscv/sifive_u_prci.h" #include "hw/riscv/sifive_u_otp.h" +#include "hw/misc/sifive_u_prci.h" #define TYPE_RISCV_U_SOC "riscv.sifive.u.soc" #define RISCV_U_SOC(obj) \ diff --git a/include/hw/riscv/sifive_u_prci.h b/include/hw/riscv/sifive_u_prci.h deleted file mode 100644 index 0a531fd..0000000 --- a/include/hw/riscv/sifive_u_prci.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * QEMU SiFive U PRCI (Power, Reset, Clock, Interrupt) interface - * - * Copyright (c) 2019 Bin Meng - * - * 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 . - */ - -#ifndef HW_SIFIVE_U_PRCI_H -#define HW_SIFIVE_U_PRCI_H - -#define SIFIVE_U_PRCI_HFXOSCCFG 0x00 -#define SIFIVE_U_PRCI_COREPLLCFG0 0x04 -#define SIFIVE_U_PRCI_DDRPLLCFG0 0x0C -#define SIFIVE_U_PRCI_DDRPLLCFG1 0x10 -#define SIFIVE_U_PRCI_GEMGXLPLLCFG0 0x1C -#define SIFIVE_U_PRCI_GEMGXLPLLCFG1 0x20 -#define SIFIVE_U_PRCI_CORECLKSEL 0x24 -#define SIFIVE_U_PRCI_DEVICESRESET 0x28 -#define SIFIVE_U_PRCI_CLKMUXSTATUS 0x2C - -/* - * Current FU540-C000 manual says ready bit is at bit 29, but - * freedom-u540-c000-bootloader codes (ux00prci.h) says it is at bit 31. - * We have to trust the actual code that works. - * - * see https://github.com/sifive/freedom-u540-c000-bootloader - */ - -#define SIFIVE_U_PRCI_HFXOSCCFG_EN (1 << 30) -#define SIFIVE_U_PRCI_HFXOSCCFG_RDY (1 << 31) - -/* xxxPLLCFG0 register bits */ -#define SIFIVE_U_PRCI_PLLCFG0_DIVR (1 << 0) -#define SIFIVE_U_PRCI_PLLCFG0_DIVF (31 << 6) -#define SIFIVE_U_PRCI_PLLCFG0_DIVQ (3 << 15) -#define SIFIVE_U_PRCI_PLLCFG0_FSE (1 << 25) -#define SIFIVE_U_PRCI_PLLCFG0_LOCK (1 << 31) - -/* xxxPLLCFG1 register bits */ -#define SIFIVE_U_PRCI_PLLCFG1_CKE (1 << 24) - -/* coreclksel register bits */ -#define SIFIVE_U_PRCI_CORECLKSEL_HFCLK (1 << 0) - - -#define SIFIVE_U_PRCI_REG_SIZE 0x1000 - -#define TYPE_SIFIVE_U_PRCI "riscv.sifive.u.prci" - -#define SIFIVE_U_PRCI(obj) \ - OBJECT_CHECK(SiFiveUPRCIState, (obj), TYPE_SIFIVE_U_PRCI) - -typedef struct SiFiveUPRCIState { - /*< private >*/ - SysBusDevice parent_obj; - - /*< public >*/ - MemoryRegion mmio; - uint32_t hfxosccfg; - uint32_t corepllcfg0; - uint32_t ddrpllcfg0; - uint32_t ddrpllcfg1; - uint32_t gemgxlpllcfg0; - uint32_t gemgxlpllcfg1; - uint32_t coreclksel; - uint32_t devicesreset; - uint32_t clkmuxstatus; -} SiFiveUPRCIState; - -/* - * Clock indexes for use by Device Tree data and the PRCI driver. - * - * These values are from sifive-fu540-prci.h in the Linux kernel. - */ -#define PRCI_CLK_COREPLL 0 -#define PRCI_CLK_DDRPLL 1 -#define PRCI_CLK_GEMGXLPLL 2 -#define PRCI_CLK_TLCLK 3 - -#endif /* HW_SIFIVE_U_PRCI_H */ -- cgit v1.1