aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Brunet <jbrunet@baylibre.com>2018-06-19 10:41:41 -0400
committerMichael Turquette <mturquette@baylibre.com>2018-06-19 13:06:29 -0400
commit9fba738a53dda20e748d6ee240b6c017c8146b4b (patch)
tree5f5844246fa0ae69bfb5ae6f532207fc344f4ecc
parentce397d215ccd07b8ae3f71db689aedb85d56ab40 (diff)
clk: add duty cycle support
Add the possibility to apply and query the clock signal duty cycle ratio. This is useful when the duty cycle of the clock signal depends on some other parameters controlled by the clock framework. For example, the duty cycle of a divider may depends on the raw divider setting (ratio = N / div) , which is controlled by the CCF. In such case, going through the pwm framework to control the duty cycle ratio of this clock would be a burden. A clock provider is not required to implement the operation to set and get the duty cycle. If it does not implement .get_duty_cycle(), the ratio is assumed to be 50%. This change also adds a new flag, CLK_DUTY_CYCLE_PARENT. This flag should be used to indicate that a clock, such as gates and muxes, may inherit the duty cycle ratio of its parent clock. If a clock does not provide a get_duty_cycle() callback and has CLK_DUTY_CYCLE_PARENT, then the call will be directly forwarded to its parent clock, if any. For set_duty_cycle(), the clock should also have CLK_SET_RATE_PARENT for the call to be forwarded Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Signed-off-by: Michael Turquette <mturquette@baylibre.com> Link: lkml.kernel.org/r/20180619144141.8506-1-jbrunet@baylibre.com
-rw-r--r--drivers/clk/clk.c199
-rw-r--r--include/linux/clk-provider.h26
-rw-r--r--include/linux/clk.h33
-rw-r--r--include/trace/events/clk.h36
4 files changed, 289 insertions, 5 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 9760b526ca31..b0a2719d86f3 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -68,6 +68,7 @@ struct clk_core {
68 unsigned long max_rate; 68 unsigned long max_rate;
69 unsigned long accuracy; 69 unsigned long accuracy;
70 int phase; 70 int phase;
71 struct clk_duty duty;
71 struct hlist_head children; 72 struct hlist_head children;
72 struct hlist_node child_node; 73 struct hlist_node child_node;
73 struct hlist_head clks; 74 struct hlist_head clks;
@@ -2402,6 +2403,172 @@ int clk_get_phase(struct clk *clk)
2402} 2403}
2403EXPORT_SYMBOL_GPL(clk_get_phase); 2404EXPORT_SYMBOL_GPL(clk_get_phase);
2404 2405
2406static void clk_core_reset_duty_cycle_nolock(struct clk_core *core)
2407{
2408 /* Assume a default value of 50% */
2409 core->duty.num = 1;
2410 core->duty.den = 2;
2411}
2412
2413static int clk_core_update_duty_cycle_parent_nolock(struct clk_core *core);
2414
2415static int clk_core_update_duty_cycle_nolock(struct clk_core *core)
2416{
2417 struct clk_duty *duty = &core->duty;
2418 int ret = 0;
2419
2420 if (!core->ops->get_duty_cycle)
2421 return clk_core_update_duty_cycle_parent_nolock(core);
2422
2423 ret = core->ops->get_duty_cycle(core->hw, duty);
2424 if (ret)
2425 goto reset;
2426
2427 /* Don't trust the clock provider too much */
2428 if (duty->den == 0 || duty->num > duty->den) {
2429 ret = -EINVAL;
2430 goto reset;
2431 }
2432
2433 return 0;
2434
2435reset:
2436 clk_core_reset_duty_cycle_nolock(core);
2437 return ret;
2438}
2439
2440static int clk_core_update_duty_cycle_parent_nolock(struct clk_core *core)
2441{
2442 int ret = 0;
2443
2444 if (core->parent &&
2445 core->flags & CLK_DUTY_CYCLE_PARENT) {
2446 ret = clk_core_update_duty_cycle_nolock(core->parent);
2447 memcpy(&core->duty, &core->parent->duty, sizeof(core->duty));
2448 } else {
2449 clk_core_reset_duty_cycle_nolock(core);
2450 }
2451
2452 return ret;
2453}
2454
2455static int clk_core_set_duty_cycle_parent_nolock(struct clk_core *core,
2456 struct clk_duty *duty);
2457
2458static int clk_core_set_duty_cycle_nolock(struct clk_core *core,
2459 struct clk_duty *duty)
2460{
2461 int ret;
2462
2463 lockdep_assert_held(&prepare_lock);
2464
2465 if (clk_core_rate_is_protected(core))
2466 return -EBUSY;
2467
2468 trace_clk_set_duty_cycle(core, duty);
2469
2470 if (!core->ops->set_duty_cycle)
2471 return clk_core_set_duty_cycle_parent_nolock(core, duty);
2472
2473 ret = core->ops->set_duty_cycle(core->hw, duty);
2474 if (!ret)
2475 memcpy(&core->duty, duty, sizeof(*duty));
2476
2477 trace_clk_set_duty_cycle_complete(core, duty);
2478
2479 return ret;
2480}
2481
2482static int clk_core_set_duty_cycle_parent_nolock(struct clk_core *core,
2483 struct clk_duty *duty)
2484{
2485 int ret = 0;
2486
2487 if (core->parent &&
2488 core->flags & (CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT)) {
2489 ret = clk_core_set_duty_cycle_nolock(core->parent, duty);
2490 memcpy(&core->duty, &core->parent->duty, sizeof(core->duty));
2491 }
2492
2493 return ret;
2494}
2495
2496/**
2497 * clk_set_duty_cycle - adjust the duty cycle ratio of a clock signal
2498 * @clk: clock signal source
2499 * @num: numerator of the duty cycle ratio to be applied
2500 * @den: denominator of the duty cycle ratio to be applied
2501 *
2502 * Apply the duty cycle ratio if the ratio is valid and the clock can
2503 * perform this operation
2504 *
2505 * Returns (0) on success, a negative errno otherwise.
2506 */
2507int clk_set_duty_cycle(struct clk *clk, unsigned int num, unsigned int den)
2508{
2509 int ret;
2510 struct clk_duty duty;
2511
2512 if (!clk)
2513 return 0;
2514
2515 /* sanity check the ratio */
2516 if (den == 0 || num > den)
2517 return -EINVAL;
2518
2519 duty.num = num;
2520 duty.den = den;
2521
2522 clk_prepare_lock();
2523
2524 if (clk->exclusive_count)
2525 clk_core_rate_unprotect(clk->core);
2526
2527 ret = clk_core_set_duty_cycle_nolock(clk->core, &duty);
2528
2529 if (clk->exclusive_count)
2530 clk_core_rate_protect(clk->core);
2531
2532 clk_prepare_unlock();
2533
2534 return ret;
2535}
2536EXPORT_SYMBOL_GPL(clk_set_duty_cycle);
2537
2538static int clk_core_get_scaled_duty_cycle(struct clk_core *core,
2539 unsigned int scale)
2540{
2541 struct clk_duty *duty = &core->duty;
2542 int ret;
2543
2544 clk_prepare_lock();
2545
2546 ret = clk_core_update_duty_cycle_nolock(core);
2547 if (!ret)
2548 ret = mult_frac(scale, duty->num, duty->den);
2549
2550 clk_prepare_unlock();
2551
2552 return ret;
2553}
2554
2555/**
2556 * clk_get_scaled_duty_cycle - return the duty cycle ratio of a clock signal
2557 * @clk: clock signal source
2558 * @scale: scaling factor to be applied to represent the ratio as an integer
2559 *
2560 * Returns the duty cycle ratio of a clock node multiplied by the provided
2561 * scaling factor, or negative errno on error.
2562 */
2563int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale)
2564{
2565 if (!clk)
2566 return 0;
2567
2568 return clk_core_get_scaled_duty_cycle(clk->core, scale);
2569}
2570EXPORT_SYMBOL_GPL(clk_get_scaled_duty_cycle);
2571
2405/** 2572/**
2406 * clk_is_match - check if two clk's point to the same hardware clock 2573 * clk_is_match - check if two clk's point to the same hardware clock
2407 * @p: clk compared against q 2574 * @p: clk compared against q
@@ -2455,12 +2622,13 @@ static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
2455 if (!c) 2622 if (!c)
2456 return; 2623 return;
2457 2624
2458 seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %-3d\n", 2625 seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n",
2459 level * 3 + 1, "", 2626 level * 3 + 1, "",
2460 30 - level * 3, c->name, 2627 30 - level * 3, c->name,
2461 c->enable_count, c->prepare_count, c->protect_count, 2628 c->enable_count, c->prepare_count, c->protect_count,
2462 clk_core_get_rate(c), clk_core_get_accuracy(c), 2629 clk_core_get_rate(c), clk_core_get_accuracy(c),
2463 clk_core_get_phase(c)); 2630 clk_core_get_phase(c),
2631 clk_core_get_scaled_duty_cycle(c, 100000));
2464} 2632}
2465 2633
2466static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c, 2634static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
@@ -2482,9 +2650,9 @@ static int clk_summary_show(struct seq_file *s, void *data)
2482 struct clk_core *c; 2650 struct clk_core *c;
2483 struct hlist_head **lists = (struct hlist_head **)s->private; 2651 struct hlist_head **lists = (struct hlist_head **)s->private;
2484 2652
2485 seq_puts(s, " enable prepare protect \n"); 2653 seq_puts(s, " enable prepare protect duty\n");
2486 seq_puts(s, " clock count count count rate accuracy phase\n"); 2654 seq_puts(s, " clock count count count rate accuracy phase cycle\n");
2487 seq_puts(s, "----------------------------------------------------------------------------------------\n"); 2655 seq_puts(s, "---------------------------------------------------------------------------------------------\n");
2488 2656
2489 clk_prepare_lock(); 2657 clk_prepare_lock();
2490 2658
@@ -2511,6 +2679,8 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
2511 seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c)); 2679 seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
2512 seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c)); 2680 seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
2513 seq_printf(s, "\"phase\": %d", clk_core_get_phase(c)); 2681 seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
2682 seq_printf(s, "\"duty_cycle\": %u",
2683 clk_core_get_scaled_duty_cycle(c, 100000));
2514} 2684}
2515 2685
2516static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level) 2686static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
@@ -2572,6 +2742,7 @@ static const struct {
2572 ENTRY(CLK_SET_RATE_UNGATE), 2742 ENTRY(CLK_SET_RATE_UNGATE),
2573 ENTRY(CLK_IS_CRITICAL), 2743 ENTRY(CLK_IS_CRITICAL),
2574 ENTRY(CLK_OPS_PARENT_ENABLE), 2744 ENTRY(CLK_OPS_PARENT_ENABLE),
2745 ENTRY(CLK_DUTY_CYCLE_PARENT),
2575#undef ENTRY 2746#undef ENTRY
2576}; 2747};
2577 2748
@@ -2610,6 +2781,17 @@ static int possible_parents_show(struct seq_file *s, void *data)
2610} 2781}
2611DEFINE_SHOW_ATTRIBUTE(possible_parents); 2782DEFINE_SHOW_ATTRIBUTE(possible_parents);
2612 2783
2784static int clk_duty_cycle_show(struct seq_file *s, void *data)
2785{
2786 struct clk_core *core = s->private;
2787 struct clk_duty *duty = &core->duty;
2788
2789 seq_printf(s, "%u/%u\n", duty->num, duty->den);
2790
2791 return 0;
2792}
2793DEFINE_SHOW_ATTRIBUTE(clk_duty_cycle);
2794
2613static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) 2795static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
2614{ 2796{
2615 struct dentry *root; 2797 struct dentry *root;
@@ -2628,6 +2810,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
2628 debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count); 2810 debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count);
2629 debugfs_create_u32("clk_protect_count", 0444, root, &core->protect_count); 2811 debugfs_create_u32("clk_protect_count", 0444, root, &core->protect_count);
2630 debugfs_create_u32("clk_notifier_count", 0444, root, &core->notifier_count); 2812 debugfs_create_u32("clk_notifier_count", 0444, root, &core->notifier_count);
2813 debugfs_create_file("clk_duty_cycle", 0444, root, core,
2814 &clk_duty_cycle_fops);
2631 2815
2632 if (core->num_parents > 1) 2816 if (core->num_parents > 1)
2633 debugfs_create_file("clk_possible_parents", 0444, root, core, 2817 debugfs_create_file("clk_possible_parents", 0444, root, core,
@@ -2846,6 +3030,11 @@ static int __clk_core_init(struct clk_core *core)
2846 core->phase = 0; 3030 core->phase = 0;
2847 3031
2848 /* 3032 /*
3033 * Set clk's duty cycle.
3034 */
3035 clk_core_update_duty_cycle_nolock(core);
3036
3037 /*
2849 * Set clk's rate. The preferred method is to use .recalc_rate. For 3038 * Set clk's rate. The preferred method is to use .recalc_rate. For
2850 * simple clocks and lazy developers the default fallback is to use the 3039 * simple clocks and lazy developers the default fallback is to use the
2851 * parent's rate. If a clock doesn't have a parent (or is orphaned) 3040 * parent's rate. If a clock doesn't have a parent (or is orphaned)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index b7cfa037e593..08b1aa70a38d 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -38,6 +38,8 @@
38#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ 38#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */
39/* parents need enable during gate/ungate, set rate and re-parent */ 39/* parents need enable during gate/ungate, set rate and re-parent */
40#define CLK_OPS_PARENT_ENABLE BIT(12) 40#define CLK_OPS_PARENT_ENABLE BIT(12)
41/* duty cycle call may be forwarded to the parent clock */
42#define CLK_DUTY_CYCLE_PARENT BIT(13)
41 43
42struct clk; 44struct clk;
43struct clk_hw; 45struct clk_hw;
@@ -67,6 +69,17 @@ struct clk_rate_request {
67}; 69};
68 70
69/** 71/**
72 * struct clk_duty - Struture encoding the duty cycle ratio of a clock
73 *
74 * @num: Numerator of the duty cycle ratio
75 * @den: Denominator of the duty cycle ratio
76 */
77struct clk_duty {
78 unsigned int num;
79 unsigned int den;
80};
81
82/**
70 * struct clk_ops - Callback operations for hardware clocks; these are to 83 * struct clk_ops - Callback operations for hardware clocks; these are to
71 * be provided by the clock implementation, and will be called by drivers 84 * be provided by the clock implementation, and will be called by drivers
72 * through the clk_* api. 85 * through the clk_* api.
@@ -169,6 +182,15 @@ struct clk_rate_request {
169 * by the second argument. Valid values for degrees are 182 * by the second argument. Valid values for degrees are
170 * 0-359. Return 0 on success, otherwise -EERROR. 183 * 0-359. Return 0 on success, otherwise -EERROR.
171 * 184 *
185 * @get_duty_cycle: Queries the hardware to get the current duty cycle ratio
186 * of a clock. Returned values denominator cannot be 0 and must be
187 * superior or equal to the numerator.
188 *
189 * @set_duty_cycle: Apply the duty cycle ratio to this clock signal specified by
190 * the numerator (2nd argurment) and denominator (3rd argument).
191 * Argument must be a valid ratio (denominator > 0
192 * and >= numerator) Return 0 on success, otherwise -EERROR.
193 *
172 * @init: Perform platform-specific initialization magic. 194 * @init: Perform platform-specific initialization magic.
173 * This is not not used by any of the basic clock types. 195 * This is not not used by any of the basic clock types.
174 * Please consider other ways of solving initialization problems 196 * Please consider other ways of solving initialization problems
@@ -218,6 +240,10 @@ struct clk_ops {
218 unsigned long parent_accuracy); 240 unsigned long parent_accuracy);
219 int (*get_phase)(struct clk_hw *hw); 241 int (*get_phase)(struct clk_hw *hw);
220 int (*set_phase)(struct clk_hw *hw, int degrees); 242 int (*set_phase)(struct clk_hw *hw, int degrees);
243 int (*get_duty_cycle)(struct clk_hw *hw,
244 struct clk_duty *duty);
245 int (*set_duty_cycle)(struct clk_hw *hw,
246 struct clk_duty *duty);
221 void (*init)(struct clk_hw *hw); 247 void (*init)(struct clk_hw *hw);
222 void (*debug_init)(struct clk_hw *hw, struct dentry *dentry); 248 void (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
223}; 249};
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 0dbd0885b2c2..4f750c481b82 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -142,6 +142,27 @@ int clk_set_phase(struct clk *clk, int degrees);
142int clk_get_phase(struct clk *clk); 142int clk_get_phase(struct clk *clk);
143 143
144/** 144/**
145 * clk_set_duty_cycle - adjust the duty cycle ratio of a clock signal
146 * @clk: clock signal source
147 * @num: numerator of the duty cycle ratio to be applied
148 * @den: denominator of the duty cycle ratio to be applied
149 *
150 * Adjust the duty cycle of a clock signal by the specified ratio. Returns 0 on
151 * success, -EERROR otherwise.
152 */
153int clk_set_duty_cycle(struct clk *clk, unsigned int num, unsigned int den);
154
155/**
156 * clk_get_duty_cycle - return the duty cycle ratio of a clock signal
157 * @clk: clock signal source
158 * @scale: scaling factor to be applied to represent the ratio as an integer
159 *
160 * Returns the duty cycle ratio multiplied by the scale provided, otherwise
161 * returns -EERROR.
162 */
163int clk_get_scaled_duty_cycle(struct clk *clk, unsigned int scale);
164
165/**
145 * clk_is_match - check if two clk's point to the same hardware clock 166 * clk_is_match - check if two clk's point to the same hardware clock
146 * @p: clk compared against q 167 * @p: clk compared against q
147 * @q: clk compared against p 168 * @q: clk compared against p
@@ -183,6 +204,18 @@ static inline long clk_get_phase(struct clk *clk)
183 return -ENOTSUPP; 204 return -ENOTSUPP;
184} 205}
185 206
207static inline int clk_set_duty_cycle(struct clk *clk, unsigned int num,
208 unsigned int den)
209{
210 return -ENOTSUPP;
211}
212
213static inline unsigned int clk_get_scaled_duty_cycle(struct clk *clk,
214 unsigned int scale)
215{
216 return 0;
217}
218
186static inline bool clk_is_match(const struct clk *p, const struct clk *q) 219static inline bool clk_is_match(const struct clk *p, const struct clk *q)
187{ 220{
188 return p == q; 221 return p == q;
diff --git a/include/trace/events/clk.h b/include/trace/events/clk.h
index 2cd449328aee..9004ffff7f32 100644
--- a/include/trace/events/clk.h
+++ b/include/trace/events/clk.h
@@ -192,6 +192,42 @@ DEFINE_EVENT(clk_phase, clk_set_phase_complete,
192 TP_ARGS(core, phase) 192 TP_ARGS(core, phase)
193); 193);
194 194
195DECLARE_EVENT_CLASS(clk_duty_cycle,
196
197 TP_PROTO(struct clk_core *core, struct clk_duty *duty),
198
199 TP_ARGS(core, duty),
200
201 TP_STRUCT__entry(
202 __string( name, core->name )
203 __field( unsigned int, num )
204 __field( unsigned int, den )
205 ),
206
207 TP_fast_assign(
208 __assign_str(name, core->name);
209 __entry->num = duty->num;
210 __entry->den = duty->den;
211 ),
212
213 TP_printk("%s %u/%u", __get_str(name), (unsigned int)__entry->num,
214 (unsigned int)__entry->den)
215);
216
217DEFINE_EVENT(clk_duty_cycle, clk_set_duty_cycle,
218
219 TP_PROTO(struct clk_core *core, struct clk_duty *duty),
220
221 TP_ARGS(core, duty)
222);
223
224DEFINE_EVENT(clk_duty_cycle, clk_set_duty_cycle_complete,
225
226 TP_PROTO(struct clk_core *core, struct clk_duty *duty),
227
228 TP_ARGS(core, duty)
229);
230
195#endif /* _TRACE_CLK_H */ 231#endif /* _TRACE_CLK_H */
196 232
197/* This part must be outside protection */ 233/* This part must be outside protection */