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

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. clk_pll_enable
  2. clk_pll_disable
  3. clk_pll_recalc_rate
  4. find_freq
  5. clk_pll_determine_rate
  6. clk_pll_set_rate
  7. wait_for_pll
  8. clk_pll_vote_enable
  9. clk_pll_configure
  10. clk_pll_configure_sr
  11. clk_pll_configure_sr_hpm_lp
  12. clk_pll_sr2_enable
  13. clk_pll_sr2_set_rate

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (c) 2013, The Linux Foundation. All rights reserved.
   4  */
   5 
   6 #include <linux/kernel.h>
   7 #include <linux/bitops.h>
   8 #include <linux/err.h>
   9 #include <linux/bug.h>
  10 #include <linux/delay.h>
  11 #include <linux/export.h>
  12 #include <linux/clk-provider.h>
  13 #include <linux/regmap.h>
  14 
  15 #include <asm/div64.h>
  16 
  17 #include "clk-pll.h"
  18 #include "common.h"
  19 
  20 #define PLL_OUTCTRL             BIT(0)
  21 #define PLL_BYPASSNL            BIT(1)
  22 #define PLL_RESET_N             BIT(2)
  23 
  24 static int clk_pll_enable(struct clk_hw *hw)
  25 {
  26         struct clk_pll *pll = to_clk_pll(hw);
  27         int ret;
  28         u32 mask, val;
  29 
  30         mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
  31         ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &val);
  32         if (ret)
  33                 return ret;
  34 
  35         /* Skip if already enabled or in FSM mode */
  36         if ((val & mask) == mask || val & PLL_VOTE_FSM_ENA)
  37                 return 0;
  38 
  39         /* Disable PLL bypass mode. */
  40         ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL,
  41                                  PLL_BYPASSNL);
  42         if (ret)
  43                 return ret;
  44 
  45         /*
  46          * H/W requires a 5us delay between disabling the bypass and
  47          * de-asserting the reset. Delay 10us just to be safe.
  48          */
  49         udelay(10);
  50 
  51         /* De-assert active-low PLL reset. */
  52         ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N,
  53                                  PLL_RESET_N);
  54         if (ret)
  55                 return ret;
  56 
  57         /* Wait until PLL is locked. */
  58         udelay(50);
  59 
  60         /* Enable PLL output. */
  61         return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
  62                                  PLL_OUTCTRL);
  63 }
  64 
  65 static void clk_pll_disable(struct clk_hw *hw)
  66 {
  67         struct clk_pll *pll = to_clk_pll(hw);
  68         u32 mask;
  69         u32 val;
  70 
  71         regmap_read(pll->clkr.regmap, pll->mode_reg, &val);
  72         /* Skip if in FSM mode */
  73         if (val & PLL_VOTE_FSM_ENA)
  74                 return;
  75         mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
  76         regmap_update_bits(pll->clkr.regmap, pll->mode_reg, mask, 0);
  77 }
  78 
  79 static unsigned long
  80 clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
  81 {
  82         struct clk_pll *pll = to_clk_pll(hw);
  83         u32 l, m, n, config;
  84         unsigned long rate;
  85         u64 tmp;
  86 
  87         regmap_read(pll->clkr.regmap, pll->l_reg, &l);
  88         regmap_read(pll->clkr.regmap, pll->m_reg, &m);
  89         regmap_read(pll->clkr.regmap, pll->n_reg, &n);
  90 
  91         l &= 0x3ff;
  92         m &= 0x7ffff;
  93         n &= 0x7ffff;
  94 
  95         rate = parent_rate * l;
  96         if (n) {
  97                 tmp = parent_rate;
  98                 tmp *= m;
  99                 do_div(tmp, n);
 100                 rate += tmp;
 101         }
 102         if (pll->post_div_width) {
 103                 regmap_read(pll->clkr.regmap, pll->config_reg, &config);
 104                 config >>= pll->post_div_shift;
 105                 config &= BIT(pll->post_div_width) - 1;
 106                 rate /= config + 1;
 107         }
 108 
 109         return rate;
 110 }
 111 
 112 static const
 113 struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
 114 {
 115         if (!f)
 116                 return NULL;
 117 
 118         for (; f->freq; f++)
 119                 if (rate <= f->freq)
 120                         return f;
 121 
 122         return NULL;
 123 }
 124 
 125 static int
 126 clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 127 {
 128         struct clk_pll *pll = to_clk_pll(hw);
 129         const struct pll_freq_tbl *f;
 130 
 131         f = find_freq(pll->freq_tbl, req->rate);
 132         if (!f)
 133                 req->rate = clk_pll_recalc_rate(hw, req->best_parent_rate);
 134         else
 135                 req->rate = f->freq;
 136 
 137         return 0;
 138 }
 139 
 140 static int
 141 clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long p_rate)
 142 {
 143         struct clk_pll *pll = to_clk_pll(hw);
 144         const struct pll_freq_tbl *f;
 145         bool enabled;
 146         u32 mode;
 147         u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
 148 
 149         f = find_freq(pll->freq_tbl, rate);
 150         if (!f)
 151                 return -EINVAL;
 152 
 153         regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
 154         enabled = (mode & enable_mask) == enable_mask;
 155 
 156         if (enabled)
 157                 clk_pll_disable(hw);
 158 
 159         regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
 160         regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
 161         regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
 162         regmap_write(pll->clkr.regmap, pll->config_reg, f->ibits);
 163 
 164         if (enabled)
 165                 clk_pll_enable(hw);
 166 
 167         return 0;
 168 }
 169 
 170 const struct clk_ops clk_pll_ops = {
 171         .enable = clk_pll_enable,
 172         .disable = clk_pll_disable,
 173         .recalc_rate = clk_pll_recalc_rate,
 174         .determine_rate = clk_pll_determine_rate,
 175         .set_rate = clk_pll_set_rate,
 176 };
 177 EXPORT_SYMBOL_GPL(clk_pll_ops);
 178 
 179 static int wait_for_pll(struct clk_pll *pll)
 180 {
 181         u32 val;
 182         int count;
 183         int ret;
 184         const char *name = clk_hw_get_name(&pll->clkr.hw);
 185 
 186         /* Wait for pll to enable. */
 187         for (count = 200; count > 0; count--) {
 188                 ret = regmap_read(pll->clkr.regmap, pll->status_reg, &val);
 189                 if (ret)
 190                         return ret;
 191                 if (val & BIT(pll->status_bit))
 192                         return 0;
 193                 udelay(1);
 194         }
 195 
 196         WARN(1, "%s didn't enable after voting for it!\n", name);
 197         return -ETIMEDOUT;
 198 }
 199 
 200 static int clk_pll_vote_enable(struct clk_hw *hw)
 201 {
 202         int ret;
 203         struct clk_pll *p = to_clk_pll(clk_hw_get_parent(hw));
 204 
 205         ret = clk_enable_regmap(hw);
 206         if (ret)
 207                 return ret;
 208 
 209         return wait_for_pll(p);
 210 }
 211 
 212 const struct clk_ops clk_pll_vote_ops = {
 213         .enable = clk_pll_vote_enable,
 214         .disable = clk_disable_regmap,
 215 };
 216 EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
 217 
 218 static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
 219         const struct pll_config *config)
 220 {
 221         u32 val;
 222         u32 mask;
 223 
 224         regmap_write(regmap, pll->l_reg, config->l);
 225         regmap_write(regmap, pll->m_reg, config->m);
 226         regmap_write(regmap, pll->n_reg, config->n);
 227 
 228         val = config->vco_val;
 229         val |= config->pre_div_val;
 230         val |= config->post_div_val;
 231         val |= config->mn_ena_mask;
 232         val |= config->main_output_mask;
 233         val |= config->aux_output_mask;
 234 
 235         mask = config->vco_mask;
 236         mask |= config->pre_div_mask;
 237         mask |= config->post_div_mask;
 238         mask |= config->mn_ena_mask;
 239         mask |= config->main_output_mask;
 240         mask |= config->aux_output_mask;
 241 
 242         regmap_update_bits(regmap, pll->config_reg, mask, val);
 243 }
 244 
 245 void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
 246                 const struct pll_config *config, bool fsm_mode)
 247 {
 248         clk_pll_configure(pll, regmap, config);
 249         if (fsm_mode)
 250                 qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 8);
 251 }
 252 EXPORT_SYMBOL_GPL(clk_pll_configure_sr);
 253 
 254 void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
 255                 const struct pll_config *config, bool fsm_mode)
 256 {
 257         clk_pll_configure(pll, regmap, config);
 258         if (fsm_mode)
 259                 qcom_pll_set_fsm_mode(regmap, pll->mode_reg, 1, 0);
 260 }
 261 EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
 262 
 263 static int clk_pll_sr2_enable(struct clk_hw *hw)
 264 {
 265         struct clk_pll *pll = to_clk_pll(hw);
 266         int ret;
 267         u32 mode;
 268 
 269         ret = regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
 270         if (ret)
 271                 return ret;
 272 
 273         /* Disable PLL bypass mode. */
 274         ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_BYPASSNL,
 275                                  PLL_BYPASSNL);
 276         if (ret)
 277                 return ret;
 278 
 279         /*
 280          * H/W requires a 5us delay between disabling the bypass and
 281          * de-asserting the reset. Delay 10us just to be safe.
 282          */
 283         udelay(10);
 284 
 285         /* De-assert active-low PLL reset. */
 286         ret = regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_RESET_N,
 287                                  PLL_RESET_N);
 288         if (ret)
 289                 return ret;
 290 
 291         ret = wait_for_pll(pll);
 292         if (ret)
 293                 return ret;
 294 
 295         /* Enable PLL output. */
 296         return regmap_update_bits(pll->clkr.regmap, pll->mode_reg, PLL_OUTCTRL,
 297                                  PLL_OUTCTRL);
 298 }
 299 
 300 static int
 301 clk_pll_sr2_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long prate)
 302 {
 303         struct clk_pll *pll = to_clk_pll(hw);
 304         const struct pll_freq_tbl *f;
 305         bool enabled;
 306         u32 mode;
 307         u32 enable_mask = PLL_OUTCTRL | PLL_BYPASSNL | PLL_RESET_N;
 308 
 309         f = find_freq(pll->freq_tbl, rate);
 310         if (!f)
 311                 return -EINVAL;
 312 
 313         regmap_read(pll->clkr.regmap, pll->mode_reg, &mode);
 314         enabled = (mode & enable_mask) == enable_mask;
 315 
 316         if (enabled)
 317                 clk_pll_disable(hw);
 318 
 319         regmap_update_bits(pll->clkr.regmap, pll->l_reg, 0x3ff, f->l);
 320         regmap_update_bits(pll->clkr.regmap, pll->m_reg, 0x7ffff, f->m);
 321         regmap_update_bits(pll->clkr.regmap, pll->n_reg, 0x7ffff, f->n);
 322 
 323         if (enabled)
 324                 clk_pll_sr2_enable(hw);
 325 
 326         return 0;
 327 }
 328 
 329 const struct clk_ops clk_pll_sr2_ops = {
 330         .enable = clk_pll_sr2_enable,
 331         .disable = clk_pll_disable,
 332         .set_rate = clk_pll_sr2_set_rate,
 333         .recalc_rate = clk_pll_recalc_rate,
 334         .determine_rate = clk_pll_determine_rate,
 335 };
 336 EXPORT_SYMBOL_GPL(clk_pll_sr2_ops);

/* [<][>][^][v][top][bottom][index][help] */