diff options
author | Nicolas Pitre <nicolas.pitre@linaro.org> | 2013-10-30 15:44:41 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2013-10-30 19:10:53 -0400 |
commit | 45cac118ffd7c9920b3d85bf551c2205674eb4f2 (patch) | |
tree | d18b9b0c1654bdf3892fdd367ff2235aad97f08d | |
parent | e79a23c5b9870b7f80425793abeb10e57f7486d4 (diff) |
cpufreq: arm_big_little: reconfigure switcher behavior at run time
The b.L switcher can be turned on/off at run time. It is therefore
necessary to change the cpufreq driver behavior accordingly.
The driver must be unregistered/registered with the cpufreq core
to reconfigure freq tables for the virtual or actual CPUs. This is
accomplished via the b.L switcher notifier callback.
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r-- | drivers/cpufreq/arm_big_little.c | 54 |
1 files changed, 51 insertions, 3 deletions
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 9986f7912328..71f1af93b585 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c | |||
@@ -40,9 +40,12 @@ | |||
40 | #define MAX_CLUSTERS 2 | 40 | #define MAX_CLUSTERS 2 |
41 | 41 | ||
42 | #ifdef CONFIG_BL_SWITCHER | 42 | #ifdef CONFIG_BL_SWITCHER |
43 | #define is_bL_switching_enabled() true | 43 | static bool bL_switching_enabled; |
44 | #define is_bL_switching_enabled() bL_switching_enabled | ||
45 | #define set_switching_enabled(x) (bL_switching_enabled = (x)) | ||
44 | #else | 46 | #else |
45 | #define is_bL_switching_enabled() false | 47 | #define is_bL_switching_enabled() false |
48 | #define set_switching_enabled(x) do { } while (0) | ||
46 | #endif | 49 | #endif |
47 | 50 | ||
48 | #define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq) | 51 | #define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq) |
@@ -508,6 +511,38 @@ static struct cpufreq_driver bL_cpufreq_driver = { | |||
508 | .attr = cpufreq_generic_attr, | 511 | .attr = cpufreq_generic_attr, |
509 | }; | 512 | }; |
510 | 513 | ||
514 | static int bL_cpufreq_switcher_notifier(struct notifier_block *nfb, | ||
515 | unsigned long action, void *_arg) | ||
516 | { | ||
517 | pr_debug("%s: action: %ld\n", __func__, action); | ||
518 | |||
519 | switch (action) { | ||
520 | case BL_NOTIFY_PRE_ENABLE: | ||
521 | case BL_NOTIFY_PRE_DISABLE: | ||
522 | cpufreq_unregister_driver(&bL_cpufreq_driver); | ||
523 | break; | ||
524 | |||
525 | case BL_NOTIFY_POST_ENABLE: | ||
526 | set_switching_enabled(true); | ||
527 | cpufreq_register_driver(&bL_cpufreq_driver); | ||
528 | break; | ||
529 | |||
530 | case BL_NOTIFY_POST_DISABLE: | ||
531 | set_switching_enabled(false); | ||
532 | cpufreq_register_driver(&bL_cpufreq_driver); | ||
533 | break; | ||
534 | |||
535 | default: | ||
536 | return NOTIFY_DONE; | ||
537 | } | ||
538 | |||
539 | return NOTIFY_OK; | ||
540 | } | ||
541 | |||
542 | static struct notifier_block bL_switcher_notifier = { | ||
543 | .notifier_call = bL_cpufreq_switcher_notifier, | ||
544 | }; | ||
545 | |||
511 | int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) | 546 | int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) |
512 | { | 547 | { |
513 | int ret, i; | 548 | int ret, i; |
@@ -525,6 +560,9 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) | |||
525 | 560 | ||
526 | arm_bL_ops = ops; | 561 | arm_bL_ops = ops; |
527 | 562 | ||
563 | ret = bL_switcher_get_enabled(); | ||
564 | set_switching_enabled(ret); | ||
565 | |||
528 | for (i = 0; i < MAX_CLUSTERS; i++) | 566 | for (i = 0; i < MAX_CLUSTERS; i++) |
529 | mutex_init(&cluster_lock[i]); | 567 | mutex_init(&cluster_lock[i]); |
530 | 568 | ||
@@ -534,10 +572,17 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) | |||
534 | __func__, ops->name, ret); | 572 | __func__, ops->name, ret); |
535 | arm_bL_ops = NULL; | 573 | arm_bL_ops = NULL; |
536 | } else { | 574 | } else { |
537 | pr_info("%s: Registered platform driver: %s\n", __func__, | 575 | ret = bL_switcher_register_notifier(&bL_switcher_notifier); |
538 | ops->name); | 576 | if (ret) { |
577 | cpufreq_unregister_driver(&bL_cpufreq_driver); | ||
578 | arm_bL_ops = NULL; | ||
579 | } else { | ||
580 | pr_info("%s: Registered platform driver: %s\n", | ||
581 | __func__, ops->name); | ||
582 | } | ||
539 | } | 583 | } |
540 | 584 | ||
585 | bL_switcher_put_enabled(); | ||
541 | return ret; | 586 | return ret; |
542 | } | 587 | } |
543 | EXPORT_SYMBOL_GPL(bL_cpufreq_register); | 588 | EXPORT_SYMBOL_GPL(bL_cpufreq_register); |
@@ -550,7 +595,10 @@ void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops) | |||
550 | return; | 595 | return; |
551 | } | 596 | } |
552 | 597 | ||
598 | bL_switcher_get_enabled(); | ||
599 | bL_switcher_unregister_notifier(&bL_switcher_notifier); | ||
553 | cpufreq_unregister_driver(&bL_cpufreq_driver); | 600 | cpufreq_unregister_driver(&bL_cpufreq_driver); |
601 | bL_switcher_put_enabled(); | ||
554 | pr_info("%s: Un-registered platform driver: %s\n", __func__, | 602 | pr_info("%s: Un-registered platform driver: %s\n", __func__, |
555 | arm_bL_ops->name); | 603 | arm_bL_ops->name); |
556 | arm_bL_ops = NULL; | 604 | arm_bL_ops = NULL; |