aboutsummaryrefslogtreecommitdiff
path: root/hw/misc/aspeed_scu.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/misc/aspeed_scu.c')
-rw-r--r--hw/misc/aspeed_scu.c75
1 files changed, 53 insertions, 22 deletions
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index 451e837..a0ab5ee 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -91,6 +91,7 @@
#define BMC_DEV_ID TO_REG(0x1A4)
#define AST2600_PROT_KEY TO_REG(0x00)
+#define AST2600_PROT_KEY2 TO_REG(0x10)
#define AST2600_SILICON_REV TO_REG(0x04)
#define AST2600_SILICON_REV2 TO_REG(0x14)
#define AST2600_SYS_RST_CTRL TO_REG(0x40)
@@ -157,6 +158,7 @@
#define AST2700_SCU_FREQ_CNTR TO_REG(0x3b0)
#define AST2700_SCU_CPU_SCRATCH_0 TO_REG(0x780)
#define AST2700_SCU_CPU_SCRATCH_1 TO_REG(0x784)
+#define AST2700_SCU_VGA_SCRATCH_0 TO_REG(0x900)
#define AST2700_SCUIO_CLK_STOP_CTL_1 TO_REG(0x240)
#define AST2700_SCUIO_CLK_STOP_CLR_1 TO_REG(0x244)
@@ -175,6 +177,7 @@
#define AST2700_SCUIO_UARTCLK_GEN TO_REG(0x330)
#define AST2700_SCUIO_HUARTCLK_GEN TO_REG(0x334)
#define AST2700_SCUIO_CLK_DUTY_MEAS_RST TO_REG(0x388)
+#define AST2700_SCUIO_FREQ_CNT_CTL TO_REG(0x3A0)
#define SCU_IO_REGION_SIZE 0x1000
@@ -426,6 +429,10 @@ static const MemoryRegionOps aspeed_ast2400_scu_ops = {
.read = aspeed_scu_read,
.write = aspeed_ast2400_scu_write,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
.valid = {
.min_access_size = 1,
.max_access_size = 4,
@@ -436,7 +443,9 @@ static const MemoryRegionOps aspeed_ast2500_scu_ops = {
.read = aspeed_scu_read,
.write = aspeed_ast2500_scu_write,
.endianness = DEVICE_LITTLE_ENDIAN,
- .valid.min_access_size = 4,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 1,
.valid.max_access_size = 4,
.valid.unaligned = false,
};
@@ -559,6 +568,8 @@ static uint32_t aspeed_silicon_revs[] = {
AST2700_A0_SILICON_REV,
AST2720_A0_SILICON_REV,
AST2750_A0_SILICON_REV,
+ AST2700_A1_SILICON_REV,
+ AST2750_A1_SILICON_REV,
};
bool is_supported_silicon_rev(uint32_t silicon_rev)
@@ -602,19 +613,18 @@ static const VMStateDescription vmstate_aspeed_scu = {
}
};
-static Property aspeed_scu_properties[] = {
+static const Property aspeed_scu_properties[] = {
DEFINE_PROP_UINT32("silicon-rev", AspeedSCUState, silicon_rev, 0),
DEFINE_PROP_UINT32("hw-strap1", AspeedSCUState, hw_strap1, 0),
DEFINE_PROP_UINT32("hw-strap2", AspeedSCUState, hw_strap2, 0),
DEFINE_PROP_UINT32("hw-prot-key", AspeedSCUState, hw_prot_key, 0),
- DEFINE_PROP_END_OF_LIST(),
};
-static void aspeed_scu_class_init(ObjectClass *klass, void *data)
+static void aspeed_scu_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = aspeed_scu_realize;
- dc->reset = aspeed_scu_reset;
+ device_class_set_legacy_reset(dc, aspeed_scu_reset);
dc->desc = "ASPEED System Control Unit";
dc->vmsd = &vmstate_aspeed_scu;
device_class_set_props(dc, aspeed_scu_properties);
@@ -629,7 +639,7 @@ static const TypeInfo aspeed_scu_info = {
.abstract = true,
};
-static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
+static void aspeed_2400_scu_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
@@ -651,7 +661,7 @@ static const TypeInfo aspeed_2400_scu_info = {
.class_init = aspeed_2400_scu_class_init,
};
-static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
+static void aspeed_2500_scu_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
@@ -714,6 +724,8 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
int reg = TO_REG(offset);
/* Truncate here so bitwise operations below behave as expected */
uint32_t data = data64;
+ bool prot_data_state = data == ASPEED_SCU_PROT_KEY;
+ bool unlocked = s->regs[AST2600_PROT_KEY] && s->regs[AST2600_PROT_KEY2];
if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
qemu_log_mask(LOG_GUEST_ERROR,
@@ -722,15 +734,24 @@ static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset,
return;
}
- if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
+ if ((reg != AST2600_PROT_KEY && reg != AST2600_PROT_KEY2) && !unlocked) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
+ return;
}
trace_aspeed_scu_write(offset, size, data);
switch (reg) {
case AST2600_PROT_KEY:
- s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
+ /*
+ * Writing a value to SCU000 will modify both protection
+ * registers to each protection register individually.
+ */
+ s->regs[AST2600_PROT_KEY] = prot_data_state;
+ s->regs[AST2600_PROT_KEY2] = prot_data_state;
+ return;
+ case AST2600_PROT_KEY2:
+ s->regs[AST2600_PROT_KEY2] = prot_data_state;
return;
case AST2600_HW_STRAP1:
case AST2600_HW_STRAP2:
@@ -777,7 +798,9 @@ static const MemoryRegionOps aspeed_ast2600_scu_ops = {
.read = aspeed_ast2600_scu_read,
.write = aspeed_ast2600_scu_write,
.endianness = DEVICE_LITTLE_ENDIAN,
- .valid.min_access_size = 4,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .valid.min_access_size = 1,
.valid.max_access_size = 4,
.valid.unaligned = false,
};
@@ -825,13 +848,13 @@ static void aspeed_ast2600_scu_reset(DeviceState *dev)
s->regs[PROT_KEY] = s->hw_prot_key;
}
-static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data)
+static void aspeed_2600_scu_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
dc->desc = "ASPEED 2600 System Control Unit";
- dc->reset = aspeed_ast2600_scu_reset;
+ device_class_set_legacy_reset(dc, aspeed_ast2600_scu_reset);
asc->resets = ast2600_a3_resets;
asc->calc_hpll = aspeed_2600_scu_calc_hpll;
asc->get_apb = aspeed_2600_scu_get_apb_freq;
@@ -904,14 +927,14 @@ static const MemoryRegionOps aspeed_ast2700_scu_ops = {
.read = aspeed_ast2700_scu_read,
.write = aspeed_ast2700_scu_write,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
.valid.min_access_size = 1,
.valid.max_access_size = 8,
.valid.unaligned = false,
};
static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
- [AST2700_SILICON_REV] = AST2700_A0_SILICON_REV,
- [AST2700_HW_STRAP1] = 0x00000800,
[AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
[AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
[AST2700_HW_STRAP1_SEC1] = 0x000000FF,
@@ -931,6 +954,7 @@ static const uint32_t ast2700_a0_resets[ASPEED_AST2700_SCU_NR_REGS] = {
[AST2700_SCU_FREQ_CNTR] = 0x000375eb,
[AST2700_SCU_CPU_SCRATCH_0] = 0x00000000,
[AST2700_SCU_CPU_SCRATCH_1] = 0x00000004,
+ [AST2700_SCU_VGA_SCRATCH_0] = 0x00000040,
};
static void aspeed_ast2700_scu_reset(DeviceState *dev)
@@ -939,15 +963,17 @@ static void aspeed_ast2700_scu_reset(DeviceState *dev)
AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
memcpy(s->regs, asc->resets, asc->nr_regs * 4);
+ s->regs[AST2700_SILICON_REV] = s->silicon_rev;
+ s->regs[AST2700_HW_STRAP1] = s->hw_strap1;
}
-static void aspeed_2700_scu_class_init(ObjectClass *klass, void *data)
+static void aspeed_2700_scu_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
dc->desc = "ASPEED 2700 System Control Unit";
- dc->reset = aspeed_ast2700_scu_reset;
+ device_class_set_legacy_reset(dc, aspeed_ast2700_scu_reset);
asc->resets = ast2700_a0_resets;
asc->calc_hpll = aspeed_2600_scu_calc_hpll;
asc->get_apb = aspeed_2700_scu_get_apb_freq;
@@ -1009,6 +1035,10 @@ static void aspeed_ast2700_scuio_write(void *opaque, hwaddr offset,
s->regs[reg - 1] ^= data;
updated = true;
break;
+ case AST2700_SCUIO_FREQ_CNT_CTL:
+ s->regs[reg] = deposit32(s->regs[reg], 6, 1, !!(data & BIT(1)));
+ updated = true;
+ break;
default:
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Unhandled write at offset 0x%" HWADDR_PRIx "\n",
@@ -1025,14 +1055,14 @@ static const MemoryRegionOps aspeed_ast2700_scuio_ops = {
.read = aspeed_ast2700_scuio_read,
.write = aspeed_ast2700_scuio_write,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
.valid.min_access_size = 1,
.valid.max_access_size = 8,
.valid.unaligned = false,
};
static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
- [AST2700_SILICON_REV] = 0x06000003,
- [AST2700_HW_STRAP1] = 0x00000504,
[AST2700_HW_STRAP1_CLR] = 0xFFF0FFF0,
[AST2700_HW_STRAP1_LOCK] = 0x00000FFF,
[AST2700_HW_STRAP1_SEC1] = 0x000000FF,
@@ -1053,15 +1083,16 @@ static const uint32_t ast2700_a0_resets_io[ASPEED_AST2700_SCU_NR_REGS] = {
[AST2700_SCUIO_UARTCLK_GEN] = 0x00014506,
[AST2700_SCUIO_HUARTCLK_GEN] = 0x000145c0,
[AST2700_SCUIO_CLK_DUTY_MEAS_RST] = 0x0c9100d2,
+ [AST2700_SCUIO_FREQ_CNT_CTL] = 0x00000080,
};
-static void aspeed_2700_scuio_class_init(ObjectClass *klass, void *data)
+static void aspeed_2700_scuio_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
dc->desc = "ASPEED 2700 System Control Unit I/O";
- dc->reset = aspeed_ast2700_scu_reset;
+ device_class_set_legacy_reset(dc, aspeed_ast2700_scu_reset);
asc->resets = ast2700_a0_resets_io;
asc->calc_hpll = aspeed_2600_scu_calc_hpll;
asc->get_apb = aspeed_2700_scuio_get_apb_freq;
@@ -1113,13 +1144,13 @@ static void aspeed_ast1030_scu_reset(DeviceState *dev)
s->regs[PROT_KEY] = s->hw_prot_key;
}
-static void aspeed_1030_scu_class_init(ObjectClass *klass, void *data)
+static void aspeed_1030_scu_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
dc->desc = "ASPEED 1030 System Control Unit";
- dc->reset = aspeed_ast1030_scu_reset;
+ device_class_set_legacy_reset(dc, aspeed_ast1030_scu_reset);
asc->resets = ast1030_a1_resets;
asc->calc_hpll = aspeed_2600_scu_calc_hpll;
asc->get_apb = aspeed_1030_scu_get_apb_freq;