@ -29,6 +29,7 @@
# include <linux/clkdev.h>
# include "soc.h"
# include "clockdomain.h"
# include "clock.h"
# include "cm2xxx_3xxx.h"
# include "cm-regbits-34xx.h"
@ -42,7 +43,11 @@
/* Private functions */
/* _omap3_dpll_write_clken - write clken_bits arg to a DPLL's enable bits */
# ifdef CONFIG_COMMON_CLK
static void _omap3_dpll_write_clken ( struct clk_hw_omap * clk , u8 clken_bits )
# else
static void _omap3_dpll_write_clken ( struct clk * clk , u8 clken_bits )
# endif
{
const struct dpll_data * dd ;
u32 v ;
@ -56,7 +61,11 @@ static void _omap3_dpll_write_clken(struct clk *clk, u8 clken_bits)
}
/* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
# ifdef CONFIG_COMMON_CLK
static int _omap3_wait_dpll_status ( struct clk_hw_omap * clk , u8 state )
# else
static int _omap3_wait_dpll_status ( struct clk * clk , u8 state )
# endif
{
const struct dpll_data * dd ;
int i = 0 ;
@ -64,7 +73,11 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
const char * clk_name ;
dd = clk - > dpll_data ;
# ifdef CONFIG_COMMON_CLK
clk_name = __clk_get_name ( clk - > hw . clk ) ;
# else
clk_name = __clk_get_name ( clk ) ;
# endif
state < < = __ffs ( dd - > idlest_mask ) ;
@ -88,7 +101,11 @@ static int _omap3_wait_dpll_status(struct clk *clk, u8 state)
}
/* From 3430 TRM ES2 4.7.6.2 */
# ifdef CONFIG_COMMON_CLK
static u16 _omap3_dpll_compute_freqsel ( struct clk_hw_omap * clk , u8 n )
# else
static u16 _omap3_dpll_compute_freqsel ( struct clk * clk , u8 n )
# endif
{
unsigned long fint ;
u16 f = 0 ;
@ -133,14 +150,22 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
* locked successfully , return 0 ; if the DPLL did not lock in the time
* allotted , or DPLL3 was passed in , return - EINVAL .
*/
# ifdef CONFIG_COMMON_CLK
static int _omap3_noncore_dpll_lock ( struct clk_hw_omap * clk )
# else
static int _omap3_noncore_dpll_lock ( struct clk * clk )
# endif
{
const struct dpll_data * dd ;
u8 ai ;
u8 state = 1 ;
int r = 0 ;
# ifdef CONFIG_COMMON_CLK
pr_debug ( " clock: locking DPLL %s \n " , __clk_get_name ( clk - > hw . clk ) ) ;
# else
pr_debug ( " clock: locking DPLL %s \n " , __clk_get_name ( clk ) ) ;
# endif
dd = clk - > dpll_data ;
state < < = __ffs ( dd - > idlest_mask ) ;
@ -178,7 +203,11 @@ done:
* DPLL3 was passed in , or the DPLL does not support low - power bypass ,
* return - EINVAL .
*/
# ifdef CONFIG_COMMON_CLK
static int _omap3_noncore_dpll_bypass ( struct clk_hw_omap * clk )
# else
static int _omap3_noncore_dpll_bypass ( struct clk * clk )
# endif
{
int r ;
u8 ai ;
@ -187,7 +216,11 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
return - EINVAL ;
pr_debug ( " clock: configuring DPLL %s for low-power bypass \n " ,
# ifdef CONFIG_COMMON_CLK
__clk_get_name ( clk - > hw . clk ) ) ;
# else
__clk_get_name ( clk ) ) ;
# endif
ai = omap3_dpll_autoidle_read ( clk ) ;
@ -210,14 +243,22 @@ static int _omap3_noncore_dpll_bypass(struct clk *clk)
* code . If DPLL3 was passed in , or the DPLL does not support
* low - power stop , return - EINVAL ; otherwise , return 0.
*/
# ifdef CONFIG_COMMON_CLK
static int _omap3_noncore_dpll_stop ( struct clk_hw_omap * clk )
# else
static int _omap3_noncore_dpll_stop ( struct clk * clk )
# endif
{
u8 ai ;
if ( ! ( clk - > dpll_data - > modes & ( 1 < < DPLL_LOW_POWER_STOP ) ) )
return - EINVAL ;
# ifdef CONFIG_COMMON_CLK
pr_debug ( " clock: stopping DPLL %s \n " , __clk_get_name ( clk - > hw . clk ) ) ;
# else
pr_debug ( " clock: stopping DPLL %s \n " , __clk_get_name ( clk ) ) ;
# endif
ai = omap3_dpll_autoidle_read ( clk ) ;
@ -241,11 +282,19 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
* XXX This code is not needed for 3430 / AM35xx ; can it be optimized
* out in non - multi - OMAP builds for those chips ?
*/
# ifdef CONFIG_COMMON_CLK
static void _lookup_dco ( struct clk_hw_omap * clk , u8 * dco , u16 m , u8 n )
# else
static void _lookup_dco ( struct clk * clk , u8 * dco , u16 m , u8 n )
# endif
{
unsigned long fint , clkinp ; /* watch out for overflow */
# ifdef CONFIG_COMMON_CLK
clkinp = __clk_get_rate ( __clk_get_parent ( clk - > hw . clk ) ) ;
# else
clkinp = __clk_get_rate ( __clk_get_parent ( clk ) ) ;
# endif
fint = ( clkinp / n ) * m ;
if ( fint < 1000000000 )
@ -266,12 +315,20 @@ static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
* XXX This code is not needed for 3430 / AM35xx ; can it be optimized
* out in non - multi - OMAP builds for those chips ?
*/
# ifdef CONFIG_COMMON_CLK
static void _lookup_sddiv ( struct clk_hw_omap * clk , u8 * sd_div , u16 m , u8 n )
# else
static void _lookup_sddiv ( struct clk * clk , u8 * sd_div , u16 m , u8 n )
# endif
{
unsigned long clkinp , sd ; /* watch out for overflow */
int mod1 , mod2 ;
# ifdef CONFIG_COMMON_CLK
clkinp = __clk_get_rate ( __clk_get_parent ( clk - > hw . clk ) ) ;
# else
clkinp = __clk_get_rate ( __clk_get_parent ( clk ) ) ;
# endif
/*
* target sigma - delta to near 250 MHz
@ -298,7 +355,12 @@ static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
* Program the DPLL with the supplied M , N values , and wait for the DPLL to
* lock . . Returns - EINVAL upon error , or 0 upon success .
*/
# ifdef CONFIG_COMMON_CLK
static int omap3_noncore_dpll_program ( struct clk_hw_omap * clk , u16 m , u8 n ,
u16 freqsel )
# else
static int omap3_noncore_dpll_program ( struct clk * clk , u16 m , u8 n , u16 freqsel )
# endif
{
struct dpll_data * dd = clk - > dpll_data ;
u8 dco , sd_div ;
@ -355,8 +417,14 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
*
* Recalculate and propagate the DPLL rate .
*/
# ifdef CONFIG_COMMON_CLK
unsigned long omap3_dpll_recalc ( struct clk_hw * hw , unsigned long parent_rate )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
# else
unsigned long omap3_dpll_recalc ( struct clk * clk )
{
# endif
return omap2_get_dpll_rate ( clk ) ;
}
@ -376,8 +444,14 @@ unsigned long omap3_dpll_recalc(struct clk *clk)
* support low - power stop , or if the DPLL took too long to enter
* bypass or lock , return - EINVAL ; otherwise , return 0.
*/
# ifdef CONFIG_COMMON_CLK
int omap3_noncore_dpll_enable ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
# else
int omap3_noncore_dpll_enable ( struct clk * clk )
{
# endif
int r ;
struct dpll_data * dd ;
struct clk * parent ;
@ -386,15 +460,34 @@ int omap3_noncore_dpll_enable(struct clk *clk)
if ( ! dd )
return - EINVAL ;
# ifdef CONFIG_COMMON_CLK
if ( clk - > clkdm ) {
r = clkdm_clk_enable ( clk - > clkdm , hw - > clk ) ;
if ( r ) {
WARN ( 1 ,
" %s: could not enable %s's clockdomain %s: %d \n " ,
__func__ , __clk_get_name ( hw - > clk ) ,
clk - > clkdm - > name , r ) ;
return r ;
}
}
parent = __clk_get_parent ( hw - > clk ) ;
if ( __clk_get_rate ( hw - > clk ) = = __clk_get_rate ( dd - > clk_bypass ) ) {
# else
parent = __clk_get_parent ( clk ) ;
if ( __clk_get_rate ( clk ) = = __clk_get_rate ( dd - > clk_bypass ) ) {
# endif
WARN_ON ( parent ! = dd - > clk_bypass ) ;
r = _omap3_noncore_dpll_bypass ( clk ) ;
} else {
WARN_ON ( parent ! = dd - > clk_ref ) ;
r = _omap3_noncore_dpll_lock ( clk ) ;
}
# ifndef CONFIG_COMMON_CLK
/*
* FIXME : this is dubious - if clk - > rate has changed , what about
* propagating ?
@ -402,6 +495,7 @@ int omap3_noncore_dpll_enable(struct clk *clk)
if ( ! r )
clk - > rate = ( clk - > recalc ) ? clk - > recalc ( clk ) :
omap2_get_dpll_rate ( clk ) ;
# endif
return r ;
}
@ -413,9 +507,21 @@ int omap3_noncore_dpll_enable(struct clk *clk)
* Instructs a non - CORE DPLL to enter low - power stop . This function is
* intended for use in struct clkops . No return value .
*/
# ifdef CONFIG_COMMON_CLK
void omap3_noncore_dpll_disable ( struct clk_hw * hw )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
_omap3_noncore_dpll_stop ( clk ) ;
if ( clk - > clkdm )
clkdm_clk_disable ( clk - > clkdm , hw - > clk ) ;
# else
void omap3_noncore_dpll_disable ( struct clk * clk )
{
_omap3_noncore_dpll_stop ( clk ) ;
if ( clk - > clkdm )
clkdm_clk_disable ( clk - > clkdm , clk ) ;
# endif
}
@ -432,6 +538,77 @@ void omap3_noncore_dpll_disable(struct clk *clk)
* target rate if it hasn ' t been done already , then program and lock
* the DPLL . Returns - EINVAL upon error , or 0 upon success .
*/
# ifdef CONFIG_COMMON_CLK
int omap3_noncore_dpll_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct clk_hw_omap * clk = to_clk_hw_omap ( hw ) ;
struct clk * new_parent = NULL ;
u16 freqsel = 0 ;
struct dpll_data * dd ;
int ret ;
if ( ! hw | | ! rate )
return - EINVAL ;
dd = clk - > dpll_data ;
if ( ! dd )
return - EINVAL ;
__clk_prepare ( dd - > clk_bypass ) ;
clk_enable ( dd - > clk_bypass ) ;
__clk_prepare ( dd - > clk_ref ) ;
clk_enable ( dd - > clk_ref ) ;
if ( __clk_get_rate ( dd - > clk_bypass ) = = rate & &
( dd - > modes & ( 1 < < DPLL_LOW_POWER_BYPASS ) ) ) {
pr_debug ( " %s: %s: set rate: entering bypass. \n " ,
__func__ , __clk_get_name ( hw - > clk ) ) ;
ret = _omap3_noncore_dpll_bypass ( clk ) ;
if ( ! ret )
new_parent = dd - > clk_bypass ;
} else {
if ( dd - > last_rounded_rate ! = rate )
rate = __clk_round_rate ( hw - > clk , rate ) ;
if ( dd - > last_rounded_rate = = 0 )
return - EINVAL ;
/* No freqsel on OMAP4 and OMAP3630 */
if ( ! cpu_is_omap44xx ( ) & & ! cpu_is_omap3630 ( ) ) {
freqsel = _omap3_dpll_compute_freqsel ( clk ,
dd - > last_rounded_n ) ;
if ( ! freqsel )
WARN_ON ( 1 ) ;
}
pr_debug ( " %s: %s: set rate: locking rate to %lu. \n " ,
__func__ , __clk_get_name ( hw - > clk ) , rate ) ;
ret = omap3_noncore_dpll_program ( clk , dd - > last_rounded_m ,
dd - > last_rounded_n , freqsel ) ;
if ( ! ret )
new_parent = dd - > clk_ref ;
}
/*
* FIXME - this is all wrong . common code handles reparenting and
* migrating prepare / enable counts . dplls should be a multiplexer
* clock and this should be a set_parent operation so that all of that
* stuff is inherited for free
*/
if ( ! ret )
__clk_reparent ( hw - > clk , new_parent ) ;
clk_disable ( dd - > clk_ref ) ;
__clk_unprepare ( dd - > clk_ref ) ;
clk_disable ( dd - > clk_bypass ) ;
__clk_unprepare ( dd - > clk_bypass ) ;
return 0 ;
}
# else
int omap3_noncore_dpll_set_rate ( struct clk * clk , unsigned long rate )
{
struct clk * new_parent = NULL ;
@ -509,6 +686,7 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
return 0 ;
}
# endif
/* DPLL autoidle read/set code */
@ -520,7 +698,11 @@ int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
* - EINVAL if passed a null pointer or if the struct clk does not
* appear to refer to a DPLL .
*/
# ifdef CONFIG_COMMON_CLK
u32 omap3_dpll_autoidle_read ( struct clk_hw_omap * clk )
# else
u32 omap3_dpll_autoidle_read ( struct clk * clk )
# endif
{
const struct dpll_data * dd ;
u32 v ;
@ -549,7 +731,11 @@ u32 omap3_dpll_autoidle_read(struct clk *clk)
* OMAP3430 . The DPLL will enter low - power stop when its downstream
* clocks are gated . No return value .
*/
# ifdef CONFIG_COMMON_CLK
void omap3_dpll_allow_idle ( struct clk_hw_omap * clk )
# else
void omap3_dpll_allow_idle ( struct clk * clk )
# endif
{
const struct dpll_data * dd ;
u32 v ;
@ -560,8 +746,10 @@ void omap3_dpll_allow_idle(struct clk *clk)
dd = clk - > dpll_data ;
if ( ! dd - > autoidle_reg ) {
# ifndef CONFIG_COMMON_CLK
pr_debug ( " clock: DPLL %s: autoidle not supported \n " ,
__clk_get_name ( clk ) ) ;
# endif
return ;
}
@ -583,7 +771,11 @@ void omap3_dpll_allow_idle(struct clk *clk)
*
* Disable DPLL automatic idle control . No return value .
*/
# ifdef CONFIG_COMMON_CLK
void omap3_dpll_deny_idle ( struct clk_hw_omap * clk )
# else
void omap3_dpll_deny_idle ( struct clk * clk )
# endif
{
const struct dpll_data * dd ;
u32 v ;
@ -594,8 +786,10 @@ void omap3_dpll_deny_idle(struct clk *clk)
dd = clk - > dpll_data ;
if ( ! dd - > autoidle_reg ) {
# ifndef CONFIG_COMMON_CLK
pr_debug ( " clock: DPLL %s: autoidle not supported \n " ,
__clk_get_name ( clk ) ) ;
# endif
return ;
}
@ -615,6 +809,27 @@ void omap3_dpll_deny_idle(struct clk *clk)
* Using parent clock DPLL data , look up DPLL state . If locked , set our
* rate to the dpll_clk * 2 ; otherwise , just use dpll_clk .
*/
# ifdef CONFIG_COMMON_CLK
unsigned long omap3_clkoutx2_recalc ( struct clk_hw * hw ,
unsigned long parent_rate )
{
const struct dpll_data * dd ;
unsigned long rate ;
u32 v ;
struct clk_hw_omap * pclk = NULL ;
struct clk * parent ;
/* Walk up the parents of clk, looking for a DPLL */
do {
do {
parent = __clk_get_parent ( hw - > clk ) ;
hw = __clk_get_hw ( parent ) ;
} while ( hw & & ( __clk_get_flags ( hw - > clk ) & CLK_IS_BASIC ) ) ;
if ( ! hw )
break ;
pclk = to_clk_hw_omap ( hw ) ;
} while ( pclk & & ! pclk - > dpll_data ) ;
# else
unsigned long omap3_clkoutx2_recalc ( struct clk * clk )
{
const struct dpll_data * dd ;
@ -628,6 +843,8 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
while ( pclk & & ! pclk - > dpll_data )
pclk = __clk_get_parent ( pclk ) ;
parent_rate = __clk_get_rate ( __clk_get_parent ( clk ) ) ;
# endif
/* clk does not have a DPLL as a parent? error in the clock data */
if ( ! pclk ) {
WARN_ON ( 1 ) ;
@ -638,7 +855,6 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
WARN_ON ( ! dd - > enable_mask ) ;
parent_rate = __clk_get_rate ( __clk_get_parent ( clk ) ) ;
v = __raw_readl ( dd - > control_reg ) & dd - > enable_mask ;
v > > = __ffs ( dd - > enable_mask ) ;
if ( ( v ! = OMAP3XXX_EN_DPLL_LOCKED ) | | ( dd - > flags & DPLL_J_TYPE ) )
@ -649,7 +865,12 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
}
/* OMAP3/4 non-CORE DPLL clkops */
# ifdef CONFIG_COMMON_CLK
const struct clk_hw_omap_ops clkhwops_omap3_dpll = {
. allow_idle = omap3_dpll_allow_idle ,
. deny_idle = omap3_dpll_deny_idle ,
} ;
# else
const struct clkops clkops_omap3_noncore_dpll_ops = {
. enable = omap3_noncore_dpll_enable ,
. disable = omap3_noncore_dpll_disable ,
@ -661,3 +882,4 @@ const struct clkops clkops_omap3_core_dpll_ops = {
. allow_idle = omap3_dpll_allow_idle ,
. deny_idle = omap3_dpll_deny_idle ,
} ;
# endif