20
#include "qemu/osdep.h"
21
#include "qemu/units.h"
23
#include "migration/vmstate.h"
25
#include "qemu/module.h"
26
#include "hw/misc/allwinner-r40-ccu.h"
30
REG_PLL_CPUX_CTRL = 0x0000,
31
REG_PLL_AUDIO_CTRL = 0x0008,
32
REG_PLL_VIDEO0_CTRL = 0x0010,
33
REG_PLL_VE_CTRL = 0x0018,
34
REG_PLL_DDR0_CTRL = 0x0020,
35
REG_PLL_PERIPH0_CTRL = 0x0028,
36
REG_PLL_PERIPH1_CTRL = 0x002c,
37
REG_PLL_VIDEO1_CTRL = 0x0030,
38
REG_PLL_SATA_CTRL = 0x0034,
39
REG_PLL_GPU_CTRL = 0x0038,
40
REG_PLL_MIPI_CTRL = 0x0040,
41
REG_PLL_DE_CTRL = 0x0048,
42
REG_PLL_DDR1_CTRL = 0x004c,
43
REG_AHB1_APB1_CFG = 0x0054,
44
REG_APB2_CFG = 0x0058,
45
REG_MMC0_CLK = 0x0088,
46
REG_MMC1_CLK = 0x008c,
47
REG_MMC2_CLK = 0x0090,
48
REG_MMC3_CLK = 0x0094,
49
REG_USBPHY_CFG = 0x00cc,
50
REG_PLL_DDR_AUX = 0x00f0,
51
REG_DRAM_CFG = 0x00f4,
52
REG_PLL_DDR1_CFG = 0x00f8,
53
REG_DRAM_CLK_GATING = 0x0100,
54
REG_GMAC_CLK = 0x0164,
55
REG_SYS_32K_CLK = 0x0310,
56
REG_PLL_LOCK_CTRL = 0x0320,
59
#define REG_INDEX(offset) (offset / sizeof(uint32_t))
63
REG_PLL_ENABLE = (1 << 31),
64
REG_PLL_LOCK = (1 << 28),
67
static uint64_t allwinner_r40_ccu_read(void *opaque, hwaddr offset,
70
const AwR40ClockCtlState *s = AW_R40_CCU(opaque);
71
const uint32_t idx = REG_INDEX(offset);
74
case 0x324 ... AW_R40_CCU_IOSIZE:
75
qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
76
__func__, (uint32_t)offset);
83
static void allwinner_r40_ccu_write(void *opaque, hwaddr offset,
84
uint64_t val, unsigned size)
86
AwR40ClockCtlState *s = AW_R40_CCU(opaque);
93
case REG_PLL_DDR1_CTRL:
96
if (val & REG_PLL_ENABLE) {
100
case REG_PLL_CPUX_CTRL:
101
case REG_PLL_AUDIO_CTRL:
102
case REG_PLL_VE_CTRL:
103
case REG_PLL_VIDEO0_CTRL:
104
case REG_PLL_DDR0_CTRL:
105
case REG_PLL_PERIPH0_CTRL:
106
case REG_PLL_PERIPH1_CTRL:
107
case REG_PLL_VIDEO1_CTRL:
108
case REG_PLL_SATA_CTRL:
109
case REG_PLL_GPU_CTRL:
110
case REG_PLL_MIPI_CTRL:
111
case REG_PLL_DE_CTRL:
112
if (val & REG_PLL_ENABLE) {
116
case 0x324 ... AW_R40_CCU_IOSIZE:
117
qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
118
__func__, (uint32_t)offset);
121
qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
122
__func__, (uint32_t)offset);
126
s->regs[REG_INDEX(offset)] = (uint32_t) val;
129
static const MemoryRegionOps allwinner_r40_ccu_ops = {
130
.read = allwinner_r40_ccu_read,
131
.write = allwinner_r40_ccu_write,
132
.endianness = DEVICE_NATIVE_ENDIAN,
134
.min_access_size = 4,
135
.max_access_size = 4,
137
.impl.min_access_size = 4,
140
static void allwinner_r40_ccu_reset(DeviceState *dev)
142
AwR40ClockCtlState *s = AW_R40_CCU(dev);
144
memset(s->regs, 0, sizeof(s->regs));
147
s->regs[REG_INDEX(REG_PLL_CPUX_CTRL)] = 0x00001000;
148
s->regs[REG_INDEX(REG_PLL_AUDIO_CTRL)] = 0x00035514;
149
s->regs[REG_INDEX(REG_PLL_VIDEO0_CTRL)] = 0x03006207;
150
s->regs[REG_INDEX(REG_PLL_VE_CTRL)] = 0x03006207;
151
s->regs[REG_INDEX(REG_PLL_DDR0_CTRL)] = 0x00001000,
152
s->regs[REG_INDEX(REG_PLL_PERIPH0_CTRL)] = 0x00041811;
153
s->regs[REG_INDEX(REG_PLL_PERIPH1_CTRL)] = 0x00041811;
154
s->regs[REG_INDEX(REG_PLL_VIDEO1_CTRL)] = 0x03006207;
155
s->regs[REG_INDEX(REG_PLL_SATA_CTRL)] = 0x00001811;
156
s->regs[REG_INDEX(REG_PLL_GPU_CTRL)] = 0x03006207;
157
s->regs[REG_INDEX(REG_PLL_MIPI_CTRL)] = 0x00000515;
158
s->regs[REG_INDEX(REG_PLL_DE_CTRL)] = 0x03006207;
159
s->regs[REG_INDEX(REG_PLL_DDR1_CTRL)] = 0x00001800;
160
s->regs[REG_INDEX(REG_AHB1_APB1_CFG)] = 0x00001010;
161
s->regs[REG_INDEX(REG_APB2_CFG)] = 0x01000000;
162
s->regs[REG_INDEX(REG_PLL_DDR_AUX)] = 0x00000001;
163
s->regs[REG_INDEX(REG_PLL_DDR1_CFG)] = 0x0ccca000;
164
s->regs[REG_INDEX(REG_SYS_32K_CLK)] = 0x0000000f;
167
static void allwinner_r40_ccu_init(Object *obj)
169
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
170
AwR40ClockCtlState *s = AW_R40_CCU(obj);
173
memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_r40_ccu_ops, s,
174
TYPE_AW_R40_CCU, AW_R40_CCU_IOSIZE);
175
sysbus_init_mmio(sbd, &s->iomem);
178
static const VMStateDescription allwinner_r40_ccu_vmstate = {
179
.name = "allwinner-r40-ccu",
181
.minimum_version_id = 1,
182
.fields = (const VMStateField[]) {
183
VMSTATE_UINT32_ARRAY(regs, AwR40ClockCtlState, AW_R40_CCU_REGS_NUM),
184
VMSTATE_END_OF_LIST()
188
static void allwinner_r40_ccu_class_init(ObjectClass *klass, void *data)
190
DeviceClass *dc = DEVICE_CLASS(klass);
192
dc->reset = allwinner_r40_ccu_reset;
193
dc->vmsd = &allwinner_r40_ccu_vmstate;
196
static const TypeInfo allwinner_r40_ccu_info = {
197
.name = TYPE_AW_R40_CCU,
198
.parent = TYPE_SYS_BUS_DEVICE,
199
.instance_init = allwinner_r40_ccu_init,
200
.instance_size = sizeof(AwR40ClockCtlState),
201
.class_init = allwinner_r40_ccu_class_init,
204
static void allwinner_r40_ccu_register(void)
206
type_register_static(&allwinner_r40_ccu_info);
209
type_init(allwinner_r40_ccu_register)