Loading drivers/clk/qcom/clk-alpha-pll.c +295 −15 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2016, 2018-2020, The Linux Foundation. * Copyright (c) 2015-2016, 2018-2021, The Linux Foundation. * All rights reserved. */ Loading Loading @@ -156,6 +156,19 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_SSC_UPDATE_RATE] = 0x30, [PLL_OFF_STATUS] = 0x38, }, [CLK_ALPHA_PLL_TYPE_ZONDA_EVO] = { [PLL_OFF_L_VAL] = 0x04, [PLL_OFF_ALPHA_VAL] = 0x08, [PLL_OFF_USER_CTL] = 0x0C, [PLL_OFF_USER_CTL_U] = 0x10, [PLL_OFF_CONFIG_CTL] = 0x14, [PLL_OFF_CONFIG_CTL_U] = 0x18, [PLL_OFF_CONFIG_CTL_U1] = 0x1C, [PLL_OFF_TEST_CTL] = 0x20, [PLL_OFF_TEST_CTL_U] = 0x24, [PLL_OFF_TEST_CTL_U1] = 0x28, [PLL_OFF_OPMODE] = 0x2C, }, [CLK_ALPHA_PLL_TYPE_LUCID_5LPE] = { [PLL_OFF_L_VAL] = 0x04, [PLL_OFF_CAL_L_VAL] = 0x08, Loading Loading @@ -250,16 +263,16 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define PLL_OPMODE_RUN 0x1 #define PLL_OUT_MASK 0x7 #define PLL_OUT_RATE_MARGIN 500 #define PLL_5LPE_ENABLE_VOTE_RUN BIT(21) #define PLL_EVO_ENABLE_VOTE_RUN BIT(25) /* LUCID PLL specific settings and offsets */ #define LUCID_PLL_CAL_VAL 0x44 #define LUCID_PCAL_DONE BIT(27) #define LUCID_5LPE_PCAL_DONE BIT(11) #define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21) #define LUCID_5LPE_PLL_LATCH_INPUT BIT(14) #define LUCID_5LPE_ALPHA_PLL_ACK_LATCH BIT(13) #define LUCID_EVO_PCAL_NOT_DONE BIT(8) #define LUCID_EVO_ENABLE_VOTE_RUN BIT(25) #define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0) #define LUCID_EVO_PLL_CAL_L_VAL_MASK GENMASK(31, 16) Loading @@ -267,7 +280,6 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define ZONDA_PLL_OUT_MASK 0xF #define ZONDA_STAY_IN_CFA BIT(16) #define ZONDA_PLL_FREQ_LOCK_DET BIT(29) #define ZONDA_5LPE_ENABLE_VOTE_RUN BIT(21) /* FABIA PLL specific settings */ #define FABIA_PLL_CAL_VAL 0x3F Loading Loading @@ -1644,7 +1656,7 @@ static int clk_zonda_5lpe_pll_enable(struct clk_hw *hw) return ret; /* If in FSM mode, just vote for it */ if (val & ZONDA_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; Loading Loading @@ -1711,7 +1723,7 @@ static void clk_zonda_5lpe_pll_disable(struct clk_hw *hw) return; /* If in FSM mode, just unvote it */ if (val & ZONDA_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } Loading Loading @@ -2983,7 +2995,7 @@ static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw) return ret; /* If in FSM mode, just vote for it */ if (val & LUCID_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; Loading Loading @@ -3040,7 +3052,7 @@ static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw) return; /* If in FSM mode, just unvote it */ if (val & LUCID_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } Loading Loading @@ -3189,7 +3201,7 @@ static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, if (ret) return ret; if (val & LUCID_5LPE_ENABLE_VOTE_RUN) if (val & PLL_5LPE_ENABLE_VOTE_RUN) return 0; if (!pll->post_div_table) { Loading Loading @@ -3450,7 +3462,7 @@ static int alpha_pll_lucid_evo_enable(struct clk_hw *hw) return ret; /* If in FSM mode, just vote for it */ if (val & LUCID_EVO_ENABLE_VOTE_RUN) { if (val & PLL_EVO_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; Loading Loading @@ -3507,7 +3519,7 @@ static void alpha_pll_lucid_evo_disable(struct clk_hw *hw) return; /* If in FSM mode, just unvote it */ if (val & LUCID_EVO_ENABLE_VOTE_RUN) { if (val & PLL_EVO_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } Loading Loading @@ -3617,7 +3629,7 @@ static int clk_lucid_evo_pll_postdiv_set_rate(struct clk_hw *hw, if (ret) return ret; if (val & LUCID_EVO_ENABLE_VOTE_RUN) if (val & PLL_EVO_ENABLE_VOTE_RUN) return 0; if (!pll->post_div_table) { Loading Loading @@ -3660,8 +3672,7 @@ static int alpha_pll_lucid_evo_set_rate(struct clk_hw *hw, unsigned long rate, regmap_update_bits(pll->clkr.regmap, PLL_L_VAL(pll), LUCID_EVO_PLL_L_VAL_MASK, l); regmap_update_bits(pll->clkr.regmap, PLL_L_VAL(pll), LUCID_EVO_PLL_CAL_L_VAL_MASK, a); regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); /* Latch the PLL input */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), Loading Loading @@ -3729,7 +3740,7 @@ static void lucid_evo_pll_list_registers(struct seq_file *f, regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); if (val & LUCID_EVO_ENABLE_VOTE_RUN) { if (val & PLL_EVO_ENABLE_VOTE_RUN) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); Loading Loading @@ -3792,6 +3803,275 @@ const struct clk_ops clk_alpha_pll_lucid_evo_ops = { }; EXPORT_SYMBOL(clk_alpha_pll_lucid_evo_ops); static int clk_zonda_evo_pll_enable(struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 val, test_ctl_val; int ret; ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); if (ret) return ret; if (val & PLL_EVO_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; return wait_for_pll_enable_active(pll); } /* Get the PLL out of bypass mode */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_BYPASSNL, PLL_BYPASSNL); if (ret) return ret; /* * H/W requires a 1us delay between disabling the bypass and * de-asserting the reset. */ mb(); udelay(1); ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); if (ret) return ret; /* Set operation mode to RUN */ regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_OPMODE_RUN); ret = regmap_read(pll->clkr.regmap, PLL_TEST_CTL(pll), &test_ctl_val); if (ret) return ret; /* If cfa mode then poll for freq lock */ if (test_ctl_val & ZONDA_STAY_IN_CFA) ret = wait_for_zonda_pll_freq_lock(pll); else ret = wait_for_pll_enable_lock(pll); if (ret) return ret; /* Enable the PLL outputs */ ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, ZONDA_PLL_OUT_MASK); if (ret) return ret; /* Enable the global PLL outputs */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); if (ret) return ret; /* Ensure that the write above goes through before returning. */ mb(); return 0; } static void clk_zonda_evo_pll_disable(struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 val, mask; int ret; ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); if (ret) return; if (val & PLL_EVO_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } /* Disable the global PLL output */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); if (ret) return; /* Disable the PLL outputs */ ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, 0); /* Put the PLL in bypass and reset */ mask = PLL_RESET_N | PLL_BYPASSNL; ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0); if (ret) return; /* Place the PLL mode in OFF state */ regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), 0x0); } static unsigned long clk_zonda_evo_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, frac; regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); return alpha_pll_calc_rate(parent_rate, l, frac, ALPHA_BITWIDTH); } static void clk_alpha_pll_zonda_evo_list_registers(struct seq_file *f, struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); int size, i, val; static struct clk_register_data data[] = { {"PLL_MODE", PLL_OFF_MODE}, {"PLL_L_VAL", PLL_OFF_L_VAL}, {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, {"PLL_USER_CTL", PLL_OFF_USER_CTL}, {"PLL_USER_CTL_U", PLL_OFF_USER_CTL_U}, {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, {"PLL_CONFIG_CTL_U1", PLL_OFF_CONFIG_CTL_U1}, {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, {"PLL_TEST_CTL_U1", PLL_OFF_TEST_CTL_U1}, {"PLL_OPMODE", PLL_OFF_OPMODE}, }; static struct clk_register_data data1[] = { {"APSS_PLL_VOTE", 0x0}, }; size = ARRAY_SIZE(data); for (i = 0; i < size; i++) { regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[i].offset], &val); clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); } regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[0].offset], &val); if (val & PLL_FSM_ENA) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); } } static struct clk_regmap_ops clk_alpha_pll_zonda_evo_regmap_ops = { .list_registers = clk_alpha_pll_zonda_evo_list_registers, }; static void clk_alpha_pll_zonda_evo_init(struct clk_hw *hw) { struct clk_regmap *rclk = to_clk_regmap(hw); if (!rclk->ops) rclk->ops = &clk_alpha_pll_zonda_evo_regmap_ops; } int clk_zonda_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config) { int ret; ret = __zonda_pll_is_enabled(pll, regmap); if (ret) return ret; if (config->l) ret |= regmap_write(regmap, PLL_L_VAL(pll), config->l); if (config->alpha) ret |= regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); if (config->config_ctl_val) ret |= regmap_write(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); if (config->config_ctl_hi_val) ret |= regmap_write(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); if (config->config_ctl_hi1_val) ret |= regmap_write(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); if (config->user_ctl_val) ret |= regmap_write(regmap, PLL_USER_CTL(pll), config->user_ctl_val); if (config->user_ctl_hi_val) ret |= regmap_write(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); if (config->user_ctl_hi1_val) ret |= regmap_write(regmap, PLL_USER_CTL_U1(pll), config->user_ctl_hi1_val); if (config->test_ctl_val) ret |= regmap_write(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); if (config->test_ctl_hi_val) ret |= regmap_write(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); if (config->test_ctl_hi1_val) ret |= regmap_write(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); ret |= regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, 0); /* Disable PLL output */ ret |= regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); /* Set operation mode to OFF */ ret |= regmap_write(regmap, PLL_OPMODE(pll), PLL_OPMODE_STANDBY); /* PLL should be in OFF mode before continuing */ wmb(); /* Place the PLL in STANDBY mode */ ret |= regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); return ret ? -EIO : 0; } EXPORT_SYMBOL(clk_zonda_evo_pll_configure); const struct clk_ops clk_alpha_pll_fixed_zonda_evo_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, .pre_rate_change = clk_pre_change_regmap, .post_rate_change = clk_post_change_regmap, .enable = clk_zonda_evo_pll_enable, .disable = clk_zonda_evo_pll_disable, .is_enabled = clk_zonda_pll_is_enabled, .recalc_rate = clk_zonda_evo_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .debug_init = clk_common_debug_init, .init = clk_alpha_pll_zonda_evo_init, #ifdef CONFIG_COMMON_CLK_QCOM_DEBUG .list_rate_vdd_level = clk_list_rate_vdd_level, #endif }; EXPORT_SYMBOL(clk_alpha_pll_fixed_zonda_evo_ops); const struct clk_ops clk_alpha_pll_postdiv_zonda_evo_ops = { .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, }; EXPORT_SYMBOL(clk_alpha_pll_postdiv_zonda_evo_ops); int clk_regera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config) { Loading drivers/clk/qcom/clk-alpha-pll.h +6 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ enum { CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_LUCID, CLK_ALPHA_PLL_TYPE_ZONDA, CLK_ALPHA_PLL_TYPE_ZONDA_EVO, CLK_ALPHA_PLL_TYPE_LUCID_5LPE, CLK_ALPHA_PLL_TYPE_ZONDA_5LPE, CLK_ALPHA_PLL_TYPE_REGERA, Loading Loading @@ -184,6 +185,8 @@ extern const struct clk_ops clk_regera_pll_ops; extern const struct clk_ops clk_agera_pll_ops; extern const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops; extern const struct clk_ops clk_alpha_pll_fixed_zonda_evo_ops; extern const struct clk_ops clk_alpha_pll_postdiv_zonda_evo_ops; extern const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops; extern const struct clk_ops clk_alpha_pll_lucid_evo_ops; Loading @@ -210,4 +213,7 @@ int clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, int clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); int clk_zonda_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); #endif Loading
drivers/clk/qcom/clk-alpha-pll.c +295 −15 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2016, 2018-2020, The Linux Foundation. * Copyright (c) 2015-2016, 2018-2021, The Linux Foundation. * All rights reserved. */ Loading Loading @@ -156,6 +156,19 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = { [PLL_OFF_SSC_UPDATE_RATE] = 0x30, [PLL_OFF_STATUS] = 0x38, }, [CLK_ALPHA_PLL_TYPE_ZONDA_EVO] = { [PLL_OFF_L_VAL] = 0x04, [PLL_OFF_ALPHA_VAL] = 0x08, [PLL_OFF_USER_CTL] = 0x0C, [PLL_OFF_USER_CTL_U] = 0x10, [PLL_OFF_CONFIG_CTL] = 0x14, [PLL_OFF_CONFIG_CTL_U] = 0x18, [PLL_OFF_CONFIG_CTL_U1] = 0x1C, [PLL_OFF_TEST_CTL] = 0x20, [PLL_OFF_TEST_CTL_U] = 0x24, [PLL_OFF_TEST_CTL_U1] = 0x28, [PLL_OFF_OPMODE] = 0x2C, }, [CLK_ALPHA_PLL_TYPE_LUCID_5LPE] = { [PLL_OFF_L_VAL] = 0x04, [PLL_OFF_CAL_L_VAL] = 0x08, Loading Loading @@ -250,16 +263,16 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define PLL_OPMODE_RUN 0x1 #define PLL_OUT_MASK 0x7 #define PLL_OUT_RATE_MARGIN 500 #define PLL_5LPE_ENABLE_VOTE_RUN BIT(21) #define PLL_EVO_ENABLE_VOTE_RUN BIT(25) /* LUCID PLL specific settings and offsets */ #define LUCID_PLL_CAL_VAL 0x44 #define LUCID_PCAL_DONE BIT(27) #define LUCID_5LPE_PCAL_DONE BIT(11) #define LUCID_5LPE_ENABLE_VOTE_RUN BIT(21) #define LUCID_5LPE_PLL_LATCH_INPUT BIT(14) #define LUCID_5LPE_ALPHA_PLL_ACK_LATCH BIT(13) #define LUCID_EVO_PCAL_NOT_DONE BIT(8) #define LUCID_EVO_ENABLE_VOTE_RUN BIT(25) #define LUCID_EVO_PLL_L_VAL_MASK GENMASK(15, 0) #define LUCID_EVO_PLL_CAL_L_VAL_MASK GENMASK(31, 16) Loading @@ -267,7 +280,6 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs); #define ZONDA_PLL_OUT_MASK 0xF #define ZONDA_STAY_IN_CFA BIT(16) #define ZONDA_PLL_FREQ_LOCK_DET BIT(29) #define ZONDA_5LPE_ENABLE_VOTE_RUN BIT(21) /* FABIA PLL specific settings */ #define FABIA_PLL_CAL_VAL 0x3F Loading Loading @@ -1644,7 +1656,7 @@ static int clk_zonda_5lpe_pll_enable(struct clk_hw *hw) return ret; /* If in FSM mode, just vote for it */ if (val & ZONDA_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; Loading Loading @@ -1711,7 +1723,7 @@ static void clk_zonda_5lpe_pll_disable(struct clk_hw *hw) return; /* If in FSM mode, just unvote it */ if (val & ZONDA_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } Loading Loading @@ -2983,7 +2995,7 @@ static int alpha_pll_lucid_5lpe_enable(struct clk_hw *hw) return ret; /* If in FSM mode, just vote for it */ if (val & LUCID_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; Loading Loading @@ -3040,7 +3052,7 @@ static void alpha_pll_lucid_5lpe_disable(struct clk_hw *hw) return; /* If in FSM mode, just unvote it */ if (val & LUCID_5LPE_ENABLE_VOTE_RUN) { if (val & PLL_5LPE_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } Loading Loading @@ -3189,7 +3201,7 @@ static int clk_lucid_5lpe_pll_postdiv_set_rate(struct clk_hw *hw, if (ret) return ret; if (val & LUCID_5LPE_ENABLE_VOTE_RUN) if (val & PLL_5LPE_ENABLE_VOTE_RUN) return 0; if (!pll->post_div_table) { Loading Loading @@ -3450,7 +3462,7 @@ static int alpha_pll_lucid_evo_enable(struct clk_hw *hw) return ret; /* If in FSM mode, just vote for it */ if (val & LUCID_EVO_ENABLE_VOTE_RUN) { if (val & PLL_EVO_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; Loading Loading @@ -3507,7 +3519,7 @@ static void alpha_pll_lucid_evo_disable(struct clk_hw *hw) return; /* If in FSM mode, just unvote it */ if (val & LUCID_EVO_ENABLE_VOTE_RUN) { if (val & PLL_EVO_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } Loading Loading @@ -3617,7 +3629,7 @@ static int clk_lucid_evo_pll_postdiv_set_rate(struct clk_hw *hw, if (ret) return ret; if (val & LUCID_EVO_ENABLE_VOTE_RUN) if (val & PLL_EVO_ENABLE_VOTE_RUN) return 0; if (!pll->post_div_table) { Loading Loading @@ -3660,8 +3672,7 @@ static int alpha_pll_lucid_evo_set_rate(struct clk_hw *hw, unsigned long rate, regmap_update_bits(pll->clkr.regmap, PLL_L_VAL(pll), LUCID_EVO_PLL_L_VAL_MASK, l); regmap_update_bits(pll->clkr.regmap, PLL_L_VAL(pll), LUCID_EVO_PLL_CAL_L_VAL_MASK, a); regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), a); /* Latch the PLL input */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), Loading Loading @@ -3729,7 +3740,7 @@ static void lucid_evo_pll_list_registers(struct seq_file *f, regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); if (val & LUCID_EVO_ENABLE_VOTE_RUN) { if (val & PLL_EVO_ENABLE_VOTE_RUN) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); Loading Loading @@ -3792,6 +3803,275 @@ const struct clk_ops clk_alpha_pll_lucid_evo_ops = { }; EXPORT_SYMBOL(clk_alpha_pll_lucid_evo_ops); static int clk_zonda_evo_pll_enable(struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 val, test_ctl_val; int ret; ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val); if (ret) return ret; if (val & PLL_EVO_ENABLE_VOTE_RUN) { ret = clk_enable_regmap(hw); if (ret) return ret; return wait_for_pll_enable_active(pll); } /* Get the PLL out of bypass mode */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_BYPASSNL, PLL_BYPASSNL); if (ret) return ret; /* * H/W requires a 1us delay between disabling the bypass and * de-asserting the reset. */ mb(); udelay(1); ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); if (ret) return ret; /* Set operation mode to RUN */ regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), PLL_OPMODE_RUN); ret = regmap_read(pll->clkr.regmap, PLL_TEST_CTL(pll), &test_ctl_val); if (ret) return ret; /* If cfa mode then poll for freq lock */ if (test_ctl_val & ZONDA_STAY_IN_CFA) ret = wait_for_zonda_pll_freq_lock(pll); else ret = wait_for_pll_enable_lock(pll); if (ret) return ret; /* Enable the PLL outputs */ ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, ZONDA_PLL_OUT_MASK); if (ret) return ret; /* Enable the global PLL outputs */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, PLL_OUTCTRL); if (ret) return ret; /* Ensure that the write above goes through before returning. */ mb(); return 0; } static void clk_zonda_evo_pll_disable(struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 val, mask; int ret; ret = regmap_read(pll->clkr.regmap, PLL_MODE(pll), &val); if (ret) return; if (val & PLL_EVO_ENABLE_VOTE_RUN) { clk_disable_regmap(hw); return; } /* Disable the global PLL output */ ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); if (ret) return; /* Disable the PLL outputs */ ret = regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll), ZONDA_PLL_OUT_MASK, 0); /* Put the PLL in bypass and reset */ mask = PLL_RESET_N | PLL_BYPASSNL; ret = regmap_update_bits(pll->clkr.regmap, PLL_MODE(pll), mask, 0); if (ret) return; /* Place the PLL mode in OFF state */ regmap_write(pll->clkr.regmap, PLL_OPMODE(pll), 0x0); } static unsigned long clk_zonda_evo_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); u32 l, frac; regmap_read(pll->clkr.regmap, PLL_L_VAL(pll), &l); regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &frac); return alpha_pll_calc_rate(parent_rate, l, frac, ALPHA_BITWIDTH); } static void clk_alpha_pll_zonda_evo_list_registers(struct seq_file *f, struct clk_hw *hw) { struct clk_alpha_pll *pll = to_clk_alpha_pll(hw); int size, i, val; static struct clk_register_data data[] = { {"PLL_MODE", PLL_OFF_MODE}, {"PLL_L_VAL", PLL_OFF_L_VAL}, {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, {"PLL_USER_CTL", PLL_OFF_USER_CTL}, {"PLL_USER_CTL_U", PLL_OFF_USER_CTL_U}, {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, {"PLL_CONFIG_CTL_U", PLL_OFF_CONFIG_CTL_U}, {"PLL_CONFIG_CTL_U1", PLL_OFF_CONFIG_CTL_U1}, {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, {"PLL_TEST_CTL_U1", PLL_OFF_TEST_CTL_U1}, {"PLL_OPMODE", PLL_OFF_OPMODE}, }; static struct clk_register_data data1[] = { {"APSS_PLL_VOTE", 0x0}, }; size = ARRAY_SIZE(data); for (i = 0; i < size; i++) { regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[i].offset], &val); clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); } regmap_read(pll->clkr.regmap, pll->offset + pll->regs[data[0].offset], &val); if (val & PLL_FSM_ENA) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); } } static struct clk_regmap_ops clk_alpha_pll_zonda_evo_regmap_ops = { .list_registers = clk_alpha_pll_zonda_evo_list_registers, }; static void clk_alpha_pll_zonda_evo_init(struct clk_hw *hw) { struct clk_regmap *rclk = to_clk_regmap(hw); if (!rclk->ops) rclk->ops = &clk_alpha_pll_zonda_evo_regmap_ops; } int clk_zonda_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config) { int ret; ret = __zonda_pll_is_enabled(pll, regmap); if (ret) return ret; if (config->l) ret |= regmap_write(regmap, PLL_L_VAL(pll), config->l); if (config->alpha) ret |= regmap_write(regmap, PLL_ALPHA_VAL(pll), config->alpha); if (config->config_ctl_val) ret |= regmap_write(regmap, PLL_CONFIG_CTL(pll), config->config_ctl_val); if (config->config_ctl_hi_val) ret |= regmap_write(regmap, PLL_CONFIG_CTL_U(pll), config->config_ctl_hi_val); if (config->config_ctl_hi1_val) ret |= regmap_write(regmap, PLL_CONFIG_CTL_U1(pll), config->config_ctl_hi1_val); if (config->user_ctl_val) ret |= regmap_write(regmap, PLL_USER_CTL(pll), config->user_ctl_val); if (config->user_ctl_hi_val) ret |= regmap_write(regmap, PLL_USER_CTL_U(pll), config->user_ctl_hi_val); if (config->user_ctl_hi1_val) ret |= regmap_write(regmap, PLL_USER_CTL_U1(pll), config->user_ctl_hi1_val); if (config->test_ctl_val) ret |= regmap_write(regmap, PLL_TEST_CTL(pll), config->test_ctl_val); if (config->test_ctl_hi_val) ret |= regmap_write(regmap, PLL_TEST_CTL_U(pll), config->test_ctl_hi_val); if (config->test_ctl_hi1_val) ret |= regmap_write(regmap, PLL_TEST_CTL_U1(pll), config->test_ctl_hi1_val); ret |= regmap_update_bits(regmap, PLL_MODE(pll), PLL_BYPASSNL, 0); /* Disable PLL output */ ret |= regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); /* Set operation mode to OFF */ ret |= regmap_write(regmap, PLL_OPMODE(pll), PLL_OPMODE_STANDBY); /* PLL should be in OFF mode before continuing */ wmb(); /* Place the PLL in STANDBY mode */ ret |= regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N); return ret ? -EIO : 0; } EXPORT_SYMBOL(clk_zonda_evo_pll_configure); const struct clk_ops clk_alpha_pll_fixed_zonda_evo_ops = { .prepare = clk_prepare_regmap, .unprepare = clk_unprepare_regmap, .pre_rate_change = clk_pre_change_regmap, .post_rate_change = clk_post_change_regmap, .enable = clk_zonda_evo_pll_enable, .disable = clk_zonda_evo_pll_disable, .is_enabled = clk_zonda_pll_is_enabled, .recalc_rate = clk_zonda_evo_pll_recalc_rate, .round_rate = clk_alpha_pll_round_rate, .debug_init = clk_common_debug_init, .init = clk_alpha_pll_zonda_evo_init, #ifdef CONFIG_COMMON_CLK_QCOM_DEBUG .list_rate_vdd_level = clk_list_rate_vdd_level, #endif }; EXPORT_SYMBOL(clk_alpha_pll_fixed_zonda_evo_ops); const struct clk_ops clk_alpha_pll_postdiv_zonda_evo_ops = { .recalc_rate = clk_alpha_pll_postdiv_fabia_recalc_rate, .round_rate = clk_alpha_pll_postdiv_fabia_round_rate, .set_rate = clk_alpha_pll_postdiv_fabia_set_rate, }; EXPORT_SYMBOL(clk_alpha_pll_postdiv_zonda_evo_ops); int clk_regera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config) { Loading
drivers/clk/qcom/clk-alpha-pll.h +6 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ enum { CLK_ALPHA_PLL_TYPE_TRION, CLK_ALPHA_PLL_TYPE_LUCID, CLK_ALPHA_PLL_TYPE_ZONDA, CLK_ALPHA_PLL_TYPE_ZONDA_EVO, CLK_ALPHA_PLL_TYPE_LUCID_5LPE, CLK_ALPHA_PLL_TYPE_ZONDA_5LPE, CLK_ALPHA_PLL_TYPE_REGERA, Loading Loading @@ -184,6 +185,8 @@ extern const struct clk_ops clk_regera_pll_ops; extern const struct clk_ops clk_agera_pll_ops; extern const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops; extern const struct clk_ops clk_alpha_pll_fixed_zonda_evo_ops; extern const struct clk_ops clk_alpha_pll_postdiv_zonda_evo_ops; extern const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops; extern const struct clk_ops clk_alpha_pll_lucid_evo_ops; Loading @@ -210,4 +213,7 @@ int clk_agera_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, int clk_lucid_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); int clk_zonda_evo_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, const struct alpha_pll_config *config); #endif