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