Skip to content

Commit 1adc528

Browse files
krzkandersson
authored andcommitted
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Bjorn Andersson <[email protected]>
1 parent 9d46289 commit 1adc528

File tree

2 files changed

+170
-1
lines changed

2 files changed

+170
-1
lines changed

drivers/clk/qcom/clk-alpha-pll.c

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U])
5959
#define PLL_TEST_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U1])
6060
#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])
6162
#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS])
6263
#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE])
6364
#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC])
@@ -197,6 +198,23 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
197198
[PLL_OFF_TEST_CTL_U1] = 0x34,
198199
[PLL_OFF_TEST_CTL_U2] = 0x38,
199200
},
201+
[CLK_ALPHA_PLL_TYPE_PONGO_ELU] = {
202+
[PLL_OFF_OPMODE] = 0x04,
203+
[PLL_OFF_STATE] = 0x08,
204+
[PLL_OFF_STATUS] = 0x0c,
205+
[PLL_OFF_L_VAL] = 0x10,
206+
[PLL_OFF_USER_CTL] = 0x14,
207+
[PLL_OFF_USER_CTL_U] = 0x18,
208+
[PLL_OFF_CONFIG_CTL] = 0x1c,
209+
[PLL_OFF_CONFIG_CTL_U] = 0x20,
210+
[PLL_OFF_CONFIG_CTL_U1] = 0x24,
211+
[PLL_OFF_CONFIG_CTL_U2] = 0x28,
212+
[PLL_OFF_TEST_CTL] = 0x2c,
213+
[PLL_OFF_TEST_CTL_U] = 0x30,
214+
[PLL_OFF_TEST_CTL_U1] = 0x34,
215+
[PLL_OFF_TEST_CTL_U2] = 0x38,
216+
[PLL_OFF_TEST_CTL_U3] = 0x3c,
217+
},
200218
[CLK_ALPHA_PLL_TYPE_TAYCAN_ELU] = {
201219
[PLL_OFF_OPMODE] = 0x04,
202220
[PLL_OFF_STATE] = 0x08,
@@ -337,6 +355,12 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
337355
#define LUCID_EVO_PLL_CAL_L_VAL_SHIFT 16
338356
#define LUCID_OLE_PLL_RINGOSC_CAL_L_VAL_SHIFT 24
339357

358+
/* PONGO ELU PLL specific setting and offsets */
359+
#define PONGO_PLL_OUT_MASK GENMASK(1, 0)
360+
#define PONGO_PLL_L_VAL_MASK GENMASK(11, 0)
361+
#define PONGO_XO_PRESENT BIT(10)
362+
#define PONGO_CLOCK_SELECT BIT(12)
363+
340364
/* ZONDA PLL specific */
341365
#define ZONDA_PLL_OUT_MASK 0xf
342366
#define ZONDA_STAY_IN_CFA BIT(16)
@@ -366,7 +390,8 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
366390
if (ret)
367391
return ret;
368392

369-
for (count = 200; count > 0; count--) {
393+
/* Pongo PLLs using a 32KHz reference can take upwards of 1500us to lock. */
394+
for (count = 1500; count > 0; count--) {
370395
ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val);
371396
if (ret)
372397
return ret;
@@ -2510,6 +2535,144 @@ const struct clk_ops clk_alpha_pll_reset_lucid_evo_ops = {
25102535
};
25112536
EXPORT_SYMBOL_GPL(clk_alpha_pll_reset_lucid_evo_ops);
25122537

2538+
static int alpha_pll_pongo_elu_prepare(struct clk_hw *hw)
2539+
{
2540+
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
2541+
struct regmap *regmap = pll->clkr.regmap;
2542+
int ret;
2543+
2544+
/* Enable PLL intially to one-time calibrate against XO. */
2545+
regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);
2546+
regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
2547+
regmap_update_bits(regmap, PLL_MODE(pll), PONGO_XO_PRESENT, PONGO_XO_PRESENT);
2548+
2549+
/* Set regmap for wait_for_pll() */
2550+
pll->clkr.regmap = regmap;
2551+
ret = wait_for_pll_enable_lock(pll);
2552+
if (ret) {
2553+
/* Reverse calibration - disable PLL output */
2554+
regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
2555+
return ret;
2556+
}
2557+
2558+
/* Disable PLL after one-time calibration. */
2559+
regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);
2560+
2561+
/* Select internally generated clock. */
2562+
regmap_update_bits(regmap, PLL_MODE(pll), PONGO_CLOCK_SELECT,
2563+
PONGO_CLOCK_SELECT);
2564+
2565+
return 0;
2566+
}
2567+
2568+
static int alpha_pll_pongo_elu_enable(struct clk_hw *hw)
2569+
{
2570+
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
2571+
struct regmap *regmap = pll->clkr.regmap;
2572+
int ret;
2573+
2574+
/* Check if PLL is already enabled */
2575+
if (trion_pll_is_enabled(pll, regmap))
2576+
return 0;
2577+
2578+
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
2579+
if (ret)
2580+
return ret;
2581+
2582+
/* Set operation mode to RUN */
2583+
regmap_write(regmap, PLL_OPMODE(pll), PLL_RUN);
2584+
2585+
ret = wait_for_pll_enable_lock(pll);
2586+
if (ret)
2587+
return ret;
2588+
2589+
/* Enable the global PLL outputs */
2590+
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL);
2591+
if (ret)
2592+
return ret;
2593+
2594+
/* Ensure that the write above goes through before returning. */
2595+
mb();
2596+
2597+
return ret;
2598+
}
2599+
2600+
static void alpha_pll_pongo_elu_disable(struct clk_hw *hw)
2601+
{
2602+
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
2603+
struct regmap *regmap = pll->clkr.regmap;
2604+
int ret;
2605+
2606+
/* Disable the global PLL output */
2607+
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
2608+
if (ret)
2609+
return;
2610+
2611+
/* Place the PLL mode in STANDBY */
2612+
regmap_write(regmap, PLL_OPMODE(pll), PLL_STANDBY);
2613+
}
2614+
2615+
static unsigned long alpha_pll_pongo_elu_recalc_rate(struct clk_hw *hw,
2616+
unsigned long parent_rate)
2617+
{
2618+
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
2619+
struct regmap *regmap = pll->clkr.regmap;
2620+
u32 l;
2621+
2622+
if (regmap_read(regmap, PLL_L_VAL(pll), &l))
2623+
return 0;
2624+
2625+
l &= PONGO_PLL_L_VAL_MASK;
2626+
2627+
return alpha_pll_calc_rate(parent_rate, l, 0, pll_alpha_width(pll));
2628+
}
2629+
2630+
const struct clk_ops clk_alpha_pll_pongo_elu_ops = {
2631+
.prepare = alpha_pll_pongo_elu_prepare,
2632+
.enable = alpha_pll_pongo_elu_enable,
2633+
.disable = alpha_pll_pongo_elu_disable,
2634+
.recalc_rate = alpha_pll_pongo_elu_recalc_rate,
2635+
};
2636+
EXPORT_SYMBOL_GPL(clk_alpha_pll_pongo_elu_ops);
2637+
2638+
void clk_pongo_elu_pll_configure(struct clk_alpha_pll *pll,
2639+
struct regmap *regmap,
2640+
const struct alpha_pll_config *config)
2641+
{
2642+
u32 val;
2643+
2644+
regmap_update_bits(regmap, PLL_USER_CTL(pll), PONGO_PLL_OUT_MASK,
2645+
PONGO_PLL_OUT_MASK);
2646+
2647+
if (trion_pll_is_enabled(pll, regmap))
2648+
return;
2649+
2650+
if (regmap_read(regmap, PLL_L_VAL(pll), &val))
2651+
return;
2652+
val &= PONGO_PLL_L_VAL_MASK;
2653+
if (val)
2654+
return;
2655+
2656+
clk_alpha_pll_write_config(regmap, PLL_L_VAL(pll), config->l);
2657+
clk_alpha_pll_write_config(regmap, PLL_ALPHA_VAL(pll), config->alpha);
2658+
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val);
2659+
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val);
2660+
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val);
2661+
clk_alpha_pll_write_config(regmap, PLL_CONFIG_CTL_U2(pll), config->config_ctl_hi2_val);
2662+
clk_alpha_pll_write_config(regmap, PLL_USER_CTL(pll),
2663+
config->user_ctl_val | PONGO_PLL_OUT_MASK);
2664+
clk_alpha_pll_write_config(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val);
2665+
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL(pll), config->test_ctl_val);
2666+
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val);
2667+
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val);
2668+
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U2(pll), config->test_ctl_hi2_val);
2669+
clk_alpha_pll_write_config(regmap, PLL_TEST_CTL_U3(pll), config->test_ctl_hi3_val);
2670+
2671+
/* Disable PLL output */
2672+
regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
2673+
}
2674+
EXPORT_SYMBOL_GPL(clk_pongo_elu_pll_configure);
2675+
25132676
void clk_rivian_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
25142677
const struct alpha_pll_config *config)
25152678
{

drivers/clk/qcom/clk-alpha-pll.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ enum {
2727
CLK_ALPHA_PLL_TYPE_ZONDA_OLE,
2828
CLK_ALPHA_PLL_TYPE_LUCID_EVO,
2929
CLK_ALPHA_PLL_TYPE_LUCID_OLE,
30+
CLK_ALPHA_PLL_TYPE_PONGO_ELU,
3031
CLK_ALPHA_PLL_TYPE_TAYCAN_ELU,
3132
CLK_ALPHA_PLL_TYPE_RIVIAN_EVO,
3233
CLK_ALPHA_PLL_TYPE_DEFAULT_EVO,
@@ -53,6 +54,7 @@ enum {
5354
PLL_OFF_TEST_CTL_U,
5455
PLL_OFF_TEST_CTL_U1,
5556
PLL_OFF_TEST_CTL_U2,
57+
PLL_OFF_TEST_CTL_U3,
5658
PLL_OFF_STATE,
5759
PLL_OFF_STATUS,
5860
PLL_OFF_OPMODE,
@@ -138,6 +140,7 @@ struct alpha_pll_config {
138140
u32 test_ctl_hi_mask;
139141
u32 test_ctl_hi1_val;
140142
u32 test_ctl_hi2_val;
143+
u32 test_ctl_hi3_val;
141144
u32 main_output_mask;
142145
u32 aux_output_mask;
143146
u32 aux2_output_mask;
@@ -196,6 +199,7 @@ extern const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops;
196199
#define clk_alpha_pll_postdiv_lucid_ole_ops clk_alpha_pll_postdiv_lucid_evo_ops
197200
#define clk_alpha_pll_postdiv_taycan_elu_ops clk_alpha_pll_postdiv_lucid_evo_ops
198201

202+
extern const struct clk_ops clk_alpha_pll_pongo_elu_ops;
199203
extern const struct clk_ops clk_alpha_pll_rivian_evo_ops;
200204
#define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_ops
201205

@@ -222,6 +226,8 @@ void clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regma
222226
const struct alpha_pll_config *config);
223227
void clk_lucid_ole_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
224228
const struct alpha_pll_config *config);
229+
void clk_pongo_elu_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
230+
const struct alpha_pll_config *config);
225231
#define clk_taycan_elu_pll_configure(pll, regmap, config) \
226232
clk_lucid_evo_pll_configure(pll, regmap, config)
227233

0 commit comments

Comments
 (0)