2013-04-01 12:57:49 +00:00
/*
* Generic big . LITTLE CPUFreq Interface driver
*
* It provides necessary ops to arm_big_little cpufreq driver and gets
* Frequency information from Device Tree . Freq table in DT must be in KHz .
*
* Copyright ( C ) 2013 Linaro .
* Viresh Kumar < viresh . kumar @ linaro . org >
*
* 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 .
*
* This program is distributed " as is " WITHOUT ANY WARRANTY of any
* kind , whether express or implied ; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/cpufreq.h>
# include <linux/device.h>
# include <linux/export.h>
# include <linux/module.h>
2013-06-17 15:51:44 +01:00
# include <linux/of_device.h>
2013-09-19 16:03:52 -05:00
# include <linux/pm_opp.h>
2013-05-20 09:57:17 +05:30
# include <linux/platform_device.h>
2013-04-01 12:57:49 +00:00
# include <linux/slab.h>
# include <linux/types.h>
# include "arm_big_little.h"
2013-05-17 11:25:11 +00:00
/* get cpu node with valid operating-points */
static struct device_node * get_cpu_node_with_valid_op ( int cpu )
2013-04-01 12:57:49 +00:00
{
2013-06-17 15:51:44 +01:00
struct device_node * np = of_cpu_device_node_get ( cpu ) ;
2013-04-01 12:57:49 +00:00
2013-06-17 15:51:44 +01:00
if ( ! of_get_property ( np , " operating-points " , NULL ) ) {
of_node_put ( np ) ;
np = NULL ;
2013-04-15 07:05:24 +00:00
}
2013-05-17 11:25:11 +00:00
return np ;
}
2013-04-01 12:57:49 +00:00
static int dt_get_transition_latency ( struct device * cpu_dev )
{
2013-05-17 11:25:11 +00:00
struct device_node * np ;
2013-04-01 12:57:49 +00:00
u32 transition_latency = CPUFREQ_ETERNAL ;
2013-06-17 15:51:44 +01:00
np = of_node_get ( cpu_dev - > of_node ) ;
if ( ! np ) {
pr_info ( " Failed to find cpu node. Use CPUFREQ_ETERNAL transition latency \n " ) ;
2013-04-29 13:24:46 +00:00
return CPUFREQ_ETERNAL ;
2013-06-17 15:51:44 +01:00
}
2013-04-15 07:05:24 +00:00
2013-05-17 11:25:11 +00:00
of_property_read_u32 ( np , " clock-latency " , & transition_latency ) ;
of_node_put ( np ) ;
2013-04-01 12:57:49 +00:00
2013-05-17 11:25:11 +00:00
pr_debug ( " %s: clock-latency: %d \n " , __func__ , transition_latency ) ;
return transition_latency ;
2013-04-01 12:57:49 +00:00
}
static struct cpufreq_arm_bL_ops dt_bL_ops = {
. name = " dt-bl " ,
. get_transition_latency = dt_get_transition_latency ,
cpufreq: arm_big_little: use generic OPP functions for {init, free}_opp_table
Currently when performing random CPU hot-plugs and suspend-to-ram(S2R)
on systems using arm_big_little cpufreq driver, we get warnings similar
to something like below:
cpu cpu1: _opp_add: duplicate OPPs detected. Existing: freq: 600000000,
volt: 800000, enabled: 1. New: freq: 600000000, volt: 800000, enabled: 1
This is mainly because the OPPs for the shared cpus are not set. We can
just use dev_pm_opp_of_cpumask_add_table in case the OPPs are obtained
from DT(arm_big_little_dt.c) or use dev_pm_opp_set_sharing_cpus if the
OPPs are obtained by other means like firmware(e.g. scpi-cpufreq.c)
Also now that the generic dev_pm_opp{,_of}_cpumask_remove_table can
handle removal of opp table and entries for all associated CPUs, we can
re-use dev_pm_opp{,_of}_cpumask_remove_table as free_opp_table in
cpufreq_arm_bL_ops.
This patch makes necessary changes to reuse the generic OPP functions for
{init,free}_opp_table and thereby eliminating the warnings.
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2016-05-03 15:05:05 +01:00
. init_opp_table = dev_pm_opp_of_cpumask_add_table ,
. free_opp_table = dev_pm_opp_of_cpumask_remove_table ,
2013-04-01 12:57:49 +00:00
} ;
2013-05-20 09:57:17 +05:30
static int generic_bL_probe ( struct platform_device * pdev )
2013-04-01 12:57:49 +00:00
{
2013-05-17 11:25:11 +00:00
struct device_node * np ;
np = get_cpu_node_with_valid_op ( 0 ) ;
if ( ! np )
return - ENODEV ;
of_node_put ( np ) ;
2013-04-01 12:57:49 +00:00
return bL_cpufreq_register ( & dt_bL_ops ) ;
}
2013-05-20 09:57:17 +05:30
static int generic_bL_remove ( struct platform_device * pdev )
2013-04-01 12:57:49 +00:00
{
2013-05-20 09:57:17 +05:30
bL_cpufreq_unregister ( & dt_bL_ops ) ;
return 0 ;
2013-04-01 12:57:49 +00:00
}
2013-05-20 09:57:17 +05:30
static struct platform_driver generic_bL_platdrv = {
. driver = {
. name = " arm-bL-cpufreq-dt " ,
} ,
. probe = generic_bL_probe ,
. remove = generic_bL_remove ,
} ;
module_platform_driver ( generic_bL_platdrv ) ;
2013-04-01 12:57:49 +00:00
MODULE_AUTHOR ( " Viresh Kumar <viresh.kumar@linaro.org> " ) ;
MODULE_DESCRIPTION ( " Generic ARM big LITTLE cpufreq driver via DT " ) ;
2014-08-08 08:56:30 +02:00
MODULE_LICENSE ( " GPL v2 " ) ;