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)
{ 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;
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;
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;
* 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);
}
.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);
#define TYPE_ASPEED_SCU "aspeed.scu"
#define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU)
+#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
+#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
#define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
extern bool is_supported_silicon_rev(uint32_t silicon_rev);
+#define ASPEED_SCU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(AspeedSCUClass, (klass), TYPE_ASPEED_SCU)
+#define ASPEED_SCU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(AspeedSCUClass, (obj), TYPE_ASPEED_SCU)
+
+typedef struct AspeedSCUClass {
+ SysBusDeviceClass parent_class;
+
+ const uint32_t *resets;
+ uint32_t (*calc_hpll)(AspeedSCUState *s);
+ uint32_t apb_divider;
+} AspeedSCUClass;
+
#define ASPEED_SCU_PROT_KEY 0x1688A8A8
/*