1550e691bSryan_chen // SPDX-License-Identifier: GPL-2.0 2550e691bSryan_chen /* 3550e691bSryan_chen * Copyright (C) ASPEED Technology Inc. 4550e691bSryan_chen * Ryan Chen <ryan_chen@aspeedtech.com> 5550e691bSryan_chen */ 6550e691bSryan_chen 7550e691bSryan_chen #include <common.h> 8550e691bSryan_chen #include <clk-uclass.h> 9550e691bSryan_chen #include <dm.h> 10550e691bSryan_chen #include <asm/io.h> 11550e691bSryan_chen #include <dm/lists.h> 1262a6bcbfSryan_chen #include <asm/arch/scu_ast2600.h> 13d6e349c7Sryan_chen #include <dt-bindings/clock/ast2600-clock.h> 1439283ea7Sryan_chen #include <dt-bindings/reset/ast2600-reset.h> 15550e691bSryan_chen 16550e691bSryan_chen /* 17550e691bSryan_chen * MAC Clock Delay settings, taken from Aspeed SDK 18550e691bSryan_chen */ 19550e691bSryan_chen #define RGMII_TXCLK_ODLY 8 20550e691bSryan_chen #define RMII_RXCLK_IDLY 2 21550e691bSryan_chen 22550e691bSryan_chen /* 23550e691bSryan_chen * TGMII Clock Duty constants, taken from Aspeed SDK 24550e691bSryan_chen */ 25550e691bSryan_chen #define RGMII2_TXCK_DUTY 0x66 26550e691bSryan_chen #define RGMII1_TXCK_DUTY 0x64 27550e691bSryan_chen 28550e691bSryan_chen #define D2PLL_DEFAULT_RATE (250 * 1000 * 1000) 29550e691bSryan_chen 30550e691bSryan_chen DECLARE_GLOBAL_DATA_PTR; 31550e691bSryan_chen 32550e691bSryan_chen /* 33550e691bSryan_chen * Clock divider/multiplier configuration struct. 34550e691bSryan_chen * For H-PLL and M-PLL the formula is 35550e691bSryan_chen * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1) 36550e691bSryan_chen * M - Numerator 37550e691bSryan_chen * N - Denumerator 38550e691bSryan_chen * P - Post Divider 39550e691bSryan_chen * They have the same layout in their control register. 40550e691bSryan_chen * 41550e691bSryan_chen * D-PLL and D2-PLL have extra divider (OD + 1), which is not 42550e691bSryan_chen * yet needed and ignored by clock configurations. 43550e691bSryan_chen */ 4439283ea7Sryan_chen struct ast2600_div_config { 45550e691bSryan_chen unsigned int num; 46550e691bSryan_chen unsigned int denum; 47550e691bSryan_chen unsigned int post_div; 48550e691bSryan_chen }; 49550e691bSryan_chen 50d6e349c7Sryan_chen #define AST2600_CLK_IN 25000000 51550e691bSryan_chen 52550e691bSryan_chen /* 53550e691bSryan_chen * Get the rate of the M-PLL clock from input clock frequency and 54550e691bSryan_chen * the value of the M-PLL Parameter Register. 55550e691bSryan_chen */ 5639283ea7Sryan_chen static u32 ast2600_get_mpll_rate(struct ast2600_scu *scu) 57550e691bSryan_chen { 58d6e349c7Sryan_chen u32 clkin = AST2600_CLK_IN; 5939283ea7Sryan_chen u32 mpll_reg = readl(&scu->m_pll_param); 609639db61Sryan_chen unsigned int mult, div = 1; 61550e691bSryan_chen 629639db61Sryan_chen if (mpll_reg & BIT(24)) { 639639db61Sryan_chen /* Pass through mode */ 649639db61Sryan_chen mult = div = 1; 659639db61Sryan_chen } else { 669639db61Sryan_chen /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1) */ 679639db61Sryan_chen u32 m = mpll_reg & 0x1fff; 689639db61Sryan_chen u32 n = (mpll_reg >> 13) & 0x3f; 699639db61Sryan_chen u32 p = (mpll_reg >> 19) & 0xf; 709639db61Sryan_chen mult = (m + 1) / (n + 1); 719639db61Sryan_chen div = (p + 1); 729639db61Sryan_chen } 739639db61Sryan_chen return ((clkin * mult)/div); 74550e691bSryan_chen 75550e691bSryan_chen } 76550e691bSryan_chen 77550e691bSryan_chen /* 78550e691bSryan_chen * Get the rate of the H-PLL clock from input clock frequency and 79550e691bSryan_chen * the value of the H-PLL Parameter Register. 80550e691bSryan_chen */ 8139283ea7Sryan_chen static ulong ast2600_get_hpll_rate(struct ast2600_scu *scu) 82550e691bSryan_chen { 83d6e349c7Sryan_chen ulong clkin = AST2600_CLK_IN; 8439283ea7Sryan_chen u32 hpll_reg = readl(&scu->h_pll_param); 85f0d895afSryan_chen 8639283ea7Sryan_chen const ulong num = (hpll_reg & 0x1fff); 8739283ea7Sryan_chen const ulong denum = (hpll_reg >> 13) & 0x3f; 8839283ea7Sryan_chen const ulong post_div = (hpll_reg >> 19) & 0xf; 89550e691bSryan_chen 90550e691bSryan_chen return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 91550e691bSryan_chen } 92550e691bSryan_chen 9339283ea7Sryan_chen static ulong ast2600_get_apll_rate(struct ast2600_scu *scu) 94550e691bSryan_chen { 9539283ea7Sryan_chen u32 clk_in = AST2600_CLK_IN; 9639283ea7Sryan_chen u32 apll_reg = readl(&scu->a_pll_param); 9739283ea7Sryan_chen unsigned int mult, div = 1; 98d6e349c7Sryan_chen 9939283ea7Sryan_chen if (apll_reg & BIT(20)) { 100d6e349c7Sryan_chen /* Pass through mode */ 101d6e349c7Sryan_chen mult = div = 1; 102d6e349c7Sryan_chen } else { 103d6e349c7Sryan_chen /* F = 25Mhz * (2-OD) * [(M + 2) / (n + 1)] */ 10439283ea7Sryan_chen u32 m = (apll_reg >> 5) & 0x3f; 10539283ea7Sryan_chen u32 od = (apll_reg >> 4) & 0x1; 10639283ea7Sryan_chen u32 n = apll_reg & 0xf; 107d6e349c7Sryan_chen 10839283ea7Sryan_chen mult = (2 - od) * ((m + 2) / (n + 1)); 109d6e349c7Sryan_chen } 110d6e349c7Sryan_chen return (clk_in * mult)/div; 111d6e349c7Sryan_chen } 112d6e349c7Sryan_chen 11339283ea7Sryan_chen static ulong ast2600_get_epll_rate(struct ast2600_scu *scu) 11439283ea7Sryan_chen { 11539283ea7Sryan_chen u32 clk_in = AST2600_CLK_IN; 11639283ea7Sryan_chen u32 epll_reg = readl(&scu->e_pll_param); 11739283ea7Sryan_chen unsigned int mult, div = 1; 11839283ea7Sryan_chen 11939283ea7Sryan_chen if (epll_reg & BIT(24)) { 12039283ea7Sryan_chen /* Pass through mode */ 12139283ea7Sryan_chen mult = div = 1; 12239283ea7Sryan_chen } else { 12339283ea7Sryan_chen /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)*/ 12439283ea7Sryan_chen u32 m = epll_reg & 0x1fff; 12539283ea7Sryan_chen u32 n = (epll_reg >> 13) & 0x3f; 12639283ea7Sryan_chen u32 p = (epll_reg >> 19) & 0x7; 12739283ea7Sryan_chen 12839283ea7Sryan_chen mult = ((m + 1) / (n + 1)); 12939283ea7Sryan_chen div = (p + 1); 13039283ea7Sryan_chen } 13139283ea7Sryan_chen return (clk_in * mult)/div; 13239283ea7Sryan_chen } 13339283ea7Sryan_chen 13439283ea7Sryan_chen static ulong ast2600_get_dpll_rate(struct ast2600_scu *scu) 13539283ea7Sryan_chen { 13639283ea7Sryan_chen u32 clk_in = AST2600_CLK_IN; 13739283ea7Sryan_chen u32 dpll_reg = readl(&scu->d_pll_param); 13839283ea7Sryan_chen unsigned int mult, div = 1; 13939283ea7Sryan_chen 14039283ea7Sryan_chen if (dpll_reg & BIT(24)) { 14139283ea7Sryan_chen /* Pass through mode */ 14239283ea7Sryan_chen mult = div = 1; 14339283ea7Sryan_chen } else { 14439283ea7Sryan_chen /* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1)*/ 14539283ea7Sryan_chen u32 m = dpll_reg & 0x1fff; 14639283ea7Sryan_chen u32 n = (dpll_reg >> 13) & 0x3f; 14739283ea7Sryan_chen u32 p = (dpll_reg >> 19) & 0x7; 14839283ea7Sryan_chen mult = ((m + 1) / (n + 1)); 14939283ea7Sryan_chen div = (p + 1); 15039283ea7Sryan_chen } 15139283ea7Sryan_chen return (clk_in * mult)/div; 15239283ea7Sryan_chen } 153d6e349c7Sryan_chen 154f0d895afSryan_chen static ulong ast2600_get_uart_clk_rate(struct ast2600_clk_priv *priv, int uart_index) 155d6e349c7Sryan_chen { 156550e691bSryan_chen ulong uart_clkin; 157550e691bSryan_chen 15839283ea7Sryan_chen printf("ast2600_get_uart_clk_rate source %ld \n\n", ast2600_get_apll_rate(priv->scu)); 159d6e349c7Sryan_chen return (24000000/13); 160d6e349c7Sryan_chen 161f0d895afSryan_chen if (readl(&priv->scu->misc_ctrl2) & 162550e691bSryan_chen (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT))) 163550e691bSryan_chen uart_clkin = 192 * 1000 * 1000; 164550e691bSryan_chen else 165550e691bSryan_chen uart_clkin = 24 * 1000 * 1000; 166550e691bSryan_chen 167f0d895afSryan_chen if (readl(&priv->scu->misc_ctrl2) & SCU_MISC_UARTCLK_DIV13) 168550e691bSryan_chen uart_clkin /= 13; 169550e691bSryan_chen 170550e691bSryan_chen return uart_clkin; 171550e691bSryan_chen } 172550e691bSryan_chen 173550e691bSryan_chen struct aspeed_clock_config { 174550e691bSryan_chen ulong input_rate; 175550e691bSryan_chen ulong rate; 17639283ea7Sryan_chen struct ast2600_div_config cfg; 177550e691bSryan_chen }; 178550e691bSryan_chen 179550e691bSryan_chen static const struct aspeed_clock_config aspeed_clock_config_defaults[] = { 1801cd71a14SDylan Hung { 25000000, 400000000, { .num = 95, .denum = 2, .post_div = 1 } }, 181550e691bSryan_chen }; 182550e691bSryan_chen 183550e691bSryan_chen static bool aspeed_get_clock_config_default(ulong input_rate, 184550e691bSryan_chen ulong requested_rate, 18539283ea7Sryan_chen struct ast2600_div_config *cfg) 186550e691bSryan_chen { 187550e691bSryan_chen int i; 188550e691bSryan_chen 189550e691bSryan_chen for (i = 0; i < ARRAY_SIZE(aspeed_clock_config_defaults); i++) { 190550e691bSryan_chen const struct aspeed_clock_config *default_cfg = 191550e691bSryan_chen &aspeed_clock_config_defaults[i]; 192550e691bSryan_chen if (default_cfg->input_rate == input_rate && 193550e691bSryan_chen default_cfg->rate == requested_rate) { 194550e691bSryan_chen *cfg = default_cfg->cfg; 195550e691bSryan_chen return true; 196550e691bSryan_chen } 197550e691bSryan_chen } 198550e691bSryan_chen 199550e691bSryan_chen return false; 200550e691bSryan_chen } 201550e691bSryan_chen 202550e691bSryan_chen /* 203550e691bSryan_chen * @input_rate - the rate of input clock in Hz 204550e691bSryan_chen * @requested_rate - desired output rate in Hz 205550e691bSryan_chen * @div - this is an IN/OUT parameter, at input all fields of the config 206550e691bSryan_chen * need to be set to their maximum allowed values. 207550e691bSryan_chen * The result (the best config we could find), would also be returned 208550e691bSryan_chen * in this structure. 209550e691bSryan_chen * 210550e691bSryan_chen * @return The clock rate, when the resulting div_config is used. 211550e691bSryan_chen */ 212550e691bSryan_chen static ulong aspeed_calc_clock_config(ulong input_rate, ulong requested_rate, 21339283ea7Sryan_chen struct ast2600_div_config *cfg) 214550e691bSryan_chen { 215550e691bSryan_chen /* 216550e691bSryan_chen * The assumption is that kHz precision is good enough and 217550e691bSryan_chen * also enough to avoid overflow when multiplying. 218550e691bSryan_chen */ 219550e691bSryan_chen const ulong input_rate_khz = input_rate / 1000; 220550e691bSryan_chen const ulong rate_khz = requested_rate / 1000; 22139283ea7Sryan_chen const struct ast2600_div_config max_vals = *cfg; 22239283ea7Sryan_chen struct ast2600_div_config it = { 0, 0, 0 }; 223550e691bSryan_chen ulong delta = rate_khz; 224550e691bSryan_chen ulong new_rate_khz = 0; 225550e691bSryan_chen 226550e691bSryan_chen /* 227550e691bSryan_chen * Look for a well known frequency first. 228550e691bSryan_chen */ 229550e691bSryan_chen if (aspeed_get_clock_config_default(input_rate, requested_rate, cfg)) 230550e691bSryan_chen return requested_rate; 231550e691bSryan_chen 232550e691bSryan_chen for (; it.denum <= max_vals.denum; ++it.denum) { 233550e691bSryan_chen for (it.post_div = 0; it.post_div <= max_vals.post_div; 234550e691bSryan_chen ++it.post_div) { 235550e691bSryan_chen it.num = (rate_khz * (it.post_div + 1) / input_rate_khz) 236550e691bSryan_chen * (it.denum + 1); 237550e691bSryan_chen if (it.num > max_vals.num) 238550e691bSryan_chen continue; 239550e691bSryan_chen 240550e691bSryan_chen new_rate_khz = (input_rate_khz 241550e691bSryan_chen * ((it.num + 1) / (it.denum + 1))) 242550e691bSryan_chen / (it.post_div + 1); 243550e691bSryan_chen 244550e691bSryan_chen /* Keep the rate below requested one. */ 245550e691bSryan_chen if (new_rate_khz > rate_khz) 246550e691bSryan_chen continue; 247550e691bSryan_chen 248550e691bSryan_chen if (new_rate_khz - rate_khz < delta) { 249550e691bSryan_chen delta = new_rate_khz - rate_khz; 250550e691bSryan_chen *cfg = it; 251550e691bSryan_chen if (delta == 0) 252550e691bSryan_chen return new_rate_khz * 1000; 253550e691bSryan_chen } 254550e691bSryan_chen } 255550e691bSryan_chen } 256550e691bSryan_chen 257550e691bSryan_chen return new_rate_khz * 1000; 258550e691bSryan_chen } 259550e691bSryan_chen 26039283ea7Sryan_chen static u32 ast2600_configure_ddr(struct ast2600_clk_priv *priv, ulong rate) 261550e691bSryan_chen { 262d6e349c7Sryan_chen u32 clkin = AST2600_CLK_IN; 263550e691bSryan_chen u32 mpll_reg; 26439283ea7Sryan_chen struct ast2600_div_config div_cfg = { 265550e691bSryan_chen .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT), 266550e691bSryan_chen .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT), 267550e691bSryan_chen .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT), 268550e691bSryan_chen }; 269550e691bSryan_chen 270550e691bSryan_chen aspeed_calc_clock_config(clkin, rate, &div_cfg); 271550e691bSryan_chen 272f0d895afSryan_chen mpll_reg = readl(&priv->scu->m_pll_param); 273550e691bSryan_chen mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK 274550e691bSryan_chen | SCU_MPLL_DENUM_MASK); 275550e691bSryan_chen mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT) 276550e691bSryan_chen | (div_cfg.num << SCU_MPLL_NUM_SHIFT) 277550e691bSryan_chen | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT); 278550e691bSryan_chen 279f0d895afSryan_chen writel(mpll_reg, &priv->scu->m_pll_param); 280550e691bSryan_chen 28139283ea7Sryan_chen return ast2600_get_mpll_rate(priv->scu); 282550e691bSryan_chen } 283550e691bSryan_chen 284*86f91560Sryan_chen #define SCU_CLKSTOP_MAC1 (20) 285*86f91560Sryan_chen #define SCU_CLKSTOP_MAC2 (21) 286*86f91560Sryan_chen #define SCU_CLKSTOP_MAC3 (20) 287*86f91560Sryan_chen #define SCU_CLKSTOP_MAC4 (21) 288*86f91560Sryan_chen 28900d2d4a5Sryan_chen static u32 ast2600_configure_mac(struct ast2600_scu *scu, int index) 290550e691bSryan_chen { 29100d2d4a5Sryan_chen u32 reset_bit; 29200d2d4a5Sryan_chen u32 clkstop_bit; 29300d2d4a5Sryan_chen 29400d2d4a5Sryan_chen 29500d2d4a5Sryan_chen switch (index) { 29600d2d4a5Sryan_chen case 1: 29700d2d4a5Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC1); 298*86f91560Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC1); 299*86f91560Sryan_chen writel(&scu->sysreset_ctrl1, reset_bit); 300*86f91560Sryan_chen udelay(100); 301*86f91560Sryan_chen clrbits_le32(&scu->clk_stop_clr_ctrl1, clkstop_bit); 302*86f91560Sryan_chen mdelay(10); 303*86f91560Sryan_chen writel(&scu->sysreset_clr_ctrl1, reset_bit); 304*86f91560Sryan_chen 305*86f91560Sryan_chen 30600d2d4a5Sryan_chen break; 30700d2d4a5Sryan_chen case 2: 30800d2d4a5Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC2); 309*86f91560Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC2); 310*86f91560Sryan_chen writel(&scu->sysreset_ctrl1, reset_bit); 311*86f91560Sryan_chen udelay(100); 312*86f91560Sryan_chen writel(&scu->clk_stop_clr_ctrl1, clkstop_bit); 313*86f91560Sryan_chen mdelay(10); 314*86f91560Sryan_chen writel(&scu->sysreset_clr_ctrl1, reset_bit); 31500d2d4a5Sryan_chen break; 31600d2d4a5Sryan_chen case 3: 317*86f91560Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC3 - 32); 318*86f91560Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC3); 319*86f91560Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC2); 320*86f91560Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC2); 321*86f91560Sryan_chen writel(&scu->sysreset_ctrl2, reset_bit); 322*86f91560Sryan_chen udelay(100); 323*86f91560Sryan_chen writel(&scu->clk_stop_clr_ctrl2, clkstop_bit); 324*86f91560Sryan_chen mdelay(10); 325*86f91560Sryan_chen writel(&scu->sysreset_clr_ctrl2, reset_bit); 326*86f91560Sryan_chen 32700d2d4a5Sryan_chen break; 32800d2d4a5Sryan_chen case 4: 329*86f91560Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC4 - 32); 330*86f91560Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC4); 331*86f91560Sryan_chen reset_bit = BIT(ASPEED_RESET_MAC2); 332*86f91560Sryan_chen clkstop_bit = BIT(SCU_CLKSTOP_MAC2); 333*86f91560Sryan_chen writel(&scu->sysreset_ctrl2, reset_bit); 334*86f91560Sryan_chen udelay(100); 335*86f91560Sryan_chen writel(&scu->clk_stop_clr_ctrl2, clkstop_bit); 336*86f91560Sryan_chen mdelay(10); 337*86f91560Sryan_chen writel(&scu->sysreset_clr_ctrl2, reset_bit); 338*86f91560Sryan_chen 33900d2d4a5Sryan_chen break; 34000d2d4a5Sryan_chen default: 34100d2d4a5Sryan_chen return -EINVAL; 34200d2d4a5Sryan_chen } 34300d2d4a5Sryan_chen 34439283ea7Sryan_chen return 0; 345550e691bSryan_chen } 346550e691bSryan_chen 347f0d895afSryan_chen static u32 ast2600_a0_axi_ahb_div_table[] = { 348f0d895afSryan_chen 2, 2, 3, 5, 349f0d895afSryan_chen }; 350f0d895afSryan_chen 351f0d895afSryan_chen static u32 ast2600_a1_axi_ahb_div_table[] = { 352f0d895afSryan_chen 4, 6, 2, 4, 353f0d895afSryan_chen }; 354f0d895afSryan_chen 355f0d895afSryan_chen static u32 ast2600_hpll_pclk_div_table[] = { 356f0d895afSryan_chen 4, 8, 12, 16, 20, 24, 28, 32, 357f0d895afSryan_chen }; 358d6e349c7Sryan_chen static ulong ast2600_clk_get_rate(struct clk *clk) 359d6e349c7Sryan_chen { 360f0d895afSryan_chen struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 361d6e349c7Sryan_chen ulong rate; 362d6e349c7Sryan_chen 363d6e349c7Sryan_chen switch (clk->id) { 364d1e64dd1Sryan_chen //HPLL 365d1e64dd1Sryan_chen case ASPEED_CLK_HPLL: 36639283ea7Sryan_chen rate = ast2600_get_hpll_rate(priv->scu); 36739283ea7Sryan_chen printf("hpll %ld \n", rate); 368d6e349c7Sryan_chen break; 369d1e64dd1Sryan_chen //HCLK 370d1e64dd1Sryan_chen case ASPEED_CLK_AHB: 37162a6bcbfSryan_chen { 372f0d895afSryan_chen u32 hw_rev = readl(&priv->scu->chip_id0); 373f0d895afSryan_chen u32 hwstrap1 = readl(&priv->scu->hwstrap1); 374f0d895afSryan_chen u32 axi_div = 1; 375f0d895afSryan_chen u32 ahb_div = 0; 376f0d895afSryan_chen if((hwstrap1 >> 16) & 0x1) 377f0d895afSryan_chen axi_div = 1; 378f0d895afSryan_chen else 379f0d895afSryan_chen axi_div = 2; 38062a6bcbfSryan_chen 381f0d895afSryan_chen if (hw_rev & BIT(16)) 382f0d895afSryan_chen ahb_div = ast2600_a1_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 383f0d895afSryan_chen else 384f0d895afSryan_chen ahb_div = ast2600_a0_axi_ahb_div_table[(hwstrap1 >> 11) & 0x3]; 385f0d895afSryan_chen 38639283ea7Sryan_chen rate = ast2600_get_hpll_rate(priv->scu); 38762a6bcbfSryan_chen rate = rate / axi_div / ahb_div; 38800d2d4a5Sryan_chen printf("hclk %ld \n", rate); 38962a6bcbfSryan_chen } 390d1e64dd1Sryan_chen break; 391f0d895afSryan_chen case ASPEED_CLK_MPLL: 39239283ea7Sryan_chen rate = ast2600_get_mpll_rate(priv->scu); 393d6e349c7Sryan_chen break; 39439283ea7Sryan_chen //pclk 39539283ea7Sryan_chen case ASPEED_CLK_APB: 396d6e349c7Sryan_chen { 397f0d895afSryan_chen u32 clk_sel1 = readl(&priv->scu->clk_sel1); 398f0d895afSryan_chen u32 apb_div = ast2600_hpll_pclk_div_table[((clk_sel1 >> 23) & 0x7)]; 39939283ea7Sryan_chen rate = ast2600_get_hpll_rate(priv->scu); 400d6e349c7Sryan_chen rate = rate / apb_div; 401d6e349c7Sryan_chen } 402d6e349c7Sryan_chen break; 403d6e349c7Sryan_chen case PCLK_UART1: 404d6e349c7Sryan_chen rate = ast2600_get_uart_clk_rate(priv, 1); 405d6e349c7Sryan_chen break; 406d6e349c7Sryan_chen case PCLK_UART2: 407d6e349c7Sryan_chen rate = ast2600_get_uart_clk_rate(priv, 2); 408d6e349c7Sryan_chen break; 409d6e349c7Sryan_chen case PCLK_UART3: 410d6e349c7Sryan_chen rate = ast2600_get_uart_clk_rate(priv, 3); 411d6e349c7Sryan_chen break; 412d6e349c7Sryan_chen case PCLK_UART4: 413d6e349c7Sryan_chen rate = ast2600_get_uart_clk_rate(priv, 4); 414d6e349c7Sryan_chen break; 415d1e64dd1Sryan_chen case ASPEED_CLK_GATE_UART5CLK: 416d6e349c7Sryan_chen rate = ast2600_get_uart_clk_rate(priv, 5); 417d6e349c7Sryan_chen break; 418d6e349c7Sryan_chen default: 419d6e349c7Sryan_chen return -ENOENT; 420d6e349c7Sryan_chen } 421d6e349c7Sryan_chen 422d6e349c7Sryan_chen return rate; 423d6e349c7Sryan_chen } 424d6e349c7Sryan_chen 425d6e349c7Sryan_chen static ulong ast2600_clk_set_rate(struct clk *clk, ulong rate) 426550e691bSryan_chen { 427f0d895afSryan_chen struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 428550e691bSryan_chen 429550e691bSryan_chen ulong new_rate; 430550e691bSryan_chen switch (clk->id) { 431f0d895afSryan_chen case ASPEED_CLK_MPLL: 43239283ea7Sryan_chen new_rate = ast2600_configure_ddr(priv, rate); 433550e691bSryan_chen break; 434550e691bSryan_chen default: 435550e691bSryan_chen return -ENOENT; 436550e691bSryan_chen } 437550e691bSryan_chen 438550e691bSryan_chen return new_rate; 439550e691bSryan_chen } 440550e691bSryan_chen 441d6e349c7Sryan_chen static int ast2600_clk_enable(struct clk *clk) 442550e691bSryan_chen { 443f0d895afSryan_chen struct ast2600_clk_priv *priv = dev_get_priv(clk->dev); 444550e691bSryan_chen 445550e691bSryan_chen switch (clk->id) { 446550e691bSryan_chen /* 447550e691bSryan_chen * For MAC clocks the clock rate is 448550e691bSryan_chen * configured based on whether RGMII or RMII mode has been selected 449550e691bSryan_chen * through hardware strapping. 450550e691bSryan_chen */ 451*86f91560Sryan_chen case ASPEED_CLK_GATE_MAC1CLK: 45200d2d4a5Sryan_chen printf("ast2600_clk_enable mac 1 ~~~\n"); 453*86f91560Sryan_chen ast2600_configure_mac(priv->scu, 1); 454550e691bSryan_chen break; 455*86f91560Sryan_chen case ASPEED_CLK_GATE_MAC2CLK: 45600d2d4a5Sryan_chen printf("ast2600_clk_enable mac 2 ~~~\n"); 457*86f91560Sryan_chen ast2600_configure_mac(priv->scu, 2); 458550e691bSryan_chen break; 459550e691bSryan_chen default: 460550e691bSryan_chen return -ENOENT; 461550e691bSryan_chen } 462550e691bSryan_chen 463550e691bSryan_chen return 0; 464550e691bSryan_chen } 465550e691bSryan_chen 466550e691bSryan_chen struct clk_ops aspeed_clk_ops = { 467d6e349c7Sryan_chen .get_rate = ast2600_clk_get_rate, 468d6e349c7Sryan_chen .set_rate = ast2600_clk_set_rate, 469d6e349c7Sryan_chen .enable = ast2600_clk_enable, 470550e691bSryan_chen }; 471550e691bSryan_chen 472d6e349c7Sryan_chen static int ast2600_clk_probe(struct udevice *dev) 473550e691bSryan_chen { 47439283ea7Sryan_chen char buf[32]; 475f0d895afSryan_chen struct ast2600_clk_priv *priv = dev_get_priv(dev); 476550e691bSryan_chen 477f0d895afSryan_chen priv->scu = devfdt_get_addr_ptr(dev); 478f0d895afSryan_chen if (IS_ERR(priv->scu)) 479f0d895afSryan_chen return PTR_ERR(priv->scu); 480550e691bSryan_chen 48139283ea7Sryan_chen printf("PLL : %4s MHz\n", strmhz(buf, AST2600_CLK_IN)); 48239283ea7Sryan_chen printf("HPLL : %4s MHz\n", strmhz(buf, ast2600_get_hpll_rate(priv->scu))); 48339283ea7Sryan_chen printf("MPLL : %4s Mhz\n", strmhz(buf, ast2600_get_mpll_rate(priv->scu))); 48439283ea7Sryan_chen printf("APLL : %4s Mhz\n", strmhz(buf, ast2600_get_apll_rate(priv->scu))); 48539283ea7Sryan_chen printf("EPLL : %4s Mhz\n", strmhz(buf, ast2600_get_epll_rate(priv->scu))); 48639283ea7Sryan_chen printf("DPLL : %4s Mhz\n", strmhz(buf, ast2600_get_dpll_rate(priv->scu))); 48739283ea7Sryan_chen 48839283ea7Sryan_chen 489550e691bSryan_chen return 0; 490550e691bSryan_chen } 491550e691bSryan_chen 492d6e349c7Sryan_chen static int ast2600_clk_bind(struct udevice *dev) 493550e691bSryan_chen { 494550e691bSryan_chen int ret; 495550e691bSryan_chen 496550e691bSryan_chen /* The reset driver does not have a device node, so bind it here */ 497550e691bSryan_chen ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); 498550e691bSryan_chen if (ret) 499550e691bSryan_chen debug("Warning: No reset driver: ret=%d\n", ret); 500550e691bSryan_chen 501550e691bSryan_chen return 0; 502550e691bSryan_chen } 503550e691bSryan_chen 504d6e349c7Sryan_chen static const struct udevice_id ast2600_clk_ids[] = { 505d6e349c7Sryan_chen { .compatible = "aspeed,ast2600-scu", }, 506550e691bSryan_chen { } 507550e691bSryan_chen }; 508550e691bSryan_chen 509aa36597fSDylan Hung U_BOOT_DRIVER(aspeed_scu) = { 510aa36597fSDylan Hung .name = "aspeed_scu", 511550e691bSryan_chen .id = UCLASS_CLK, 512d6e349c7Sryan_chen .of_match = ast2600_clk_ids, 513f0d895afSryan_chen .priv_auto_alloc_size = sizeof(struct ast2600_clk_priv), 514550e691bSryan_chen .ops = &aspeed_clk_ops, 515d6e349c7Sryan_chen .bind = ast2600_clk_bind, 516d6e349c7Sryan_chen .probe = ast2600_clk_probe, 517550e691bSryan_chen }; 518