linux/arch/arm/mach-imx/clk-pllv3.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Freescale Semiconductor, Inc.
   3 * Copyright 2012 Linaro Ltd.
   4 *
   5 * The code contained herein is licensed under the GNU General Public
   6 * License. You may obtain a copy of the GNU General Public License
   7 * Version 2 or later at the following locations:
   8 *
   9 * http://www.opensource.org/licenses/gpl-license.html
  10 * http://www.gnu.org/copyleft/gpl.html
  11 */
  12
  13#include <linux/clk.h>
  14#include <linux/clk-provider.h>
  15#include <linux/io.h>
  16#include <linux/slab.h>
  17#include <linux/jiffies.h>
  18#include <linux/err.h>
  19#include "clk.h"
  20
  21#define PLL_NUM_OFFSET          0x10
  22#define PLL_DENOM_OFFSET        0x20
  23
  24#define BM_PLL_POWER            (0x1 << 12)
  25#define BM_PLL_ENABLE           (0x1 << 13)
  26#define BM_PLL_BYPASS           (0x1 << 16)
  27#define BM_PLL_LOCK             (0x1 << 31)
  28
  29/**
  30 * struct clk_pllv3 - IMX PLL clock version 3
  31 * @clk_hw:      clock source
  32 * @base:        base address of PLL registers
  33 * @powerup_set: set POWER bit to power up the PLL
  34 * @div_mask:    mask of divider bits
  35 *
  36 * IMX PLL clock version 3, found on i.MX6 series.  Divider for pllv3
  37 * is actually a multiplier, and always sits at bit 0.
  38 */
  39struct clk_pllv3 {
  40        struct clk_hw   hw;
  41        void __iomem    *base;
  42        bool            powerup_set;
  43        u32             div_mask;
  44};
  45
  46#define to_clk_pllv3(_hw) container_of(_hw, struct clk_pllv3, hw)
  47
  48static int clk_pllv3_prepare(struct clk_hw *hw)
  49{
  50        struct clk_pllv3 *pll = to_clk_pllv3(hw);
  51        unsigned long timeout = jiffies + msecs_to_jiffies(10);
  52        u32 val;
  53
  54        val = readl_relaxed(pll->base);
  55        val &= ~BM_PLL_BYPASS;
  56        if (pll->powerup_set)
  57                val |= BM_PLL_POWER;
  58        else
  59                val &= ~BM_PLL_POWER;
  60        writel_relaxed(val, pll->base);
  61
  62        /* Wait for PLL to lock */
  63        while (!(readl_relaxed(pll->base) & BM_PLL_LOCK))
  64                if (time_after(jiffies, timeout))
  65                        return -ETIMEDOUT;
  66
  67        return 0;
  68}
  69
  70static void clk_pllv3_unprepare(struct clk_hw *hw)
  71{
  72        struct clk_pllv3 *pll = to_clk_pllv3(hw);
  73        u32 val;
  74
  75        val = readl_relaxed(pll->base);
  76        val |= BM_PLL_BYPASS;
  77        if (pll->powerup_set)
  78                val &= ~BM_PLL_POWER;
  79        else
  80                val |= BM_PLL_POWER;
  81        writel_relaxed(val, pll->base);
  82}
  83
  84static int clk_pllv3_enable(struct clk_hw *hw)
  85{
  86        struct clk_pllv3 *pll = to_clk_pllv3(hw);
  87        u32 val;
  88
  89        val = readl_relaxed(pll->base);
  90        val |= BM_PLL_ENABLE;
  91        writel_relaxed(val, pll->base);
  92
  93        return 0;
  94}
  95
  96static void clk_pllv3_disable(struct clk_hw *hw)
  97{
  98        struct clk_pllv3 *pll = to_clk_pllv3(hw);
  99        u32 val;
 100
 101        val = readl_relaxed(pll->base);
 102        val &= ~BM_PLL_ENABLE;
 103        writel_relaxed(val, pll->base);
 104}
 105
 106static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
 107                                           unsigned long parent_rate)
 108{
 109        struct clk_pllv3 *pll = to_clk_pllv3(hw);
 110        u32 div = readl_relaxed(pll->base)  & pll->div_mask;
 111
 112        return (div == 1) ? parent_rate * 22 : parent_rate * 20;
 113}
 114
 115static long clk_pllv3_round_rate(struct clk_hw *hw, unsigned long rate,
 116                                 unsigned long *prate)
 117{
 118        unsigned long parent_rate = *prate;
 119
 120        return (rate >= parent_rate * 22) ? parent_rate * 22 :
 121                                            parent_rate * 20;
 122}
 123
 124static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
 125                unsigned long parent_rate)
 126{
 127        struct clk_pllv3 *pll = to_clk_pllv3(hw);
 128        u32 val, div;
 129
 130        if (rate == parent_rate * 22)
 131                div = 1;
 132        else if (rate == parent_rate * 20)
 133                div = 0;
 134        else
 135                return -EINVAL;
 136
 137        val = readl_relaxed(pll->base);
 138        val &= ~pll->div_mask;
 139        val |= div;
 140        writel_relaxed(val, pll->base);
 141
 142        return 0;
 143}
 144
 145static const struct clk_ops clk_pllv3_ops = {
 146        .prepare        = clk_pllv3_prepare,
 147        .unprepare      = clk_pllv3_unprepare,
 148        .enable         = clk_pllv3_enable,
 149        .disable        = clk_pllv3_disable,
 150        .recalc_rate    = clk_pllv3_recalc_rate,
 151        .round_rate     = clk_pllv3_round_rate,
 152        .set_rate       = clk_pllv3_set_rate,
 153};
 154
 155static unsigned long clk_pllv3_sys_recalc_rate(struct clk_hw *hw,
 156                                               unsigned long parent_rate)
 157{
 158        struct clk_pllv3 *pll = to_clk_pllv3(hw);
 159        u32 div = readl_relaxed(pll->base) & pll->div_mask;
 160
 161        return parent_rate * div / 2;
 162}
 163
 164static long clk_pllv3_sys_round_rate(struct clk_hw *hw, unsigned long rate,
 165                                     unsigned long *prate)
 166{
 167        unsigned long parent_rate = *prate;
 168        unsigned long min_rate = parent_rate * 54 / 2;
 169        unsigned long max_rate = parent_rate * 108 / 2;
 170        u32 div;
 171
 172        if (rate > max_rate)
 173                rate = max_rate;
 174        else if (rate < min_rate)
 175                rate = min_rate;
 176        div = rate * 2 / parent_rate;
 177
 178        return parent_rate * div / 2;
 179}
 180
 181static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
 182                unsigned long parent_rate)
 183{
 184        struct clk_pllv3 *pll = to_clk_pllv3(hw);
 185        unsigned long min_rate = parent_rate * 54 / 2;
 186        unsigned long max_rate = parent_rate * 108 / 2;
 187        u32 val, div;
 188
 189        if (rate < min_rate || rate > max_rate)
 190                return -EINVAL;
 191
 192        div = rate * 2 / parent_rate;
 193        val = readl_relaxed(pll->base);
 194        val &= ~pll->div_mask;
 195        val |= div;
 196        writel_relaxed(val, pll->base);
 197
 198        return 0;
 199}
 200
 201static const struct clk_ops clk_pllv3_sys_ops = {
 202        .prepare        = clk_pllv3_prepare,
 203        .unprepare      = clk_pllv3_unprepare,
 204        .enable         = clk_pllv3_enable,
 205        .disable        = clk_pllv3_disable,
 206        .recalc_rate    = clk_pllv3_sys_recalc_rate,
 207        .round_rate     = clk_pllv3_sys_round_rate,
 208        .set_rate       = clk_pllv3_sys_set_rate,
 209};
 210
 211static unsigned long clk_pllv3_av_recalc_rate(struct clk_hw *hw,
 212                                              unsigned long parent_rate)
 213{
 214        struct clk_pllv3 *pll = to_clk_pllv3(hw);
 215        u32 mfn = readl_relaxed(pll->base + PLL_NUM_OFFSET);
 216        u32 mfd = readl_relaxed(pll->base + PLL_DENOM_OFFSET);
 217        u32 div = readl_relaxed(pll->base) & pll->div_mask;
 218
 219        return (parent_rate * div) + ((parent_rate / mfd) * mfn);
 220}
 221
 222static long clk_pllv3_av_round_rate(struct clk_hw *hw, unsigned long rate,
 223                                    unsigned long *prate)
 224{
 225        unsigned long parent_rate = *prate;
 226        unsigned long min_rate = parent_rate * 27;
 227        unsigned long max_rate = parent_rate * 54;
 228        u32 div;
 229        u32 mfn, mfd = 1000000;
 230        s64 temp64;
 231
 232        if (rate > max_rate)
 233                rate = max_rate;
 234        else if (rate < min_rate)
 235                rate = min_rate;
 236
 237        div = rate / parent_rate;
 238        temp64 = (u64) (rate - div * parent_rate);
 239        temp64 *= mfd;
 240        do_div(temp64, parent_rate);
 241        mfn = temp64;
 242
 243        return parent_rate * div + parent_rate / mfd * mfn;
 244}
 245
 246static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
 247                unsigned long parent_rate)
 248{
 249        struct clk_pllv3 *pll = to_clk_pllv3(hw);
 250        unsigned long min_rate = parent_rate * 27;
 251        unsigned long max_rate = parent_rate * 54;
 252        u32 val, div;
 253        u32 mfn, mfd = 1000000;
 254        s64 temp64;
 255
 256        if (rate < min_rate || rate > max_rate)
 257                return -EINVAL;
 258
 259        div = rate / parent_rate;
 260        temp64 = (u64) (rate - div * parent_rate);
 261        temp64 *= mfd;
 262        do_div(temp64, parent_rate);
 263        mfn = temp64;
 264
 265        val = readl_relaxed(pll->base);
 266        val &= ~pll->div_mask;
 267        val |= div;
 268        writel_relaxed(val, pll->base);
 269        writel_relaxed(mfn, pll->base + PLL_NUM_OFFSET);
 270        writel_relaxed(mfd, pll->base + PLL_DENOM_OFFSET);
 271
 272        return 0;
 273}
 274
 275static const struct clk_ops clk_pllv3_av_ops = {
 276        .prepare        = clk_pllv3_prepare,
 277        .unprepare      = clk_pllv3_unprepare,
 278        .enable         = clk_pllv3_enable,
 279        .disable        = clk_pllv3_disable,
 280        .recalc_rate    = clk_pllv3_av_recalc_rate,
 281        .round_rate     = clk_pllv3_av_round_rate,
 282        .set_rate       = clk_pllv3_av_set_rate,
 283};
 284
 285static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
 286                                                unsigned long parent_rate)
 287{
 288        return 500000000;
 289}
 290
 291static const struct clk_ops clk_pllv3_enet_ops = {
 292        .prepare        = clk_pllv3_prepare,
 293        .unprepare      = clk_pllv3_unprepare,
 294        .enable         = clk_pllv3_enable,
 295        .disable        = clk_pllv3_disable,
 296        .recalc_rate    = clk_pllv3_enet_recalc_rate,
 297};
 298
 299static const struct clk_ops clk_pllv3_mlb_ops = {
 300        .prepare        = clk_pllv3_prepare,
 301        .unprepare      = clk_pllv3_unprepare,
 302        .enable         = clk_pllv3_enable,
 303        .disable        = clk_pllv3_disable,
 304};
 305
 306struct clk *imx_clk_pllv3(enum imx_pllv3_type type, const char *name,
 307                          const char *parent_name, void __iomem *base,
 308                          u32 div_mask)
 309{
 310        struct clk_pllv3 *pll;
 311        const struct clk_ops *ops;
 312        struct clk *clk;
 313        struct clk_init_data init;
 314
 315        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 316        if (!pll)
 317                return ERR_PTR(-ENOMEM);
 318
 319        switch (type) {
 320        case IMX_PLLV3_SYS:
 321                ops = &clk_pllv3_sys_ops;
 322                break;
 323        case IMX_PLLV3_USB:
 324                ops = &clk_pllv3_ops;
 325                pll->powerup_set = true;
 326                break;
 327        case IMX_PLLV3_AV:
 328                ops = &clk_pllv3_av_ops;
 329                break;
 330        case IMX_PLLV3_ENET:
 331                ops = &clk_pllv3_enet_ops;
 332                break;
 333        case IMX_PLLV3_MLB:
 334                ops = &clk_pllv3_mlb_ops;
 335                break;
 336        default:
 337                ops = &clk_pllv3_ops;
 338        }
 339        pll->base = base;
 340        pll->div_mask = div_mask;
 341
 342        init.name = name;
 343        init.ops = ops;
 344        init.flags = 0;
 345        init.parent_names = &parent_name;
 346        init.num_parents = 1;
 347
 348        pll->hw.init = &init;
 349
 350        clk = clk_register(NULL, &pll->hw);
 351        if (IS_ERR(clk))
 352                kfree(pll);
 353
 354        return clk;
 355}
 356