2012-11-27 17:05:26 +04:00
/*
* drivers / cpufreq / spear - cpufreq . c
*
* CPU Frequency Scaling for SPEAr platform
*
* Copyright ( C ) 2012 ST Microelectronics
* Deepak Sikri < deepak . sikri @ st . com >
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed " as is " without any
* warranty of any kind , whether express or implied .
*/
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/clk.h>
# include <linux/cpufreq.h>
# include <linux/err.h>
# include <linux/init.h>
# include <linux/module.h>
2013-06-17 18:09:15 +04:00
# include <linux/of_device.h>
2014-03-10 14:13:18 +04:00
# include <linux/platform_device.h>
2012-11-27 17:05:26 +04:00
# include <linux/slab.h>
# include <linux/types.h>
/* SPEAr CPUFreq driver data structure */
static struct {
struct clk * clk ;
unsigned int transition_latency ;
struct cpufreq_frequency_table * freq_tbl ;
u32 cnt ;
} spear_cpufreq ;
static struct clk * spear1340_cpu_get_possible_parent ( unsigned long newfreq )
{
struct clk * sys_pclk ;
int pclk ;
/*
* In SPEAr1340 , cpu clk ' s parent sys clk can take input from
* following sources
*/
const char * sys_clk_src [ ] = {
" sys_syn_clk " ,
" pll1_clk " ,
" pll2_clk " ,
" pll3_clk " ,
} ;
/*
* As sys clk can have multiple source with their own range
* limitation so we choose possible sources accordingly
*/
if ( newfreq < = 300000000 )
pclk = 0 ; /* src is sys_syn_clk */
else if ( newfreq > 300000000 & & newfreq < = 500000000 )
pclk = 3 ; /* src is pll3_clk */
else if ( newfreq = = 600000000 )
pclk = 1 ; /* src is pll1_clk */
else
return ERR_PTR ( - EINVAL ) ;
/* Get parent to sys clock */
sys_pclk = clk_get ( NULL , sys_clk_src [ pclk ] ) ;
if ( IS_ERR ( sys_pclk ) )
pr_err ( " Failed to get %s clock \n " , sys_clk_src [ pclk ] ) ;
return sys_pclk ;
}
/*
* In SPEAr1340 , we cannot use newfreq directly because we need to actually
* access a source clock ( clk ) which might not be ancestor of cpu at present .
* Hence in SPEAr1340 we would operate on source clock directly before switching
* cpu clock to it .
*/
static int spear1340_set_cpu_rate ( struct clk * sys_pclk , unsigned long newfreq )
{
struct clk * sys_clk ;
int ret = 0 ;
sys_clk = clk_get_parent ( spear_cpufreq . clk ) ;
if ( IS_ERR ( sys_clk ) ) {
pr_err ( " failed to get cpu's parent (sys) clock \n " ) ;
return PTR_ERR ( sys_clk ) ;
}
/* Set the rate of the source clock before changing the parent */
ret = clk_set_rate ( sys_pclk , newfreq ) ;
if ( ret ) {
pr_err ( " Failed to set sys clk rate to %lu \n " , newfreq ) ;
return ret ;
}
ret = clk_set_parent ( sys_clk , sys_pclk ) ;
if ( ret ) {
pr_err ( " Failed to set sys clk parent \n " ) ;
return ret ;
}
return 0 ;
}
static int spear_cpufreq_target ( struct cpufreq_policy * policy ,
2013-10-25 18:15:48 +04:00
unsigned int index )
2012-11-27 17:05:26 +04:00
{
2013-09-26 09:26:42 +04:00
long newfreq ;
2012-11-27 17:05:26 +04:00
struct clk * srcclk ;
2013-10-25 18:15:48 +04:00
int ret , mult = 1 ;
2012-11-27 17:05:26 +04:00
newfreq = spear_cpufreq . freq_tbl [ index ] . frequency * 1000 ;
2013-10-25 18:15:48 +04:00
2012-11-27 17:05:26 +04:00
if ( of_machine_is_compatible ( " st,spear1340 " ) ) {
/*
* SPEAr1340 is special in the sense that due to the possibility
* of multiple clock sources for cpu clk ' s parent we can have
* different clock source for different frequency of cpu clk .
* Hence we need to choose one from amongst these possible clock
* sources .
*/
srcclk = spear1340_cpu_get_possible_parent ( newfreq ) ;
if ( IS_ERR ( srcclk ) ) {
pr_err ( " Failed to get src clk \n " ) ;
return PTR_ERR ( srcclk ) ;
}
/* SPEAr1340: src clk is always 2 * intended cpu clk */
mult = 2 ;
} else {
/*
* src clock to be altered is ancestor of cpu clock . Hence we
* can directly work on cpu clk
*/
srcclk = spear_cpufreq . clk ;
}
newfreq = clk_round_rate ( srcclk , newfreq * mult ) ;
2013-11-26 06:04:34 +04:00
if ( newfreq < = 0 ) {
2012-11-27 17:05:26 +04:00
pr_err ( " clk_round_rate failed for cpu src clock \n " ) ;
return newfreq ;
}
if ( mult = = 2 )
ret = spear1340_set_cpu_rate ( srcclk , newfreq ) ;
else
ret = clk_set_rate ( spear_cpufreq . clk , newfreq ) ;
2013-08-14 18:08:24 +04:00
if ( ret )
2012-11-27 17:05:26 +04:00
pr_err ( " CPU Freq: cpu clk_set_rate failed: %d \n " , ret ) ;
return ret ;
}
static int spear_cpufreq_init ( struct cpufreq_policy * policy )
{
2014-01-09 19:08:43 +04:00
policy - > clk = spear_cpufreq . clk ;
2019-07-16 07:06:08 +03:00
cpufreq_generic_init ( policy , spear_cpufreq . freq_tbl ,
2013-10-03 19:12:10 +04:00
spear_cpufreq . transition_latency ) ;
2019-07-16 07:06:08 +03:00
return 0 ;
2012-11-27 17:05:26 +04:00
}
static struct cpufreq_driver spear_cpufreq_driver = {
. name = " cpufreq-spear " ,
2013-12-03 09:50:45 +04:00
. flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK ,
2013-10-03 18:58:27 +04:00
. verify = cpufreq_generic_frequency_table_verify ,
2013-10-25 18:15:48 +04:00
. target_index = spear_cpufreq_target ,
2014-01-09 19:08:43 +04:00
. get = cpufreq_generic_get ,
2012-11-27 17:05:26 +04:00
. init = spear_cpufreq_init ,
2013-10-03 18:58:27 +04:00
. attr = cpufreq_generic_attr ,
2012-11-27 17:05:26 +04:00
} ;
2014-03-10 14:13:18 +04:00
static int spear_cpufreq_probe ( struct platform_device * pdev )
2012-11-27 17:05:26 +04:00
{
struct device_node * np ;
const struct property * prop ;
struct cpufreq_frequency_table * freq_tbl ;
const __be32 * val ;
int cnt , i , ret ;
2013-06-17 18:09:15 +04:00
np = of_cpu_device_node_get ( 0 ) ;
2012-11-27 17:05:26 +04:00
if ( ! np ) {
2017-09-25 13:13:49 +03:00
pr_err ( " No cpu node found \n " ) ;
2012-11-27 17:05:26 +04:00
return - ENODEV ;
}
if ( of_property_read_u32 ( np , " clock-latency " ,
& spear_cpufreq . transition_latency ) )
spear_cpufreq . transition_latency = CPUFREQ_ETERNAL ;
prop = of_find_property ( np , " cpufreq_tbl " , NULL ) ;
if ( ! prop | | ! prop - > value ) {
2017-09-25 13:13:49 +03:00
pr_err ( " Invalid cpufreq_tbl \n " ) ;
2012-11-27 17:05:26 +04:00
ret = - ENODEV ;
goto out_put_node ;
}
cnt = prop - > length / sizeof ( u32 ) ;
val = prop - > value ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:03:40 +03:00
freq_tbl = kcalloc ( cnt + 1 , sizeof ( * freq_tbl ) , GFP_KERNEL ) ;
2012-11-27 17:05:26 +04:00
if ( ! freq_tbl ) {
ret = - ENOMEM ;
goto out_put_node ;
}
2014-03-28 17:41:46 +04:00
for ( i = 0 ; i < cnt ; i + + )
2012-11-27 17:05:26 +04:00
freq_tbl [ i ] . frequency = be32_to_cpup ( val + + ) ;
freq_tbl [ i ] . frequency = CPUFREQ_TABLE_END ;
spear_cpufreq . freq_tbl = freq_tbl ;
of_node_put ( np ) ;
spear_cpufreq . clk = clk_get ( NULL , " cpu_clk " ) ;
if ( IS_ERR ( spear_cpufreq . clk ) ) {
pr_err ( " Unable to get CPU clock \n " ) ;
ret = PTR_ERR ( spear_cpufreq . clk ) ;
goto out_put_mem ;
}
ret = cpufreq_register_driver ( & spear_cpufreq_driver ) ;
if ( ! ret )
return 0 ;
pr_err ( " failed register driver: %d \n " , ret ) ;
clk_put ( spear_cpufreq . clk ) ;
out_put_mem :
kfree ( freq_tbl ) ;
return ret ;
out_put_node :
of_node_put ( np ) ;
return ret ;
}
2014-03-10 14:13:18 +04:00
static struct platform_driver spear_cpufreq_platdrv = {
. driver = {
. name = " spear-cpufreq " ,
} ,
. probe = spear_cpufreq_probe ,
} ;
module_platform_driver ( spear_cpufreq_platdrv ) ;
2012-11-27 17:05:26 +04:00
MODULE_AUTHOR ( " Deepak Sikri <deepak.sikri@st.com> " ) ;
MODULE_DESCRIPTION ( " SPEAr CPUFreq driver " ) ;
MODULE_LICENSE ( " GPL " ) ;