0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/clk-provider.h>
0009 #include <linux/io.h>
0010 #include <linux/of.h>
0011 #include <linux/of_address.h>
0012 #include <linux/slab.h>
0013 #include <linux/spinlock.h>
0014
0015 #define TCON_CH1_SCLK2_PARENTS 4
0016
0017 #define TCON_CH1_SCLK2_GATE_BIT BIT(31)
0018 #define TCON_CH1_SCLK2_MUX_MASK 3
0019 #define TCON_CH1_SCLK2_MUX_SHIFT 24
0020 #define TCON_CH1_SCLK2_DIV_MASK 0xf
0021 #define TCON_CH1_SCLK2_DIV_SHIFT 0
0022
0023 #define TCON_CH1_SCLK1_GATE_BIT BIT(15)
0024 #define TCON_CH1_SCLK1_HALF_BIT BIT(11)
0025
0026 struct tcon_ch1_clk {
0027 struct clk_hw hw;
0028 spinlock_t lock;
0029 void __iomem *reg;
0030 };
0031
0032 #define hw_to_tclk(hw) container_of(hw, struct tcon_ch1_clk, hw)
0033
0034 static void tcon_ch1_disable(struct clk_hw *hw)
0035 {
0036 struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
0037 unsigned long flags;
0038 u32 reg;
0039
0040 spin_lock_irqsave(&tclk->lock, flags);
0041 reg = readl(tclk->reg);
0042 reg &= ~(TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
0043 writel(reg, tclk->reg);
0044 spin_unlock_irqrestore(&tclk->lock, flags);
0045 }
0046
0047 static int tcon_ch1_enable(struct clk_hw *hw)
0048 {
0049 struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
0050 unsigned long flags;
0051 u32 reg;
0052
0053 spin_lock_irqsave(&tclk->lock, flags);
0054 reg = readl(tclk->reg);
0055 reg |= TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT;
0056 writel(reg, tclk->reg);
0057 spin_unlock_irqrestore(&tclk->lock, flags);
0058
0059 return 0;
0060 }
0061
0062 static int tcon_ch1_is_enabled(struct clk_hw *hw)
0063 {
0064 struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
0065 u32 reg;
0066
0067 reg = readl(tclk->reg);
0068 return reg & (TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
0069 }
0070
0071 static u8 tcon_ch1_get_parent(struct clk_hw *hw)
0072 {
0073 struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
0074 u32 reg;
0075
0076 reg = readl(tclk->reg) >> TCON_CH1_SCLK2_MUX_SHIFT;
0077 reg &= reg >> TCON_CH1_SCLK2_MUX_MASK;
0078
0079 return reg;
0080 }
0081
0082 static int tcon_ch1_set_parent(struct clk_hw *hw, u8 index)
0083 {
0084 struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
0085 unsigned long flags;
0086 u32 reg;
0087
0088 spin_lock_irqsave(&tclk->lock, flags);
0089 reg = readl(tclk->reg);
0090 reg &= ~(TCON_CH1_SCLK2_MUX_MASK << TCON_CH1_SCLK2_MUX_SHIFT);
0091 reg |= index << TCON_CH1_SCLK2_MUX_SHIFT;
0092 writel(reg, tclk->reg);
0093 spin_unlock_irqrestore(&tclk->lock, flags);
0094
0095 return 0;
0096 };
0097
0098 static unsigned long tcon_ch1_calc_divider(unsigned long rate,
0099 unsigned long parent_rate,
0100 u8 *div,
0101 bool *half)
0102 {
0103 unsigned long best_rate = 0;
0104 u8 best_m = 0, m;
0105 bool is_double;
0106
0107 for (m = 1; m < 16; m++) {
0108 u8 d;
0109
0110 for (d = 1; d < 3; d++) {
0111 unsigned long tmp_rate;
0112
0113 tmp_rate = parent_rate / m / d;
0114
0115 if (tmp_rate > rate)
0116 continue;
0117
0118 if (!best_rate ||
0119 (rate - tmp_rate) < (rate - best_rate)) {
0120 best_rate = tmp_rate;
0121 best_m = m;
0122 is_double = d;
0123 }
0124 }
0125 }
0126
0127 if (div && half) {
0128 *div = best_m;
0129 *half = is_double;
0130 }
0131
0132 return best_rate;
0133 }
0134
0135 static int tcon_ch1_determine_rate(struct clk_hw *hw,
0136 struct clk_rate_request *req)
0137 {
0138 long best_rate = -EINVAL;
0139 int i;
0140
0141 for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
0142 unsigned long parent_rate;
0143 unsigned long tmp_rate;
0144 struct clk_hw *parent;
0145
0146 parent = clk_hw_get_parent_by_index(hw, i);
0147 if (!parent)
0148 continue;
0149
0150 parent_rate = clk_hw_get_rate(parent);
0151
0152 tmp_rate = tcon_ch1_calc_divider(req->rate, parent_rate,
0153 NULL, NULL);
0154
0155 if (best_rate < 0 ||
0156 (req->rate - tmp_rate) < (req->rate - best_rate)) {
0157 best_rate = tmp_rate;
0158 req->best_parent_rate = parent_rate;
0159 req->best_parent_hw = parent;
0160 }
0161 }
0162
0163 if (best_rate < 0)
0164 return best_rate;
0165
0166 req->rate = best_rate;
0167 return 0;
0168 }
0169
0170 static unsigned long tcon_ch1_recalc_rate(struct clk_hw *hw,
0171 unsigned long parent_rate)
0172 {
0173 struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
0174 u32 reg;
0175
0176 reg = readl(tclk->reg);
0177
0178 parent_rate /= (reg & TCON_CH1_SCLK2_DIV_MASK) + 1;
0179
0180 if (reg & TCON_CH1_SCLK1_HALF_BIT)
0181 parent_rate /= 2;
0182
0183 return parent_rate;
0184 }
0185
0186 static int tcon_ch1_set_rate(struct clk_hw *hw, unsigned long rate,
0187 unsigned long parent_rate)
0188 {
0189 struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
0190 unsigned long flags;
0191 bool half;
0192 u8 div_m;
0193 u32 reg;
0194
0195 tcon_ch1_calc_divider(rate, parent_rate, &div_m, &half);
0196
0197 spin_lock_irqsave(&tclk->lock, flags);
0198 reg = readl(tclk->reg);
0199 reg &= ~(TCON_CH1_SCLK2_DIV_MASK | TCON_CH1_SCLK1_HALF_BIT);
0200 reg |= (div_m - 1) & TCON_CH1_SCLK2_DIV_MASK;
0201
0202 if (half)
0203 reg |= TCON_CH1_SCLK1_HALF_BIT;
0204
0205 writel(reg, tclk->reg);
0206 spin_unlock_irqrestore(&tclk->lock, flags);
0207
0208 return 0;
0209 }
0210
0211 static const struct clk_ops tcon_ch1_ops = {
0212 .disable = tcon_ch1_disable,
0213 .enable = tcon_ch1_enable,
0214 .is_enabled = tcon_ch1_is_enabled,
0215
0216 .get_parent = tcon_ch1_get_parent,
0217 .set_parent = tcon_ch1_set_parent,
0218
0219 .determine_rate = tcon_ch1_determine_rate,
0220 .recalc_rate = tcon_ch1_recalc_rate,
0221 .set_rate = tcon_ch1_set_rate,
0222 };
0223
0224 static void __init tcon_ch1_setup(struct device_node *node)
0225 {
0226 const char *parents[TCON_CH1_SCLK2_PARENTS];
0227 const char *clk_name = node->name;
0228 struct clk_init_data init;
0229 struct tcon_ch1_clk *tclk;
0230 struct resource res;
0231 struct clk *clk;
0232 void __iomem *reg;
0233 int ret;
0234
0235 of_property_read_string(node, "clock-output-names", &clk_name);
0236
0237 reg = of_io_request_and_map(node, 0, of_node_full_name(node));
0238 if (IS_ERR(reg)) {
0239 pr_err("%s: Could not map the clock registers\n", clk_name);
0240 return;
0241 }
0242
0243 ret = of_clk_parent_fill(node, parents, TCON_CH1_SCLK2_PARENTS);
0244 if (ret != TCON_CH1_SCLK2_PARENTS) {
0245 pr_err("%s Could not retrieve the parents\n", clk_name);
0246 goto err_unmap;
0247 }
0248
0249 tclk = kzalloc(sizeof(*tclk), GFP_KERNEL);
0250 if (!tclk)
0251 goto err_unmap;
0252
0253 init.name = clk_name;
0254 init.ops = &tcon_ch1_ops;
0255 init.parent_names = parents;
0256 init.num_parents = TCON_CH1_SCLK2_PARENTS;
0257 init.flags = CLK_SET_RATE_PARENT;
0258
0259 tclk->reg = reg;
0260 tclk->hw.init = &init;
0261 spin_lock_init(&tclk->lock);
0262
0263 clk = clk_register(NULL, &tclk->hw);
0264 if (IS_ERR(clk)) {
0265 pr_err("%s: Couldn't register the clock\n", clk_name);
0266 goto err_free_data;
0267 }
0268
0269 ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
0270 if (ret) {
0271 pr_err("%s: Couldn't register our clock provider\n", clk_name);
0272 goto err_unregister_clk;
0273 }
0274
0275 return;
0276
0277 err_unregister_clk:
0278 clk_unregister(clk);
0279 err_free_data:
0280 kfree(tclk);
0281 err_unmap:
0282 iounmap(reg);
0283 of_address_to_resource(node, 0, &res);
0284 release_mem_region(res.start, resource_size(&res));
0285 }
0286
0287 CLK_OF_DECLARE(tcon_ch1, "allwinner,sun4i-a10-tcon-ch1-clk",
0288 tcon_ch1_setup);