aspeed/scu: introduce clock frequencies
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 <clg@kaod.org> Reviewed-by: Andrew Jeffery <andrew@aj.id.au> Message-id: 20180622075700.5923-2-clg@kaod.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
							parent
							
								
									832e4222c8
								
							
						
					
					
						commit
						fda9aaa60e
					
				@ -168,6 +168,27 @@ static uint32_t aspeed_scu_get_random(void)
 | 
				
			|||||||
    return num;
 | 
					    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)
 | 
					static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AspeedSCUState *s = ASPEED_SCU(opaque);
 | 
					    AspeedSCUState *s = ASPEED_SCU(opaque);
 | 
				
			||||||
@ -222,6 +243,10 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
 | 
				
			|||||||
    case PROT_KEY:
 | 
					    case PROT_KEY:
 | 
				
			||||||
        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
 | 
					        s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					    case CLK_SEL:
 | 
				
			||||||
 | 
					        s->regs[reg] = data;
 | 
				
			||||||
 | 
					        aspeed_scu_set_apb_freq(s);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case FREQ_CNTR_EVAL:
 | 
					    case FREQ_CNTR_EVAL:
 | 
				
			||||||
    case VGA_SCRATCH1 ... VGA_SCRATCH8:
 | 
					    case VGA_SCRATCH1 ... VGA_SCRATCH8:
 | 
				
			||||||
@ -247,19 +272,93 @@ static const MemoryRegionOps aspeed_scu_ops = {
 | 
				
			|||||||
    .valid.unaligned = false,
 | 
					    .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)
 | 
					static void aspeed_scu_reset(DeviceState *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AspeedSCUState *s = ASPEED_SCU(dev);
 | 
					    AspeedSCUState *s = ASPEED_SCU(dev);
 | 
				
			||||||
    const uint32_t *reset;
 | 
					    const uint32_t *reset;
 | 
				
			||||||
 | 
					    uint32_t (*calc_hpll)(AspeedSCUState *s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (s->silicon_rev) {
 | 
					    switch (s->silicon_rev) {
 | 
				
			||||||
    case AST2400_A0_SILICON_REV:
 | 
					    case AST2400_A0_SILICON_REV:
 | 
				
			||||||
    case AST2400_A1_SILICON_REV:
 | 
					    case AST2400_A1_SILICON_REV:
 | 
				
			||||||
        reset = ast2400_a0_resets;
 | 
					        reset = ast2400_a0_resets;
 | 
				
			||||||
 | 
					        calc_hpll = aspeed_scu_calc_hpll_ast2400;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case AST2500_A0_SILICON_REV:
 | 
					    case AST2500_A0_SILICON_REV:
 | 
				
			||||||
    case AST2500_A1_SILICON_REV:
 | 
					    case AST2500_A1_SILICON_REV:
 | 
				
			||||||
        reset = ast2500_a1_resets;
 | 
					        reset = ast2500_a1_resets;
 | 
				
			||||||
 | 
					        calc_hpll = aspeed_scu_calc_hpll_ast2500;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        g_assert_not_reached();
 | 
					        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_STRAP1] = s->hw_strap1;
 | 
				
			||||||
    s->regs[HW_STRAP2] = s->hw_strap2;
 | 
					    s->regs[HW_STRAP2] = s->hw_strap2;
 | 
				
			||||||
    s->regs[PROT_KEY] = s->hw_prot_key;
 | 
					    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[] = {
 | 
					static uint32_t aspeed_silicon_revs[] = {
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,10 @@ typedef struct AspeedSCUState {
 | 
				
			|||||||
    uint32_t hw_strap1;
 | 
					    uint32_t hw_strap1;
 | 
				
			||||||
    uint32_t hw_strap2;
 | 
					    uint32_t hw_strap2;
 | 
				
			||||||
    uint32_t hw_prot_key;
 | 
					    uint32_t hw_prot_key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint32_t clkin;
 | 
				
			||||||
 | 
					    uint32_t hpll;
 | 
				
			||||||
 | 
					    uint32_t apb_freq;
 | 
				
			||||||
} AspeedSCUState;
 | 
					} AspeedSCUState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define AST2400_A0_SILICON_REV   0x02000303U
 | 
					#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
 | 
					 *       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
 | 
					 * 31:29  Software defined strapping registers
 | 
				
			||||||
 * 28:27  DRAM size setting (for VGA driver use)
 | 
					 * 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) \
 | 
					#define SCU_AST2400_HW_STRAP_GET_CLK_SOURCE(x)     (((((x) >> 23) & 0x1) << 1) \
 | 
				
			||||||
                                                    | (((x) >> 18) & 0x1))
 | 
					                                                    | (((x) >> 18) & 0x1))
 | 
				
			||||||
#define SCU_AST2400_HW_STRAP_CLK_SOURCE_MASK       ((0x1 << 23) | (0x1 << 18))
 | 
					#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_24M_IN                         0
 | 
				
			||||||
#define     AST2400_CLK_48M_IN                         1
 | 
					#define     AST2400_CLK_48M_IN                         1
 | 
				
			||||||
#define     AST2400_CLK_25M_IN_24M_USB_CKI             2
 | 
					#define     AST2400_CLK_25M_IN_24M_USB_CKI             2
 | 
				
			||||||
#define     AST2400_CLK_25M_IN_48M_USB_CKI             3
 | 
					#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_2ND_BOOT_WDT                  (0x1 << 17)
 | 
				
			||||||
#define SCU_HW_STRAP_SUPER_IO_CONFIG               (0x1 << 16)
 | 
					#define SCU_HW_STRAP_SUPER_IO_CONFIG               (0x1 << 16)
 | 
				
			||||||
#define SCU_HW_STRAP_VGA_CLASS_CODE                (0x1 << 15)
 | 
					#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
 | 
					#define     AST2400_DIS_BOOT                           3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Hardware strapping register definition (for Aspeed AST2500 SoC and
 | 
					 * SCU70  Hardware strapping register definition (for Aspeed AST2500
 | 
				
			||||||
 * higher)
 | 
					 *        SoC and higher)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * 31     Enable SPI Flash Strap Auto Fetch Mode
 | 
					 * 31     Enable SPI Flash Strap Auto Fetch Mode
 | 
				
			||||||
 * 30     Enable GPIO Strap Mode
 | 
					 * 30     Enable GPIO Strap Mode
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user