From: Peter Delevoryas <p...@fb.com> UART5 is typically used as the default debug UART on the AST2600, but UART1 is also designed to be a debug UART. All the AST2600 UART's have semi-configurable clock rates through registers in the System Control Unit (SCU), but only UART5 works out of the box with zero-initialized values. The rest of the UART's expect a few of the registers to be initialized to non-zero values, or else the clock rate calculation will yield zero or undefined (due to a divide-by-zero).
For reference, the U-Boot clock rate driver here shows the calculation: https://github.com/facebook/openbmc-uboot/blob/main/drivers/clk/aspeed/clk_ast2600.c#L357) To summarize, UART5 allows selection from 4 rates: 24 MHz, 192 MHz, 24 / 13 MHz, and 192 / 13 MHz. The other UART's allow selecting either the "low" rate (UARTCLK) or the "high" rate (HUARTCLK). UARTCLK and HUARTCLK are configurable themselves: UARTCLK = UXCLK * R / (N * 2) HUARTCLK = HUXCLK * HR / (HN * 2) UXCLK and HUXCLK are also configurable, and depend on the APLL and/or HPLL clock rates, which also derive from complicated calculations. Long story short, there's lots of multiplication and division from configurable registers, and most of these registers are zero-initialized in QEMU, which at best is unexpected and at worst causes this clock rate driver to hang from divide-by-zero's. This can also be difficult to diagnose, because it may cause U-Boot to hang before serial console initialization completes, requiring intervention from gdb. This change just initializes all of these registers with default values from the datasheet. Signed-off-by: Peter Delevoryas <p...@fb.com> --- hw/misc/aspeed_scu.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c index c373e678f0..d51fe8564d 100644 --- a/hw/misc/aspeed_scu.c +++ b/hw/misc/aspeed_scu.c @@ -104,11 +104,16 @@ #define AST2600_SDRAM_HANDSHAKE TO_REG(0x100) #define AST2600_HPLL_PARAM TO_REG(0x200) #define AST2600_HPLL_EXT TO_REG(0x204) +#define AST2600_APLL_PARAM TO_REG(0x210) #define AST2600_MPLL_EXT TO_REG(0x224) #define AST2600_EPLL_EXT TO_REG(0x244) #define AST2600_CLK_SEL TO_REG(0x300) #define AST2600_CLK_SEL2 TO_REG(0x304) #define AST2600_CLK_SEL3 TO_REG(0x308) +#define AST2600_CLK_SEL4 TO_REG(0x310) +#define AST2600_CLK_SEL5 TO_REG(0x314) +#define AST2600_UARTCLK_PARAM TO_REG(0x338) +#define AST2600_HUARTCLK_PARAM TO_REG(0x33C) #define AST2600_HW_STRAP1 TO_REG(0x500) #define AST2600_HW_STRAP1_CLR TO_REG(0x504) #define AST2600_HW_STRAP1_PROT TO_REG(0x508) @@ -658,9 +663,15 @@ static const uint32_t ast2600_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = { [AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0, [AST2600_SDRAM_HANDSHAKE] = 0x00000000, [AST2600_HPLL_PARAM] = 0x1000405F, + [AST2600_APLL_PARAM] = 0x1000405F, [AST2600_CHIP_ID0] = 0x1234ABCD, [AST2600_CHIP_ID1] = 0x88884444, - + [AST2600_CLK_SEL2] = 0x00700000, + [AST2600_CLK_SEL3] = 0x00000000, + [AST2600_CLK_SEL4] = 0xF3F40000, + [AST2600_CLK_SEL5] = 0x30000000, + [AST2600_UARTCLK_PARAM] = 0x00014506, + [AST2600_HUARTCLK_PARAM] = 0x000145C0, }; static void aspeed_ast2600_scu_reset(DeviceState *dev) -- 2.30.2