[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-arm] [PATCH v2 1/3] aspeed/scu: introduce clock frequencies
From: |
Andrew Jeffery |
Subject: |
Re: [Qemu-arm] [PATCH v2 1/3] aspeed/scu: introduce clock frequencies |
Date: |
Mon, 25 Jun 2018 10:24:09 +0930 |
On Fri, 22 Jun 2018, at 17:26, Cédric Le Goater wrote:
> All Aspeed SoC clocks are driven by an input source clock which can
> have different frequencies : 24MHz or 25MHz, and also, on the Aspeed
> AST2400 SoC, 48MHz. The H-PLL (CPU) clock is defined from a
> calculation using parameters in the H-PLL Parameter register or from a
> predefined set of frequencies if the setting is strapped by hardware
> (Aspeed AST2400 SoC). The other clocks of the SoC are then defined
> from the H-PLL using dividers.
>
> We introduce first the APB clock because it should be used to drive
> the Aspeed timer model.
>
> Signed-off-by: Cédric Le Goater <address@hidden>
Reviewed-by: Andrew Jeffery <address@hidden>
> ---
> include/hw/misc/aspeed_scu.h | 70 ++++++++++++++++++++++++++--
> hw/misc/aspeed_scu.c | 106
> +++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 172 insertions(+), 4 deletions(-)
>
> diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
> index d70cc0aeca61..f662c38188f4 100644
> --- a/include/hw/misc/aspeed_scu.h
> +++ b/include/hw/misc/aspeed_scu.h
> @@ -30,6 +30,10 @@ typedef struct AspeedSCUState {
> uint32_t hw_strap1;
> uint32_t hw_strap2;
> uint32_t hw_prot_key;
> +
> + uint32_t clkin;
> + uint32_t hpll;
> + uint32_t apb_freq;
> } AspeedSCUState;
>
> #define AST2400_A0_SILICON_REV 0x02000303U
> @@ -58,7 +62,64 @@ extern bool is_supported_silicon_rev(uint32_t silicon_rev);
> * 1. 2012/12/29 Ryan Chen Create
> */
>
> -/* Hardware Strapping Register definition (for Aspeed AST2400 SOC)
> +/* SCU08 Clock Selection Register
> + *
> + * 31 Enable Video Engine clock dynamic slow down
> + * 30:28 Video Engine clock slow down setting
> + * 27 2D Engine GCLK clock source selection
> + * 26 2D Engine GCLK clock throttling enable
> + * 25:23 APB PCLK divider selection
> + * 22:20 LPC Host LHCLK divider selection
> + * 19 LPC Host LHCLK clock generation/output enable control
> + * 18:16 MAC AHB bus clock divider selection
> + * 15 SD/SDIO clock running enable
> + * 14:12 SD/SDIO divider selection
> + * 11 Reserved
> + * 10:8 Video port output clock delay control bit
> + * 7 ARM CPU/AHB clock slow down enable
> + * 6:4 ARM CPU/AHB clock slow down setting
> + * 3:2 ECLK clock source selection
> + * 1 CPU/AHB clock slow down idle timer
> + * 0 CPU/AHB clock dynamic slow down enable (defined in bit[6:4])
> + */
> +#define SCU_CLK_GET_PCLK_DIV(x) (((x) >> 23) & 0x7)
> +
> +/* SCU24 H-PLL Parameter Register (for Aspeed AST2400 SOC)
> + *
> + * 18 H-PLL parameter selection
> + * 0: Select H-PLL by strapping resistors
> + * 1: Select H-PLL by the programmed registers (SCU24[17:0])
> + * 17 Enable H-PLL bypass mode
> + * 16 Turn off H-PLL
> + * 10:5 H-PLL Numerator
> + * 4 H-PLL Output Divider
> + * 3:0 H-PLL Denumerator
> + *
> + * (Output frequency) = 24MHz * (2-OD) * [(Numerator+2) / (Denumerator
> +1)]
> + */
> +
> +#define SCU_AST2400_H_PLL_PROGRAMMED (0x1 << 18)
> +#define SCU_AST2400_H_PLL_BYPASS_EN (0x1 << 17)
> +#define SCU_AST2400_H_PLL_OFF (0x1 << 16)
> +
> +/* SCU24 H-PLL Parameter Register (for Aspeed AST2500 SOC)
> + *
> + * 21 Enable H-PLL reset
> + * 20 Enable H-PLL bypass mode
> + * 19 Turn off H-PLL
> + * 18:13 H-PLL Post Divider
> + * 12:5 H-PLL Numerator (M)
> + * 4:0 H-PLL Denumerator (N)
> + *
> + * (Output frequency) = CLKIN(24MHz) * [(M+1) / (N+1)] / (P+1)
> + *
> + * The default frequency is 792Mhz when CLKIN = 24MHz
> + */
> +
> +#define SCU_H_PLL_BYPASS_EN (0x1 << 20)
> +#define SCU_H_PLL_OFF (0x1 << 19)
> +
> +/* SCU70 Hardware Strapping Register definition (for Aspeed AST2400
> SOC)
> *
> * 31:29 Software defined strapping registers
> * 28:27 DRAM size setting (for VGA driver use)
> @@ -107,12 +168,13 @@ extern bool is_supported_silicon_rev(uint32_t
> silicon_rev);
> #define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x) (((((x) >> 23) &
> 0x1) << 1) \
> | (((x) >> 18) &
> 0x1))
> #define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK ((0x1 << 23) | (0x1
> << 18))
> -#define AST2400_CLK_25M_IN (0x1 << 23)
> +#define SCU_HW_STRAP_CLK_25M_IN (0x1 << 23)
> #define AST2400_CLK_24M_IN 0
> #define AST2400_CLK_48M_IN 1
> #define AST2400_CLK_25M_IN_24M_USB_CKI 2
> #define AST2400_CLK_25M_IN_48M_USB_CKI 3
>
> +#define SCU_HW_STRAP_CLK_48M_IN (0x1 << 18)
> #define SCU_HW_STRAP_2ND_BOOT_WDT (0x1 << 17)
> #define SCU_HW_STRAP_SUPER_IO_CONFIG (0x1 << 16)
> #define SCU_HW_STRAP_VGA_CLASS_CODE (0x1 << 15)
> @@ -160,8 +222,8 @@ extern bool is_supported_silicon_rev(uint32_t
> silicon_rev);
> #define AST2400_DIS_BOOT 3
>
> /*
> - * Hardware strapping register definition (for Aspeed AST2500 SoC and
> - * higher)
> + * SCU70 Hardware strapping register definition (for Aspeed AST2500
> + * SoC and higher)
> *
> * 31 Enable SPI Flash Strap Auto Fetch Mode
> * 30 Enable GPIO Strap Mode
> diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
> index 59315010db9a..59333b50abdd 100644
> --- a/hw/misc/aspeed_scu.c
> +++ b/hw/misc/aspeed_scu.c
> @@ -168,6 +168,27 @@ static uint32_t aspeed_scu_get_random(void)
> return num;
> }
>
> +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();
> + }
> +
> + s->apb_freq = s->hpll / (SCU_CLK_GET_PCLK_DIV(s->regs[CLK_SEL]) +
> 1)
> + / apb_divider;
> +}
> +
> static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned
> size)
> {
> AspeedSCUState *s = ASPEED_SCU(opaque);
> @@ -222,6 +243,10 @@ static void aspeed_scu_write(void *opaque, hwaddr
> offset, uint64_t data,
> case PROT_KEY:
> s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
> return;
> + case CLK_SEL:
> + s->regs[reg] = data;
> + aspeed_scu_set_apb_freq(s);
> + break;
>
> case FREQ_CNTR_EVAL:
> case VGA_SCRATCH1 ... VGA_SCRATCH8:
> @@ -247,19 +272,93 @@ static const MemoryRegionOps aspeed_scu_ops = {
> .valid.unaligned = false,
> };
>
> +static uint32_t aspeed_scu_get_clkin(AspeedSCUState *s)
> +{
> + if (s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN) {
> + return 25000000;
> + } else if (s->hw_strap1 & SCU_HW_STRAP_CLK_48M_IN) {
> + return 48000000;
> + } else {
> + return 24000000;
> + }
> +}
> +
> +/*
> + * Strapped frequencies for the AST2400 in MHz. They depend on the
> + * clkin frequency.
> + */
> +static const uint32_t hpll_ast2400_freqs[][4] = {
> + { 384, 360, 336, 408 }, /* 24MHz or 48MHz */
> + { 400, 375, 350, 425 }, /* 25MHz */
> +};
> +
> +static uint32_t aspeed_scu_calc_hpll_ast2400(AspeedSCUState *s)
> +{
> + uint32_t hpll_reg = s->regs[HPLL_PARAM];
> + uint8_t freq_select;
> + bool clk_25m_in;
> +
> + if (hpll_reg & SCU_AST2400_H_PLL_OFF) {
> + return 0;
> + }
> +
> + if (hpll_reg & SCU_AST2400_H_PLL_PROGRAMMED) {
> + uint32_t multiplier = 1;
> +
> + if (!(hpll_reg & SCU_AST2400_H_PLL_BYPASS_EN)) {
> + uint32_t n = (hpll_reg >> 5) & 0x3f;
> + uint32_t od = (hpll_reg >> 4) & 0x1;
> + uint32_t d = hpll_reg & 0xf;
> +
> + multiplier = (2 - od) * ((n + 2) / (d + 1));
> + }
> +
> + return s->clkin * multiplier;
> + }
> +
> + /* HW strapping */
> + clk_25m_in = !!(s->hw_strap1 & SCU_HW_STRAP_CLK_25M_IN);
> + freq_select = SCU_AST2400_HW_STRAP_GET_H_PLL_CLK(s->hw_strap1);
> +
> + return hpll_ast2400_freqs[clk_25m_in][freq_select] * 1000000;
> +}
> +
> +static uint32_t aspeed_scu_calc_hpll_ast2500(AspeedSCUState *s)
> +{
> + uint32_t hpll_reg = s->regs[HPLL_PARAM];
> + uint32_t multiplier = 1;
> +
> + if (hpll_reg & SCU_H_PLL_OFF) {
> + return 0;
> + }
> +
> + if (!(hpll_reg & SCU_H_PLL_BYPASS_EN)) {
> + uint32_t p = (hpll_reg >> 13) & 0x3f;
> + uint32_t m = (hpll_reg >> 5) & 0xff;
> + uint32_t n = hpll_reg & 0x1f;
> +
> + multiplier = ((m + 1) / (n + 1)) / (p + 1);
> + }
> +
> + return s->clkin * multiplier;
> +}
> +
> 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();
> @@ -270,6 +369,13 @@ static void aspeed_scu_reset(DeviceState *dev)
> s->regs[HW_STRAP1] = s->hw_strap1;
> s->regs[HW_STRAP2] = s->hw_strap2;
> s->regs[PROT_KEY] = s->hw_prot_key;
> +
> + /*
> + * All registers are set. Now compute the frequencies of the main clocks
> + */
> + s->clkin = aspeed_scu_get_clkin(s);
> + s->hpll = calc_hpll(s);
> + aspeed_scu_set_apb_freq(s);
> }
>
> static uint32_t aspeed_silicon_revs[] = {
> --
> 2.13.6
>
- [Qemu-arm] [PATCH v2 0/3] aspeed: introduce the APB clock settings, Cédric Le Goater, 2018/06/22
- [Qemu-arm] [PATCH v2 1/3] aspeed/scu: introduce clock frequencies, Cédric Le Goater, 2018/06/22
- Re: [Qemu-arm] [PATCH v2 1/3] aspeed/scu: introduce clock frequencies,
Andrew Jeffery <=
- [Qemu-arm] [PATCH v2 2/3] aspeed: initialize the SCU controller first, Cédric Le Goater, 2018/06/22
- [Qemu-arm] [PATCH v2 3/3] aspeed/timer: use the APB frequency from the SCU, Cédric Le Goater, 2018/06/22
- Re: [Qemu-arm] [Qemu-devel] [PATCH v2 0/3] aspeed: introduce the APB clock settings, no-reply, 2018/06/22
- Re: [Qemu-arm] [PATCH v2 0/3] aspeed: introduce the APB clock settings, Peter Maydell, 2018/06/26