linux/arch/arm/mach-imx/clk-pllv1.c
<<
>>
Prefs
   1#include <linux/clk.h>
   2#include <linux/clk-provider.h>
   3#include <linux/io.h>
   4#include <linux/slab.h>
   5#include <linux/kernel.h>
   6#include <linux/err.h>
   7
   8#include "clk.h"
   9#include "common.h"
  10#include "hardware.h"
  11
  12/**
  13 * pll v1
  14 *
  15 * @clk_hw      clock source
  16 * @parent      the parent clock name
  17 * @base        base address of pll registers
  18 *
  19 * PLL clock version 1, found on i.MX1/21/25/27/31/35
  20 */
  21struct clk_pllv1 {
  22        struct clk_hw   hw;
  23        void __iomem    *base;
  24};
  25
  26#define to_clk_pllv1(clk) (container_of(clk, struct clk_pllv1, clk))
  27
  28static unsigned long clk_pllv1_recalc_rate(struct clk_hw *hw,
  29                unsigned long parent_rate)
  30{
  31        struct clk_pllv1 *pll = to_clk_pllv1(hw);
  32        long long ll;
  33        int mfn_abs;
  34        unsigned int mfi, mfn, mfd, pd;
  35        u32 reg;
  36        unsigned long rate;
  37
  38        reg = readl(pll->base);
  39
  40        /*
  41         * Get the resulting clock rate from a PLL register value and the input
  42         * frequency. PLLs with this register layout can be found on i.MX1,
  43         * i.MX21, i.MX27 and i,MX31
  44         *
  45         *                  mfi + mfn / (mfd + 1)
  46         *  f = 2 * f_ref * --------------------
  47         *                        pd + 1
  48         */
  49
  50        mfi = (reg >> 10) & 0xf;
  51        mfn = reg & 0x3ff;
  52        mfd = (reg >> 16) & 0x3ff;
  53        pd =  (reg >> 26) & 0xf;
  54
  55        mfi = mfi <= 5 ? 5 : mfi;
  56
  57        mfn_abs = mfn;
  58
  59        /*
  60         * On all i.MXs except i.MX1 and i.MX21 mfn is a 10bit
  61         * 2's complements number
  62         */
  63        if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
  64                mfn_abs = 0x400 - mfn;
  65
  66        rate = parent_rate * 2;
  67        rate /= pd + 1;
  68
  69        ll = (unsigned long long)rate * mfn_abs;
  70
  71        do_div(ll, mfd + 1);
  72
  73        if (!cpu_is_mx1() && !cpu_is_mx21() && mfn >= 0x200)
  74                ll = -ll;
  75
  76        ll = (rate * mfi) + ll;
  77
  78        return ll;
  79}
  80
  81static struct clk_ops clk_pllv1_ops = {
  82        .recalc_rate = clk_pllv1_recalc_rate,
  83};
  84
  85struct clk *imx_clk_pllv1(const char *name, const char *parent,
  86                void __iomem *base)
  87{
  88        struct clk_pllv1 *pll;
  89        struct clk *clk;
  90        struct clk_init_data init;
  91
  92        pll = kmalloc(sizeof(*pll), GFP_KERNEL);
  93        if (!pll)
  94                return ERR_PTR(-ENOMEM);
  95
  96        pll->base = base;
  97
  98        init.name = name;
  99        init.ops = &clk_pllv1_ops;
 100        init.flags = 0;
 101        init.parent_names = &parent;
 102        init.num_parents = 1;
 103
 104        pll->hw.init = &init;
 105
 106        clk = clk_register(NULL, &pll->hw);
 107        if (IS_ERR(clk))
 108                kfree(pll);
 109
 110        return clk;
 111}
 112