aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Elder <elder@linaro.org>2014-04-21 17:11:43 -0400
committerMike Turquette <mturquette@linaro.org>2014-04-30 14:51:38 -0400
commitdc613840a625bfad38141d2d8bbdb0c7bc3d45eb (patch)
tree9cc26fa89833eee39df05a074cbcf8eb414d023d
parenta597faccc7eedd406313e880ed05ff75bc522910 (diff)
clk: bcm281xx: add clock hysteresis support
Add support for clock gate hysteresis control. For now, if it's defined for a clock, it's enabled. Signed-off-by: Alex Elder <elder@linaro.org> Signed-off-by: Mike Turquette <mturquette@linaro.org>
-rw-r--r--drivers/clk/bcm/clk-kona-setup.c30
-rw-r--r--drivers/clk/bcm/clk-kona.c33
-rw-r--r--drivers/clk/bcm/clk-kona.h19
3 files changed, 82 insertions, 0 deletions
diff --git a/drivers/clk/bcm/clk-kona-setup.c b/drivers/clk/bcm/clk-kona-setup.c
index 773ad7c7dd59..e5aededdd322 100644
--- a/drivers/clk/bcm/clk-kona-setup.c
+++ b/drivers/clk/bcm/clk-kona-setup.c
@@ -81,6 +81,7 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
81 struct peri_clk_data *peri; 81 struct peri_clk_data *peri;
82 struct bcm_clk_policy *policy; 82 struct bcm_clk_policy *policy;
83 struct bcm_clk_gate *gate; 83 struct bcm_clk_gate *gate;
84 struct bcm_clk_hyst *hyst;
84 struct bcm_clk_div *div; 85 struct bcm_clk_div *div;
85 struct bcm_clk_sel *sel; 86 struct bcm_clk_sel *sel;
86 struct bcm_clk_trig *trig; 87 struct bcm_clk_trig *trig;
@@ -106,12 +107,25 @@ static bool peri_clk_data_offsets_valid(struct kona_clk *bcm_clk)
106 } 107 }
107 108
108 gate = &peri->gate; 109 gate = &peri->gate;
110 hyst = &peri->hyst;
109 if (gate_exists(gate)) { 111 if (gate_exists(gate)) {
110 if (gate->offset > limit) { 112 if (gate->offset > limit) {
111 pr_err("%s: bad gate offset for %s (%u > %u)\n", 113 pr_err("%s: bad gate offset for %s (%u > %u)\n",
112 __func__, name, gate->offset, limit); 114 __func__, name, gate->offset, limit);
113 return false; 115 return false;
114 } 116 }
117
118 if (hyst_exists(hyst)) {
119 if (hyst->offset > limit) {
120 pr_err("%s: bad hysteresis offset for %s "
121 "(%u > %u)\n", __func__,
122 name, hyst->offset, limit);
123 return false;
124 }
125 }
126 } else if (hyst_exists(hyst)) {
127 pr_err("%s: hysteresis but no gate for %s\n", __func__, name);
128 return false;
115 } 129 }
116 130
117 div = &peri->div; 131 div = &peri->div;
@@ -261,6 +275,17 @@ static bool gate_valid(struct bcm_clk_gate *gate, const char *field_name,
261 return true; 275 return true;
262} 276}
263 277
278static bool hyst_valid(struct bcm_clk_hyst *hyst, const char *clock_name)
279{
280 if (!bit_posn_valid(hyst->en_bit, "hysteresis enable", clock_name))
281 return false;
282
283 if (!bit_posn_valid(hyst->val_bit, "hysteresis value", clock_name))
284 return false;
285
286 return true;
287}
288
264/* 289/*
265 * A selector bitfield must be valid. Its parent_sel array must 290 * A selector bitfield must be valid. Its parent_sel array must
266 * also be reasonable for the field. 291 * also be reasonable for the field.
@@ -379,6 +404,7 @@ peri_clk_data_valid(struct kona_clk *bcm_clk)
379 struct peri_clk_data *peri; 404 struct peri_clk_data *peri;
380 struct bcm_clk_policy *policy; 405 struct bcm_clk_policy *policy;
381 struct bcm_clk_gate *gate; 406 struct bcm_clk_gate *gate;
407 struct bcm_clk_hyst *hyst;
382 struct bcm_clk_sel *sel; 408 struct bcm_clk_sel *sel;
383 struct bcm_clk_div *div; 409 struct bcm_clk_div *div;
384 struct bcm_clk_div *pre_div; 410 struct bcm_clk_div *pre_div;
@@ -406,6 +432,10 @@ peri_clk_data_valid(struct kona_clk *bcm_clk)
406 if (gate_exists(gate) && !gate_valid(gate, "gate", name)) 432 if (gate_exists(gate) && !gate_valid(gate, "gate", name))
407 return false; 433 return false;
408 434
435 hyst = &peri->hyst;
436 if (hyst_exists(hyst) && !hyst_valid(hyst, name))
437 return false;
438
409 sel = &peri->sel; 439 sel = &peri->sel;
410 if (selector_exists(sel)) { 440 if (selector_exists(sel)) {
411 if (!sel_valid(sel, "selector", name)) 441 if (!sel_valid(sel, "selector", name))
diff --git a/drivers/clk/bcm/clk-kona.c b/drivers/clk/bcm/clk-kona.c
index 7d90c34d1336..d603c4e22fca 100644
--- a/drivers/clk/bcm/clk-kona.c
+++ b/drivers/clk/bcm/clk-kona.c
@@ -527,6 +527,35 @@ static int clk_gate(struct ccu_data *ccu, const char *name,
527 return -EIO; 527 return -EIO;
528} 528}
529 529
530/* Hysteresis operations */
531
532/*
533 * If a clock gate requires a turn-off delay it will have
534 * "hysteresis" register bits defined. The first, if set, enables
535 * the delay; and if enabled, the second bit determines whether the
536 * delay is "low" or "high" (1 means high). For now, if it's
537 * defined for a clock, we set it.
538 */
539static bool hyst_init(struct ccu_data *ccu, struct bcm_clk_hyst *hyst)
540{
541 u32 offset;
542 u32 reg_val;
543 u32 mask;
544
545 if (!hyst_exists(hyst))
546 return true;
547
548 offset = hyst->offset;
549 mask = (u32)1 << hyst->en_bit;
550 mask |= (u32)1 << hyst->val_bit;
551
552 reg_val = __ccu_read(ccu, offset);
553 reg_val |= mask;
554 __ccu_write(ccu, offset, reg_val);
555
556 return true;
557}
558
530/* Trigger operations */ 559/* Trigger operations */
531 560
532/* 561/*
@@ -1131,6 +1160,10 @@ static bool __peri_clk_init(struct kona_clk *bcm_clk)
1131 pr_err("%s: error initializing gate for %s\n", __func__, name); 1160 pr_err("%s: error initializing gate for %s\n", __func__, name);
1132 return false; 1161 return false;
1133 } 1162 }
1163 if (!hyst_init(ccu, &peri->hyst)) {
1164 pr_err("%s: error initializing hyst for %s\n", __func__, name);
1165 return false;
1166 }
1134 if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) { 1167 if (!div_init(ccu, &peri->gate, &peri->div, &peri->trig)) {
1135 pr_err("%s: error initializing divider for %s\n", __func__, 1168 pr_err("%s: error initializing divider for %s\n", __func__,
1136 name); 1169 name);
diff --git a/drivers/clk/bcm/clk-kona.h b/drivers/clk/bcm/clk-kona.h
index 4bcba1331561..2537b3072910 100644
--- a/drivers/clk/bcm/clk-kona.h
+++ b/drivers/clk/bcm/clk-kona.h
@@ -60,6 +60,8 @@
60 60
61#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED) 61#define gate_flip_enabled(gate) FLAG_FLIP(gate, GATE, ENABLED)
62 62
63#define hyst_exists(hyst) ((hyst)->offset != 0)
64
63#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS) 65#define divider_exists(div) FLAG_TEST(div, DIV, EXISTS)
64#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED) 66#define divider_is_fixed(div) FLAG_TEST(div, DIV, FIXED)
65#define divider_has_fraction(div) (!divider_is_fixed(div) && \ 67#define divider_has_fraction(div) (!divider_is_fixed(div) && \
@@ -205,6 +207,22 @@ struct bcm_clk_gate {
205 .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \ 207 .flags = FLAG(GATE, HW)|FLAG(GATE, EXISTS), \
206 } 208 }
207 209
210/* Gate hysteresis for clocks */
211struct bcm_clk_hyst {
212 u32 offset; /* hyst register offset (normally CLKGATE) */
213 u32 en_bit; /* bit used to enable hysteresis */
214 u32 val_bit; /* if enabled: 0 = low delay; 1 = high delay */
215};
216
217/* Hysteresis initialization macro */
218
219#define HYST(_offset, _en_bit, _val_bit) \
220 { \
221 .offset = (_offset), \
222 .en_bit = (_en_bit), \
223 .val_bit = (_val_bit), \
224 }
225
208/* 226/*
209 * Each clock can have zero, one, or two dividers which change the 227 * Each clock can have zero, one, or two dividers which change the
210 * output rate of the clock. Each divider can be either fixed or 228 * output rate of the clock. Each divider can be either fixed or
@@ -372,6 +390,7 @@ struct bcm_clk_trig {
372struct peri_clk_data { 390struct peri_clk_data {
373 struct bcm_clk_policy policy; 391 struct bcm_clk_policy policy;
374 struct bcm_clk_gate gate; 392 struct bcm_clk_gate gate;
393 struct bcm_clk_hyst hyst;
375 struct bcm_clk_trig pre_trig; 394 struct bcm_clk_trig pre_trig;
376 struct bcm_clk_div pre_div; 395 struct bcm_clk_div pre_div;
377 struct bcm_clk_trig trig; 396 struct bcm_clk_trig trig;