2 * Allwinner H3 System Control emulation
4 * Copyright (C) 2019 Niek Linnenbank <nieklinnenbank@gmail.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
21 #include "qemu/units.h"
22 #include "hw/sysbus.h"
23 #include "migration/vmstate.h"
25 #include "qemu/module.h"
26 #include "hw/misc/allwinner-h3-sysctrl.h"
28 /* System Control register offsets */
30 REG_VER
= 0x24, /* Version */
31 REG_EMAC_PHY_CLK
= 0x30, /* EMAC PHY Clock */
34 #define REG_INDEX(offset) (offset / sizeof(uint32_t))
36 /* System Control register reset values */
39 REG_EMAC_PHY_CLK_RST
= 0x58000,
42 static uint64_t allwinner_h3_sysctrl_read(void *opaque
, hwaddr offset
,
45 const AwH3SysCtrlState
*s
= AW_H3_SYSCTRL(opaque
);
46 const uint32_t idx
= REG_INDEX(offset
);
48 if (idx
>= AW_H3_SYSCTRL_REGS_NUM
) {
49 qemu_log_mask(LOG_GUEST_ERROR
, "%s: out-of-bounds offset 0x%04x\n",
50 __func__
, (uint32_t)offset
);
57 static void allwinner_h3_sysctrl_write(void *opaque
, hwaddr offset
,
58 uint64_t val
, unsigned size
)
60 AwH3SysCtrlState
*s
= AW_H3_SYSCTRL(opaque
);
61 const uint32_t idx
= REG_INDEX(offset
);
63 if (idx
>= AW_H3_SYSCTRL_REGS_NUM
) {
64 qemu_log_mask(LOG_GUEST_ERROR
, "%s: out-of-bounds offset 0x%04x\n",
65 __func__
, (uint32_t)offset
);
70 case REG_VER
: /* Version */
73 s
->regs
[idx
] = (uint32_t) val
;
78 static const MemoryRegionOps allwinner_h3_sysctrl_ops
= {
79 .read
= allwinner_h3_sysctrl_read
,
80 .write
= allwinner_h3_sysctrl_write
,
81 .endianness
= DEVICE_NATIVE_ENDIAN
,
86 .impl
.min_access_size
= 4,
89 static void allwinner_h3_sysctrl_reset(DeviceState
*dev
)
91 AwH3SysCtrlState
*s
= AW_H3_SYSCTRL(dev
);
93 /* Set default values for registers */
94 s
->regs
[REG_INDEX(REG_VER
)] = REG_VER_RST
;
95 s
->regs
[REG_INDEX(REG_EMAC_PHY_CLK
)] = REG_EMAC_PHY_CLK_RST
;
98 static void allwinner_h3_sysctrl_init(Object
*obj
)
100 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
101 AwH3SysCtrlState
*s
= AW_H3_SYSCTRL(obj
);
104 memory_region_init_io(&s
->iomem
, OBJECT(s
), &allwinner_h3_sysctrl_ops
, s
,
105 TYPE_AW_H3_SYSCTRL
, 4 * KiB
);
106 sysbus_init_mmio(sbd
, &s
->iomem
);
109 static const VMStateDescription allwinner_h3_sysctrl_vmstate
= {
110 .name
= "allwinner-h3-sysctrl",
112 .minimum_version_id
= 1,
113 .fields
= (const VMStateField
[]) {
114 VMSTATE_UINT32_ARRAY(regs
, AwH3SysCtrlState
, AW_H3_SYSCTRL_REGS_NUM
),
115 VMSTATE_END_OF_LIST()
119 static void allwinner_h3_sysctrl_class_init(ObjectClass
*klass
, void *data
)
121 DeviceClass
*dc
= DEVICE_CLASS(klass
);
123 device_class_set_legacy_reset(dc
, allwinner_h3_sysctrl_reset
);
124 dc
->vmsd
= &allwinner_h3_sysctrl_vmstate
;
127 static const TypeInfo allwinner_h3_sysctrl_info
= {
128 .name
= TYPE_AW_H3_SYSCTRL
,
129 .parent
= TYPE_SYS_BUS_DEVICE
,
130 .instance_init
= allwinner_h3_sysctrl_init
,
131 .instance_size
= sizeof(AwH3SysCtrlState
),
132 .class_init
= allwinner_h3_sysctrl_class_init
,
135 static void allwinner_h3_sysctrl_register(void)
137 type_register_static(&allwinner_h3_sysctrl_info
);
140 type_init(allwinner_h3_sysctrl_register
)