// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright 2012 Linaro Ltd .
*/
#include <linux/cpuidle.h>
#include <linux/of.h>
#include <asm /cpuidle.h>
extern struct of_cpuidle_method __cpuidle_method_of_table[];
static const struct of_cpuidle_method __cpuidle_method_of_table_sentinel
__used __section("__cpuidle_method_of_table_end" );
static struct cpuidle_ops cpuidle_ops[NR_CPUS] __ro_after_init;
/**
* arm_cpuidle_simple_enter ( ) - a wrapper to cpu_do_idle ( )
* @ dev : not used
* @ drv : not used
* @ index : not used
*
* A trivial wrapper to allow the cpu_do_idle function to be assigned as a
* cpuidle callback by matching the function signature .
*
* Returns the index passed as parameter
*/
__cpuidle int arm_cpuidle_simple_enter(struct cpuidle_device *dev, struct
cpuidle_driver *drv, int index)
{
cpu_do_idle();
return index;
}
/**
* arm_cpuidle_suspend ( ) - function to enter low power idle states
* @ index : an integer used as an identifier for the low level PM callbacks
*
* This function calls the underlying arch specific low level PM code as
* registered at the init time .
*
* Returns the result of the suspend callback .
*/
int arm_cpuidle_suspend(int index)
{
int cpu = smp_processor_id();
return cpuidle_ops[cpu].suspend(index);
}
/**
* arm_cpuidle_get_ops ( ) - find a registered cpuidle_ops by name
* @ method : the method name
*
* Search in the _ _ cpuidle_method_of_table array the cpuidle ops matching the
* method name .
*
* Returns a struct cpuidle_ops pointer , NULL if not found .
*/
static const struct cpuidle_ops *__init arm_cpuidle_get_ops(const char *method)
{
struct of_cpuidle_method *m = __cpuidle_method_of_table;
for (; m->method; m++)
if (!strcmp(m->method, method))
return m->ops;
return NULL;
}
/**
* arm_cpuidle_read_ops ( ) - Initialize the cpuidle ops with the device tree
* @ dn : a pointer to a struct device node corresponding to a cpu node
* @ cpu : the cpu identifier
*
* Get the method name defined in the ' enable - method ' property , retrieve the
* associated cpuidle_ops and do a struct copy . This copy is needed because all
* cpuidle_ops are tagged _ _ initconst and will be unloaded after the init
* process .
*
* Return 0 on sucess , - ENOENT if no ' enable - method ' is defined , - EOPNOTSUPP if
* no cpuidle_ops is registered for the ' enable - method ' , or if either init or
* suspend callback isn ' t defined .
*/
static int __init arm_cpuidle_read_ops(struct device_node *dn, int cpu)
{
const char *enable_method;
const struct cpuidle_ops *ops;
enable_method = of_get_property(dn, "enable-method" , NULL);
if (!enable_method)
return -ENOENT;
ops = arm_cpuidle_get_ops(enable_method);
if (!ops) {
pr_warn("%pOF: unsupported enable-method property: %s\n" ,
dn, enable_method);
return -EOPNOTSUPP;
}
if (!ops->init || !ops->suspend) {
pr_warn("cpuidle_ops '%s': no init or suspend callback\n" ,
enable_method);
return -EOPNOTSUPP;
}
cpuidle_ops[cpu] = *ops; /* structure copy */
pr_notice("cpuidle: enable-method property '%s'"
" found operations\n" , enable_method);
return 0 ;
}
/**
* arm_cpuidle_init ( ) - Initialize cpuidle_ops for a specific cpu
* @ cpu : the cpu to be initialized
*
* Initialize the cpuidle ops with the device for the cpu and then call
* the cpu ' s idle initialization callback . This may fail if the underlying HW
* is not operational .
*
* Returns :
* 0 on success ,
* - ENODEV if it fails to find the cpu node in the device tree ,
* - EOPNOTSUPP if it does not find a registered and valid cpuidle_ops for
* this cpu ,
* - ENOENT if it fails to find an ' enable - method ' property ,
* - ENXIO if the HW reports a failure or a misconfiguration ,
* - ENOMEM if the HW report an memory allocation failure
*/
int __init arm_cpuidle_init(int cpu)
{
struct device_node *cpu_node = of_cpu_device_node_get(cpu);
int ret;
if (!cpu_node)
return -ENODEV;
ret = arm_cpuidle_read_ops(cpu_node, cpu);
if (!ret)
ret = cpuidle_ops[cpu].init(cpu_node, cpu);
of_node_put(cpu_node);
return ret;
}
Messung V0.5 in Prozent C=95 H=92 G=93
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-09-27)
¤
*© Formatika GbR, Deutschland