1 | /* |
2 | * QEMU SiFive PRCI (Power, Reset, Clock, Interrupt) |
3 | * |
4 | * Copyright (c) 2017 SiFive, Inc. |
5 | * |
6 | * Simple model of the PRCI to emulate register reads made by the SDK BSP |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms and conditions of the GNU General Public License, |
10 | * version 2 or later, as published by the Free Software Foundation. |
11 | * |
12 | * This program is distributed in the hope it will be useful, but WITHOUT |
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
15 | * more details. |
16 | * |
17 | * You should have received a copy of the GNU General Public License along with |
18 | * this program. If not, see <http://www.gnu.org/licenses/>. |
19 | */ |
20 | |
21 | #include "qemu/osdep.h" |
22 | #include "hw/hw.h" |
23 | #include "hw/sysbus.h" |
24 | #include "qemu/module.h" |
25 | #include "target/riscv/cpu.h" |
26 | #include "hw/hw.h" |
27 | #include "hw/riscv/sifive_prci.h" |
28 | |
29 | static uint64_t sifive_prci_read(void *opaque, hwaddr addr, unsigned int size) |
30 | { |
31 | SiFivePRCIState *s = opaque; |
32 | switch (addr) { |
33 | case SIFIVE_PRCI_HFROSCCFG: |
34 | return s->hfrosccfg; |
35 | case SIFIVE_PRCI_HFXOSCCFG: |
36 | return s->hfxosccfg; |
37 | case SIFIVE_PRCI_PLLCFG: |
38 | return s->pllcfg; |
39 | case SIFIVE_PRCI_PLLOUTDIV: |
40 | return s->plloutdiv; |
41 | } |
42 | hw_error("%s: read: addr=0x%x\n" , __func__, (int)addr); |
43 | return 0; |
44 | } |
45 | |
46 | static void sifive_prci_write(void *opaque, hwaddr addr, |
47 | uint64_t val64, unsigned int size) |
48 | { |
49 | SiFivePRCIState *s = opaque; |
50 | switch (addr) { |
51 | case SIFIVE_PRCI_HFROSCCFG: |
52 | s->hfrosccfg = (uint32_t) val64; |
53 | /* OSC stays ready */ |
54 | s->hfrosccfg |= SIFIVE_PRCI_HFROSCCFG_RDY; |
55 | break; |
56 | case SIFIVE_PRCI_HFXOSCCFG: |
57 | s->hfxosccfg = (uint32_t) val64; |
58 | /* OSC stays ready */ |
59 | s->hfxosccfg |= SIFIVE_PRCI_HFXOSCCFG_RDY; |
60 | break; |
61 | case SIFIVE_PRCI_PLLCFG: |
62 | s->pllcfg = (uint32_t) val64; |
63 | /* PLL stays locked */ |
64 | s->pllcfg |= SIFIVE_PRCI_PLLCFG_LOCK; |
65 | break; |
66 | case SIFIVE_PRCI_PLLOUTDIV: |
67 | s->plloutdiv = (uint32_t) val64; |
68 | break; |
69 | default: |
70 | hw_error("%s: bad write: addr=0x%x v=0x%x\n" , |
71 | __func__, (int)addr, (int)val64); |
72 | } |
73 | } |
74 | |
75 | static const MemoryRegionOps sifive_prci_ops = { |
76 | .read = sifive_prci_read, |
77 | .write = sifive_prci_write, |
78 | .endianness = DEVICE_NATIVE_ENDIAN, |
79 | .valid = { |
80 | .min_access_size = 4, |
81 | .max_access_size = 4 |
82 | } |
83 | }; |
84 | |
85 | static void sifive_prci_init(Object *obj) |
86 | { |
87 | SiFivePRCIState *s = SIFIVE_PRCI(obj); |
88 | |
89 | memory_region_init_io(&s->mmio, obj, &sifive_prci_ops, s, |
90 | TYPE_SIFIVE_PRCI, 0x8000); |
91 | sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); |
92 | |
93 | s->hfrosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN); |
94 | s->hfxosccfg = (SIFIVE_PRCI_HFROSCCFG_RDY | SIFIVE_PRCI_HFROSCCFG_EN); |
95 | s->pllcfg = (SIFIVE_PRCI_PLLCFG_REFSEL | SIFIVE_PRCI_PLLCFG_BYPASS | |
96 | SIFIVE_PRCI_PLLCFG_LOCK); |
97 | s->plloutdiv = SIFIVE_PRCI_PLLOUTDIV_DIV1; |
98 | |
99 | } |
100 | |
101 | static const TypeInfo sifive_prci_info = { |
102 | .name = TYPE_SIFIVE_PRCI, |
103 | .parent = TYPE_SYS_BUS_DEVICE, |
104 | .instance_size = sizeof(SiFivePRCIState), |
105 | .instance_init = sifive_prci_init, |
106 | }; |
107 | |
108 | static void sifive_prci_register_types(void) |
109 | { |
110 | type_register_static(&sifive_prci_info); |
111 | } |
112 | |
113 | type_init(sifive_prci_register_types) |
114 | |
115 | |
116 | /* |
117 | * Create PRCI device. |
118 | */ |
119 | DeviceState *sifive_prci_create(hwaddr addr) |
120 | { |
121 | DeviceState *dev = qdev_create(NULL, TYPE_SIFIVE_PRCI); |
122 | qdev_init_nofail(dev); |
123 | sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, addr); |
124 | return dev; |
125 | } |
126 | |