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

Configure Feed

Select the types of activity you want to include in your feed.

clk: qcom: clk-alpha-pll: Add Pongo PLL

Add support for Pongo type of PLL clocks, used in Qualcomm SM8750 SoC.
Notable difference comparing to other PLLs is the need for calibration
for internally generated clock followed by wait_for_pll(). This is done
in configure call and at this time clocks are not yet registered, thus
wait_for_pll() cannot use clk_hw_get_name. Locking during this
calibration requires much more time, thus increase the timeout in
wait_for_pll().

Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20250106-sm8750-dispcc-v2-2-6f42beda6317@linaro.org
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Krzysztof Kozlowski and committed by
Bjorn Andersson
1adc5289 9d46289f

+170 -1
+164 -1
drivers/clk/qcom/clk-alpha-pll.c
··· 58 58 #define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U]) 59 59 #define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1]) 60 60 #define PLL_TEST_CTL_U2(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U2]) 61 + #define PLL_TEST_CTL_U3(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U3]) 61 62 #define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS]) 62 63 #define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE]) 63 64 #define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC]) ··· 197 196 [PLL_OFF_TEST_CTL_U] = 0x30, 198 197 [PLL_OFF_TEST_CTL_U1] = 0x34, 199 198 [PLL_OFF_TEST_CTL_U2] = 0x38, 199 + }, 200 + [CLK_ALPHA_PLL_TYPE_PONGO_ELU] = { 201 + [PLL_OFF_OPMODE] = 0x04, 202 + [PLL_OFF_STATE] = 0x08, 203 + [PLL_OFF_STATUS] = 0x0c, 204 + [PLL_OFF_L_VAL] = 0x10, 205 + [PLL_OFF_USER_CTL] = 0x14, 206 + [PLL_OFF_USER_CTL_U] = 0x18, 207 + [PLL_OFF_CONFIG_CTL] = 0x1c, 208 + [PLL_OFF_CONFIG_CTL_U] = 0x20, 209 + [PLL_OFF_CONFIG_CTL_U1] = 0x24, 210 + [PLL_OFF_CONFIG_CTL_U2] = 0x28, 211 + [PLL_OFF_TEST_CTL] = 0x2c, 212 + [PLL_OFF_TEST_CTL_U] = 0x30, 213 + [PLL_OFF_TEST_CTL_U1] = 0x34, 214 + [PLL_OFF_TEST_CTL_U2] = 0x38, 215 + [PLL_OFF_TEST_CTL_U3] = 0x3c, 200 216 }, 201 217 [CLK_ALPHA_PLL_TYPE_TAYCAN_ELU] = { 202 218 [PLL_OFF_OPMODE] = 0x04, ··· 355 337 #define LUCID_EVO_PLL_CAL_L_VAL_SHIFT 16 356 338 #define LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT 24 357 339 340 + /* PONGO ELU PLL specific setting and offsets */ 341 + #define PONGO_PLL_OUT_MASK GENMASK(1, 0) 342 + #define PONGO_PLL_L_VAL_MASK GENMASK(11, 0) 343 + #define PONGO_XO_PRESENT BIT(10) 344 + #define PONGO_CLOCK_SELECT BIT(12) 345 + 358 346 /* ZONDA PLL specific */ 359 347 #define ZONDA_PLL_OUT_MASK 0xf 360 348 #define ZONDA_STAY_IN_CFA BIT(16) ··· 390 366 if (ret) 391 367 return ret; 392 368 393 - for (count = 200; count > 0; count--) { 369 + /* Pongo PLLs using a 32KHz reference can take upwards of 1500us to lock. */ 370 + for (count = 1500; count > 0; count--) { 394 371 ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); 395 372 if (ret) 396 373 return ret; ··· 2534 2509 .set_rate = alpha_pll_lucid_5lpe_set_rate, 2535 2510 }; 2536 2511 EXPORT_SYMBOL_GPL(clk_alpha_pll_reset_lucid_evo_ops); 2512 + 2513 + static int alpha_pll_pongo_elu_prepare(struct clk_hw *hw) 2514 + { 2515 + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 2516 + struct regmap *regmap = pll->clkr.regmap; 2517 + int ret; 2518 + 2519 + /* Enable PLL intially to one-time calibrate against XO. */ 2520 + regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); 2521 + regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 2522 + regmap_update_bits(regmap, PLL_MODE(pll), PONGO_XO_PRESENT, PONGO_XO_PRESENT); 2523 + 2524 + /* Set regmap for wait_for_pll() */ 2525 + pll->clkr.regmap = regmap; 2526 + ret = wait_for_pll_enable_lock(pll); 2527 + if (ret) { 2528 + /* Reverse calibration - disable PLL output */ 2529 + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 2530 + return ret; 2531 + } 2532 + 2533 + /* Disable PLL after one-time calibration. */ 2534 + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 2535 + 2536 + /* Select internally generated clock. */ 2537 + regmap_update_bits(regmap, PLL_MODE(pll), PONGO_CLOCK_SELECT, 2538 + PONGO_CLOCK_SELECT); 2539 + 2540 + return 0; 2541 + } 2542 + 2543 + static int alpha_pll_pongo_elu_enable(struct clk_hw *hw) 2544 + { 2545 + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 2546 + struct regmap *regmap = pll->clkr.regmap; 2547 + int ret; 2548 + 2549 + /* Check if PLL is already enabled */ 2550 + if (trion_pll_is_enabled(pll, regmap)) 2551 + return 0; 2552 + 2553 + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); 2554 + if (ret) 2555 + return ret; 2556 + 2557 + /* Set operation mode to RUN */ 2558 + regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN); 2559 + 2560 + ret = wait_for_pll_enable_lock(pll); 2561 + if (ret) 2562 + return ret; 2563 + 2564 + /* Enable the global PLL outputs */ 2565 + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); 2566 + if (ret) 2567 + return ret; 2568 + 2569 + /* Ensure that the write above goes through before returning. */ 2570 + mb(); 2571 + 2572 + return ret; 2573 + } 2574 + 2575 + static void alpha_pll_pongo_elu_disable(struct clk_hw *hw) 2576 + { 2577 + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 2578 + struct regmap *regmap = pll->clkr.regmap; 2579 + int ret; 2580 + 2581 + /* Disable the global PLL output */ 2582 + ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 2583 + if (ret) 2584 + return; 2585 + 2586 + /* Place the PLL mode in STANDBY */ 2587 + regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY); 2588 + } 2589 + 2590 + static unsigned long alpha_pll_pongo_elu_recalc_rate(struct clk_hw *hw, 2591 + unsigned long parent_rate) 2592 + { 2593 + struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); 2594 + struct regmap *regmap = pll->clkr.regmap; 2595 + u32 l; 2596 + 2597 + if (regmap_read(regmap, PLL_L_VAL(pll), &l)) 2598 + return 0; 2599 + 2600 + l &= PONGO_PLL_L_VAL_MASK; 2601 + 2602 + return alpha_pll_calc_rate(parent_rate, l, 0, pll_alpha_width(pll)); 2603 + } 2604 + 2605 + const struct clk_ops clk_alpha_pll_pongo_elu_ops = { 2606 + .prepare = alpha_pll_pongo_elu_prepare, 2607 + .enable = alpha_pll_pongo_elu_enable, 2608 + .disable = alpha_pll_pongo_elu_disable, 2609 + .recalc_rate = alpha_pll_pongo_elu_recalc_rate, 2610 + }; 2611 + EXPORT_SYMBOL_GPL(clk_alpha_pll_pongo_elu_ops); 2612 + 2613 + void clk_pongo_elu_pll_configure(struct clk_alpha_pll *pll, 2614 + struct regmap *regmap, 2615 + const struct alpha_pll_config *config) 2616 + { 2617 + u32 val; 2618 + 2619 + regmap_update_bits(regmap, PLL_USER_CTL(pll), PONGO_PLL_OUT_MASK, 2620 + PONGO_PLL_OUT_MASK); 2621 + 2622 + if (trion_pll_is_enabled(pll, regmap)) 2623 + return; 2624 + 2625 + if (regmap_read(regmap, PLL_L_VAL(pll), &val)) 2626 + return; 2627 + val &= PONGO_PLL_L_VAL_MASK; 2628 + if (val) 2629 + return; 2630 + 2631 + clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l); 2632 + clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha); 2633 + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); 2634 + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); 2635 + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); 2636 + clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U2(pll), config->config_ctl_hi2_val); 2637 + clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll), 2638 + config->user_ctl_val | PONGO_PLL_OUT_MASK); 2639 + clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); 2640 + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); 2641 + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); 2642 + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); 2643 + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val); 2644 + clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U3(pll), config->test_ctl_hi3_val); 2645 + 2646 + /* Disable PLL output */ 2647 + regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); 2648 + } 2649 + EXPORT_SYMBOL_GPL(clk_pongo_elu_pll_configure); 2537 2650 2538 2651 void clk_rivian_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 2539 2652 const struct alpha_pll_config *config)
+6
drivers/clk/qcom/clk-alpha-pll.h
··· 27 27 CLK_ALPHA_PLL_TYPE_ZONDA_OLE, 28 28 CLK_ALPHA_PLL_TYPE_LUCID_EVO, 29 29 CLK_ALPHA_PLL_TYPE_LUCID_OLE, 30 + CLK_ALPHA_PLL_TYPE_PONGO_ELU, 30 31 CLK_ALPHA_PLL_TYPE_TAYCAN_ELU, 31 32 CLK_ALPHA_PLL_TYPE_RIVIAN_EVO, 32 33 CLK_ALPHA_PLL_TYPE_DEFAULT_EVO, ··· 54 53 PLL_OFF_TEST_CTL_U, 55 54 PLL_OFF_TEST_CTL_U1, 56 55 PLL_OFF_TEST_CTL_U2, 56 + PLL_OFF_TEST_CTL_U3, 57 57 PLL_OFF_STATE, 58 58 PLL_OFF_STATUS, 59 59 PLL_OFF_OPMODE, ··· 140 138 u32 test_ctl_hi_mask; 141 139 u32 test_ctl_hi1_val; 142 140 u32 test_ctl_hi2_val; 141 + u32 test_ctl_hi3_val; 143 142 u32 main_output_mask; 144 143 u32 aux_output_mask; 145 144 u32 aux2_output_mask; ··· 199 196 #define clk_alpha_pll_postdiv_lucid_ole_ops clk_alpha_pll_postdiv_lucid_evo_ops 200 197 #define clk_alpha_pll_postdiv_taycan_elu_ops clk_alpha_pll_postdiv_lucid_evo_ops 201 198 199 + extern const struct clk_ops clk_alpha_pll_pongo_elu_ops; 202 200 extern const struct clk_ops clk_alpha_pll_rivian_evo_ops; 203 201 #define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_ops 204 202 ··· 225 221 void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 226 222 const struct alpha_pll_config *config); 227 223 void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 224 + const struct alpha_pll_config *config); 225 + void clk_pongo_elu_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, 228 226 const struct alpha_pll_config *config); 229 227 #define clk_taycan_elu_pll_configure(pll, regmap, config) \ 230 228 clk_lucid_evo_pll_configure(pll, regmap, config)