|
28 | 28 | #define SCU_SILICON_REVISION 0x7c |
29 | 29 |
|
30 | 30 | #define AST2500_SCU_H_PLL 0x24 |
31 | | -#define AST2500_SCU_H_PLL_P_MASK GENMASK(18, 13) |
32 | | -#define AST2500_SCU_H_PLL_P_SHIFT 13 |
33 | | -#define AST2500_SCU_H_PLL_M_MASK GENMASK(12, 5) |
34 | | -#define AST2500_SCU_H_PLL_M_SHIFT 5 |
35 | | -#define AST2500_SCU_H_PLL_N_MASK GENMASK(4, 0) |
| 31 | +#define AST2500_SCU_H_PLL_P_MASK GENMASK(18, 13) |
| 32 | +#define AST2500_SCU_H_PLL_P_SHIFT 13 |
| 33 | +#define AST2500_SCU_H_PLL_M_MASK GENMASK(12, 5) |
| 34 | +#define AST2500_SCU_H_PLL_M_SHIFT 5 |
| 35 | +#define AST2500_SCU_H_PLL_N_MASK GENMASK(4, 0) |
| 36 | + |
| 37 | +/* We only care about SCU004 for now, revision is not required here */ |
| 38 | +#define AST2600_SCU_SILICON_REVISION 0x04 |
| 39 | + |
| 40 | +#define AST2600_SCU_H_PLL 0x200 |
| 41 | +#define AST2600_SCU_H_PLL_P_MASK GENMASK(22, 19) |
| 42 | +#define AST2600_SCU_H_PLL_P_SHIFT 19 |
| 43 | +#define AST2600_SCU_H_PLL_N_MASK GENMASK(18, 13) |
| 44 | +#define AST2600_SCU_H_PLL_N_SHIFT 13 |
| 45 | +#define AST2600_SCU_H_PLL_M_MASK GENMASK(12, 0) |
| 46 | + |
| 47 | +#define AST2600_SCU_HW_STRAP1 0x500 |
| 48 | +#define AST2600_SCU_HW_STRAP1_ARM_CLK BIT(0) |
| 49 | +#define AST2600_SCU_HW_STRAP1_CPU_AXI_RATIO BIT(16) |
| 50 | +#define AST2600_SCU_HW_STRAP1_AHB_FREQ_RATIO_MASK GENMASK(12, 11) |
| 51 | +#define AST2600_SCU_HW_STRAP1_AHB_FREQ_RATIO_SHIFT 11 |
| 52 | + |
| 53 | +#define AST2600_SCU_HW_STRAP1_CLEAR 0x504 |
36 | 54 |
|
37 | 55 | struct clk_ops { |
38 | 56 | int64_t (*rate_ahb)(struct clk *ctx); |
@@ -256,9 +274,84 @@ static const struct clk_ops ast2500_clk_ops = { |
256 | 274 | .enable = ast2500_clk_enable, |
257 | 275 | }; |
258 | 276 |
|
| 277 | +static int64_t ast2600_clk_rate_ahb(struct clk *ctx) |
| 278 | +{ |
| 279 | + uint32_t h_pll_reg, h_pll, h_pll_m, h_pll_n, h_pll_p; |
| 280 | + uint32_t strap, ahb_ratio, cpu_axi_ratio, hclk; |
| 281 | + int rc; |
| 282 | + |
| 283 | + if ((rc = scu_readl(ctx->scu, AST2600_SCU_HW_STRAP1, &strap)) < 0) |
| 284 | + return rc; |
| 285 | + |
| 286 | + /* The H-PLL register allows us to calculate the CPU freq */ |
| 287 | + if ((rc = scu_readl(ctx->scu, AST2600_SCU_H_PLL, &h_pll_reg)) < 0) |
| 288 | + return rc; |
| 289 | + |
| 290 | + h_pll_p = ((h_pll_reg & AST2600_SCU_H_PLL_P_MASK) >> AST2600_SCU_H_PLL_P_SHIFT) + 1; |
| 291 | + h_pll_n = ((h_pll_reg & AST2600_SCU_H_PLL_N_MASK) >> AST2600_SCU_H_PLL_N_SHIFT) + 1; |
| 292 | + h_pll_m = (h_pll_reg & AST2600_SCU_H_PLL_M_MASK) + 1; |
| 293 | + |
| 294 | + /* H-PLL = CLKIN (always 25 MHz) * (M+1/N+1) / P+1 */ |
| 295 | + h_pll = 25 * (h_pll_m / h_pll_n) / h_pll_p; |
| 296 | + logt("clk: ast2600: calculated h-pll is %d MHz\n", h_pll); |
| 297 | + |
| 298 | + cpu_axi_ratio = (strap & AST2600_SCU_HW_STRAP1_CPU_AXI_RATIO); |
| 299 | + |
| 300 | + /* AXI/AHB clock frequency ratio selection */ |
| 301 | + ahb_ratio = (strap & AST2600_SCU_HW_STRAP1_AHB_FREQ_RATIO_MASK) >> AST2600_SCU_HW_STRAP1_AHB_FREQ_RATIO_SHIFT; |
| 302 | + if (!ahb_ratio) |
| 303 | + return -EINVAL; |
| 304 | + |
| 305 | + /* |
| 306 | + * If cpu_axi_ratio is set, then the ratios are default, 4, 6, 8. |
| 307 | + * Otherwise, the ratios are default, 2, 3, 4. |
| 308 | + * The default is "that makes HCLK = 200MHz", but there's no explanation |
| 309 | + * how HCLK is being calculated so I'll just return 200 MHz as AHB Rate if no |
| 310 | + * ratio is set lol |
| 311 | + */ |
| 312 | + if (!ahb_ratio) |
| 313 | + return 200; |
| 314 | + |
| 315 | + /* Ratio calc from the binary value */ |
| 316 | + ahb_ratio++; |
| 317 | + if (cpu_axi_ratio) |
| 318 | + ahb_ratio *= 2; |
| 319 | + |
| 320 | + logt("clk: ast2600: ahb ratio: %d:1\n", ahb_ratio); |
| 321 | + |
| 322 | + /* I'm just gonna assume that HCLK = H-PLL / 2 / ahb_ratio */ |
| 323 | + hclk = h_pll / 2 / ahb_ratio; |
| 324 | + logt("clk: ast2600: ahb freq: %d MHz\n", hclk); |
| 325 | + |
| 326 | + return hclk; |
| 327 | +} |
| 328 | + |
| 329 | +int ast2600_clk_disable(struct clk *ctx, enum clksrc src) |
| 330 | +{ |
| 331 | + if (src != clk_arm) |
| 332 | + return -ENOTSUP; |
| 333 | + |
| 334 | + return scu_writel(ctx->scu, AST2600_SCU_HW_STRAP1, AST2600_SCU_HW_STRAP1_ARM_CLK); |
| 335 | +} |
| 336 | + |
| 337 | +int ast2600_clk_enable(struct clk *ctx, enum clksrc src) |
| 338 | +{ |
| 339 | + if (src != clk_arm) |
| 340 | + return -ENOTSUP; |
| 341 | + |
| 342 | + return scu_writel(ctx->scu, AST2600_SCU_HW_STRAP1_CLEAR, AST2600_SCU_HW_STRAP1_ARM_CLK); |
| 343 | +} |
| 344 | + |
| 345 | +static const struct clk_ops ast2600_clk_ops = { |
| 346 | + .rate_ahb = ast2600_clk_rate_ahb, |
| 347 | + .disable = ast2600_clk_disable, |
| 348 | + .enable = ast2600_clk_enable, |
| 349 | +}; |
| 350 | + |
259 | 351 | static const struct soc_device_id clk_match[] = { |
260 | 352 | { .compatible = "aspeed,ast2400-clock", .data = &ast2400_clk_ops }, |
261 | 353 | { .compatible = "aspeed,ast2500-clock", .data = &ast2500_clk_ops }, |
| 354 | + { .compatible = "aspeed,ast2600-clock", .data = &ast2600_clk_ops }, |
262 | 355 | { }, |
263 | 356 | }; |
264 | 357 |
|
|
0 commit comments