diff options
author | Mark Brown <broonie@kernel.org> | 2015-01-18 13:12:48 +0000 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-01-18 13:12:48 +0000 |
commit | cc43a17507644ad34d07a3e95d7376d55fd82b15 (patch) | |
tree | aa6c48a80f001853e780d0738b5a8d843250ff46 /drivers | |
parent | 71220c39c683cc0eb4d5300268cd061dd249933e (diff) | |
parent | 4bb26215c07fb204ae1d66e54406dd6bae793c20 (diff) |
Merge remote-tracking branch 'lsk/v3.10/topic/arm64-cpuidle' into linux-linaro-lsk
Conflicts:
arch/arm64/kernel/Makefile
drivers/cpuidle/Makefile
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/cpuidle/Kconfig | 20 | ||||
-rw-r--r-- | drivers/cpuidle/Kconfig.arm64 | 9 | ||||
-rw-r--r-- | drivers/cpuidle/Makefile | 2 | ||||
-rw-r--r-- | drivers/cpuidle/cpuidle-arm64.c | 162 | ||||
-rw-r--r-- | drivers/cpuidle/dt_idle_states.c | 213 | ||||
-rw-r--r-- | drivers/cpuidle/dt_idle_states.h | 7 | ||||
-rw-r--r-- | drivers/cpuidle/of_idle_states.c | 274 | ||||
-rw-r--r-- | drivers/cpuidle/of_idle_states.h | 8 |
8 files changed, 301 insertions, 394 deletions
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index 842d7ba83101..9625ce7ed5f8 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -31,26 +31,20 @@ config CPU_IDLE_GOV_MENU config ARCH_NEEDS_CPU_IDLE_COUPLED def_bool n -config OF_IDLE_STATES - bool "Idle states DT support" - depends on ARM || ARM64 - default n - help - Allows the CPU idle framework to initialize CPU idle drivers - state data by using DT provided nodes compliant with idle states - device tree bindings. +config DT_IDLE_STATES + bool if CPU_IDLE +menu "ARM64 CPU Idle Drivers" +depends on ARM64 +source "drivers/cpuidle/Kconfig.arm64" +endmenu + config CPU_IDLE_CALXEDA bool "CPU Idle Driver for Calxeda processors" depends on ARCH_HIGHBANK help Select this to enable cpuidle on Calxeda processors. -menu "ARM64 CPU Idle Drivers" -depends on ARM64 -source "drivers/cpuidle/Kconfig.arm64" -endmenu - endif diff --git a/drivers/cpuidle/Kconfig.arm64 b/drivers/cpuidle/Kconfig.arm64 index b83612c67e6d..d0a08ed1b2ee 100644 --- a/drivers/cpuidle/Kconfig.arm64 +++ b/drivers/cpuidle/Kconfig.arm64 @@ -4,10 +4,11 @@ config ARM64_CPUIDLE bool "Generic ARM64 CPU idle Driver" - select OF_IDLE_STATES + select ARM64_CPU_SUSPEND + select DT_IDLE_STATES help - Select this to enable generic cpuidle driver for ARM v8. + Select this to enable generic cpuidle driver for ARM64. It provides a generic idle driver whose idle states are configured at run-time through DT nodes. The CPUidle suspend backend is - initialized by the device tree parsing code on matching the entry - method to the respective CPU operations. + initialized by calling the CPU operations init idle hook + provided by architecture code. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 2d97bcfecd00..0bd32cd03f0a 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -5,7 +5,7 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o obj-$(CONFIG_BIG_LITTLE) += arm_big_little.o -obj-$(CONFIG_OF_IDLE_STATES) += of_idle_states.o +obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o obj-$(CONFIG_ARCH_KIRKWOOD) += cpuidle-kirkwood.o diff --git a/drivers/cpuidle/cpuidle-arm64.c b/drivers/cpuidle/cpuidle-arm64.c index 2cfde6ce3086..50997ea942fc 100644 --- a/drivers/cpuidle/cpuidle-arm64.c +++ b/drivers/cpuidle/cpuidle-arm64.c @@ -9,6 +9,8 @@ * published by the Free Software Foundation. */ +#define pr_fmt(fmt) "CPUidle arm64: " fmt + #include <linux/cpuidle.h> #include <linux/cpumask.h> #include <linux/cpu_pm.h> @@ -16,50 +18,23 @@ #include <linux/module.h> #include <linux/of.h> -#include <asm/psci.h> +#include <asm/cpuidle.h> #include <asm/suspend.h> -#include "of_idle_states.h" - -typedef int (*suspend_init_fn)(struct cpuidle_driver *, - struct device_node *[]); - -struct cpu_suspend_ops { - const char *id; - suspend_init_fn init_fn; -}; - -static const struct cpu_suspend_ops suspend_operations[] __initconst = { - {"arm,psci", psci_dt_register_idle_states}, - {} -}; - -static __init const struct cpu_suspend_ops *get_suspend_ops(const char *str) -{ - int i; - - if (!str) - return NULL; - - for (i = 0; suspend_operations[i].id; i++) - if (!strcmp(suspend_operations[i].id, str)) - return &suspend_operations[i]; - - return NULL; -} +#include "dt_idle_states.h" /* - * arm_enter_idle_state - Programs CPU to enter the specified state + * arm64_enter_idle_state - Programs CPU to enter the specified state * - * @dev: cpuidle device - * @drv: cpuidle driver - * @idx: state index + * dev: cpuidle device + * drv: cpuidle driver + * idx: state index * * Called from the CPUidle framework to program the device to the * specified target state selected by the governor. */ -static int arm_enter_idle_state(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int idx) +static int arm64_enter_idle_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx) { int ret; @@ -68,30 +43,47 @@ static int arm_enter_idle_state(struct cpuidle_device *dev, return idx; } - cpu_pm_enter(); - /* - * Pass idle state index to cpu_suspend which in turn will call - * the CPU ops suspend protocol with idle index as a parameter. - * - * Some states would not require context to be saved and flushed - * to DRAM, so calling cpu_suspend would not be stricly necessary. - * When power domains specifications for ARM CPUs are finalized then - * this code can be optimized to prevent saving registers if not - * needed. - */ - ret = cpu_suspend(idx); + ret = cpu_pm_enter(); + if (!ret) { + /* + * Pass idle state index to cpu_suspend which in turn will + * call the CPU ops suspend protocol with idle index as a + * parameter. + */ + ret = cpu_suspend(idx); - cpu_pm_exit(); + cpu_pm_exit(); + } return ret ? -1 : idx; } -struct cpuidle_driver arm64_idle_driver = { +static struct cpuidle_driver arm64_idle_driver = { .name = "arm64_idle", .owner = THIS_MODULE, + /* + * 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. + */ + .states[0] = { + .enter = arm64_enter_idle_state, + .exit_latency = 1, + .target_residency = 1, + .power_usage = UINT_MAX, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "WFI", + .desc = "ARM64 WFI", + } }; -static struct device_node *state_nodes[CPUIDLE_STATE_MAX] __initdata; +static const struct of_device_id arm64_idle_state_match[] __initconst = { + { .compatible = "arm,idle-state", + .data = arm64_enter_idle_state }, + { }, +}; /* * arm64_idle_init @@ -102,58 +94,40 @@ static struct device_node *state_nodes[CPUIDLE_STATE_MAX] __initdata; */ static int __init arm64_idle_init(void) { - int i, ret; - const char *entry_method; - struct device_node *idle_states_node; - const struct cpu_suspend_ops *suspend_init; + int cpu, ret; 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; - } - - suspend_init = get_suspend_ops(entry_method); - if (!suspend_init) { - pr_warn("Missing suspend initializer\n"); - 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. + * Initialize idle states data, starting at index 1. + * This driver is DT only, if no DT idle states are detected (ret == 0) + * let the driver initialization fail accordingly since there is no + * reason to initialize the idle driver if only wfi is supported. */ - drv->states[0].exit_latency = 1; - drv->states[0].target_residency = 1; - drv->states[0].flags = CPUIDLE_FLAG_TIME_VALID; - strncpy(drv->states[0].name, "ARM WFI", CPUIDLE_NAME_LEN); - strncpy(drv->states[0].desc, "ARM WFI", CPUIDLE_DESC_LEN); + ret = dt_init_idle_driver(drv, arm64_idle_state_match, 1); + if (ret <= 0) { + if (ret) + pr_err("failed to initialize idle states\n"); + return ret ? : -ENODEV; + } - drv->cpumask = (struct cpumask *) cpu_possible_mask; /* - * Start at index 1, request idle state nodes to be filled + * Call arch CPU operations in order to initialize + * idle states suspend back-end specific data */ - ret = of_init_idle_driver(drv, state_nodes, 1, true); - if (ret) - return ret; - - if (suspend_init->init_fn(drv, state_nodes)) - return -EOPNOTSUPP; + for_each_possible_cpu(cpu) { + ret = cpu_init_idle(cpu); + if (ret) { + pr_err("CPU %d failed to init idle CPU ops\n", cpu); + return ret; + } + } - for (i = 0; i < drv->state_count; i++) - drv->states[i].enter = arm_enter_idle_state; + ret = cpuidle_register(drv, NULL); + if (ret) { + pr_err("failed to register cpuidle driver\n"); + return ret; + } - return cpuidle_register(drv, NULL); + return 0; } device_initcall(arm64_idle_init); diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c new file mode 100644 index 000000000000..52f4d11bbf3f --- /dev/null +++ b/drivers/cpuidle/dt_idle_states.c @@ -0,0 +1,213 @@ +/* + * DT idle states parsing code. + * + * Copyright (C) 2014 ARM Ltd. + * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define pr_fmt(fmt) "DT idle-states: " fmt + +#include <linux/cpuidle.h> +#include <linux/cpumask.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> + +#include "dt_idle_states.h" + +static int init_state_node(struct cpuidle_state *idle_state, + const struct of_device_id *matches, + struct device_node *state_node) +{ + int err; + const struct of_device_id *match_id; + + match_id = of_match_node(matches, state_node); + if (!match_id) + return -ENODEV; + /* + * CPUidle drivers are expected to initialize the const void *data + * pointer of the passed in struct of_device_id array to the idle + * state enter function. + */ + idle_state->enter = match_id->data; + + err = of_property_read_u32(state_node, "wakeup-latency-us", + &idle_state->exit_latency); + if (err) { + u32 entry_latency, exit_latency; + + err = of_property_read_u32(state_node, "entry-latency-us", + &entry_latency); + if (err) { + pr_debug(" * %s missing entry-latency-us property\n", + state_node->full_name); + return -EINVAL; + } + + err = of_property_read_u32(state_node, "exit-latency-us", + &exit_latency); + if (err) { + pr_debug(" * %s missing exit-latency-us property\n", + state_node->full_name); + return -EINVAL; + } + /* + * If wakeup-latency-us is missing, default to entry+exit + * latencies as defined in idle states bindings + */ + idle_state->exit_latency = entry_latency + exit_latency; + } + + err = of_property_read_u32(state_node, "min-residency-us", + &idle_state->target_residency); + if (err) { + pr_debug(" * %s missing min-residency-us property\n", + state_node->full_name); + return -EINVAL; + } + + idle_state->flags = CPUIDLE_FLAG_TIME_VALID; + if (of_property_read_bool(state_node, "local-timer-stop")) + idle_state->flags |= CPUIDLE_FLAG_TIMER_STOP; + /* + * TODO: + * replace with kstrdup and pointer assignment when name + * and desc become string pointers + */ + strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN - 1); + strncpy(idle_state->desc, state_node->name, CPUIDLE_DESC_LEN - 1); + return 0; +} + +/* + * Check that the idle state is uniform across all CPUs in the CPUidle driver + * cpumask + */ +static bool idle_state_valid(struct device_node *state_node, unsigned int idx, + const cpumask_t *cpumask) +{ + int cpu; + struct device_node *cpu_node, *curr_state_node; + bool valid = true; + + /* + * Compare idle state phandles for index idx on all CPUs in the + * CPUidle driver cpumask. Start from next logical cpu following + * cpumask_first(cpumask) since that's the CPU state_node was + * retrieved from. If a mismatch is found bail out straight + * away since we certainly hit a firmware misconfiguration. + */ + for (cpu = cpumask_next(cpumask_first(cpumask), cpumask); + cpu < nr_cpu_ids; cpu = cpumask_next(cpu, cpumask)) { + cpu_node = of_cpu_device_node_get(cpu); + curr_state_node = of_parse_phandle(cpu_node, "cpu-idle-states", + idx); + if (state_node != curr_state_node) + valid = false; + + of_node_put(curr_state_node); + of_node_put(cpu_node); + if (!valid) + break; + } + + return valid; +} + +/** + * dt_init_idle_driver() - Parse the DT idle states and initialize the + * idle driver states array + * @drv: Pointer to CPU idle driver to be initialized + * @matches: Array of of_device_id match structures to search in for + * compatible idle state nodes. The data pointer for each valid + * struct of_device_id entry in the matches array must point to + * a function with the following signature, that corresponds to + * the CPUidle state enter function signature: + * + * int (*)(struct cpuidle_device *dev, + * struct cpuidle_driver *drv, + * int index); + * + * @start_idx: First idle state index to be initialized + * + * If DT idle states are detected and are valid the state count and states + * array entries in the cpuidle driver are initialized accordingly starting + * from index start_idx. + * + * Return: number of valid DT idle states parsed, <0 on failure + */ +int dt_init_idle_driver(struct cpuidle_driver *drv, + const struct of_device_id *matches, + unsigned int start_idx) +{ + struct cpuidle_state *idle_state; + struct device_node *state_node, *cpu_node; + int i, err = 0; + const cpumask_t *cpumask; + unsigned int state_idx = start_idx; + + if (state_idx >= CPUIDLE_STATE_MAX) + return -EINVAL; + /* + * We get the idle states for the first logical cpu in the + * driver mask (or cpu_possible_mask if the driver cpumask is not set) + * and we check through idle_state_valid() if they are uniform + * across CPUs, otherwise we hit a firmware misconfiguration. + */ + cpumask = drv->cpumask ? : cpu_possible_mask; + cpu_node = of_cpu_device_node_get(cpumask_first(cpumask)); + + for (i = 0; ; i++) { + state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); + if (!state_node) + break; + + if (!idle_state_valid(state_node, i, cpumask)) { + pr_warn("%s idle state not valid, bailing out\n", + state_node->full_name); + err = -EINVAL; + break; + } + + if (state_idx == CPUIDLE_STATE_MAX) { + pr_warn("State index reached static CPU idle driver states array size\n"); + break; + } + + idle_state = &drv->states[state_idx++]; + err = init_state_node(idle_state, matches, state_node); + if (err) { + pr_err("Parsing idle state node %s failed with err %d\n", + state_node->full_name, err); + err = -EINVAL; + break; + } + of_node_put(state_node); + } + + of_node_put(state_node); + of_node_put(cpu_node); + if (err) + return err; + /* + * Update the driver state count only if some valid DT idle states + * were detected + */ + if (i) + drv->state_count = state_idx; + + /* + * Return the number of present and valid DT idle states, which can + * also be 0 on platforms with missing DT idle states or legacy DT + * configuration predating the DT idle states bindings. + */ + return i; +} +EXPORT_SYMBOL_GPL(dt_init_idle_driver); diff --git a/drivers/cpuidle/dt_idle_states.h b/drivers/cpuidle/dt_idle_states.h new file mode 100644 index 000000000000..4818134bc65b --- /dev/null +++ b/drivers/cpuidle/dt_idle_states.h @@ -0,0 +1,7 @@ +#ifndef __DT_IDLE_STATES +#define __DT_IDLE_STATES + +int dt_init_idle_driver(struct cpuidle_driver *drv, + const struct of_device_id *matches, + unsigned int start_idx); +#endif diff --git a/drivers/cpuidle/of_idle_states.c b/drivers/cpuidle/of_idle_states.c deleted file mode 100644 index eceb1b4c4657..000000000000 --- a/drivers/cpuidle/of_idle_states.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * OF idle states parsing code. - * - * Copyright (C) 2014 ARM Ltd. - * Author: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/cpuidle.h> -#include <linux/cpumask.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/list_sort.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/slab.h> - -#include "of_idle_states.h" - -struct state_elem { - struct list_head list; - struct device_node *node; - int val; -}; - -static struct list_head head __initdata = LIST_HEAD_INIT(head); - -static bool __init state_cpu_valid(struct device_node *state_node, - struct device_node *cpu_node) -{ - int i = 0; - struct device_node *cpu_state; - - while ((cpu_state = of_parse_phandle(cpu_node, - "cpu-idle-states", i++))) { - if (cpu_state && state_node == cpu_state) { - of_node_put(cpu_state); - return true; - } - of_node_put(cpu_state); - } - return false; -} - -static bool __init state_cpus_valid(const cpumask_t *cpus, - struct device_node *state_node) -{ - int cpu; - struct device_node *cpu_node; - - /* - * Check if state is valid on driver cpumask cpus - */ - for_each_cpu(cpu, cpus) { - cpu_node = of_get_cpu_node(cpu, NULL); - - if (!cpu_node) { - pr_err("Missing device node for CPU %d\n", cpu); - return false; - } - - if (!state_cpu_valid(state_node, cpu_node)) - return false; - } - - return true; -} - -static int __init state_cmp(void *priv, struct list_head *a, - struct list_head *b) -{ - struct state_elem *ela, *elb; - - ela = container_of(a, struct state_elem, list); - elb = container_of(b, struct state_elem, list); - - return ela->val - elb->val; -} - -static int __init add_state_node(cpumask_t *cpumask, - struct device_node *state_node) -{ - struct state_elem *el; - u32 val; - - pr_debug(" * %s...\n", state_node->full_name); - - if (!state_cpus_valid(cpumask, state_node)) - return -EINVAL; - /* - * Parse just the value required to sort the states. - */ - if (of_property_read_u32(state_node, "min-residency-us", - &val)) { - pr_debug(" * %s missing min-residency-us property\n", - state_node->full_name); - return -EINVAL; - } - - el = kmalloc(sizeof(*el), GFP_KERNEL); - if (!el) { - pr_err("%s failed to allocate memory\n", __func__); - return -ENOMEM; - } - - el->node = state_node; - el->val = val; - list_add_tail(&el->list, &head); - - return 0; -} - -static void __init init_state_node(struct cpuidle_driver *drv, - struct device_node *state_node, - int *cnt) -{ - struct cpuidle_state *idle_state; - - pr_debug(" * %s...\n", state_node->full_name); - - idle_state = &drv->states[*cnt]; - - if (of_property_read_u32(state_node, "exit-latency-us", - &idle_state->exit_latency)) { - pr_debug(" * %s missing exit-latency-us property\n", - state_node->full_name); - return; - } - - if (of_property_read_u32(state_node, "min-residency-us", - &idle_state->target_residency)) { - pr_debug(" * %s missing min-residency-us property\n", - state_node->full_name); - return; - } - /* - * It is unknown to the idle driver if and when the tick_device - * loses context when the CPU enters the idle states. To solve - * this issue the tick device must be linked to a power domain - * so that the idle driver can check on which states the device - * loses its context. Current code takes the conservative choice - * of defining the idle state as one where the tick device always - * loses its context. On platforms where tick device never loses - * its context (ie it is not a C3STOP device) this turns into - * a nop. On platforms where the tick device does lose context in some - * states, this code can be optimized, when power domain specifications - * for ARM CPUs are finalized. - */ - idle_state->flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TIMER_STOP; - - strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN); - strncpy(idle_state->desc, state_node->name, CPUIDLE_NAME_LEN); - - (*cnt)++; -} - -static int __init init_idle_states(struct cpuidle_driver *drv, - struct device_node *state_nodes[], - unsigned int start_idx, bool init_nodes) -{ - struct state_elem *el; - struct list_head *curr, *tmp; - unsigned int cnt = start_idx; - - list_for_each_entry(el, &head, list) { - /* - * Check if the init function has to fill the - * state_nodes array on behalf of the CPUidle driver. - */ - if (init_nodes) - state_nodes[cnt] = el->node; - /* - * cnt is updated on return if a state was added. - */ - init_state_node(drv, el->node, &cnt); - - if (cnt == CPUIDLE_STATE_MAX) { - pr_warn("State index reached static CPU idle state limit\n"); - break; - } - } - - drv->state_count = cnt; - - list_for_each_safe(curr, tmp, &head) { - list_del(curr); - kfree(container_of(curr, struct state_elem, list)); - } - - /* - * If no idle states are detected, return an error and let the idle - * driver initialization fail accordingly. - */ - return (cnt > start_idx) ? 0 : -ENODATA; -} - -static void __init add_idle_states(struct cpuidle_driver *drv, - struct device_node *idle_states) -{ - struct device_node *state_node; - - for_each_child_of_node(idle_states, state_node) { - if ((!of_device_is_compatible(state_node, "arm,idle-state"))) { - pr_warn(" * %s: children of /cpus/idle-states must be \"arm,idle-state\" compatible\n", - state_node->full_name); - continue; - } - /* - * If memory allocation fails, better bail out. - * Initialized nodes are freed at initialization - * completion in of_init_idle_driver(). - */ - if ((add_state_node(drv->cpumask, state_node) == -ENOMEM)) - break; - } - /* - * Sort the states list before initializing the CPUidle driver - * states array. - */ - list_sort(NULL, &head, state_cmp); -} - -/* - * of_init_idle_driver - Parse the DT idle states and initialize the - * idle driver states array - * - * @drv: Pointer to CPU idle driver to be initialized - * @state_nodes: Array of struct device_nodes to be initialized if - * init_nodes == true. Must be sized CPUIDLE_STATE_MAX - * @start_idx: First idle state index to be initialized - * @init_nodes: Boolean to request device nodes initialization - * - * Returns: - * 0 on success - * <0 on failure - * - * On success the states array in the cpuidle driver contains - * initialized entries in the states array, starting from index start_idx. - * If init_nodes == true, on success the state_nodes array is initialized - * with idle state DT node pointers, starting from index start_idx, - * in a 1:1 relation with the idle driver states array. - */ -int __init of_init_idle_driver(struct cpuidle_driver *drv, - struct device_node *state_nodes[], - unsigned int start_idx, bool init_nodes) -{ - struct device_node *idle_states_node; - int ret; - - if (start_idx >= CPUIDLE_STATE_MAX) { - pr_warn("State index exceeds static CPU idle driver states array size\n"); - return -EINVAL; - } - - if (WARN(init_nodes && !state_nodes, - "Requested nodes stashing in an invalid nodes container\n")) - return -EINVAL; - - idle_states_node = of_find_node_by_path("/cpus/idle-states"); - if (!idle_states_node) - return -ENOENT; - - add_idle_states(drv, idle_states_node); - - ret = init_idle_states(drv, state_nodes, start_idx, init_nodes); - - of_node_put(idle_states_node); - - return ret; -} diff --git a/drivers/cpuidle/of_idle_states.h b/drivers/cpuidle/of_idle_states.h deleted file mode 100644 index 049f94ff4428..000000000000 --- a/drivers/cpuidle/of_idle_states.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __OF_IDLE_STATES -#define __OF_IDLE_STATES - -int __init of_init_idle_driver(struct cpuidle_driver *drv, - struct device_node *state_nodes[], - unsigned int start_idx, - bool init_nodes); -#endif |