Merge remote-tracking branches 'regulator/fix/88pm800', 'regulator/fix/max8973',...
[linux-drm-fsl-dcu.git] / drivers / clk / at91 / clk-master.c
1 /*
2  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
3  *
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.
8  *
9  */
10
11 #include <linux/clk-provider.h>
12 #include <linux/clkdev.h>
13 #include <linux/clk/at91_pmc.h>
14 #include <linux/of.h>
15 #include <linux/of_address.h>
16 #include <linux/of_irq.h>
17 #include <linux/io.h>
18 #include <linux/wait.h>
19 #include <linux/sched.h>
20 #include <linux/interrupt.h>
21 #include <linux/irq.h>
22
23 #include "pmc.h"
24
25 #define MASTER_SOURCE_MAX       4
26
27 #define MASTER_PRES_MASK        0x7
28 #define MASTER_PRES_MAX         MASTER_PRES_MASK
29 #define MASTER_DIV_SHIFT        8
30 #define MASTER_DIV_MASK         0x3
31
32 struct clk_master_characteristics {
33         struct clk_range output;
34         u32 divisors[4];
35         u8 have_div3_pres;
36 };
37
38 struct clk_master_layout {
39         u32 mask;
40         u8 pres_shift;
41 };
42
43 #define to_clk_master(hw) container_of(hw, struct clk_master, hw)
44
45 struct clk_master {
46         struct clk_hw hw;
47         struct at91_pmc *pmc;
48         unsigned int irq;
49         wait_queue_head_t wait;
50         const struct clk_master_layout *layout;
51         const struct clk_master_characteristics *characteristics;
52 };
53
54 static irqreturn_t clk_master_irq_handler(int irq, void *dev_id)
55 {
56         struct clk_master *master = (struct clk_master *)dev_id;
57
58         wake_up(&master->wait);
59         disable_irq_nosync(master->irq);
60
61         return IRQ_HANDLED;
62 }
63 static int clk_master_prepare(struct clk_hw *hw)
64 {
65         struct clk_master *master = to_clk_master(hw);
66         struct at91_pmc *pmc = master->pmc;
67
68         while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY)) {
69                 enable_irq(master->irq);
70                 wait_event(master->wait,
71                            pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY);
72         }
73
74         return 0;
75 }
76
77 static int clk_master_is_prepared(struct clk_hw *hw)
78 {
79         struct clk_master *master = to_clk_master(hw);
80
81         return !!(pmc_read(master->pmc, AT91_PMC_SR) & AT91_PMC_MCKRDY);
82 }
83
84 static unsigned long clk_master_recalc_rate(struct clk_hw *hw,
85                                             unsigned long parent_rate)
86 {
87         u8 pres;
88         u8 div;
89         unsigned long rate = parent_rate;
90         struct clk_master *master = to_clk_master(hw);
91         struct at91_pmc *pmc = master->pmc;
92         const struct clk_master_layout *layout = master->layout;
93         const struct clk_master_characteristics *characteristics =
94                                                 master->characteristics;
95         u32 tmp;
96
97         pmc_lock(pmc);
98         tmp = pmc_read(pmc, AT91_PMC_MCKR) & layout->mask;
99         pmc_unlock(pmc);
100
101         pres = (tmp >> layout->pres_shift) & MASTER_PRES_MASK;
102         div = (tmp >> MASTER_DIV_SHIFT) & MASTER_DIV_MASK;
103
104         if (characteristics->have_div3_pres && pres == MASTER_PRES_MAX)
105                 rate /= 3;
106         else
107                 rate >>= pres;
108
109         rate /= characteristics->divisors[div];
110
111         if (rate < characteristics->output.min)
112                 pr_warn("master clk is underclocked");
113         else if (rate > characteristics->output.max)
114                 pr_warn("master clk is overclocked");
115
116         return rate;
117 }
118
119 static u8 clk_master_get_parent(struct clk_hw *hw)
120 {
121         struct clk_master *master = to_clk_master(hw);
122         struct at91_pmc *pmc = master->pmc;
123
124         return pmc_read(pmc, AT91_PMC_MCKR) & AT91_PMC_CSS;
125 }
126
127 static const struct clk_ops master_ops = {
128         .prepare = clk_master_prepare,
129         .is_prepared = clk_master_is_prepared,
130         .recalc_rate = clk_master_recalc_rate,
131         .get_parent = clk_master_get_parent,
132 };
133
134 static struct clk * __init
135 at91_clk_register_master(struct at91_pmc *pmc, unsigned int irq,
136                 const char *name, int num_parents,
137                 const char **parent_names,
138                 const struct clk_master_layout *layout,
139                 const struct clk_master_characteristics *characteristics)
140 {
141         int ret;
142         struct clk_master *master;
143         struct clk *clk = NULL;
144         struct clk_init_data init;
145
146         if (!pmc || !irq || !name || !num_parents || !parent_names)
147                 return ERR_PTR(-EINVAL);
148
149         master = kzalloc(sizeof(*master), GFP_KERNEL);
150         if (!master)
151                 return ERR_PTR(-ENOMEM);
152
153         init.name = name;
154         init.ops = &master_ops;
155         init.parent_names = parent_names;
156         init.num_parents = num_parents;
157         init.flags = 0;
158
159         master->hw.init = &init;
160         master->layout = layout;
161         master->characteristics = characteristics;
162         master->pmc = pmc;
163         master->irq = irq;
164         init_waitqueue_head(&master->wait);
165         irq_set_status_flags(master->irq, IRQ_NOAUTOEN);
166         ret = request_irq(master->irq, clk_master_irq_handler,
167                           IRQF_TRIGGER_HIGH, "clk-master", master);
168         if (ret) {
169                 kfree(master);
170                 return ERR_PTR(ret);
171         }
172
173         clk = clk_register(NULL, &master->hw);
174         if (IS_ERR(clk)) {
175                 free_irq(master->irq, master);
176                 kfree(master);
177         }
178
179         return clk;
180 }
181
182
183 static const struct clk_master_layout at91rm9200_master_layout = {
184         .mask = 0x31F,
185         .pres_shift = 2,
186 };
187
188 static const struct clk_master_layout at91sam9x5_master_layout = {
189         .mask = 0x373,
190         .pres_shift = 4,
191 };
192
193
194 static struct clk_master_characteristics * __init
195 of_at91_clk_master_get_characteristics(struct device_node *np)
196 {
197         struct clk_master_characteristics *characteristics;
198
199         characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL);
200         if (!characteristics)
201                 return NULL;
202
203         if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
204                 goto out_free_characteristics;
205
206         of_property_read_u32_array(np, "atmel,clk-divisors",
207                                    characteristics->divisors, 4);
208
209         characteristics->have_div3_pres =
210                 of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
211
212         return characteristics;
213
214 out_free_characteristics:
215         kfree(characteristics);
216         return NULL;
217 }
218
219 static void __init
220 of_at91_clk_master_setup(struct device_node *np, struct at91_pmc *pmc,
221                          const struct clk_master_layout *layout)
222 {
223         struct clk *clk;
224         int num_parents;
225         int i;
226         unsigned int irq;
227         const char *parent_names[MASTER_SOURCE_MAX];
228         const char *name = np->name;
229         struct clk_master_characteristics *characteristics;
230
231         num_parents = of_clk_get_parent_count(np);
232         if (num_parents <= 0 || num_parents > MASTER_SOURCE_MAX)
233                 return;
234
235         for (i = 0; i < num_parents; ++i) {
236                 parent_names[i] = of_clk_get_parent_name(np, i);
237                 if (!parent_names[i])
238                         return;
239         }
240
241         of_property_read_string(np, "clock-output-names", &name);
242
243         characteristics = of_at91_clk_master_get_characteristics(np);
244         if (!characteristics)
245                 return;
246
247         irq = irq_of_parse_and_map(np, 0);
248         if (!irq)
249                 goto out_free_characteristics;
250
251         clk = at91_clk_register_master(pmc, irq, name, num_parents,
252                                        parent_names, layout,
253                                        characteristics);
254         if (IS_ERR(clk))
255                 goto out_free_characteristics;
256
257         of_clk_add_provider(np, of_clk_src_simple_get, clk);
258         return;
259
260 out_free_characteristics:
261         kfree(characteristics);
262 }
263
264 void __init of_at91rm9200_clk_master_setup(struct device_node *np,
265                                            struct at91_pmc *pmc)
266 {
267         of_at91_clk_master_setup(np, pmc, &at91rm9200_master_layout);
268 }
269
270 void __init of_at91sam9x5_clk_master_setup(struct device_node *np,
271                                            struct at91_pmc *pmc)
272 {
273         of_at91_clk_master_setup(np, pmc, &at91sam9x5_master_layout);
274 }