/*
 * arm64_idle_sprd_init
 *
 * Registers the arm64 specific cpuidle driver with the cpuidle
 * framework. It relies on core code to parse the idle states
 * and initialize them using driver data structures accordingly.
 */
int __init arm64_idle_sprd_init(void)
{
	int i, ret;
	const char *entry_method;
	struct device_node *idle_states_node;
	const struct cpu_suspend_ops *suspend_init;
	struct cpuidle_driver *drv = &arm64_idle_driver;

	idle_states_node = of_find_node_by_path("/cpus/idle-states");
	if (!idle_states_node) {
		return -ENOENT;
	}
	if (of_property_read_string(idle_states_node, "entry-method",
				    &entry_method)) {
		pr_warn(" * %s missing entry-method property\n",
			    idle_states_node->full_name);
		of_node_put(idle_states_node);
		return -EOPNOTSUPP;
	}
	/*
	 * State at index 0 is standby wfi and considered standard
	 * on all ARM platforms. If in some platforms simple wfi
	 * can't be used as "state 0", DT bindings must be implemented
	 * to work around this issue and allow installing a special
	 * handler for idle state index 0.
	 */
	drv->states[0].exit_latency = 1;
	drv->states[0].target_residency = 1;
	drv->states[0].flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TIMER_STOP;
	strncpy(drv->states[0].name, "ARM WFI", CPUIDLE_NAME_LEN);
	strncpy(drv->states[0].desc, "ARM WFI", CPUIDLE_DESC_LEN);

	drv->cpumask = (struct cpumask *) cpu_possible_mask;
	/*
	 * Start at index 1, request idle state nodes to be filled
	 */
	ret = of_init_idle_driver(drv, state_nodes, 1, true);
	if (ret) {
		return ret;
	}

	for (i = 0; i < drv->state_count; i++)
		drv->states[i].enter = arm_enter_idle_state;
	printk("[CPUIDLE]<arm64_idle_sprd_init> init OK. \n");
	return cpuidle_register(drv, NULL);
}
예제 #2
0
static int __init exynos_idle_state_init(struct cpuidle_driver *idle_drv,
					 const struct cpumask *mask)
{
	int i, ret;
	const char *entry_method;
	struct device_node *idle_states_node;
	const struct cpu_suspend_ops *suspend_init;
	struct cpuidle_driver *drv = idle_drv;

	idle_states_node = of_find_node_by_path("/cpus/idle-states");
	if (!idle_states_node)
		return -ENOENT;

	if (of_property_read_string(idle_states_node, "entry-method",
				    &entry_method)) {
		pr_warn(" * %s missing entry-method property\n",
			    idle_states_node->full_name);
		of_node_put(idle_states_node);
		return -EOPNOTSUPP;
	}

	suspend_init = get_suspend_ops(entry_method);
	if (!suspend_init) {
		pr_warn("Missing suspend initializer\n");
		of_node_put(idle_states_node);
		return -EOPNOTSUPP;
	}

	drv->cpumask = (struct cpumask *)mask;

	ret = of_init_idle_driver(drv, state_nodes, 0, true);
	if (ret)
		return ret;

	if (suspend_init->init_fn(drv, state_nodes))
		return -EOPNOTSUPP;

	for (i = 0; i < drv->state_count; i++)
		drv->states[i].enter = exynos_enter_idle_state;

	return 0;
}