2 * Allwinner R40 SRAM controller emulation
4 * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.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 "qapi/error.h"
27 #include "hw/qdev-properties.h"
28 #include "hw/qdev-properties-system.h"
29 #include "hw/misc/allwinner-sramc.h"
34 * https://linux-sunxi.org/SRAM_Controller_Register_Guide
37 REG_SRAM_CTL1_CFG
= 0x04, /* SRAM Control register 1 */
38 REG_SRAM_VER
= 0x24, /* SRAM Version register */
39 REG_SRAM_R40_SOFT_ENTRY_REG0
= 0xbc,
42 /* REG_SRAMC_VERSION bit defines */
43 #define SRAM_VER_READ_ENABLE (1 << 15)
44 #define SRAM_VER_VERSION_SHIFT 16
45 #define SRAM_VERSION_SUN8I_R40 0x1701
47 static uint64_t allwinner_sramc_read(void *opaque
, hwaddr offset
,
50 AwSRAMCState
*s
= AW_SRAMC(opaque
);
51 AwSRAMCClass
*sc
= AW_SRAMC_GET_CLASS(s
);
55 case REG_SRAM_CTL1_CFG
:
59 /* bit15: lock bit, set this bit before reading this register */
60 if (s
->sram_ver
& SRAM_VER_READ_ENABLE
) {
61 val
= SRAM_VER_READ_ENABLE
|
62 (sc
->sram_version_code
<< SRAM_VER_VERSION_SHIFT
);
65 case REG_SRAM_R40_SOFT_ENTRY_REG0
:
66 val
= s
->sram_soft_entry_reg0
;
69 qemu_log_mask(LOG_GUEST_ERROR
, "%s: out-of-bounds offset 0x%04x\n",
70 __func__
, (uint32_t)offset
);
74 trace_allwinner_sramc_read(offset
, val
);
79 static void allwinner_sramc_write(void *opaque
, hwaddr offset
,
80 uint64_t val
, unsigned size
)
82 AwSRAMCState
*s
= AW_SRAMC(opaque
);
84 trace_allwinner_sramc_write(offset
, val
);
87 case REG_SRAM_CTL1_CFG
:
91 /* Only the READ_ENABLE bit is writeable */
92 s
->sram_ver
= val
& SRAM_VER_READ_ENABLE
;
94 case REG_SRAM_R40_SOFT_ENTRY_REG0
:
95 s
->sram_soft_entry_reg0
= val
;
98 qemu_log_mask(LOG_GUEST_ERROR
, "%s: out-of-bounds offset 0x%04x\n",
99 __func__
, (uint32_t)offset
);
104 static const MemoryRegionOps allwinner_sramc_ops
= {
105 .read
= allwinner_sramc_read
,
106 .write
= allwinner_sramc_write
,
107 .endianness
= DEVICE_NATIVE_ENDIAN
,
109 .min_access_size
= 4,
110 .max_access_size
= 4,
112 .impl
.min_access_size
= 4,
115 static const VMStateDescription allwinner_sramc_vmstate
= {
116 .name
= "allwinner-sramc",
118 .minimum_version_id
= 1,
119 .fields
= (VMStateField
[]) {
120 VMSTATE_UINT32(sram_ver
, AwSRAMCState
),
121 VMSTATE_UINT32(sram_soft_entry_reg0
, AwSRAMCState
),
122 VMSTATE_END_OF_LIST()
126 static void allwinner_sramc_reset(DeviceState
*dev
)
128 AwSRAMCState
*s
= AW_SRAMC(dev
);
129 AwSRAMCClass
*sc
= AW_SRAMC_GET_CLASS(s
);
131 switch (sc
->sram_version_code
) {
132 case SRAM_VERSION_SUN8I_R40
:
133 s
->sram_ctl1
= 0x1300;
138 static void allwinner_sramc_class_init(ObjectClass
*klass
, void *data
)
140 DeviceClass
*dc
= DEVICE_CLASS(klass
);
142 dc
->reset
= allwinner_sramc_reset
;
143 dc
->vmsd
= &allwinner_sramc_vmstate
;
146 static void allwinner_sramc_init(Object
*obj
)
148 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
149 AwSRAMCState
*s
= AW_SRAMC(obj
);
152 memory_region_init_io(&s
->iomem
, OBJECT(s
), &allwinner_sramc_ops
, s
,
153 TYPE_AW_SRAMC
, 1 * KiB
);
154 sysbus_init_mmio(sbd
, &s
->iomem
);
157 static const TypeInfo allwinner_sramc_info
= {
158 .name
= TYPE_AW_SRAMC
,
159 .parent
= TYPE_SYS_BUS_DEVICE
,
160 .instance_init
= allwinner_sramc_init
,
161 .instance_size
= sizeof(AwSRAMCState
),
162 .class_size
= sizeof(AwSRAMCClass
),
163 .class_init
= allwinner_sramc_class_init
,
166 static void allwinner_r40_sramc_class_init(ObjectClass
*klass
, void *data
)
168 AwSRAMCClass
*sc
= AW_SRAMC_CLASS(klass
);
170 sc
->sram_version_code
= SRAM_VERSION_SUN8I_R40
;
173 static const TypeInfo allwinner_r40_sramc_info
= {
174 .name
= TYPE_AW_SRAMC_SUN8I_R40
,
175 .parent
= TYPE_AW_SRAMC
,
176 .class_init
= allwinner_r40_sramc_class_init
,
179 static void allwinner_sramc_register(void)
181 type_register_static(&allwinner_sramc_info
);
182 type_register_static(&allwinner_r40_sramc_info
);
185 type_init(allwinner_sramc_register
)