diff options
author | Krishna Sitaraman <ksitaraman@nvidia.com> | 2016-02-08 20:21:33 -0500 |
---|---|---|
committer | Krishna Sitaraman <ksitaraman@nvidia.com> | 2016-02-24 14:26:05 -0500 |
commit | 2e29dd4687e6b0bae2f3e8d428c32c25d5dac7ee (patch) | |
tree | 1eba4559749e87f697583228d98e5fef29bb9eff /drivers/cpuidle | |
parent | 116e0682ec38a5c2ec53c9750bf6dc4b47250105 (diff) |
t18x: cpuidle: Move xover init to platform init
Bug 200166800
Crossover threshold programming was part of early init
separated from rest of the cpuidle init. Moving it be part
of the platform init with rest of cpuidle initialization.
Change-Id: I52873e8f842d5938b38753877b61c526ad778484
Signed-off-by: Krishna Sitaraman <ksitaraman@nvidia.com>
Reviewed-on: http://git-master/r/1009750
GVS: Gerrit_Virtual_Submit
Reviewed-by: Alexander Van Brunt <avanbrunt@nvidia.com>
Diffstat (limited to 'drivers/cpuidle')
-rw-r--r-- | drivers/cpuidle/cpuidle-tegra18x.c | 155 |
1 files changed, 68 insertions, 87 deletions
diff --git a/drivers/cpuidle/cpuidle-tegra18x.c b/drivers/cpuidle/cpuidle-tegra18x.c index df82cb141..fe7beb88b 100644 --- a/drivers/cpuidle/cpuidle-tegra18x.c +++ b/drivers/cpuidle/cpuidle-tegra18x.c | |||
@@ -471,6 +471,72 @@ static void cluster_state_init(void *data) | |||
471 | } | 471 | } |
472 | } | 472 | } |
473 | 473 | ||
474 | struct xover_table { | ||
475 | char *name; | ||
476 | int index; | ||
477 | }; | ||
478 | |||
479 | static void send_crossover(void *data) | ||
480 | { | ||
481 | struct device_node *child; | ||
482 | struct device_node *of_states = (struct device_node *)data; | ||
483 | u32 value; | ||
484 | int i; | ||
485 | |||
486 | struct xover_table table1[] = { | ||
487 | {"crossover_c1_c6", TEGRA_MCE_XOVER_C1_C6}, | ||
488 | {"crossover_cc1_cc6", TEGRA_MCE_XOVER_CC1_CC6}, | ||
489 | {"crossover_cc1_cc7", TEGRA_MCE_XOVER_CC1_CC7}, | ||
490 | {"crossover_ccp1_ccp3", TEGRA_MCE_XOVER_CCP1_CCP3}, | ||
491 | {"crossover_ccp3_sc2", TEGRA_MCE_XOVER_CCP3_SC2}, | ||
492 | {"crossover_ccp3_sc3", TEGRA_MCE_XOVER_CCP3_SC3}, | ||
493 | {"crossover_ccp3_sc4", TEGRA_MCE_XOVER_CCP3_SC4}, | ||
494 | {"crossover_ccp3_sc7", TEGRA_MCE_XOVER_CCP3_SC7}, | ||
495 | }; | ||
496 | |||
497 | for_each_child_of_node(of_states, child) | ||
498 | for (i = 0; i < TEGRA_MCE_XOVER_MAX; i++) { | ||
499 | if (of_property_read_u32(child, | ||
500 | table1[i].name, &value) == 0) | ||
501 | tegra_mce_update_crossover_time | ||
502 | (table1[i].index, value); | ||
503 | } | ||
504 | } | ||
505 | |||
506 | static int crossover_init(struct cpumask *denver_cpumask, | ||
507 | struct cpumask *a57_cpumask) | ||
508 | { | ||
509 | struct device_node *denver_xover; | ||
510 | struct device_node *a57_xover; | ||
511 | |||
512 | if (!check_mce_version()) { | ||
513 | pr_err("WARNING: cpuidle: skipping crossover programming." | ||
514 | " Incompatible MCE version.\n"); | ||
515 | return -ENODEV; | ||
516 | } | ||
517 | |||
518 | denver_xover = of_find_node_by_name(NULL, | ||
519 | "denver_crossover_thresholds"); | ||
520 | a57_xover = of_find_node_by_name(NULL, "a57_crossover_thresholds"); | ||
521 | |||
522 | pr_debug("cpuidle: Init Power Crossover thresholds.\n"); | ||
523 | if (!a57_xover) | ||
524 | pr_err("WARNING: cpuidle: %s: DT entry missing for A57" | ||
525 | " thresholds\n", __func__); | ||
526 | else | ||
527 | smp_call_function_any(a57_cpumask, send_crossover, | ||
528 | a57_xover, 1); | ||
529 | |||
530 | if (!denver_xover) | ||
531 | pr_err("WARNING: cpuidle: %s: DT entry missing for Denver" | ||
532 | " thresholds\n", __func__); | ||
533 | else | ||
534 | smp_call_function_any(denver_cpumask, send_crossover, | ||
535 | denver_xover, 1); | ||
536 | |||
537 | return 0; | ||
538 | } | ||
539 | |||
474 | static int tegra18x_cpuidle_probe(struct platform_device *pdev) | 540 | static int tegra18x_cpuidle_probe(struct platform_device *pdev) |
475 | { | 541 | { |
476 | int cpu_number; | 542 | int cpu_number; |
@@ -504,6 +570,8 @@ static int tegra18x_cpuidle_probe(struct platform_device *pdev) | |||
504 | } | 570 | } |
505 | } | 571 | } |
506 | 572 | ||
573 | crossover_init(&denver_cpumask, &a57_cpumask); | ||
574 | |||
507 | a57_cluster_states = | 575 | a57_cluster_states = |
508 | of_find_node_by_name(NULL, "a57_cluster_power_states"); | 576 | of_find_node_by_name(NULL, "a57_cluster_power_states"); |
509 | denver_cluster_states = | 577 | denver_cluster_states = |
@@ -577,90 +645,3 @@ static struct platform_driver tegra18x_cpuidle_driver = { | |||
577 | }; | 645 | }; |
578 | 646 | ||
579 | module_platform_driver(tegra18x_cpuidle_driver); | 647 | module_platform_driver(tegra18x_cpuidle_driver); |
580 | |||
581 | struct xover_table { | ||
582 | char *name; | ||
583 | int index; | ||
584 | }; | ||
585 | |||
586 | static void crossover_init(struct device_node *of_states) { | ||
587 | |||
588 | struct device_node *child; | ||
589 | u32 value; | ||
590 | int i; | ||
591 | |||
592 | struct xover_table table1[] = { | ||
593 | {"crossover_c1_c6", TEGRA_MCE_XOVER_C1_C6}, | ||
594 | {"crossover_cc1_cc6", TEGRA_MCE_XOVER_CC1_CC6}, | ||
595 | {"crossover_cc1_cc7", TEGRA_MCE_XOVER_CC1_CC7}, | ||
596 | {"crossover_ccp1_ccp3", TEGRA_MCE_XOVER_CCP1_CCP3}, | ||
597 | {"crossover_ccp3_sc2", TEGRA_MCE_XOVER_CCP3_SC2}, | ||
598 | {"crossover_ccp3_sc3", TEGRA_MCE_XOVER_CCP3_SC3}, | ||
599 | {"crossover_ccp3_sc4", TEGRA_MCE_XOVER_CCP3_SC4}, | ||
600 | {"crossover_ccp3_sc7", TEGRA_MCE_XOVER_CCP3_SC7}, | ||
601 | }; | ||
602 | |||
603 | for_each_child_of_node(of_states, child) | ||
604 | for (i=0; i< TEGRA_MCE_XOVER_MAX; i++) { | ||
605 | if (of_property_read_u32(child, | ||
606 | table1[i].name, &value) == 0) | ||
607 | tegra_mce_update_crossover_time | ||
608 | (table1[i].index, value); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | static int tegra_mce_cpu_notify(struct notifier_block *nb, | ||
613 | unsigned long action, void *pcpu) | ||
614 | { | ||
615 | struct device_node *denver_xover; | ||
616 | struct device_node *a57_xover; | ||
617 | int cpu = (long)pcpu; | ||
618 | |||
619 | denver_xover = of_find_node_by_name(NULL, "denver_crossover_thresholds"); | ||
620 | a57_xover = of_find_node_by_name(NULL, "a57_crossover_thresholds"); | ||
621 | |||
622 | switch (action) { | ||
623 | case CPU_STARTING: | ||
624 | pr_debug("cpuidle: Init Power Crossover thresholds for core %d\n" | ||
625 | , cpu); | ||
626 | if (read_cpuid_implementor() == ARM_CPU_IMP_ARM) { | ||
627 | if (!a57_xover) { | ||
628 | pr_err("%s: failed to init xover for core %d\n", | ||
629 | __func__, cpu); | ||
630 | break; | ||
631 | } | ||
632 | crossover_init(a57_xover); | ||
633 | } else { | ||
634 | if (!denver_xover) { | ||
635 | pr_err("%s: failed to init xover for core %d\n", | ||
636 | __func__, cpu); | ||
637 | break; | ||
638 | } | ||
639 | crossover_init(denver_xover); | ||
640 | } | ||
641 | break; | ||
642 | } | ||
643 | |||
644 | return NOTIFY_OK; | ||
645 | } | ||
646 | |||
647 | static struct notifier_block mce_cpu_notifier = { | ||
648 | .notifier_call = tegra_mce_cpu_notify, | ||
649 | }; | ||
650 | |||
651 | static int __init tegra_mce_early_init(void) | ||
652 | { | ||
653 | |||
654 | if (!check_mce_version()) { | ||
655 | pr_err("cpuidle: skipping crossover programming." | ||
656 | " Incompatible MCE version.\n"); | ||
657 | return -ENODEV; | ||
658 | } | ||
659 | |||
660 | /* Initialize thresholds for boot cpu now */ | ||
661 | tegra_mce_cpu_notify(NULL, CPU_STARTING, (void *)0); | ||
662 | /* Initialize thresholds for rest of the cpu when they start */ | ||
663 | register_cpu_notifier(&mce_cpu_notifier); | ||
664 | return 0; | ||
665 | } | ||
666 | early_initcall(tegra_mce_early_init); | ||