Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

clk: rockchip: rk3588: register GATE_LINK later

The proper GATE_LINK implementation will use runtime PM to handle the
linked gate clocks, which requires device context. Currently all clocks
are registered early via CLK_OF_DECLARE, which is before the kernel
knows about devices.

Moving the full clocks registration to the probe routine does not work,
since the clocks needed for timers must be registered early.

To work around this issue, most of the clock tree is registered early,
but GATE_LINK clocks are handled in the probe routine. Since the resets
are not needed early either, they have also been moved to the probe
routine.

Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Link: https://lore.kernel.org/r/20241211165957.94922-3-sebastian.reichel@collabora.com
Signed-off-by: Heiko Stuebner <heiko@sntech.de>

authored by

Sebastian Reichel and committed by
Heiko Stuebner
33af9624 9e89f02d

+63 -13
+63 -13
drivers/clk/rockchip/clk-rk3588.c
··· 266 266 }, \ 267 267 } 268 268 269 + static struct rockchip_clk_provider *early_ctx; 270 + 269 271 static struct rockchip_cpuclk_rate_table rk3588_cpub0clk_rates[] __initdata = { 270 272 RK3588_CPUB01CLK_RATE(2496000000, 1), 271 273 RK3588_CPUB01CLK_RATE(2400000000, 1), ··· 696 694 RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates), 697 695 }; 698 696 699 - static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = { 697 + static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = { 700 698 /* 701 699 * CRU Clock-Architecture 702 700 */ ··· 2430 2428 RK3588_CLKGATE_CON(68), 5, GFLAGS), 2431 2429 GATE(ACLK_AV1, "aclk_av1", "aclk_av1_pre", 0, 2432 2430 RK3588_CLKGATE_CON(68), 2, GFLAGS), 2431 + }; 2433 2432 2433 + static struct rockchip_clk_branch rk3588_clk_branches[] = { 2434 2434 GATE_LINK(ACLK_ISP1_PRE, "aclk_isp1_pre", "aclk_isp1_root", ACLK_VI_ROOT, 0, RK3588_CLKGATE_CON(26), 6, GFLAGS), 2435 2435 GATE_LINK(HCLK_ISP1_PRE, "hclk_isp1_pre", "hclk_isp1_root", HCLK_VI_ROOT, 0, RK3588_CLKGATE_CON(26), 8, GFLAGS), 2436 2436 GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", ACLK_NVM_ROOT, RK3588_LINKED_CLK, RK3588_CLKGATE_CON(31), 2, GFLAGS), ··· 2457 2453 GATE_LINK(PCLK_VO1GRF, "pclk_vo1grf", "pclk_vo1_root", HCLK_VO1, CLK_IGNORE_UNUSED, RK3588_CLKGATE_CON(59), 12, GFLAGS), 2458 2454 }; 2459 2455 2460 - static void __init rk3588_clk_init(struct device_node *np) 2456 + static void __init rk3588_clk_early_init(struct device_node *np) 2461 2457 { 2462 2458 struct rockchip_clk_provider *ctx; 2463 - unsigned long clk_nr_clks; 2459 + unsigned long clk_nr_clks, max_clk_id1, max_clk_id2; 2464 2460 void __iomem *reg_base; 2465 2461 2466 - clk_nr_clks = rockchip_clk_find_max_clk_id(rk3588_clk_branches, 2467 - ARRAY_SIZE(rk3588_clk_branches)) + 1; 2462 + max_clk_id1 = rockchip_clk_find_max_clk_id(rk3588_clk_branches, 2463 + ARRAY_SIZE(rk3588_clk_branches)); 2464 + max_clk_id2 = rockchip_clk_find_max_clk_id(rk3588_early_clk_branches, 2465 + ARRAY_SIZE(rk3588_early_clk_branches)); 2466 + clk_nr_clks = max(max_clk_id1, max_clk_id2) + 1; 2467 + 2468 2468 reg_base = of_iomap(np, 0); 2469 2469 if (!reg_base) { 2470 2470 pr_err("%s: could not map cru region\n", __func__); 2471 2471 return; 2472 2472 } 2473 2473 2474 - ctx = rockchip_clk_init(np, reg_base, clk_nr_clks); 2474 + ctx = rockchip_clk_init_early(np, reg_base, clk_nr_clks); 2475 2475 if (IS_ERR(ctx)) { 2476 2476 pr_err("%s: rockchip clk init failed\n", __func__); 2477 2477 iounmap(reg_base); 2478 2478 return; 2479 2479 } 2480 + early_ctx = ctx; 2480 2481 2481 2482 rockchip_clk_register_plls(ctx, rk3588_pll_clks, 2482 2483 ARRAY_SIZE(rk3588_pll_clks), ··· 2500 2491 &rk3588_cpub1clk_data, rk3588_cpub1clk_rates, 2501 2492 ARRAY_SIZE(rk3588_cpub1clk_rates)); 2502 2493 2503 - rockchip_clk_register_branches(ctx, rk3588_clk_branches, 2504 - ARRAY_SIZE(rk3588_clk_branches)); 2505 - 2506 - rk3588_rst_init(np, reg_base); 2507 - 2508 - rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST, NULL); 2494 + rockchip_clk_register_branches(ctx, rk3588_early_clk_branches, 2495 + ARRAY_SIZE(rk3588_early_clk_branches)); 2509 2496 2510 2497 rockchip_clk_of_add_provider(np, ctx); 2511 2498 } 2499 + CLK_OF_DECLARE_DRIVER(rk3588_cru, "rockchip,rk3588-cru", rk3588_clk_early_init); 2512 2500 2513 - CLK_OF_DECLARE(rk3588_cru, "rockchip,rk3588-cru", rk3588_clk_init); 2501 + static int clk_rk3588_probe(struct platform_device *pdev) 2502 + { 2503 + struct rockchip_clk_provider *ctx = early_ctx; 2504 + struct device *dev = &pdev->dev; 2505 + struct device_node *np = dev->of_node; 2506 + 2507 + rockchip_clk_register_branches(ctx, rk3588_clk_branches, 2508 + ARRAY_SIZE(rk3588_clk_branches)); 2509 + 2510 + rockchip_clk_finalize(ctx); 2511 + 2512 + rk3588_rst_init(np, ctx->reg_base); 2513 + rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST, NULL); 2514 + 2515 + /* 2516 + * Re-add clock provider, so that the newly added clocks are also 2517 + * re-parented and get their defaults configured. 2518 + */ 2519 + of_clk_del_provider(np); 2520 + rockchip_clk_of_add_provider(np, ctx); 2521 + 2522 + return 0; 2523 + } 2524 + 2525 + static const struct of_device_id clk_rk3588_match_table[] = { 2526 + { 2527 + .compatible = "rockchip,rk3588-cru", 2528 + }, 2529 + { } 2530 + }; 2531 + 2532 + static struct platform_driver clk_rk3588_driver = { 2533 + .probe = clk_rk3588_probe, 2534 + .driver = { 2535 + .name = "clk-rk3588", 2536 + .of_match_table = clk_rk3588_match_table, 2537 + .suppress_bind_attrs = true, 2538 + }, 2539 + }; 2540 + 2541 + static int __init rockchip_clk_rk3588_drv_register(void) 2542 + { 2543 + return platform_driver_register(&clk_rk3588_driver); 2544 + } 2545 + core_initcall(rockchip_clk_rk3588_drv_register);