aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Jacques Hiblot <jjhiblot@traphandler.com>2014-03-11 05:00:34 -0400
committerMike Turquette <mturquette@linaro.org>2014-03-19 18:21:56 -0400
commitcce6db80a049b23f867f4afded70ca8027876a08 (patch)
tree89533d08d02e7209c5f1f37cd9b7777fe1c298b8
parent693bb3d99d06e174c31471b58c8f0b97e1479b08 (diff)
clk: at91: fix programmable clk irq handling
The PCKRDY bit is not set until the system clock is enabled. This patch moves the management of the ready status in the system clock driver. Signed-off-by: Boris BREZILLON <b.brezillon@overkiz.com> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com> Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r--drivers/clk/at91/clk-programmable.c108
-rw-r--r--drivers/clk/at91/clk-system.c74
2 files changed, 89 insertions, 93 deletions
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index eff701665f04..7bcc725f67af 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -13,12 +13,9 @@
13#include <linux/clk/at91_pmc.h> 13#include <linux/clk/at91_pmc.h>
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/of_irq.h>
17#include <linux/io.h> 16#include <linux/io.h>
18#include <linux/wait.h> 17#include <linux/wait.h>
19#include <linux/sched.h> 18#include <linux/sched.h>
20#include <linux/interrupt.h>
21#include <linux/irq.h>
22 19
23#include "pmc.h" 20#include "pmc.h"
24 21
@@ -38,68 +35,23 @@ struct clk_programmable_layout {
38struct clk_programmable { 35struct clk_programmable {
39 struct clk_hw hw; 36 struct clk_hw hw;
40 struct at91_pmc *pmc; 37 struct at91_pmc *pmc;
41 unsigned int irq;
42 wait_queue_head_t wait;
43 u8 id; 38 u8 id;
44 u8 css;
45 u8 pres;
46 u8 slckmck;
47 const struct clk_programmable_layout *layout; 39 const struct clk_programmable_layout *layout;
48}; 40};
49 41
50#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw) 42#define to_clk_programmable(hw) container_of(hw, struct clk_programmable, hw)
51 43
52
53static irqreturn_t clk_programmable_irq_handler(int irq, void *dev_id)
54{
55 struct clk_programmable *prog = (struct clk_programmable *)dev_id;
56
57 wake_up(&prog->wait);
58
59 return IRQ_HANDLED;
60}
61
62static int clk_programmable_prepare(struct clk_hw *hw)
63{
64 u32 tmp;
65 struct clk_programmable *prog = to_clk_programmable(hw);
66 struct at91_pmc *pmc = prog->pmc;
67 const struct clk_programmable_layout *layout = prog->layout;
68 u8 id = prog->id;
69 u32 mask = PROG_STATUS_MASK(id);
70
71 tmp = prog->css | (prog->pres << layout->pres_shift);
72 if (layout->have_slck_mck && prog->slckmck)
73 tmp |= AT91_PMC_CSSMCK_MCK;
74
75 pmc_write(pmc, AT91_PMC_PCKR(id), tmp);
76
77 while (!(pmc_read(pmc, AT91_PMC_SR) & mask))
78 wait_event(prog->wait, pmc_read(pmc, AT91_PMC_SR) & mask);
79
80 return 0;
81}
82
83static int clk_programmable_is_ready(struct clk_hw *hw)
84{
85 struct clk_programmable *prog = to_clk_programmable(hw);
86 struct at91_pmc *pmc = prog->pmc;
87
88 return !!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_PCKR(prog->id));
89}
90
91static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, 44static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
92 unsigned long parent_rate) 45 unsigned long parent_rate)
93{ 46{
94 u32 tmp; 47 u32 pres;
95 struct clk_programmable *prog = to_clk_programmable(hw); 48 struct clk_programmable *prog = to_clk_programmable(hw);
96 struct at91_pmc *pmc = prog->pmc; 49 struct at91_pmc *pmc = prog->pmc;
97 const struct clk_programmable_layout *layout = prog->layout; 50 const struct clk_programmable_layout *layout = prog->layout;
98 51
99 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); 52 pres = (pmc_read(pmc, AT91_PMC_PCKR(prog->id)) >> layout->pres_shift) &
100 prog->pres = (tmp >> layout->pres_shift) & PROG_PRES_MASK; 53 PROG_PRES_MASK;
101 54 return parent_rate >> pres;
102 return parent_rate >> prog->pres;
103} 55}
104 56
105static long clk_programmable_determine_rate(struct clk_hw *hw, 57static long clk_programmable_determine_rate(struct clk_hw *hw,
@@ -146,17 +98,22 @@ static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
146{ 98{
147 struct clk_programmable *prog = to_clk_programmable(hw); 99 struct clk_programmable *prog = to_clk_programmable(hw);
148 const struct clk_programmable_layout *layout = prog->layout; 100 const struct clk_programmable_layout *layout = prog->layout;
101 struct at91_pmc *pmc = prog->pmc;
102 u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & ~layout->css_mask;
103
104 if (layout->have_slck_mck)
105 tmp &= AT91_PMC_CSSMCK_MCK;
106
149 if (index > layout->css_mask) { 107 if (index > layout->css_mask) {
150 if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { 108 if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) {
151 prog->css = 0; 109 tmp |= AT91_PMC_CSSMCK_MCK;
152 prog->slckmck = 1;
153 return 0; 110 return 0;
154 } else { 111 } else {
155 return -EINVAL; 112 return -EINVAL;
156 } 113 }
157 } 114 }
158 115
159 prog->css = index; 116 pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | index);
160 return 0; 117 return 0;
161} 118}
162 119
@@ -169,13 +126,9 @@ static u8 clk_programmable_get_parent(struct clk_hw *hw)
169 const struct clk_programmable_layout *layout = prog->layout; 126 const struct clk_programmable_layout *layout = prog->layout;
170 127
171 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); 128 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id));
172 prog->css = tmp & layout->css_mask; 129 ret = tmp & layout->css_mask;
173 ret = prog->css; 130 if (layout->have_slck_mck && (tmp & AT91_PMC_CSSMCK_MCK) && !ret)
174 if (layout->have_slck_mck) { 131 ret = PROG_MAX_RM9200_CSS + 1;
175 prog->slckmck = !!(tmp & AT91_PMC_CSSMCK_MCK);
176 if (prog->slckmck && !ret)
177 ret = PROG_MAX_RM9200_CSS + 1;
178 }
179 132
180 return ret; 133 return ret;
181} 134}
@@ -184,11 +137,15 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate,
184 unsigned long parent_rate) 137 unsigned long parent_rate)
185{ 138{
186 struct clk_programmable *prog = to_clk_programmable(hw); 139 struct clk_programmable *prog = to_clk_programmable(hw);
140 struct at91_pmc *pmc = prog->pmc;
141 const struct clk_programmable_layout *layout = prog->layout;
187 unsigned long best_rate = parent_rate; 142 unsigned long best_rate = parent_rate;
188 unsigned long best_diff; 143 unsigned long best_diff;
189 unsigned long new_diff; 144 unsigned long new_diff;
190 unsigned long cur_rate; 145 unsigned long cur_rate;
191 int shift = 0; 146 int shift = 0;
147 u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) &
148 ~(PROG_PRES_MASK << layout->pres_shift);
192 149
193 if (rate > parent_rate) 150 if (rate > parent_rate)
194 return parent_rate; 151 return parent_rate;
@@ -196,7 +153,7 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate,
196 best_diff = parent_rate - rate; 153 best_diff = parent_rate - rate;
197 154
198 if (!best_diff) { 155 if (!best_diff) {
199 prog->pres = shift; 156 pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | shift);
200 return 0; 157 return 0;
201 } 158 }
202 159
@@ -220,13 +177,13 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate,
220 break; 177 break;
221 } 178 }
222 179
223 prog->pres = shift; 180 pmc_write(pmc, AT91_PMC_PCKR(prog->id),
181 tmp | (shift << layout->pres_shift));
182
224 return 0; 183 return 0;
225} 184}
226 185
227static const struct clk_ops programmable_ops = { 186static const struct clk_ops programmable_ops = {
228 .prepare = clk_programmable_prepare,
229 .is_prepared = clk_programmable_is_ready,
230 .recalc_rate = clk_programmable_recalc_rate, 187 .recalc_rate = clk_programmable_recalc_rate,
231 .determine_rate = clk_programmable_determine_rate, 188 .determine_rate = clk_programmable_determine_rate,
232 .get_parent = clk_programmable_get_parent, 189 .get_parent = clk_programmable_get_parent,
@@ -235,16 +192,14 @@ static const struct clk_ops programmable_ops = {
235}; 192};
236 193
237static struct clk * __init 194static struct clk * __init
238at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq, 195at91_clk_register_programmable(struct at91_pmc *pmc,
239 const char *name, const char **parent_names, 196 const char *name, const char **parent_names,
240 u8 num_parents, u8 id, 197 u8 num_parents, u8 id,
241 const struct clk_programmable_layout *layout) 198 const struct clk_programmable_layout *layout)
242{ 199{
243 int ret;
244 struct clk_programmable *prog; 200 struct clk_programmable *prog;
245 struct clk *clk = NULL; 201 struct clk *clk = NULL;
246 struct clk_init_data init; 202 struct clk_init_data init;
247 char irq_name[11];
248 203
249 if (id > PROG_ID_MAX) 204 if (id > PROG_ID_MAX)
250 return ERR_PTR(-EINVAL); 205 return ERR_PTR(-EINVAL);
@@ -263,14 +218,6 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
263 prog->layout = layout; 218 prog->layout = layout;
264 prog->hw.init = &init; 219 prog->hw.init = &init;
265 prog->pmc = pmc; 220 prog->pmc = pmc;
266 prog->irq = irq;
267 init_waitqueue_head(&prog->wait);
268 irq_set_status_flags(prog->irq, IRQ_NOAUTOEN);
269 snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id);
270 ret = request_irq(prog->irq, clk_programmable_irq_handler,
271 IRQF_TRIGGER_HIGH, irq_name, prog);
272 if (ret)
273 return ERR_PTR(ret);
274 221
275 clk = clk_register(NULL, &prog->hw); 222 clk = clk_register(NULL, &prog->hw);
276 if (IS_ERR(clk)) 223 if (IS_ERR(clk))
@@ -304,7 +251,6 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
304 int num; 251 int num;
305 u32 id; 252 u32 id;
306 int i; 253 int i;
307 unsigned int irq;
308 struct clk *clk; 254 struct clk *clk;
309 int num_parents; 255 int num_parents;
310 const char *parent_names[PROG_SOURCE_MAX]; 256 const char *parent_names[PROG_SOURCE_MAX];
@@ -332,11 +278,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc,
332 if (of_property_read_string(np, "clock-output-names", &name)) 278 if (of_property_read_string(np, "clock-output-names", &name))
333 name = progclknp->name; 279 name = progclknp->name;
334 280
335 irq = irq_of_parse_and_map(progclknp, 0); 281 clk = at91_clk_register_programmable(pmc, name,
336 if (!irq)
337 continue;
338
339 clk = at91_clk_register_programmable(pmc, irq, name,
340 parent_names, num_parents, 282 parent_names, num_parents,
341 id, layout); 283 id, layout);
342 if (IS_ERR(clk)) 284 if (IS_ERR(clk))
diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
index 48c89fe0cfe8..8c96307d7363 100644
--- a/drivers/clk/at91/clk-system.c
+++ b/drivers/clk/at91/clk-system.c
@@ -14,6 +14,11 @@
14#include <linux/of.h> 14#include <linux/of.h>
15#include <linux/of_address.h> 15#include <linux/of_address.h>
16#include <linux/io.h> 16#include <linux/io.h>
17#include <linux/irq.h>
18#include <linux/of_irq.h>
19#include <linux/interrupt.h>
20#include <linux/wait.h>
21#include <linux/sched.h>
17 22
18#include "pmc.h" 23#include "pmc.h"
19 24
@@ -25,19 +30,48 @@
25struct clk_system { 30struct clk_system {
26 struct clk_hw hw; 31 struct clk_hw hw;
27 struct at91_pmc *pmc; 32 struct at91_pmc *pmc;
33 unsigned int irq;
34 wait_queue_head_t wait;
28 u8 id; 35 u8 id;
29}; 36};
30 37
31static int clk_system_enable(struct clk_hw *hw) 38static inline int is_pck(int id)
39{
40 return (id >= 8) && (id <= 15);
41}
42static irqreturn_t clk_system_irq_handler(int irq, void *dev_id)
43{
44 struct clk_system *sys = (struct clk_system *)dev_id;
45
46 wake_up(&sys->wait);
47 disable_irq_nosync(sys->irq);
48
49 return IRQ_HANDLED;
50}
51
52static int clk_system_prepare(struct clk_hw *hw)
32{ 53{
33 struct clk_system *sys = to_clk_system(hw); 54 struct clk_system *sys = to_clk_system(hw);
34 struct at91_pmc *pmc = sys->pmc; 55 struct at91_pmc *pmc = sys->pmc;
56 u32 mask = 1 << sys->id;
35 57
36 pmc_write(pmc, AT91_PMC_SCER, 1 << sys->id); 58 pmc_write(pmc, AT91_PMC_SCER, mask);
59
60 if (!is_pck(sys->id))
61 return 0;
62
63 while (!(pmc_read(pmc, AT91_PMC_SR) & mask)) {
64 if (sys->irq) {
65 enable_irq(sys->irq);
66 wait_event(sys->wait,
67 pmc_read(pmc, AT91_PMC_SR) & mask);
68 } else
69 cpu_relax();
70 }
37 return 0; 71 return 0;
38} 72}
39 73
40static void clk_system_disable(struct clk_hw *hw) 74static void clk_system_unprepare(struct clk_hw *hw)
41{ 75{
42 struct clk_system *sys = to_clk_system(hw); 76 struct clk_system *sys = to_clk_system(hw);
43 struct at91_pmc *pmc = sys->pmc; 77 struct at91_pmc *pmc = sys->pmc;
@@ -45,27 +79,34 @@ static void clk_system_disable(struct clk_hw *hw)
45 pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id); 79 pmc_write(pmc, AT91_PMC_SCDR, 1 << sys->id);
46} 80}
47 81
48static int clk_system_is_enabled(struct clk_hw *hw) 82static int clk_system_is_prepared(struct clk_hw *hw)
49{ 83{
50 struct clk_system *sys = to_clk_system(hw); 84 struct clk_system *sys = to_clk_system(hw);
51 struct at91_pmc *pmc = sys->pmc; 85 struct at91_pmc *pmc = sys->pmc;
52 86
53 return !!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id)); 87 if (!(pmc_read(pmc, AT91_PMC_SCSR) & (1 << sys->id)))
88 return 0;
89
90 if (!is_pck(sys->id))
91 return 1;
92
93 return !!(pmc_read(pmc, AT91_PMC_SR) & (1 << sys->id));
54} 94}
55 95
56static const struct clk_ops system_ops = { 96static const struct clk_ops system_ops = {
57 .enable = clk_system_enable, 97 .prepare = clk_system_prepare,
58 .disable = clk_system_disable, 98 .unprepare = clk_system_unprepare,
59 .is_enabled = clk_system_is_enabled, 99 .is_prepared = clk_system_is_prepared,
60}; 100};
61 101
62static struct clk * __init 102static struct clk * __init
63at91_clk_register_system(struct at91_pmc *pmc, const char *name, 103at91_clk_register_system(struct at91_pmc *pmc, const char *name,
64 const char *parent_name, u8 id) 104 const char *parent_name, u8 id, int irq)
65{ 105{
66 struct clk_system *sys; 106 struct clk_system *sys;
67 struct clk *clk = NULL; 107 struct clk *clk = NULL;
68 struct clk_init_data init; 108 struct clk_init_data init;
109 int ret;
69 110
70 if (!parent_name || id > SYSTEM_MAX_ID) 111 if (!parent_name || id > SYSTEM_MAX_ID)
71 return ERR_PTR(-EINVAL); 112 return ERR_PTR(-EINVAL);
@@ -89,6 +130,15 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
89 sys->id = id; 130 sys->id = id;
90 sys->hw.init = &init; 131 sys->hw.init = &init;
91 sys->pmc = pmc; 132 sys->pmc = pmc;
133 sys->irq = irq;
134 if (irq) {
135 init_waitqueue_head(&sys->wait);
136 irq_set_status_flags(sys->irq, IRQ_NOAUTOEN);
137 ret = request_irq(sys->irq, clk_system_irq_handler,
138 IRQF_TRIGGER_HIGH, name, sys);
139 if (ret)
140 return ERR_PTR(ret);
141 }
92 142
93 clk = clk_register(NULL, &sys->hw); 143 clk = clk_register(NULL, &sys->hw);
94 if (IS_ERR(clk)) 144 if (IS_ERR(clk))
@@ -101,6 +151,7 @@ static void __init
101of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc) 151of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc)
102{ 152{
103 int num; 153 int num;
154 int irq = 0;
104 u32 id; 155 u32 id;
105 struct clk *clk; 156 struct clk *clk;
106 const char *name; 157 const char *name;
@@ -118,9 +169,12 @@ of_at91_clk_sys_setup(struct device_node *np, struct at91_pmc *pmc)
118 if (of_property_read_string(np, "clock-output-names", &name)) 169 if (of_property_read_string(np, "clock-output-names", &name))
119 name = sysclknp->name; 170 name = sysclknp->name;
120 171
172 if (is_pck(id))
173 irq = irq_of_parse_and_map(sysclknp, 0);
174
121 parent_name = of_clk_get_parent_name(sysclknp, 0); 175 parent_name = of_clk_get_parent_name(sysclknp, 0);
122 176
123 clk = at91_clk_register_system(pmc, name, parent_name, id); 177 clk = at91_clk_register_system(pmc, name, parent_name, id, irq);
124 if (IS_ERR(clk)) 178 if (IS_ERR(clk))
125 continue; 179 continue;
126 180