1*550e691bSryan_chen // SPDX-License-Identifier: GPL-2.0 2*550e691bSryan_chen /* 3*550e691bSryan_chen * Copyright (C) ASPEED Technology Inc. 4*550e691bSryan_chen * Ryan Chen <ryan_chen@aspeedtech.com> 5*550e691bSryan_chen */ 6*550e691bSryan_chen 7*550e691bSryan_chen #include <common.h> 8*550e691bSryan_chen #include <clk-uclass.h> 9*550e691bSryan_chen #include <dm.h> 10*550e691bSryan_chen #include <asm/io.h> 11*550e691bSryan_chen #include <asm/arch/scu_aspeed.h> 12*550e691bSryan_chen #include <dm/lists.h> 13*550e691bSryan_chen #include <dt-bindings/clock/ast2500-scu.h> 14*550e691bSryan_chen 15*550e691bSryan_chen /* register */ 16*550e691bSryan_chen #define ASPEED_STRAP 0x70 17*550e691bSryan_chen #define SCU_HWSTRAP_VGAMEM_SHIFT 2 18*550e691bSryan_chen #define SCU_HWSTRAP_VGAMEM_MASK (3 << SCU_HWSTRAP_VGAMEM_SHIFT) 19*550e691bSryan_chen #define SCU_HWSTRAP_MAC1_RGMII (1 << 6) 20*550e691bSryan_chen #define SCU_HWSTRAP_MAC2_RGMII (1 << 7) 21*550e691bSryan_chen #define SCU_HWSTRAP_DDR4 (1 << 24) 22*550e691bSryan_chen #define SCU_HWSTRAP_CLKIN_25MHZ (1 << 23) 23*550e691bSryan_chen 24*550e691bSryan_chen #define ASPEED_CLK_SELECT 0x08 25*550e691bSryan_chen #define SCU_PCLK_DIV_SHIFT 23 26*550e691bSryan_chen #define SCU_PCLK_DIV_MASK (7 << SCU_PCLK_DIV_SHIFT) 27*550e691bSryan_chen 28*550e691bSryan_chen #define ASPEED_MSIC2 0x4C 29*550e691bSryan_chen #define SCU_MISC2_RGMII_HPLL (1 << 23) 30*550e691bSryan_chen #define SCU_MISC2_RGMII_CLKDIV_SHIFT 20 31*550e691bSryan_chen #define SCU_MISC2_RGMII_CLKDIV_MASK (3 << SCU_MISC2_RGMII_CLKDIV_SHIFT) 32*550e691bSryan_chen #define SCU_MISC2_RMII_MPLL (1 << 19) 33*550e691bSryan_chen #define SCU_MISC2_RMII_CLKDIV_SHIFT 16 34*550e691bSryan_chen #define SCU_MISC2_RMII_CLKDIV_MASK (3 << SCU_MISC2_RMII_CLKDIV_SHIFT) 35*550e691bSryan_chen #define SCU_MISC2_UARTCLK_SHIFT 24 36*550e691bSryan_chen 37*550e691bSryan_chen #define ASPEED_MPLL_PARAMETER 0x20 38*550e691bSryan_chen #define SCU_MPLL_DENUM_SHIFT 0 39*550e691bSryan_chen #define SCU_MPLL_DENUM_MASK 0x1f 40*550e691bSryan_chen #define SCU_MPLL_NUM_SHIFT 5 41*550e691bSryan_chen #define SCU_MPLL_NUM_MASK (0xff << SCU_MPLL_NUM_SHIFT) 42*550e691bSryan_chen #define SCU_MPLL_POST_SHIFT 13 43*550e691bSryan_chen #define SCU_MPLL_POST_MASK (0x3f << SCU_MPLL_POST_SHIFT) 44*550e691bSryan_chen 45*550e691bSryan_chen #define ASPEED_HPLL_PARAMETER 0x24 46*550e691bSryan_chen #define SCU_HPLL_DENUM_SHIFT 0 47*550e691bSryan_chen #define SCU_HPLL_DENUM_MASK 0x1f 48*550e691bSryan_chen #define SCU_HPLL_NUM_SHIFT 5 49*550e691bSryan_chen #define SCU_HPLL_NUM_MASK (0xff << SCU_HPLL_NUM_SHIFT) 50*550e691bSryan_chen #define SCU_HPLL_POST_SHIFT 13 51*550e691bSryan_chen #define SCU_HPLL_POST_MASK (0x3f << SCU_HPLL_POST_SHIFT) 52*550e691bSryan_chen 53*550e691bSryan_chen 54*550e691bSryan_chen /* 55*550e691bSryan_chen * MAC Clock Delay settings, taken from Aspeed SDK 56*550e691bSryan_chen */ 57*550e691bSryan_chen #define RGMII_TXCLK_ODLY 8 58*550e691bSryan_chen #define RMII_RXCLK_IDLY 2 59*550e691bSryan_chen 60*550e691bSryan_chen /* 61*550e691bSryan_chen * TGMII Clock Duty constants, taken from Aspeed SDK 62*550e691bSryan_chen */ 63*550e691bSryan_chen #define RGMII2_TXCK_DUTY 0x66 64*550e691bSryan_chen #define RGMII1_TXCK_DUTY 0x64 65*550e691bSryan_chen 66*550e691bSryan_chen #define D2PLL_DEFAULT_RATE (250 * 1000 * 1000) 67*550e691bSryan_chen 68*550e691bSryan_chen DECLARE_GLOBAL_DATA_PTR; 69*550e691bSryan_chen 70*550e691bSryan_chen /* 71*550e691bSryan_chen * Clock divider/multiplier configuration struct. 72*550e691bSryan_chen * For H-PLL and M-PLL the formula is 73*550e691bSryan_chen * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1) 74*550e691bSryan_chen * M - Numerator 75*550e691bSryan_chen * N - Denumerator 76*550e691bSryan_chen * P - Post Divider 77*550e691bSryan_chen * They have the same layout in their control register. 78*550e691bSryan_chen * 79*550e691bSryan_chen * D-PLL and D2-PLL have extra divider (OD + 1), which is not 80*550e691bSryan_chen * yet needed and ignored by clock configurations. 81*550e691bSryan_chen */ 82*550e691bSryan_chen struct aspeed_div_config { 83*550e691bSryan_chen unsigned int num; 84*550e691bSryan_chen unsigned int denum; 85*550e691bSryan_chen unsigned int post_div; 86*550e691bSryan_chen }; 87*550e691bSryan_chen 88*550e691bSryan_chen static u32 aspeed_get_clkin(struct aspeed_clk_priv *priv) 89*550e691bSryan_chen { 90*550e691bSryan_chen switch(priv->version) { 91*550e691bSryan_chen case AST2400: 92*550e691bSryan_chen case AST2500: 93*550e691bSryan_chen return readl(priv->regs + ASPEED_STRAP) & SCU_HWSTRAP_CLKIN_25MHZ 94*550e691bSryan_chen ? 25 * 1000 * 1000 : 24 * 1000 * 1000; 95*550e691bSryan_chen break; 96*550e691bSryan_chen case AST2600: 97*550e691bSryan_chen return 25000000; 98*550e691bSryan_chen break; 99*550e691bSryan_chen } 100*550e691bSryan_chen return 0; 101*550e691bSryan_chen } 102*550e691bSryan_chen 103*550e691bSryan_chen /* 104*550e691bSryan_chen * Get the rate of the M-PLL clock from input clock frequency and 105*550e691bSryan_chen * the value of the M-PLL Parameter Register. 106*550e691bSryan_chen */ 107*550e691bSryan_chen static u32 aspeed_get_mpll_rate(struct aspeed_clk_priv *priv) 108*550e691bSryan_chen { 109*550e691bSryan_chen u32 clkin = aspeed_get_clkin(priv); 110*550e691bSryan_chen u32 mpll_reg = readl(priv->regs + ASPEED_MPLL_PARAMETER); 111*550e691bSryan_chen 112*550e691bSryan_chen const ulong num = (mpll_reg & SCU_MPLL_NUM_MASK) >> SCU_MPLL_NUM_SHIFT; 113*550e691bSryan_chen const ulong denum = (mpll_reg & SCU_MPLL_DENUM_MASK) 114*550e691bSryan_chen >> SCU_MPLL_DENUM_SHIFT; 115*550e691bSryan_chen const ulong post_div = (mpll_reg & SCU_MPLL_POST_MASK) 116*550e691bSryan_chen >> SCU_MPLL_POST_SHIFT; 117*550e691bSryan_chen 118*550e691bSryan_chen return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 119*550e691bSryan_chen } 120*550e691bSryan_chen 121*550e691bSryan_chen /* 122*550e691bSryan_chen * Get the rate of the H-PLL clock from input clock frequency and 123*550e691bSryan_chen * the value of the H-PLL Parameter Register. 124*550e691bSryan_chen */ 125*550e691bSryan_chen static ulong aspeed_get_hpll_rate(struct aspeed_clk_priv *priv) 126*550e691bSryan_chen { 127*550e691bSryan_chen ulong clkin = aspeed_get_clkin(priv); 128*550e691bSryan_chen u32 hpll_reg = readl(priv->regs + ASPEED_HPLL_PARAMETER); 129*550e691bSryan_chen const ulong num = (hpll_reg & SCU_HPLL_NUM_MASK) >> SCU_HPLL_NUM_SHIFT; 130*550e691bSryan_chen const ulong denum = (hpll_reg & SCU_HPLL_DENUM_MASK) 131*550e691bSryan_chen >> SCU_HPLL_DENUM_SHIFT; 132*550e691bSryan_chen const ulong post_div = (hpll_reg & SCU_HPLL_POST_MASK) 133*550e691bSryan_chen >> SCU_HPLL_POST_SHIFT; 134*550e691bSryan_chen 135*550e691bSryan_chen return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 136*550e691bSryan_chen } 137*550e691bSryan_chen 138*550e691bSryan_chen 139*550e691bSryan_chen /** 140*550e691bSryan_chen * Get current rate or uart clock 141*550e691bSryan_chen * 142*550e691bSryan_chen * @scu SCU registers 143*550e691bSryan_chen * @uart_index UART index, 1-5 144*550e691bSryan_chen * 145*550e691bSryan_chen * @return current setting for uart clock rate 146*550e691bSryan_chen */ 147*550e691bSryan_chen static ulong aspeed_get_uart_clk_rate(struct aspeed_clk_priv *priv, int uart_index) 148*550e691bSryan_chen { 149*550e691bSryan_chen /* 150*550e691bSryan_chen * ast2600 datasheet is very confusing when it comes to UART clocks, 151*550e691bSryan_chen * especially when CLKIN = 25 MHz. The settings are in 152*550e691bSryan_chen * different registers and it is unclear how they interact. 153*550e691bSryan_chen * 154*550e691bSryan_chen * This has only been tested with default settings and CLKIN = 24 MHz. 155*550e691bSryan_chen */ 156*550e691bSryan_chen ulong uart_clkin; 157*550e691bSryan_chen 158*550e691bSryan_chen if (readl(priv->regs + ASPEED_MSIC2) & 159*550e691bSryan_chen (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT))) 160*550e691bSryan_chen uart_clkin = 192 * 1000 * 1000; 161*550e691bSryan_chen else 162*550e691bSryan_chen uart_clkin = 24 * 1000 * 1000; 163*550e691bSryan_chen 164*550e691bSryan_chen if (readl(priv->regs + ASPEED_MSIC2) & SCU_MISC_UARTCLK_DIV13) 165*550e691bSryan_chen uart_clkin /= 13; 166*550e691bSryan_chen 167*550e691bSryan_chen return uart_clkin; 168*550e691bSryan_chen } 169*550e691bSryan_chen 170*550e691bSryan_chen static ulong aspeed_clk_get_rate(struct clk *clk) 171*550e691bSryan_chen { 172*550e691bSryan_chen struct aspeed_clk_priv *priv = dev_get_priv(clk->dev); 173*550e691bSryan_chen ulong rate; 174*550e691bSryan_chen 175*550e691bSryan_chen switch (clk->id) { 176*550e691bSryan_chen case PLL_HPLL: 177*550e691bSryan_chen case ARMCLK: 178*550e691bSryan_chen /* 179*550e691bSryan_chen * This ignores dynamic/static slowdown of ARMCLK and may 180*550e691bSryan_chen * be inaccurate. 181*550e691bSryan_chen */ 182*550e691bSryan_chen rate = aspeed_get_hpll_rate(priv); 183*550e691bSryan_chen 184*550e691bSryan_chen break; 185*550e691bSryan_chen case MCLK_DDR: 186*550e691bSryan_chen rate = aspeed_get_mpll_rate(priv); 187*550e691bSryan_chen break; 188*550e691bSryan_chen case BCLK_PCLK: 189*550e691bSryan_chen { 190*550e691bSryan_chen ulong apb_div = 4 + 4 * ((readl(priv->regs + ASPEED_CLK_SELECT) 191*550e691bSryan_chen & SCU_PCLK_DIV_MASK) 192*550e691bSryan_chen >> SCU_PCLK_DIV_SHIFT); 193*550e691bSryan_chen rate = aspeed_get_hpll_rate(priv); 194*550e691bSryan_chen rate = rate / apb_div; 195*550e691bSryan_chen } 196*550e691bSryan_chen break; 197*550e691bSryan_chen case PCLK_UART1: 198*550e691bSryan_chen rate = aspeed_get_uart_clk_rate(priv, 1); 199*550e691bSryan_chen break; 200*550e691bSryan_chen case PCLK_UART2: 201*550e691bSryan_chen rate = aspeed_get_uart_clk_rate(priv, 2); 202*550e691bSryan_chen break; 203*550e691bSryan_chen case PCLK_UART3: 204*550e691bSryan_chen rate = aspeed_get_uart_clk_rate(priv, 3); 205*550e691bSryan_chen break; 206*550e691bSryan_chen case PCLK_UART4: 207*550e691bSryan_chen rate = aspeed_get_uart_clk_rate(priv, 4); 208*550e691bSryan_chen break; 209*550e691bSryan_chen case PCLK_UART5: 210*550e691bSryan_chen rate = aspeed_get_uart_clk_rate(priv, 5); 211*550e691bSryan_chen break; 212*550e691bSryan_chen default: 213*550e691bSryan_chen return -ENOENT; 214*550e691bSryan_chen } 215*550e691bSryan_chen 216*550e691bSryan_chen return rate; 217*550e691bSryan_chen } 218*550e691bSryan_chen 219*550e691bSryan_chen struct aspeed_clock_config { 220*550e691bSryan_chen ulong input_rate; 221*550e691bSryan_chen ulong rate; 222*550e691bSryan_chen struct aspeed_div_config cfg; 223*550e691bSryan_chen }; 224*550e691bSryan_chen 225*550e691bSryan_chen static const struct aspeed_clock_config aspeed_clock_config_defaults[] = { 226*550e691bSryan_chen { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } }, 227*550e691bSryan_chen }; 228*550e691bSryan_chen 229*550e691bSryan_chen static bool aspeed_get_clock_config_default(ulong input_rate, 230*550e691bSryan_chen ulong requested_rate, 231*550e691bSryan_chen struct aspeed_div_config *cfg) 232*550e691bSryan_chen { 233*550e691bSryan_chen int i; 234*550e691bSryan_chen 235*550e691bSryan_chen for (i = 0; i < ARRAY_SIZE(aspeed_clock_config_defaults); i++) { 236*550e691bSryan_chen const struct aspeed_clock_config *default_cfg = 237*550e691bSryan_chen &aspeed_clock_config_defaults[i]; 238*550e691bSryan_chen if (default_cfg->input_rate == input_rate && 239*550e691bSryan_chen default_cfg->rate == requested_rate) { 240*550e691bSryan_chen *cfg = default_cfg->cfg; 241*550e691bSryan_chen return true; 242*550e691bSryan_chen } 243*550e691bSryan_chen } 244*550e691bSryan_chen 245*550e691bSryan_chen return false; 246*550e691bSryan_chen } 247*550e691bSryan_chen 248*550e691bSryan_chen /* 249*550e691bSryan_chen * @input_rate - the rate of input clock in Hz 250*550e691bSryan_chen * @requested_rate - desired output rate in Hz 251*550e691bSryan_chen * @div - this is an IN/OUT parameter, at input all fields of the config 252*550e691bSryan_chen * need to be set to their maximum allowed values. 253*550e691bSryan_chen * The result (the best config we could find), would also be returned 254*550e691bSryan_chen * in this structure. 255*550e691bSryan_chen * 256*550e691bSryan_chen * @return The clock rate, when the resulting div_config is used. 257*550e691bSryan_chen */ 258*550e691bSryan_chen static ulong aspeed_calc_clock_config(ulong input_rate, ulong requested_rate, 259*550e691bSryan_chen struct aspeed_div_config *cfg) 260*550e691bSryan_chen { 261*550e691bSryan_chen /* 262*550e691bSryan_chen * The assumption is that kHz precision is good enough and 263*550e691bSryan_chen * also enough to avoid overflow when multiplying. 264*550e691bSryan_chen */ 265*550e691bSryan_chen const ulong input_rate_khz = input_rate / 1000; 266*550e691bSryan_chen const ulong rate_khz = requested_rate / 1000; 267*550e691bSryan_chen const struct aspeed_div_config max_vals = *cfg; 268*550e691bSryan_chen struct aspeed_div_config it = { 0, 0, 0 }; 269*550e691bSryan_chen ulong delta = rate_khz; 270*550e691bSryan_chen ulong new_rate_khz = 0; 271*550e691bSryan_chen 272*550e691bSryan_chen /* 273*550e691bSryan_chen * Look for a well known frequency first. 274*550e691bSryan_chen */ 275*550e691bSryan_chen if (aspeed_get_clock_config_default(input_rate, requested_rate, cfg)) 276*550e691bSryan_chen return requested_rate; 277*550e691bSryan_chen 278*550e691bSryan_chen for (; it.denum <= max_vals.denum; ++it.denum) { 279*550e691bSryan_chen for (it.post_div = 0; it.post_div <= max_vals.post_div; 280*550e691bSryan_chen ++it.post_div) { 281*550e691bSryan_chen it.num = (rate_khz * (it.post_div + 1) / input_rate_khz) 282*550e691bSryan_chen * (it.denum + 1); 283*550e691bSryan_chen if (it.num > max_vals.num) 284*550e691bSryan_chen continue; 285*550e691bSryan_chen 286*550e691bSryan_chen new_rate_khz = (input_rate_khz 287*550e691bSryan_chen * ((it.num + 1) / (it.denum + 1))) 288*550e691bSryan_chen / (it.post_div + 1); 289*550e691bSryan_chen 290*550e691bSryan_chen /* Keep the rate below requested one. */ 291*550e691bSryan_chen if (new_rate_khz > rate_khz) 292*550e691bSryan_chen continue; 293*550e691bSryan_chen 294*550e691bSryan_chen if (new_rate_khz - rate_khz < delta) { 295*550e691bSryan_chen delta = new_rate_khz - rate_khz; 296*550e691bSryan_chen *cfg = it; 297*550e691bSryan_chen if (delta == 0) 298*550e691bSryan_chen return new_rate_khz * 1000; 299*550e691bSryan_chen } 300*550e691bSryan_chen } 301*550e691bSryan_chen } 302*550e691bSryan_chen 303*550e691bSryan_chen return new_rate_khz * 1000; 304*550e691bSryan_chen } 305*550e691bSryan_chen 306*550e691bSryan_chen static u32 aspeed_configure_ddr(struct aspeed_clk_priv *priv, ulong rate) 307*550e691bSryan_chen { 308*550e691bSryan_chen u32 clkin = aspeed_get_clkin(priv); 309*550e691bSryan_chen u32 mpll_reg; 310*550e691bSryan_chen struct aspeed_div_config div_cfg = { 311*550e691bSryan_chen .num = (SCU_MPLL_NUM_MASK >> SCU_MPLL_NUM_SHIFT), 312*550e691bSryan_chen .denum = (SCU_MPLL_DENUM_MASK >> SCU_MPLL_DENUM_SHIFT), 313*550e691bSryan_chen .post_div = (SCU_MPLL_POST_MASK >> SCU_MPLL_POST_SHIFT), 314*550e691bSryan_chen }; 315*550e691bSryan_chen 316*550e691bSryan_chen aspeed_calc_clock_config(clkin, rate, &div_cfg); 317*550e691bSryan_chen 318*550e691bSryan_chen mpll_reg = readl(priv->regs + ASPEED_MPLL_PARAMETER); 319*550e691bSryan_chen mpll_reg &= ~(SCU_MPLL_POST_MASK | SCU_MPLL_NUM_MASK 320*550e691bSryan_chen | SCU_MPLL_DENUM_MASK); 321*550e691bSryan_chen mpll_reg |= (div_cfg.post_div << SCU_MPLL_POST_SHIFT) 322*550e691bSryan_chen | (div_cfg.num << SCU_MPLL_NUM_SHIFT) 323*550e691bSryan_chen | (div_cfg.denum << SCU_MPLL_DENUM_SHIFT); 324*550e691bSryan_chen 325*550e691bSryan_chen writel(mpll_reg, priv->regs + ASPEED_MPLL_PARAMETER); 326*550e691bSryan_chen 327*550e691bSryan_chen return aspeed_get_mpll_rate(priv); 328*550e691bSryan_chen } 329*550e691bSryan_chen 330*550e691bSryan_chen static u32 aspeed_configure_mac(struct aspeed_clk_priv *priv, int index) 331*550e691bSryan_chen { 332*550e691bSryan_chen u32 clkin = aspeed_get_clkin(priv); 333*550e691bSryan_chen u32 hpll_rate = aspeed_get_hpll_rate(priv); 334*550e691bSryan_chen ulong required_rate; 335*550e691bSryan_chen u32 hwstrap; 336*550e691bSryan_chen u32 divisor; 337*550e691bSryan_chen u32 reset_bit; 338*550e691bSryan_chen u32 clkstop_bit; 339*550e691bSryan_chen #if 0 340*550e691bSryan_chen /* 341*550e691bSryan_chen * According to data sheet, for 10/100 mode the MAC clock frequency 342*550e691bSryan_chen * should be at least 25MHz and for 1000 mode at least 100MHz 343*550e691bSryan_chen */ 344*550e691bSryan_chen hwstrap = readl(priv->regs + ASPEED_STRAP); 345*550e691bSryan_chen if (hwstrap & (SCU_HWSTRAP_MAC1_RGMII | SCU_HWSTRAP_MAC2_RGMII)) 346*550e691bSryan_chen required_rate = 100 * 1000 * 1000; 347*550e691bSryan_chen else 348*550e691bSryan_chen required_rate = 25 * 1000 * 1000; 349*550e691bSryan_chen 350*550e691bSryan_chen divisor = hpll_rate / required_rate; 351*550e691bSryan_chen 352*550e691bSryan_chen if (divisor < 4) { 353*550e691bSryan_chen /* Clock can't run fast enough, but let's try anyway */ 354*550e691bSryan_chen debug("MAC clock too slow\n"); 355*550e691bSryan_chen divisor = 4; 356*550e691bSryan_chen } else if (divisor > 16) { 357*550e691bSryan_chen /* Can't slow down the clock enough, but let's try anyway */ 358*550e691bSryan_chen debug("MAC clock too fast\n"); 359*550e691bSryan_chen divisor = 16; 360*550e691bSryan_chen } 361*550e691bSryan_chen 362*550e691bSryan_chen switch (index) { 363*550e691bSryan_chen case 1: 364*550e691bSryan_chen reset_bit = SCU_SYSRESET_MAC1; 365*550e691bSryan_chen clkstop_bit = SCU_CLKSTOP_MAC1; 366*550e691bSryan_chen break; 367*550e691bSryan_chen case 2: 368*550e691bSryan_chen reset_bit = SCU_SYSRESET_MAC2; 369*550e691bSryan_chen clkstop_bit = SCU_CLKSTOP_MAC2; 370*550e691bSryan_chen break; 371*550e691bSryan_chen default: 372*550e691bSryan_chen return -EINVAL; 373*550e691bSryan_chen } 374*550e691bSryan_chen 375*550e691bSryan_chen clrsetbits_le32(priv->regs + ASPEED_CLK_SELECT, SCU_MACCLK_MASK, 376*550e691bSryan_chen ((divisor - 2) / 2) << SCU_MACCLK_SHIFT); 377*550e691bSryan_chen 378*550e691bSryan_chen /* 379*550e691bSryan_chen * Disable MAC, start its clock and re-enable it. 380*550e691bSryan_chen * The procedure and the delays (100us & 10ms) are 381*550e691bSryan_chen * specified in the datasheet. 382*550e691bSryan_chen */ 383*550e691bSryan_chen setbits_le32(&scu->sysreset_ctrl1, reset_bit); 384*550e691bSryan_chen udelay(100); 385*550e691bSryan_chen clrbits_le32(&scu->clk_stop_ctrl1, clkstop_bit); 386*550e691bSryan_chen mdelay(10); 387*550e691bSryan_chen clrbits_le32(&scu->sysreset_ctrl1, reset_bit); 388*550e691bSryan_chen 389*550e691bSryan_chen writel((RGMII2_TXCK_DUTY << SCU_CLKDUTY_RGMII2TXCK_SHIFT) 390*550e691bSryan_chen | (RGMII1_TXCK_DUTY << SCU_CLKDUTY_RGMII1TXCK_SHIFT), 391*550e691bSryan_chen &scu->clk_duty_sel); 392*550e691bSryan_chen #endif 393*550e691bSryan_chen return required_rate; 394*550e691bSryan_chen } 395*550e691bSryan_chen 396*550e691bSryan_chen static ulong aspeed_configure_d2pll(struct aspeed_clk_priv *priv, ulong rate) 397*550e691bSryan_chen { 398*550e691bSryan_chen /* 399*550e691bSryan_chen * The values and the meaning of the next three 400*550e691bSryan_chen * parameters are undocumented. Taken from Aspeed SDK. 401*550e691bSryan_chen * 402*550e691bSryan_chen * TODO(clg@kaod.org): the SIP and SIC values depend on the 403*550e691bSryan_chen * Numerator value 404*550e691bSryan_chen */ 405*550e691bSryan_chen 406*550e691bSryan_chen const u32 d2_pll_ext_param = 0x2c; 407*550e691bSryan_chen const u32 d2_pll_sip = 0x11; 408*550e691bSryan_chen const u32 d2_pll_sic = 0x18; 409*550e691bSryan_chen u32 clk_delay_settings = 410*550e691bSryan_chen (RMII_RXCLK_IDLY << SCU_MICDS_MAC1RMII_RDLY_SHIFT) 411*550e691bSryan_chen | (RMII_RXCLK_IDLY << SCU_MICDS_MAC2RMII_RDLY_SHIFT) 412*550e691bSryan_chen | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC1RGMII_TXDLY_SHIFT) 413*550e691bSryan_chen | (RGMII_TXCLK_ODLY << SCU_MICDS_MAC2RGMII_TXDLY_SHIFT); 414*550e691bSryan_chen struct aspeed_div_config div_cfg = { 415*550e691bSryan_chen .num = SCU_D2PLL_NUM_MASK >> SCU_D2PLL_NUM_SHIFT, 416*550e691bSryan_chen .denum = SCU_D2PLL_DENUM_MASK >> SCU_D2PLL_DENUM_SHIFT, 417*550e691bSryan_chen .post_div = SCU_D2PLL_POST_MASK >> SCU_D2PLL_POST_SHIFT, 418*550e691bSryan_chen }; 419*550e691bSryan_chen ulong clkin = aspeed_get_clkin(priv); 420*550e691bSryan_chen ulong new_rate; 421*550e691bSryan_chen #if 0 422*550e691bSryan_chen writel((d2_pll_ext_param << SCU_D2PLL_EXT1_PARAM_SHIFT) 423*550e691bSryan_chen | SCU_D2PLL_EXT1_OFF 424*550e691bSryan_chen | SCU_D2PLL_EXT1_RESET, &scu->d2_pll_ext_param[0]); 425*550e691bSryan_chen 426*550e691bSryan_chen /* 427*550e691bSryan_chen * Select USB2.0 port1 PHY clock as a clock source for GCRT. 428*550e691bSryan_chen * This would disconnect it from D2-PLL. 429*550e691bSryan_chen */ 430*550e691bSryan_chen clrsetbits_le32(&scu->misc_ctrl1, SCU_MISC_D2PLL_OFF, 431*550e691bSryan_chen SCU_MISC_GCRT_USB20CLK); 432*550e691bSryan_chen 433*550e691bSryan_chen new_rate = aspeed_calc_clock_config(clkin, rate, &div_cfg); 434*550e691bSryan_chen writel((d2_pll_sip << SCU_D2PLL_SIP_SHIFT) 435*550e691bSryan_chen | (d2_pll_sic << SCU_D2PLL_SIC_SHIFT) 436*550e691bSryan_chen | (div_cfg.num << SCU_D2PLL_NUM_SHIFT) 437*550e691bSryan_chen | (div_cfg.denum << SCU_D2PLL_DENUM_SHIFT) 438*550e691bSryan_chen | (div_cfg.post_div << SCU_D2PLL_POST_SHIFT), 439*550e691bSryan_chen &scu->d2_pll_param); 440*550e691bSryan_chen 441*550e691bSryan_chen clrbits_le32(&scu->d2_pll_ext_param[0], 442*550e691bSryan_chen SCU_D2PLL_EXT1_OFF | SCU_D2PLL_EXT1_RESET); 443*550e691bSryan_chen 444*550e691bSryan_chen clrsetbits_le32(&scu->misc_ctrl2, 445*550e691bSryan_chen SCU_MISC2_RGMII_HPLL | SCU_MISC2_RMII_MPLL 446*550e691bSryan_chen | SCU_MISC2_RGMII_CLKDIV_MASK | 447*550e691bSryan_chen SCU_MISC2_RMII_CLKDIV_MASK, 448*550e691bSryan_chen (4 << SCU_MISC2_RMII_CLKDIV_SHIFT)); 449*550e691bSryan_chen 450*550e691bSryan_chen writel(clk_delay_settings | SCU_MICDS_RGMIIPLL, &scu->mac_clk_delay); 451*550e691bSryan_chen writel(clk_delay_settings, &scu->mac_clk_delay_100M); 452*550e691bSryan_chen writel(clk_delay_settings, &scu->mac_clk_delay_10M); 453*550e691bSryan_chen #endif 454*550e691bSryan_chen return new_rate; 455*550e691bSryan_chen } 456*550e691bSryan_chen 457*550e691bSryan_chen static ulong aspeed_clk_set_rate(struct clk *clk, ulong rate) 458*550e691bSryan_chen { 459*550e691bSryan_chen struct aspeed_clk_priv *priv = dev_get_priv(clk->dev); 460*550e691bSryan_chen 461*550e691bSryan_chen ulong new_rate; 462*550e691bSryan_chen switch (clk->id) { 463*550e691bSryan_chen case PLL_MPLL: 464*550e691bSryan_chen case MCLK_DDR: 465*550e691bSryan_chen new_rate = aspeed_configure_ddr(priv, rate); 466*550e691bSryan_chen break; 467*550e691bSryan_chen case PLL_D2PLL: 468*550e691bSryan_chen new_rate = aspeed_configure_d2pll(priv, rate); 469*550e691bSryan_chen break; 470*550e691bSryan_chen default: 471*550e691bSryan_chen return -ENOENT; 472*550e691bSryan_chen } 473*550e691bSryan_chen 474*550e691bSryan_chen return new_rate; 475*550e691bSryan_chen } 476*550e691bSryan_chen 477*550e691bSryan_chen static int aspeed_clk_enable(struct clk *clk) 478*550e691bSryan_chen { 479*550e691bSryan_chen struct aspeed_clk_priv *priv = dev_get_priv(clk->dev); 480*550e691bSryan_chen 481*550e691bSryan_chen switch (clk->id) { 482*550e691bSryan_chen /* 483*550e691bSryan_chen * For MAC clocks the clock rate is 484*550e691bSryan_chen * configured based on whether RGMII or RMII mode has been selected 485*550e691bSryan_chen * through hardware strapping. 486*550e691bSryan_chen */ 487*550e691bSryan_chen case PCLK_MAC1: 488*550e691bSryan_chen aspeed_configure_mac(priv, 1); 489*550e691bSryan_chen break; 490*550e691bSryan_chen case PCLK_MAC2: 491*550e691bSryan_chen aspeed_configure_mac(priv, 2); 492*550e691bSryan_chen break; 493*550e691bSryan_chen case PLL_D2PLL: 494*550e691bSryan_chen aspeed_configure_d2pll(priv, D2PLL_DEFAULT_RATE); 495*550e691bSryan_chen break; 496*550e691bSryan_chen default: 497*550e691bSryan_chen return -ENOENT; 498*550e691bSryan_chen } 499*550e691bSryan_chen 500*550e691bSryan_chen return 0; 501*550e691bSryan_chen } 502*550e691bSryan_chen 503*550e691bSryan_chen struct clk_ops aspeed_clk_ops = { 504*550e691bSryan_chen .get_rate = aspeed_clk_get_rate, 505*550e691bSryan_chen .set_rate = aspeed_clk_set_rate, 506*550e691bSryan_chen .enable = aspeed_clk_enable, 507*550e691bSryan_chen }; 508*550e691bSryan_chen 509*550e691bSryan_chen static int aspeed_clk_probe(struct udevice *dev) 510*550e691bSryan_chen { 511*550e691bSryan_chen struct aspeed_clk_priv *priv = dev_get_priv(dev); 512*550e691bSryan_chen 513*550e691bSryan_chen priv->regs = devfdt_get_addr_ptr(dev); 514*550e691bSryan_chen 515*550e691bSryan_chen if (IS_ERR(priv->regs)) 516*550e691bSryan_chen return PTR_ERR(priv->regs); 517*550e691bSryan_chen 518*550e691bSryan_chen priv->version = dev_get_driver_data(dev); 519*550e691bSryan_chen 520*550e691bSryan_chen return 0; 521*550e691bSryan_chen } 522*550e691bSryan_chen 523*550e691bSryan_chen static int aspeed_clk_bind(struct udevice *dev) 524*550e691bSryan_chen { 525*550e691bSryan_chen int ret; 526*550e691bSryan_chen 527*550e691bSryan_chen /* The reset driver does not have a device node, so bind it here */ 528*550e691bSryan_chen ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); 529*550e691bSryan_chen if (ret) 530*550e691bSryan_chen debug("Warning: No reset driver: ret=%d\n", ret); 531*550e691bSryan_chen 532*550e691bSryan_chen return 0; 533*550e691bSryan_chen } 534*550e691bSryan_chen 535*550e691bSryan_chen static const struct udevice_id aspeed_clk_ids[] = { 536*550e691bSryan_chen { .compatible = "aspeed,ast2500-scu", .data = AST2500}, 537*550e691bSryan_chen { .compatible = "aspeed,ast2600-scu", .data = AST2600}, 538*550e691bSryan_chen { } 539*550e691bSryan_chen }; 540*550e691bSryan_chen 541*550e691bSryan_chen U_BOOT_DRIVER(aspeed_scu) = { 542*550e691bSryan_chen .name = "aspeed_scu", 543*550e691bSryan_chen .id = UCLASS_CLK, 544*550e691bSryan_chen .of_match = aspeed_clk_ids, 545*550e691bSryan_chen .priv_auto_alloc_size = sizeof(struct aspeed_clk_priv), 546*550e691bSryan_chen .ops = &aspeed_clk_ops, 547*550e691bSryan_chen .bind = aspeed_clk_bind, 548*550e691bSryan_chen .probe = aspeed_clk_probe, 549*550e691bSryan_chen }; 550