aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Brunet <jbrunet@baylibre.com>2018-07-09 07:47:38 -0400
committerJerome Brunet <jbrunet@baylibre.com>2018-07-09 07:47:38 -0400
commit2eb2a01b6477ac50ec686f4b0a74f2c3b6a55fe4 (patch)
tree2a33a23c318afc5e5e2b534741b365b2a6780705
parente8dd9207763e0317ac256c78dcd50dca7826f2f6 (diff)
parent9fba738a53dda20e748d6ee240b6c017c8146b4b (diff)
Merge remote-tracking branch 'clk/clk-core-duty-cycle' into next/drivers
-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 */