1 /* 2 * (C) Copyright 2016 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0 5 */ 6 7 #include <common.h> 8 #include <clk-uclass.h> 9 #include <dm.h> 10 #include <asm/io.h> 11 #include <asm/arch/scu_ast2500.h> 12 #include <dm/lists.h> 13 #include <dt-bindings/clock/ast2500-scu.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 /* 18 * For H-PLL and M-PLL the formula is 19 * (Output Frequency) = CLKIN * ((M + 1) / (N + 1)) / (P + 1) 20 * M - Numerator 21 * N - Denumerator 22 * P - Post Divider 23 * They have the same layout in their control register. 24 */ 25 26 /* 27 * Get the rate of the M-PLL clock from input clock frequency and 28 * the value of the M-PLL Parameter Register. 29 */ 30 static ulong ast2500_get_mpll_rate(ulong clkin, u32 mpll_reg) 31 { 32 const ulong num = (mpll_reg >> SCU_MPLL_NUM_SHIFT) & SCU_MPLL_NUM_MASK; 33 const ulong denum = (mpll_reg >> SCU_MPLL_DENUM_SHIFT) 34 & SCU_MPLL_DENUM_MASK; 35 const ulong post_div = (mpll_reg >> SCU_MPLL_POST_SHIFT) 36 & SCU_MPLL_POST_MASK; 37 38 return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 39 } 40 41 /* 42 * Get the rate of the H-PLL clock from input clock frequency and 43 * the value of the H-PLL Parameter Register. 44 */ 45 static ulong ast2500_get_hpll_rate(ulong clkin, u32 hpll_reg) 46 { 47 const ulong num = (hpll_reg >> SCU_HPLL_NUM_SHIFT) & SCU_HPLL_NUM_MASK; 48 const ulong denum = (hpll_reg >> SCU_HPLL_DENUM_SHIFT) 49 & SCU_HPLL_DENUM_MASK; 50 const ulong post_div = (hpll_reg >> SCU_HPLL_POST_SHIFT) 51 & SCU_HPLL_POST_MASK; 52 53 return (clkin * ((num + 1) / (denum + 1))) / (post_div + 1); 54 } 55 56 static ulong ast2500_get_clkin(struct ast2500_scu *scu) 57 { 58 return readl(&scu->hwstrap) & SCU_HWSTRAP_CLKIN_25MHZ 59 ? 25 * 1000 * 1000 : 24 * 1000 * 1000; 60 } 61 62 /** 63 * Get current rate or uart clock 64 * 65 * @scu SCU registers 66 * @uart_index UART index, 1-5 67 * 68 * @return current setting for uart clock rate 69 */ 70 static ulong ast2500_get_uart_clk_rate(struct ast2500_scu *scu, int uart_index) 71 { 72 /* 73 * ast2500 datasheet is very confusing when it comes to UART clocks, 74 * especially when CLKIN = 25 MHz. The settings are in 75 * different registers and it is unclear how they interact. 76 * 77 * This has only been tested with default settings and CLKIN = 24 MHz. 78 */ 79 ulong uart_clkin; 80 81 if (readl(&scu->misc_ctrl2) & 82 (1 << (uart_index - 1 + SCU_MISC2_UARTCLK_SHIFT))) 83 uart_clkin = 192 * 1000 * 1000; 84 else 85 uart_clkin = 24 * 1000 * 1000; 86 87 if (readl(&scu->misc_ctrl1) & SCU_MISC_UARTCLK_DIV13) 88 uart_clkin /= 13; 89 90 return uart_clkin; 91 } 92 93 static ulong ast2500_clk_get_rate(struct clk *clk) 94 { 95 struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); 96 ulong clkin = ast2500_get_clkin(priv->scu); 97 ulong rate; 98 99 switch (clk->id) { 100 case PLL_HPLL: 101 case ARMCLK: 102 /* 103 * This ignores dynamic/static slowdown of ARMCLK and may 104 * be inaccurate. 105 */ 106 rate = ast2500_get_hpll_rate(clkin, 107 readl(&priv->scu->h_pll_param)); 108 break; 109 case MCLK_DDR: 110 rate = ast2500_get_mpll_rate(clkin, 111 readl(&priv->scu->m_pll_param)); 112 break; 113 case PCLK_UART1: 114 rate = ast2500_get_uart_clk_rate(priv->scu, 1); 115 break; 116 case PCLK_UART2: 117 rate = ast2500_get_uart_clk_rate(priv->scu, 2); 118 break; 119 case PCLK_UART3: 120 rate = ast2500_get_uart_clk_rate(priv->scu, 3); 121 break; 122 case PCLK_UART4: 123 rate = ast2500_get_uart_clk_rate(priv->scu, 4); 124 break; 125 case PCLK_UART5: 126 rate = ast2500_get_uart_clk_rate(priv->scu, 5); 127 break; 128 default: 129 return -ENOENT; 130 } 131 132 return rate; 133 } 134 135 static void ast2500_scu_unlock(struct ast2500_scu *scu) 136 { 137 writel(SCU_UNLOCK_VALUE, &scu->protection_key); 138 while (!readl(&scu->protection_key)) 139 ; 140 } 141 142 static void ast2500_scu_lock(struct ast2500_scu *scu) 143 { 144 writel(~SCU_UNLOCK_VALUE, &scu->protection_key); 145 while (readl(&scu->protection_key)) 146 ; 147 } 148 149 static ulong ast2500_configure_ddr(struct ast2500_scu *scu, ulong rate) 150 { 151 ulong clkin = ast2500_get_clkin(scu); 152 u32 mpll_reg; 153 154 /* 155 * There are not that many combinations of numerator, denumerator 156 * and post divider, so just brute force the best combination. 157 * However, to avoid overflow when multiplying, use kHz. 158 */ 159 const ulong clkin_khz = clkin / 1000; 160 const ulong rate_khz = rate / 1000; 161 ulong best_num = 0; 162 ulong best_denum = 0; 163 ulong best_post = 0; 164 ulong delta = rate; 165 ulong num, denum, post; 166 167 for (denum = 0; denum <= SCU_MPLL_DENUM_MASK; ++denum) { 168 for (post = 0; post <= SCU_MPLL_POST_MASK; ++post) { 169 num = (rate_khz * (post + 1) / clkin_khz) * (denum + 1); 170 ulong new_rate_khz = (clkin_khz 171 * ((num + 1) / (denum + 1))) 172 / (post + 1); 173 174 /* Keep the rate below requested one. */ 175 if (new_rate_khz > rate_khz) 176 continue; 177 178 if (new_rate_khz - rate_khz < delta) { 179 delta = new_rate_khz - rate_khz; 180 181 best_num = num; 182 best_denum = denum; 183 best_post = post; 184 185 if (delta == 0) 186 goto rate_calc_done; 187 } 188 } 189 } 190 191 rate_calc_done: 192 mpll_reg = readl(&scu->m_pll_param); 193 mpll_reg &= ~((SCU_MPLL_POST_MASK << SCU_MPLL_POST_SHIFT) 194 | (SCU_MPLL_NUM_MASK << SCU_MPLL_NUM_SHIFT) 195 | (SCU_MPLL_DENUM_MASK << SCU_MPLL_DENUM_SHIFT)); 196 mpll_reg |= (best_post << SCU_MPLL_POST_SHIFT) 197 | (best_num << SCU_MPLL_NUM_SHIFT) 198 | (best_denum << SCU_MPLL_DENUM_SHIFT); 199 200 ast2500_scu_unlock(scu); 201 writel(mpll_reg, &scu->m_pll_param); 202 ast2500_scu_lock(scu); 203 204 return ast2500_get_mpll_rate(clkin, mpll_reg); 205 } 206 207 static ulong ast2500_clk_set_rate(struct clk *clk, ulong rate) 208 { 209 struct ast2500_clk_priv *priv = dev_get_priv(clk->dev); 210 211 ulong new_rate; 212 switch (clk->id) { 213 case PLL_MPLL: 214 case MCLK_DDR: 215 new_rate = ast2500_configure_ddr(priv->scu, rate); 216 break; 217 default: 218 return -ENOENT; 219 } 220 221 return new_rate; 222 } 223 224 struct clk_ops ast2500_clk_ops = { 225 .get_rate = ast2500_clk_get_rate, 226 .set_rate = ast2500_clk_set_rate, 227 }; 228 229 static int ast2500_clk_probe(struct udevice *dev) 230 { 231 struct ast2500_clk_priv *priv = dev_get_priv(dev); 232 233 priv->scu = dev_get_addr_ptr(dev); 234 if (IS_ERR(priv->scu)) 235 return PTR_ERR(priv->scu); 236 237 return 0; 238 } 239 240 static int ast2500_clk_bind(struct udevice *dev) 241 { 242 int ret; 243 244 /* The reset driver does not have a device node, so bind it here */ 245 ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); 246 if (ret) 247 debug("Warning: No reset driver: ret=%d\n", ret); 248 249 return 0; 250 } 251 252 static const struct udevice_id ast2500_clk_ids[] = { 253 { .compatible = "aspeed,ast2500-scu" }, 254 { } 255 }; 256 257 U_BOOT_DRIVER(aspeed_ast2500_scu) = { 258 .name = "aspeed_ast2500_scu", 259 .id = UCLASS_CLK, 260 .of_match = ast2500_clk_ids, 261 .priv_auto_alloc_size = sizeof(struct ast2500_clk_priv), 262 .ops = &ast2500_clk_ops, 263 .bind = ast2500_clk_bind, 264 .probe = ast2500_clk_probe, 265 }; 266