2013-07-23 12:05:37 +05:30
/*
* OMAP APLL clock support
*
* Copyright ( C ) 2013 Texas Instruments , Inc .
*
* J Keerthy < j - keerthy @ ti . 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 .
*
* 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 .
*/
2015-06-19 15:00:46 -07:00
# include <linux/clk.h>
2013-07-23 12:05:37 +05:30
# include <linux/clk-provider.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/io.h>
# include <linux/err.h>
# include <linux/string.h>
# include <linux/log2.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/clk/ti.h>
# include <linux/delay.h>
2015-03-04 21:02:05 +02:00
# include "clock.h"
2013-07-23 12:05:37 +05:30
# define APLL_FORCE_LOCK 0x1
# define APLL_AUTO_IDLE 0x2
# define MAX_APLL_WAIT_TRIES 1000000
# undef pr_fmt
# define pr_fmt(fmt) "%s: " fmt, __func__
static int dra7_apll_enable ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
int r = 0 , i = 0 ;
struct dpll_data * ad ;
const char * clk_name ;
u8 state = 1 ;
u32 v ;
ad = clk - > dpll_data ;
if ( ! ad )
return - EINVAL ;
2015-08-12 11:42:23 -07:00
clk_name = clk_hw_get_name ( & clk - > hw ) ;
2013-07-23 12:05:37 +05:30
state < < = __ffs ( ad - > idlest_mask ) ;
/* Check is already locked */
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > idlest_reg ) ;
2013-07-23 12:05:37 +05:30
if ( ( v & ad - > idlest_mask ) = = state )
return r ;
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > control_reg ) ;
2013-07-23 12:05:37 +05:30
v & = ~ ad - > enable_mask ;
v | = APLL_FORCE_LOCK < < __ffs ( ad - > enable_mask ) ;
2017-02-09 11:24:37 +02:00
ti_clk_ll_ops - > clk_writel ( v , & ad - > control_reg ) ;
2013-07-23 12:05:37 +05:30
state < < = __ffs ( ad - > idlest_mask ) ;
while ( 1 ) {
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > idlest_reg ) ;
2013-07-23 12:05:37 +05:30
if ( ( v & ad - > idlest_mask ) = = state )
break ;
if ( i > MAX_APLL_WAIT_TRIES )
break ;
i + + ;
udelay ( 1 ) ;
}
if ( i = = MAX_APLL_WAIT_TRIES ) {
pr_warn ( " clock: %s failed transition to '%s' \n " ,
clk_name , ( state ) ? " locked " : " bypassed " ) ;
2014-05-19 19:25:48 +08:00
r = - EBUSY ;
} else
2013-07-23 12:05:37 +05:30
pr_debug ( " clock: %s transition to '%s' in %d loops \n " ,
clk_name , ( state ) ? " locked " : " bypassed " , i ) ;
return r ;
}
static void dra7_apll_disable ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
struct dpll_data * ad ;
u8 state = 1 ;
u32 v ;
ad = clk - > dpll_data ;
state < < = __ffs ( ad - > idlest_mask ) ;
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > control_reg ) ;
2013-07-23 12:05:37 +05:30
v & = ~ ad - > enable_mask ;
v | = APLL_AUTO_IDLE < < __ffs ( ad - > enable_mask ) ;
2017-02-09 11:24:37 +02:00
ti_clk_ll_ops - > clk_writel ( v , & ad - > control_reg ) ;
2013-07-23 12:05:37 +05:30
}
static int dra7_apll_is_enabled ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
struct dpll_data * ad ;
u32 v ;
ad = clk - > dpll_data ;
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > control_reg ) ;
2013-07-23 12:05:37 +05:30
v & = ad - > enable_mask ;
v > > = __ffs ( ad - > enable_mask ) ;
return v = = APLL_AUTO_IDLE ? 0 : 1 ;
}
static u8 dra7_init_apll_parent ( struct clk_hw * hw )
{
return 0 ;
}
static const struct clk_ops apll_ck_ops = {
. enable = & dra7_apll_enable ,
. disable = & dra7_apll_disable ,
. is_enabled = & dra7_apll_is_enabled ,
. get_parent = & dra7_init_apll_parent ,
} ;
2017-11-06 09:43:16 +02:00
static void __init omap_clk_register_apll ( void * user ,
2013-07-23 12:05:37 +05:30
struct device_node * node )
{
2017-11-06 09:43:16 +02:00
struct clk_hw * hw = user ;
2013-07-23 12:05:37 +05:30
struct clk_hw_omap * clk_hw = to_clk_hw_omap ( hw ) ;
struct dpll_data * ad = clk_hw - > dpll_data ;
struct clk * clk ;
2019-08-15 15:12:49 -07:00
const struct clk_init_data * init = clk_hw - > hw . init ;
2013-07-23 12:05:37 +05:30
2016-02-20 13:24:26 +02:00
clk = of_clk_get ( node , 0 ) ;
if ( IS_ERR ( clk ) ) {
2018-08-28 10:44:29 -05:00
pr_debug ( " clk-ref for %pOFn not ready, retry \n " ,
node ) ;
2016-02-20 13:24:26 +02:00
if ( ! ti_clk_retry_init ( node , hw , omap_clk_register_apll ) )
return ;
goto cleanup ;
}
2013-07-23 12:05:37 +05:30
2016-02-20 13:24:26 +02:00
ad - > clk_ref = __clk_get_hw ( clk ) ;
clk = of_clk_get ( node , 1 ) ;
if ( IS_ERR ( clk ) ) {
2018-08-28 10:44:29 -05:00
pr_debug ( " clk-bypass for %pOFn not ready, retry \n " ,
node ) ;
2013-07-23 12:05:37 +05:30
if ( ! ti_clk_retry_init ( node , hw , omap_clk_register_apll ) )
return ;
goto cleanup ;
}
2016-02-20 13:24:26 +02:00
ad - > clk_bypass = __clk_get_hw ( clk ) ;
2019-01-15 11:15:15 +02:00
clk = ti_clk_register_omap_hw ( NULL , & clk_hw - > hw , node - > name ) ;
2013-07-23 12:05:37 +05:30
if ( ! IS_ERR ( clk ) ) {
of_clk_add_provider ( node , of_clk_src_simple_get , clk ) ;
2019-08-15 15:12:49 -07:00
kfree ( init - > parent_names ) ;
kfree ( init ) ;
2013-07-23 12:05:37 +05:30
return ;
}
cleanup :
kfree ( clk_hw - > dpll_data ) ;
2019-08-15 15:12:49 -07:00
kfree ( init - > parent_names ) ;
kfree ( init ) ;
2013-07-23 12:05:37 +05:30
kfree ( clk_hw ) ;
}
static void __init of_dra7_apll_setup ( struct device_node * node )
{
struct dpll_data * ad = NULL ;
struct clk_hw_omap * clk_hw = NULL ;
struct clk_init_data * init = NULL ;
const char * * parent_names = NULL ;
2017-02-09 11:24:37 +02:00
int ret ;
2013-07-23 12:05:37 +05:30
ad = kzalloc ( sizeof ( * ad ) , GFP_KERNEL ) ;
clk_hw = kzalloc ( sizeof ( * clk_hw ) , GFP_KERNEL ) ;
init = kzalloc ( sizeof ( * init ) , GFP_KERNEL ) ;
if ( ! ad | | ! clk_hw | | ! init )
goto cleanup ;
clk_hw - > dpll_data = ad ;
clk_hw - > hw . init = init ;
init - > name = node - > name ;
init - > ops = & apll_ck_ops ;
init - > num_parents = of_clk_get_parent_count ( node ) ;
if ( init - > num_parents < 1 ) {
2018-08-28 10:44:29 -05:00
pr_err ( " dra7 apll %pOFn must have parent(s) \n " , node ) ;
2013-07-23 12:05:37 +05:30
goto cleanup ;
}
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-12 14:03:40 -07:00
parent_names = kcalloc ( init - > num_parents , sizeof ( char * ) , GFP_KERNEL ) ;
2013-07-23 12:05:37 +05:30
if ( ! parent_names )
goto cleanup ;
2015-07-06 22:59:06 -05:00
of_clk_parent_fill ( node , parent_names , init - > num_parents ) ;
2013-07-23 12:05:37 +05:30
init - > parent_names = parent_names ;
2017-02-09 11:24:37 +02:00
ret = ti_clk_get_reg_addr ( node , 0 , & ad - > control_reg ) ;
ret | = ti_clk_get_reg_addr ( node , 1 , & ad - > idlest_reg ) ;
2013-07-23 12:05:37 +05:30
2017-02-09 11:24:37 +02:00
if ( ret )
2013-07-23 12:05:37 +05:30
goto cleanup ;
ad - > idlest_mask = 0x1 ;
ad - > enable_mask = 0x3 ;
omap_clk_register_apll ( & clk_hw - > hw , node ) ;
return ;
cleanup :
kfree ( parent_names ) ;
kfree ( ad ) ;
kfree ( clk_hw ) ;
kfree ( init ) ;
}
CLK_OF_DECLARE ( dra7_apll_clock , " ti,dra7-apll-clock " , of_dra7_apll_setup ) ;
2014-02-24 16:06:34 +02:00
# define OMAP2_EN_APLL_LOCKED 0x3
# define OMAP2_EN_APLL_STOPPED 0x0
static int omap2_apll_is_enabled ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
struct dpll_data * ad = clk - > dpll_data ;
u32 v ;
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > control_reg ) ;
2014-02-24 16:06:34 +02:00
v & = ad - > enable_mask ;
v > > = __ffs ( ad - > enable_mask ) ;
return v = = OMAP2_EN_APLL_LOCKED ? 1 : 0 ;
}
static unsigned long omap2_apll_recalc ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
if ( omap2_apll_is_enabled ( hw ) )
return clk - > fixed_rate ;
return 0 ;
}
static int omap2_apll_enable ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
struct dpll_data * ad = clk - > dpll_data ;
u32 v ;
int i = 0 ;
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > control_reg ) ;
2014-02-24 16:06:34 +02:00
v & = ~ ad - > enable_mask ;
v | = OMAP2_EN_APLL_LOCKED < < __ffs ( ad - > enable_mask ) ;
2017-02-09 11:24:37 +02:00
ti_clk_ll_ops - > clk_writel ( v , & ad - > control_reg ) ;
2014-02-24 16:06:34 +02:00
while ( 1 ) {
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > idlest_reg ) ;
2014-02-24 16:06:34 +02:00
if ( v & ad - > idlest_mask )
break ;
if ( i > MAX_APLL_WAIT_TRIES )
break ;
i + + ;
udelay ( 1 ) ;
}
if ( i = = MAX_APLL_WAIT_TRIES ) {
pr_warn ( " %s failed to transition to locked \n " ,
2015-08-12 11:42:23 -07:00
clk_hw_get_name ( & clk - > hw ) ) ;
2014-02-24 16:06:34 +02:00
return - EBUSY ;
}
return 0 ;
}
static void omap2_apll_disable ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
struct dpll_data * ad = clk - > dpll_data ;
u32 v ;
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > control_reg ) ;
2014-02-24 16:06:34 +02:00
v & = ~ ad - > enable_mask ;
v | = OMAP2_EN_APLL_STOPPED < < __ffs ( ad - > enable_mask ) ;
2017-02-09 11:24:37 +02:00
ti_clk_ll_ops - > clk_writel ( v , & ad - > control_reg ) ;
2014-02-24 16:06:34 +02:00
}
2017-08-22 18:41:15 +05:30
static const struct clk_ops omap2_apll_ops = {
2014-02-24 16:06:34 +02:00
. enable = & omap2_apll_enable ,
. disable = & omap2_apll_disable ,
. is_enabled = & omap2_apll_is_enabled ,
. recalc_rate = & omap2_apll_recalc ,
} ;
static void omap2_apll_set_autoidle ( struct clk_hw_omap * clk , u32 val )
{
struct dpll_data * ad = clk - > dpll_data ;
u32 v ;
2017-02-09 11:24:37 +02:00
v = ti_clk_ll_ops - > clk_readl ( & ad - > autoidle_reg ) ;
2014-02-24 16:06:34 +02:00
v & = ~ ad - > autoidle_mask ;
v | = val < < __ffs ( ad - > autoidle_mask ) ;
2017-02-09 11:24:37 +02:00
ti_clk_ll_ops - > clk_writel ( v , & ad - > control_reg ) ;
2014-02-24 16:06:34 +02:00
}
# define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP 0x3
# define OMAP2_APLL_AUTOIDLE_DISABLE 0x0
static void omap2_apll_allow_idle ( struct clk_hw_omap * clk )
{
omap2_apll_set_autoidle ( clk , OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP ) ;
}
static void omap2_apll_deny_idle ( struct clk_hw_omap * clk )
{
omap2_apll_set_autoidle ( clk , OMAP2_APLL_AUTOIDLE_DISABLE ) ;
}
2015-11-15 20:48:14 +01:00
static const struct clk_hw_omap_ops omap2_apll_hwops = {
2014-02-24 16:06:34 +02:00
. allow_idle = & omap2_apll_allow_idle ,
. deny_idle = & omap2_apll_deny_idle ,
} ;
static void __init of_omap2_apll_setup ( struct device_node * node )
{
struct dpll_data * ad = NULL ;
struct clk_hw_omap * clk_hw = NULL ;
struct clk_init_data * init = NULL ;
struct clk * clk ;
const char * parent_name ;
u32 val ;
2017-02-09 11:24:37 +02:00
int ret ;
2014-02-24 16:06:34 +02:00
2014-06-16 12:32:33 +03:00
ad = kzalloc ( sizeof ( * ad ) , GFP_KERNEL ) ;
2014-02-24 16:06:34 +02:00
clk_hw = kzalloc ( sizeof ( * clk_hw ) , GFP_KERNEL ) ;
init = kzalloc ( sizeof ( * init ) , GFP_KERNEL ) ;
if ( ! ad | | ! clk_hw | | ! init )
goto cleanup ;
clk_hw - > dpll_data = ad ;
clk_hw - > hw . init = init ;
init - > ops = & omap2_apll_ops ;
init - > name = node - > name ;
clk_hw - > ops = & omap2_apll_hwops ;
init - > num_parents = of_clk_get_parent_count ( node ) ;
if ( init - > num_parents ! = 1 ) {
2018-08-28 10:44:29 -05:00
pr_err ( " %pOFn must have one parent \n " , node ) ;
2014-02-24 16:06:34 +02:00
goto cleanup ;
}
parent_name = of_clk_get_parent_name ( node , 0 ) ;
init - > parent_names = & parent_name ;
if ( of_property_read_u32 ( node , " ti,clock-frequency " , & val ) ) {
2018-08-28 10:44:29 -05:00
pr_err ( " %pOFn missing clock-frequency \n " , node ) ;
2014-02-24 16:06:34 +02:00
goto cleanup ;
}
clk_hw - > fixed_rate = val ;
if ( of_property_read_u32 ( node , " ti,bit-shift " , & val ) ) {
2018-08-28 10:44:29 -05:00
pr_err ( " %pOFn missing bit-shift \n " , node ) ;
2014-02-24 16:06:34 +02:00
goto cleanup ;
}
clk_hw - > enable_bit = val ;
ad - > enable_mask = 0x3 < < val ;
ad - > autoidle_mask = 0x3 < < val ;
if ( of_property_read_u32 ( node , " ti,idlest-shift " , & val ) ) {
2018-08-28 10:44:29 -05:00
pr_err ( " %pOFn missing idlest-shift \n " , node ) ;
2014-02-24 16:06:34 +02:00
goto cleanup ;
}
ad - > idlest_mask = 1 < < val ;
2017-02-09 11:24:37 +02:00
ret = ti_clk_get_reg_addr ( node , 0 , & ad - > control_reg ) ;
ret | = ti_clk_get_reg_addr ( node , 1 , & ad - > autoidle_reg ) ;
ret | = ti_clk_get_reg_addr ( node , 2 , & ad - > idlest_reg ) ;
2014-02-24 16:06:34 +02:00
2017-02-09 11:24:37 +02:00
if ( ret )
2014-02-24 16:06:34 +02:00
goto cleanup ;
2019-01-15 11:15:15 +02:00
clk = ti_clk_register_omap_hw ( NULL , & clk_hw - > hw , node - > name ) ;
2014-02-24 16:06:34 +02:00
if ( ! IS_ERR ( clk ) ) {
of_clk_add_provider ( node , of_clk_src_simple_get , clk ) ;
kfree ( init ) ;
return ;
}
cleanup :
kfree ( ad ) ;
kfree ( clk_hw ) ;
kfree ( init ) ;
}
CLK_OF_DECLARE ( omap2_apll_clock , " ti,omap2-apll-clock " ,
of_omap2_apll_setup ) ;