0001
0002
0003
0004
0005
0006 #include <linux/clk-provider.h>
0007 #include <linux/delay.h>
0008 #include <linux/err.h>
0009 #include <linux/io.h>
0010 #include <linux/slab.h>
0011 #include "clk.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 struct clk_pll {
0024 struct clk_hw hw;
0025 void __iomem *base;
0026 u8 power;
0027 unsigned long rate;
0028 };
0029
0030 #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
0031
0032 static int clk_pll_prepare(struct clk_hw *hw)
0033 {
0034 struct clk_pll *pll = to_clk_pll(hw);
0035
0036 writel_relaxed(1 << pll->power, pll->base + SET);
0037
0038 udelay(10);
0039
0040 return 0;
0041 }
0042
0043 static void clk_pll_unprepare(struct clk_hw *hw)
0044 {
0045 struct clk_pll *pll = to_clk_pll(hw);
0046
0047 writel_relaxed(1 << pll->power, pll->base + CLR);
0048 }
0049
0050 static int clk_pll_enable(struct clk_hw *hw)
0051 {
0052 struct clk_pll *pll = to_clk_pll(hw);
0053
0054 writel_relaxed(1 << 31, pll->base + CLR);
0055
0056 return 0;
0057 }
0058
0059 static void clk_pll_disable(struct clk_hw *hw)
0060 {
0061 struct clk_pll *pll = to_clk_pll(hw);
0062
0063 writel_relaxed(1 << 31, pll->base + SET);
0064 }
0065
0066 static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
0067 unsigned long parent_rate)
0068 {
0069 struct clk_pll *pll = to_clk_pll(hw);
0070
0071 return pll->rate;
0072 }
0073
0074 static const struct clk_ops clk_pll_ops = {
0075 .prepare = clk_pll_prepare,
0076 .unprepare = clk_pll_unprepare,
0077 .enable = clk_pll_enable,
0078 .disable = clk_pll_disable,
0079 .recalc_rate = clk_pll_recalc_rate,
0080 };
0081
0082 struct clk *mxs_clk_pll(const char *name, const char *parent_name,
0083 void __iomem *base, u8 power, unsigned long rate)
0084 {
0085 struct clk_pll *pll;
0086 struct clk *clk;
0087 struct clk_init_data init;
0088
0089 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
0090 if (!pll)
0091 return ERR_PTR(-ENOMEM);
0092
0093 init.name = name;
0094 init.ops = &clk_pll_ops;
0095 init.flags = 0;
0096 init.parent_names = (parent_name ? &parent_name: NULL);
0097 init.num_parents = (parent_name ? 1 : 0);
0098
0099 pll->base = base;
0100 pll->rate = rate;
0101 pll->power = power;
0102 pll->hw.init = &init;
0103
0104 clk = clk_register(NULL, &pll->hw);
0105 if (IS_ERR(clk))
0106 kfree(pll);
0107
0108 return clk;
0109 }