2 * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
11 #include <linux/clk-provider.h>
12 #include <linux/clkdev.h>
13 #include <linux/clk/at91_pmc.h>
15 #include <linux/of_address.h>
16 #include <linux/of_irq.h>
18 #include <linux/wait.h>
19 #include <linux/sched.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22 #include <linux/mfd/syscon.h>
23 #include <linux/regmap.h>
27 #define MASTER_SOURCE_MAX 4
29 #define MASTER_PRES_MASK 0x7
30 #define MASTER_PRES_MAX MASTER_PRES_MASK
31 #define MASTER_DIV_SHIFT 8
32 #define MASTER_DIV_MASK 0x3
34 struct clk_master_characteristics {
35 struct clk_range output;
40 struct clk_master_layout {
45 #define to_clk_master(hw) container_of(hw, struct clk_master, hw)
49 struct regmap *regmap;
51 wait_queue_head_t wait;
52 const struct clk_master_layout *layout;
53 const struct clk_master_characteristics *characteristics;
56 static irqreturn_t clk_master_irq_handler(int irq, void *dev_id)
58 struct clk_master *master = (struct clk_master *)dev_id;
60 wake_up(&master->wait);
61 disable_irq_nosync(master->irq);
66 static inline bool clk_master_ready(struct regmap *regmap)
70 regmap_read(regmap, AT91_PMC_SR, &status);
72 return status & AT91_PMC_MCKRDY ? 1 : 0;
75 static int clk_master_prepare(struct clk_hw *hw)
77 struct clk_master *master = to_clk_master(hw);
79 while (!clk_master_ready(master->regmap)) {
80 enable_irq(master->irq);
81 wait_event(master->wait,
82 clk_master_ready(master->regmap));
88 static int clk_master_is_prepared(struct clk_hw *hw)
90 struct clk_master *master = to_clk_master(hw);
92 return clk_master_ready(master->regmap);
95 static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
96 unsigned long parent_rate)
100 unsigned long rate = parent_rate;
101 struct clk_master *master = to_clk_master(hw);
102 const struct clk_master_layout *layout = master->layout;
103 const struct clk_master_characteristics *characteristics =
104 master->characteristics;
107 regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
108 mckr &= layout->mask;
110 pres = (mckr >> layout->pres_shift) & MASTER_PRES_MASK;
111 div = (mckr >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
113 if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX)
118 rate /= characteristics->divisors[div];
120 if (rate < characteristics->output.min)
121 pr_warn("master clk is underclocked");
122 else if (rate > characteristics->output.max)
123 pr_warn("master clk is overclocked");
128 static u8 clk_master_get_parent(struct clk_hw *hw)
130 struct clk_master *master = to_clk_master(hw);
133 regmap_read(master->regmap, AT91_PMC_MCKR, &mckr);
135 return mckr & AT91_PMC_CSS;
138 static const struct clk_ops master_ops = {
139 .prepare = clk_master_prepare,
140 .is_prepared = clk_master_is_prepared,
141 .recalc_rate = clk_master_recalc_rate,
142 .get_parent = clk_master_get_parent,
145 static struct clk * __init
146 at91_clk_register_master(struct regmap *regmap, unsigned int irq,
147 const char *name, int num_parents,
148 const char **parent_names,
149 const struct clk_master_layout *layout,
150 const struct clk_master_characteristics *characteristics)
153 struct clk_master *master;
154 struct clk *clk = NULL;
155 struct clk_init_data init;
157 if (!name || !num_parents || !parent_names)
158 return ERR_PTR(-EINVAL);
160 master = kzalloc(sizeof(*master), GFP_KERNEL);
162 return ERR_PTR(-ENOMEM);
165 init.ops = &master_ops;
166 init.parent_names = parent_names;
167 init.num_parents = num_parents;
170 master->hw.init = &init;
171 master->layout = layout;
172 master->characteristics = characteristics;
173 master->regmap = regmap;
175 init_waitqueue_head(&master->wait);
176 irq_set_status_flags(master->irq, IRQ_NOAUTOEN);
177 ret = request_irq(master->irq, clk_master_irq_handler,
178 IRQF_TRIGGER_HIGH, "clk-master", master);
184 clk = clk_register(NULL, &master->hw);
186 free_irq(master->irq, master);
194 static const struct clk_master_layout at91rm9200_master_layout = {
199 static const struct clk_master_layout at91sam9x5_master_layout = {
205 static struct clk_master_characteristics * __init
206 of_at91_clk_master_get_characteristics(struct device_node *np)
208 struct clk_master_characteristics *characteristics;
210 characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
211 if (!characteristics)
214 if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
215 goto out_free_characteristics;
217 of_property_read_u32_array(np, "atmel,clk-divisors",
218 characteristics->divisors, 4);
220 characteristics->have_div3_pres =
221 of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
223 return characteristics;
225 out_free_characteristics:
226 kfree(characteristics);
231 of_at91_clk_master_setup(struct device_node *np,
232 const struct clk_master_layout *layout)
237 const char *parent_names[MASTER_SOURCE_MAX];
238 const char *name = np->name;
239 struct clk_master_characteristics *characteristics;
240 struct regmap *regmap;
242 num_parents = of_clk_get_parent_count(np);
243 if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
246 of_clk_parent_fill(np, parent_names, num_parents);
248 of_property_read_string(np, "clock-output-names", &name);
250 characteristics = of_at91_clk_master_get_characteristics(np);
251 if (!characteristics)
254 regmap = syscon_node_to_regmap(of_get_parent(np));
258 irq = irq_of_parse_and_map(np, 0);
260 goto out_free_characteristics;
262 clk = at91_clk_register_master(regmap, irq, name, num_parents,
263 parent_names, layout,
266 goto out_free_characteristics;
268 of_clk_add_provider(np, of_clk_src_simple_get, clk);
271 out_free_characteristics:
272 kfree(characteristics);
275 static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
277 of_at91_clk_master_setup(np, &at91rm9200_master_layout);
279 CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
280 of_at91rm9200_clk_master_setup);
282 static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
284 of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
286 CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
287 of_at91sam9x5_clk_master_setup);