static int __init bl_idle_init(void) { int ret; struct device_node *root = of_find_node_by_path("/"); if (!root) return -ENODEV; /* * Initialize the driver just for a compliant set of machines */ if (!of_match_node(compatible_machine_match, root)) return -ENODEV; /* * For now the differentiation between little and big cores * is based on the part number. A7 cores are considered little * cores, A15 are considered big cores. This distinction may * evolve in the future with a more generic matching approach. */ ret = bl_idle_driver_init(&bl_idle_little_driver, ARM_CPU_PART_CORTEX_A7); if (ret) return ret; ret = bl_idle_driver_init(&bl_idle_big_driver, ARM_CPU_PART_CORTEX_A15); if (ret) goto out_uninit_little; /* Start at index 1, index 0 standard WFI */ ret = dt_init_idle_driver(&bl_idle_big_driver, bl_idle_state_match, 1); if (ret < 0) goto out_uninit_big; /* Start at index 1, index 0 standard WFI */ ret = dt_init_idle_driver(&bl_idle_little_driver, bl_idle_state_match, 1); if (ret < 0) goto out_uninit_big; ret = cpuidle_register(&bl_idle_little_driver, NULL); if (ret) goto out_uninit_big; ret = cpuidle_register(&bl_idle_big_driver, NULL); if (ret) goto out_unregister_little; return 0; out_unregister_little: cpuidle_unregister(&bl_idle_little_driver); out_uninit_big: kfree(bl_idle_big_driver.cpumask); out_uninit_little: kfree(bl_idle_little_driver.cpumask); return ret; }
static void __exit tegra_cpuidle_exit(void) { int cpu; struct cpuidle_driver *drv; unregister_pm_notifier(&tegra_cpuidle_pm_notifier); for_each_possible_cpu(cpu) { drv = &per_cpu(cpuidle_drv, cpu); on_each_cpu_mask(drv->cpumask, tegra_cpuidle_setup_bctimer, (void *)CLOCK_EVT_NOTIFY_BROADCAST_OFF, 1); cpuidle_unregister(drv); } }
static int __init bl_idle_init(void) { int ret; /* * Initialize the driver just for a compliant set of machines */ if (!of_machine_is_compatible("arm,vexpress,v2p-ca15_a7")) return -ENODEV; /* * For now the differentiation between little and big cores * is based on the part number. A7 cores are considered little * cores, A15 are considered big cores. This distinction may * evolve in the future with a more generic matching approach. */ ret = bl_idle_driver_init(&bl_idle_little_driver, ARM_CPU_PART_CORTEX_A7); if (ret) return ret; ret = bl_idle_driver_init(&bl_idle_big_driver, ARM_CPU_PART_CORTEX_A15); if (ret) goto out_uninit_little; ret = cpuidle_register(&bl_idle_little_driver, NULL); if (ret) goto out_uninit_big; ret = cpuidle_register(&bl_idle_big_driver, NULL); if (ret) goto out_unregister_little; return 0; out_unregister_little: cpuidle_unregister(&bl_idle_little_driver); out_uninit_big: kfree(bl_idle_big_driver.cpumask); out_uninit_little: kfree(bl_idle_little_driver.cpumask); return ret; }
/** * cpuidle_register: registers the driver and the cpu devices with the * coupled_cpus passed as parameter. This function is used for all common * initialization pattern there are in the arch specific drivers. The * devices is globally defined in this file. * * @drv : a valid pointer to a struct cpuidle_driver * @coupled_cpus: a cpumask for the coupled states * * Returns 0 on success, < 0 otherwise */ int cpuidle_register(struct cpuidle_driver *drv, const struct cpumask *const coupled_cpus) { int ret, cpu; struct cpuidle_device *device; ret = cpuidle_register_driver(drv); if (ret) { pr_err("failed to register cpuidle driver\n"); return ret; } for_each_possible_cpu(cpu) { device = &per_cpu(cpuidle_dev, cpu); device->cpu = cpu; #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED /* * On multiplatform for ARM, the coupled idle states could * enabled in the kernel even if the cpuidle driver does not * use it. Note, coupled_cpus is a struct copy. */ if (coupled_cpus) device->coupled_cpus = *coupled_cpus; #endif ret = cpuidle_register_device(device); if (!ret) continue; pr_err("Failed to register cpuidle device for cpu%d\n", cpu); cpuidle_unregister(drv); break; } return ret; }
static int kirkwood_cpuidle_remove(struct platform_device *pdev) { cpuidle_unregister(&kirkwood_idle_driver); return 0; }