Skip to content

Commit

Permalink
hw/arm/aspeed: Initialize AST2600 UART clock selection registers
Browse files Browse the repository at this point in the history
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/15f7e0dc01d8/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.

To test this, I used Facebook's AST2600 OpenBMC image for "fuji", with
the following diff applied (because fuji uses UART1 for console output,
not UART5).

  @@ -323,8 +323,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
       }

      /* UART - attach an 8250 to the IO space as our UART5 */
  -    serial_mm_init(get_system_memory(), sc->memmap[ASPEED_DEV_UART5], 2,
  -                   aspeed_soc_get_irq(s, ASPEED_DEV_UART5),
  +    serial_mm_init(get_system_memory(), sc->memmap[ASPEED_DEV_UART1], 2,
  +                   aspeed_soc_get_irq(s, ASPEED_DEV_UART1),
                    38400, serial_hd(0), DEVICE_LITTLE_ENDIAN);

       /* I2C */

Without these clock rate registers being initialized, U-Boot hangs in
the clock rate driver from a divide-by-zero, because the UART1 clock
rate register reads return zero, and there's no console output. After
initializing them with default values, fuji boots successfully.

Signed-off-by: Peter Delevoryas <pdel@fb.com>
Reviewed-by: Joel Stanley <joel@jms.id.au>
[ clg: Removed _PARAM suffix ]
Message-Id: <20210906134023.3711031-2-pdel@fb.com>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
  • Loading branch information
peterdelevoryas authored and legoater committed Sep 20, 2021
1 parent b61ea6e commit 9dca455
Showing 1 changed file with 4 additions and 0 deletions.
4 changes: 4 additions & 0 deletions hw/misc/aspeed_scu.c
Expand Up @@ -119,6 +119,8 @@
#define AST2600_CLK_SEL3 TO_REG(0x308)
#define AST2600_CLK_SEL4 TO_REG(0x310)
#define AST2600_CLK_SEL5 TO_REG(0x314)
#define AST2600_UARTCLK TO_REG(0x338)
#define AST2600_HUARTCLK 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)
Expand Down Expand Up @@ -681,6 +683,8 @@ static const uint32_t ast2600_a3_resets[ASPEED_AST2600_SCU_NR_REGS] = {
[AST2600_CLK_SEL3] = 0x00000000,
[AST2600_CLK_SEL4] = 0xF3F40000,
[AST2600_CLK_SEL5] = 0x30000000,
[AST2600_UARTCLK] = 0x00014506,
[AST2600_HUARTCLK] = 0x000145C0,
[AST2600_CHIP_ID0] = 0x1234ABCD,
[AST2600_CHIP_ID1] = 0x88884444,
};
Expand Down

0 comments on commit 9dca455

Please sign in to comment.