0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "clk-gpt-synth: " fmt
0010
0011 #include <linux/clk-provider.h>
0012 #include <linux/slab.h>
0013 #include <linux/io.h>
0014 #include <linux/err.h>
0015 #include "clk.h"
0016
0017 #define GPT_MSCALE_MASK 0xFFF
0018 #define GPT_NSCALE_SHIFT 12
0019 #define GPT_NSCALE_MASK 0xF
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #define to_clk_gpt(_hw) container_of(_hw, struct clk_gpt, hw)
0030
0031 static unsigned long gpt_calc_rate(struct clk_hw *hw, unsigned long prate,
0032 int index)
0033 {
0034 struct clk_gpt *gpt = to_clk_gpt(hw);
0035 struct gpt_rate_tbl *rtbl = gpt->rtbl;
0036
0037 prate /= ((1 << (rtbl[index].nscale + 1)) * (rtbl[index].mscale + 1));
0038
0039 return prate;
0040 }
0041
0042 static long clk_gpt_round_rate(struct clk_hw *hw, unsigned long drate,
0043 unsigned long *prate)
0044 {
0045 struct clk_gpt *gpt = to_clk_gpt(hw);
0046 int unused;
0047
0048 return clk_round_rate_index(hw, drate, *prate, gpt_calc_rate,
0049 gpt->rtbl_cnt, &unused);
0050 }
0051
0052 static unsigned long clk_gpt_recalc_rate(struct clk_hw *hw,
0053 unsigned long parent_rate)
0054 {
0055 struct clk_gpt *gpt = to_clk_gpt(hw);
0056 unsigned long flags = 0;
0057 unsigned int div = 1, val;
0058
0059 if (gpt->lock)
0060 spin_lock_irqsave(gpt->lock, flags);
0061
0062 val = readl_relaxed(gpt->reg);
0063
0064 if (gpt->lock)
0065 spin_unlock_irqrestore(gpt->lock, flags);
0066
0067 div += val & GPT_MSCALE_MASK;
0068 div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1);
0069
0070 if (!div)
0071 return 0;
0072
0073 return parent_rate / div;
0074 }
0075
0076
0077 static int clk_gpt_set_rate(struct clk_hw *hw, unsigned long drate,
0078 unsigned long prate)
0079 {
0080 struct clk_gpt *gpt = to_clk_gpt(hw);
0081 struct gpt_rate_tbl *rtbl = gpt->rtbl;
0082 unsigned long flags = 0, val;
0083 int i;
0084
0085 clk_round_rate_index(hw, drate, prate, gpt_calc_rate, gpt->rtbl_cnt,
0086 &i);
0087
0088 if (gpt->lock)
0089 spin_lock_irqsave(gpt->lock, flags);
0090
0091 val = readl(gpt->reg) & ~GPT_MSCALE_MASK;
0092 val &= ~(GPT_NSCALE_MASK << GPT_NSCALE_SHIFT);
0093
0094 val |= rtbl[i].mscale & GPT_MSCALE_MASK;
0095 val |= (rtbl[i].nscale & GPT_NSCALE_MASK) << GPT_NSCALE_SHIFT;
0096
0097 writel_relaxed(val, gpt->reg);
0098
0099 if (gpt->lock)
0100 spin_unlock_irqrestore(gpt->lock, flags);
0101
0102 return 0;
0103 }
0104
0105 static const struct clk_ops clk_gpt_ops = {
0106 .recalc_rate = clk_gpt_recalc_rate,
0107 .round_rate = clk_gpt_round_rate,
0108 .set_rate = clk_gpt_set_rate,
0109 };
0110
0111 struct clk *clk_register_gpt(const char *name, const char *parent_name, unsigned
0112 long flags, void __iomem *reg, struct gpt_rate_tbl *rtbl, u8
0113 rtbl_cnt, spinlock_t *lock)
0114 {
0115 struct clk_init_data init;
0116 struct clk_gpt *gpt;
0117 struct clk *clk;
0118
0119 if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
0120 pr_err("Invalid arguments passed\n");
0121 return ERR_PTR(-EINVAL);
0122 }
0123
0124 gpt = kzalloc(sizeof(*gpt), GFP_KERNEL);
0125 if (!gpt)
0126 return ERR_PTR(-ENOMEM);
0127
0128
0129 gpt->reg = reg;
0130 gpt->rtbl = rtbl;
0131 gpt->rtbl_cnt = rtbl_cnt;
0132 gpt->lock = lock;
0133 gpt->hw.init = &init;
0134
0135 init.name = name;
0136 init.ops = &clk_gpt_ops;
0137 init.flags = flags;
0138 init.parent_names = &parent_name;
0139 init.num_parents = 1;
0140
0141 clk = clk_register(NULL, &gpt->hw);
0142 if (!IS_ERR_OR_NULL(clk))
0143 return clk;
0144
0145 pr_err("clk register failed\n");
0146 kfree(gpt);
0147
0148 return NULL;
0149 }