diff options
author | Cédric Le Goater <clg@kaod.org> | 2019-09-04 09:05:05 +0200 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-09-13 16:05:01 +0100 |
commit | 9a937f6cc4c18a335e813882d15c83252d611042 (patch) | |
tree | 1f74f5b1b863010fd3f2f85b05163cfd3ce7e673 /hw | |
parent | ae275f71338ad4e567c7f2683bf28e66847eabe4 (diff) | |
download | qemu-9a937f6cc4c18a335e813882d15c83252d611042.zip qemu-9a937f6cc4c18a335e813882d15c83252d611042.tar.gz qemu-9a937f6cc4c18a335e813882d15c83252d611042.tar.bz2 |
aspeed/scu: Introduce per-SoC SCU types
and use a class AspeedSCUClass to define each SoC characteristics.
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-id: 20190904070506.1052-10-clg@kaod.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/arm/aspeed_soc.c | 3 | ||||
-rw-r--r-- | hw/misc/aspeed_scu.c | 83 |
2 files changed, 49 insertions, 37 deletions
diff --git a/hw/arm/aspeed_soc.c b/hw/arm/aspeed_soc.c index da508c9..cf1d0cf 100644 --- a/hw/arm/aspeed_soc.c +++ b/hw/arm/aspeed_soc.c @@ -161,8 +161,9 @@ static void aspeed_soc_init(Object *obj) &error_abort, NULL); } + snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname); sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu), - TYPE_ASPEED_SCU); + typename); qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev", sc->info->silicon_rev); object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu), diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index 268cb24..d284458 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -166,23 +166,10 @@ static uint32_t aspeed_scu_get_random(void) static void aspeed_scu_set_apb_freq(AspeedSCUState *s) { - uint32_t apb_divider; - - switch (s->silicon_rev) { - case AST2400_A0_SILICON_REV: - case AST2400_A1_SILICON_REV: - apb_divider = 2; - break; - case AST2500_A0_SILICON_REV: - case AST2500_A1_SILICON_REV: - apb_divider = 4; - break; - default: - g_assert_not_reached(); - } + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(s); s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) + 1) - / apb_divider; + / asc->apb_divider; } static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size) @@ -303,7 +290,7 @@ static const uint32_t hpll_ast2400_freqs[][4] = { { 400, 375, 350, 425 }, /* 25MHz */ }; -static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s) +static uint32_t aspeed_2400_scu_calc_hpll(AspeedSCUState *s) { uint32_t hpll_reg = s->regs[HPLL_PARAM]; uint8_t freq_select; @@ -334,7 +321,7 @@ static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s) return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000; } -static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s) +static uint32_t aspeed_2500_scu_calc_hpll(AspeedSCUState *s) { uint32_t hpll_reg = s->regs[HPLL_PARAM]; uint32_t multiplier = 1; @@ -357,25 +344,9 @@ static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s) static void aspeed_scu_reset(DeviceState *dev) { AspeedSCUState *s = ASPEED_SCU(dev); - const uint32_t *reset; - uint32_t (*calc_hpll)(AspeedSCUState *s); - - switch (s->silicon_rev) { - case AST2400_A0_SILICON_REV: - case AST2400_A1_SILICON_REV: - reset = ast2400_a0_resets; - calc_hpll = aspeed_scu_calc_hpll_ast2400; - break; - case AST2500_A0_SILICON_REV: - case AST2500_A1_SILICON_REV: - reset = ast2500_a1_resets; - calc_hpll = aspeed_scu_calc_hpll_ast2500; - break; - default: - g_assert_not_reached(); - } + AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev); - memcpy(s->regs, reset, sizeof(s->regs)); + memcpy(s->regs, asc->resets, sizeof(s->regs)); s->regs[SILICON_REV] = s->silicon_rev; s->regs[HW_STRAP1] = s->hw_strap1; s->regs[HW_STRAP2] = s->hw_strap2; @@ -385,7 +356,7 @@ static void aspeed_scu_reset(DeviceState *dev) * All registers are set. Now compute the frequencies of the main clocks */ s->clkin = aspeed_scu_get_clkin(s); - s->hpll = calc_hpll(s); + s->hpll = asc->calc_hpll(s); aspeed_scu_set_apb_freq(s); } @@ -459,11 +430,51 @@ static const TypeInfo aspeed_scu_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(AspeedSCUState), .class_init = aspeed_scu_class_init, + .class_size = sizeof(AspeedSCUClass), + .abstract = true, +}; + +static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass); + + dc->desc = "ASPEED 2400 System Control Unit"; + asc->resets = ast2400_a0_resets; + asc->calc_hpll = aspeed_2400_scu_calc_hpll; + asc->apb_divider = 2; +} + +static const TypeInfo aspeed_2400_scu_info = { + .name = TYPE_ASPEED_2400_SCU, + .parent = TYPE_ASPEED_SCU, + .instance_size = sizeof(AspeedSCUState), + .class_init = aspeed_2400_scu_class_init, +}; + +static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass); + + dc->desc = "ASPEED 2500 System Control Unit"; + asc->resets = ast2500_a1_resets; + asc->calc_hpll = aspeed_2500_scu_calc_hpll; + asc->apb_divider = 4; +} + +static const TypeInfo aspeed_2500_scu_info = { + .name = TYPE_ASPEED_2500_SCU, + .parent = TYPE_ASPEED_SCU, + .instance_size = sizeof(AspeedSCUState), + .class_init = aspeed_2500_scu_class_init, }; static void aspeed_scu_register_types(void) { type_register_static(&aspeed_scu_info); + type_register_static(&aspeed_2400_scu_info); + type_register_static(&aspeed_2500_scu_info); } type_init(aspeed_scu_register_types); |