sifive_prci: Read and write PRCI registers
Writes to the SiFive PRCI registers are preserved while leaving the ready bits set for the HFX/HFR oscillators and the lock bit set for the PLL. Signed-off-by: Nathaniel Graff <nathaniel.graff@sifive.com> Reviewed-by: Michael Clark <mjc@sifive.com> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
This commit is contained in:
parent
b55d7d34f6
commit
b9d1848ebe
|
@ -24,15 +24,18 @@
|
|||
#include "target/riscv/cpu.h"
|
||||
#include "hw/riscv/sifive_prci.h"
|
||||
|
||||
/* currently implements enough to mock freedom-e-sdk BSP clock programming */
|
||||
|
||||
static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
if (addr == 0 /* PRCI_HFROSCCFG */) {
|
||||
return 1 << 31; /* ROSC_RDY */
|
||||
}
|
||||
if (addr == 8 /* PRCI_PLLCFG */) {
|
||||
return 1 << 31; /* PLL_LOCK */
|
||||
SiFivePRCIState *s = opaque;
|
||||
switch (addr) {
|
||||
case SIFIVE_PRCI_HFROSCCFG:
|
||||
return s->hfrosccfg;
|
||||
case SIFIVE_PRCI_HFXOSCCFG:
|
||||
return s->hfxosccfg;
|
||||
case SIFIVE_PRCI_PLLCFG:
|
||||
return s->pllcfg;
|
||||
case SIFIVE_PRCI_PLLOUTDIV:
|
||||
return s->plloutdiv;
|
||||
}
|
||||
hw_error("%s: read: addr=0x%x\n", __func__, (int)addr);
|
||||
return 0;
|
||||
|
@ -41,7 +44,30 @@ static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size)
|
|||
static void sifive_prci_write(void *opaque, hwaddr addr,
|
||||
uint64_t val64, unsigned int size)
|
||||
{
|
||||
/* discard writes */
|
||||
SiFivePRCIState *s = opaque;
|
||||
switch (addr) {
|
||||
case SIFIVE_PRCI_HFROSCCFG:
|
||||
s->hfrosccfg = (uint32_t) val64;
|
||||
/* OSC stays ready */
|
||||
s->hfrosccfg |= SIFIVE_PRCI_HFROSCCFG_RDY;
|
||||
break;
|
||||
case SIFIVE_PRCI_HFXOSCCFG:
|
||||
s->hfxosccfg = (uint32_t) val64;
|
||||
/* OSC stays ready */
|
||||
s->hfxosccfg |= SIFIVE_PRCI_HFXOSCCFG_RDY;
|
||||
break;
|
||||
case SIFIVE_PRCI_PLLCFG:
|
||||
s->pllcfg = (uint32_t) val64;
|
||||
/* PLL stays locked */
|
||||
s->pllcfg |= SIFIVE_PRCI_PLLCFG_LOCK;
|
||||
break;
|
||||
case SIFIVE_PRCI_PLLOUTDIV:
|
||||
s->plloutdiv = (uint32_t) val64;
|
||||
break;
|
||||
default:
|
||||
hw_error("%s: bad write: addr=0x%x v=0x%x\n",
|
||||
__func__, (int)addr, (int)val64);
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps sifive_prci_ops = {
|
||||
|
@ -61,6 +87,13 @@ static void sifive_prci_init(Object *obj)
|
|||
memory_region_init_io(&s->mmio, obj, &sifive_prci_ops, s,
|
||||
TYPE_SIFIVE_PRCI, 0x8000);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
|
||||
|
||||
s->hfrosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN);
|
||||
s->hfxosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN);
|
||||
s->pllcfg = (SIFIVE_PRCI_PLLCFG_REFSEL | SIFIVE_PRCI_PLLCFG_BYPASS |
|
||||
SIFIVE_PRCI_PLLCFG_LOCK);
|
||||
s->plloutdiv = SIFIVE_PRCI_PLLOUTDIV_DIV1;
|
||||
|
||||
}
|
||||
|
||||
static const TypeInfo sifive_prci_info = {
|
||||
|
|
|
@ -19,6 +19,34 @@
|
|||
#ifndef HW_SIFIVE_PRCI_H
|
||||
#define HW_SIFIVE_PRCI_H
|
||||
|
||||
enum {
|
||||
SIFIVE_PRCI_HFROSCCFG = 0x0,
|
||||
SIFIVE_PRCI_HFXOSCCFG = 0x4,
|
||||
SIFIVE_PRCI_PLLCFG = 0x8,
|
||||
SIFIVE_PRCI_PLLOUTDIV = 0xC
|
||||
};
|
||||
|
||||
enum {
|
||||
SIFIVE_PRCI_HFROSCCFG_RDY = (1 << 31),
|
||||
SIFIVE_PRCI_HFROSCCFG_EN = (1 << 30)
|
||||
};
|
||||
|
||||
enum {
|
||||
SIFIVE_PRCI_HFXOSCCFG_RDY = (1 << 31),
|
||||
SIFIVE_PRCI_HFXOSCCFG_EN = (1 << 30)
|
||||
};
|
||||
|
||||
enum {
|
||||
SIFIVE_PRCI_PLLCFG_PLLSEL = (1 << 16),
|
||||
SIFIVE_PRCI_PLLCFG_REFSEL = (1 << 17),
|
||||
SIFIVE_PRCI_PLLCFG_BYPASS = (1 << 18),
|
||||
SIFIVE_PRCI_PLLCFG_LOCK = (1 << 31)
|
||||
};
|
||||
|
||||
enum {
|
||||
SIFIVE_PRCI_PLLOUTDIV_DIV1 = (1 << 8)
|
||||
};
|
||||
|
||||
#define TYPE_SIFIVE_PRCI "riscv.sifive.prci"
|
||||
|
||||
#define SIFIVE_PRCI(obj) \
|
||||
|
@ -30,6 +58,10 @@ typedef struct SiFivePRCIState {
|
|||
|
||||
/*< public >*/
|
||||
MemoryRegion mmio;
|
||||
uint32_t hfrosccfg;
|
||||
uint32_t hfxosccfg;
|
||||
uint32_t pllcfg;
|
||||
uint32_t plloutdiv;
|
||||
} SiFivePRCIState;
|
||||
|
||||
DeviceState *sifive_prci_create(hwaddr addr);
|
||||
|
|
Loading…
Reference in a new issue