2015-01-14 01:51:27 +03:00
/*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2.
*
* 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-20 01:00:46 +03:00
# include <linux/clk.h>
2015-01-14 01:51:27 +03:00
# include <linux/clk-provider.h>
# include <linux/delay.h>
# include <linux/err.h>
2015-03-17 04:04:20 +03:00
# include <linux/math64.h>
2015-01-14 01:51:27 +03:00
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/clk/ti.h>
/* FAPLL Control Register PLL_CTRL */
2015-03-23 01:35:26 +03:00
# define FAPLL_MAIN_MULT_N_SHIFT 16
# define FAPLL_MAIN_DIV_P_SHIFT 8
2015-01-14 01:51:27 +03:00
# define FAPLL_MAIN_LOCK BIT(7)
# define FAPLL_MAIN_PLLEN BIT(3)
# define FAPLL_MAIN_BP BIT(2)
# define FAPLL_MAIN_LOC_CTL BIT(0)
2015-03-23 01:35:26 +03:00
# define FAPLL_MAIN_MAX_MULT_N 0xffff
# define FAPLL_MAIN_MAX_DIV_P 0xff
# define FAPLL_MAIN_CLEAR_MASK \
( ( FAPLL_MAIN_MAX_MULT_N < < FAPLL_MAIN_MULT_N_SHIFT ) | \
( FAPLL_MAIN_DIV_P_SHIFT < < FAPLL_MAIN_DIV_P_SHIFT ) | \
FAPLL_MAIN_LOC_CTL )
2015-01-14 01:51:27 +03:00
/* FAPLL powerdown register PWD */
# define FAPLL_PWD_OFFSET 4
# define MAX_FAPLL_OUTPUTS 7
# define FAPLL_MAX_RETRIES 1000
# define to_fapll(_hw) container_of(_hw, struct fapll_data, hw)
# define to_synth(_hw) container_of(_hw, struct fapll_synth, hw)
/* The bypass bit is inverted on the ddr_pll.. */
# define fapll_is_ddr_pll(va) (((u32)(va) & 0xffff) == 0x0440)
/*
* The audio_pll_clk1 input is hard wired to the 27 MHz bypass clock ,
* and the audio_pll_clk1 synthesizer is hardwared to 32 KiHz output .
*/
# define is_ddr_pll_clk1(va) (((u32)(va) & 0xffff) == 0x044c)
# define is_audio_pll_clk1(va) (((u32)(va) & 0xffff) == 0x04a8)
/* Synthesizer divider register */
# define SYNTH_LDMDIV1 BIT(8)
/* Synthesizer frequency register */
# define SYNTH_LDFREQ BIT(31)
2015-03-17 04:04:20 +03:00
# define SYNTH_PHASE_K 8
# define SYNTH_MAX_INT_DIV 0xf
2015-03-23 01:35:24 +03:00
# define SYNTH_MAX_DIV_M 0xff
2015-01-14 01:51:27 +03:00
struct fapll_data {
struct clk_hw hw ;
void __iomem * base ;
const char * name ;
struct clk * clk_ref ;
struct clk * clk_bypass ;
struct clk_onecell_data outputs ;
bool bypass_bit_inverted ;
} ;
struct fapll_synth {
struct clk_hw hw ;
struct fapll_data * fd ;
int index ;
void __iomem * freq ;
void __iomem * div ;
const char * name ;
struct clk * clk_pll ;
} ;
static bool ti_fapll_clock_is_bypass ( struct fapll_data * fd )
{
u32 v = readl_relaxed ( fd - > base ) ;
if ( fd - > bypass_bit_inverted )
return ! ( v & FAPLL_MAIN_BP ) ;
else
return ! ! ( v & FAPLL_MAIN_BP ) ;
}
2015-03-23 01:35:26 +03:00
static void ti_fapll_set_bypass ( struct fapll_data * fd )
{
u32 v = readl_relaxed ( fd - > base ) ;
if ( fd - > bypass_bit_inverted )
v & = ~ FAPLL_MAIN_BP ;
else
v | = FAPLL_MAIN_BP ;
writel_relaxed ( v , fd - > base ) ;
}
static void ti_fapll_clear_bypass ( struct fapll_data * fd )
{
u32 v = readl_relaxed ( fd - > base ) ;
if ( fd - > bypass_bit_inverted )
v | = FAPLL_MAIN_BP ;
else
v & = ~ FAPLL_MAIN_BP ;
writel_relaxed ( v , fd - > base ) ;
}
static int ti_fapll_wait_lock ( struct fapll_data * fd )
{
int retries = FAPLL_MAX_RETRIES ;
u32 v ;
while ( ( v = readl_relaxed ( fd - > base ) ) ) {
if ( v & FAPLL_MAIN_LOCK )
return 0 ;
if ( retries - - < = 0 )
break ;
udelay ( 1 ) ;
}
pr_err ( " %s failed to lock \n " , fd - > name ) ;
return - ETIMEDOUT ;
}
2015-01-14 01:51:27 +03:00
static int ti_fapll_enable ( struct clk_hw * hw )
{
struct fapll_data * fd = to_fapll ( hw ) ;
u32 v = readl_relaxed ( fd - > base ) ;
2015-01-28 20:00:49 +03:00
v | = FAPLL_MAIN_PLLEN ;
2015-01-14 01:51:27 +03:00
writel_relaxed ( v , fd - > base ) ;
2015-03-23 01:35:26 +03:00
ti_fapll_wait_lock ( fd ) ;
2015-01-14 01:51:27 +03:00
return 0 ;
}
static void ti_fapll_disable ( struct clk_hw * hw )
{
struct fapll_data * fd = to_fapll ( hw ) ;
u32 v = readl_relaxed ( fd - > base ) ;
2015-01-28 20:00:49 +03:00
v & = ~ FAPLL_MAIN_PLLEN ;
2015-01-14 01:51:27 +03:00
writel_relaxed ( v , fd - > base ) ;
}
static int ti_fapll_is_enabled ( struct clk_hw * hw )
{
struct fapll_data * fd = to_fapll ( hw ) ;
u32 v = readl_relaxed ( fd - > base ) ;
2015-01-28 20:00:49 +03:00
return v & FAPLL_MAIN_PLLEN ;
2015-01-14 01:51:27 +03:00
}
static unsigned long ti_fapll_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct fapll_data * fd = to_fapll ( hw ) ;
u32 fapll_n , fapll_p , v ;
2015-11-04 07:17:11 +03:00
u64 rate ;
2015-01-14 01:51:27 +03:00
if ( ti_fapll_clock_is_bypass ( fd ) )
return parent_rate ;
rate = parent_rate ;
/* PLL pre-divider is P and multiplier is N */
v = readl_relaxed ( fd - > base ) ;
fapll_p = ( v > > 8 ) & 0xff ;
if ( fapll_p )
do_div ( rate , fapll_p ) ;
fapll_n = v > > 16 ;
if ( fapll_n )
rate * = fapll_n ;
return rate ;
}
static u8 ti_fapll_get_parent ( struct clk_hw * hw )
{
struct fapll_data * fd = to_fapll ( hw ) ;
if ( ti_fapll_clock_is_bypass ( fd ) )
return 1 ;
return 0 ;
}
2015-03-23 01:35:26 +03:00
static int ti_fapll_set_div_mult ( unsigned long rate ,
unsigned long parent_rate ,
u32 * pre_div_p , u32 * mult_n )
{
/*
* So far no luck getting decent clock with PLL divider ,
* PLL does not seem to lock and the signal does not look
* right . It seems the divider can only be used together
* with the multiplier ?
*/
if ( rate < parent_rate ) {
pr_warn ( " FAPLL main divider rates unsupported \n " ) ;
return - EINVAL ;
}
* mult_n = rate / parent_rate ;
if ( * mult_n > FAPLL_MAIN_MAX_MULT_N )
return - EINVAL ;
* pre_div_p = 1 ;
return 0 ;
}
static long ti_fapll_round_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long * parent_rate )
{
u32 pre_div_p , mult_n ;
int error ;
if ( ! rate )
return - EINVAL ;
error = ti_fapll_set_div_mult ( rate , * parent_rate ,
& pre_div_p , & mult_n ) ;
if ( error )
return error ;
rate = * parent_rate / pre_div_p ;
rate * = mult_n ;
return rate ;
}
static int ti_fapll_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct fapll_data * fd = to_fapll ( hw ) ;
u32 pre_div_p , mult_n , v ;
int error ;
if ( ! rate )
return - EINVAL ;
error = ti_fapll_set_div_mult ( rate , parent_rate ,
& pre_div_p , & mult_n ) ;
if ( error )
return error ;
ti_fapll_set_bypass ( fd ) ;
v = readl_relaxed ( fd - > base ) ;
v & = ~ FAPLL_MAIN_CLEAR_MASK ;
v | = pre_div_p < < FAPLL_MAIN_DIV_P_SHIFT ;
v | = mult_n < < FAPLL_MAIN_MULT_N_SHIFT ;
writel_relaxed ( v , fd - > base ) ;
if ( ti_fapll_is_enabled ( hw ) )
ti_fapll_wait_lock ( fd ) ;
ti_fapll_clear_bypass ( fd ) ;
return 0 ;
}
2015-01-14 01:51:27 +03:00
static struct clk_ops ti_fapll_ops = {
. enable = ti_fapll_enable ,
. disable = ti_fapll_disable ,
. is_enabled = ti_fapll_is_enabled ,
. recalc_rate = ti_fapll_recalc_rate ,
. get_parent = ti_fapll_get_parent ,
2015-03-23 01:35:26 +03:00
. round_rate = ti_fapll_round_rate ,
. set_rate = ti_fapll_set_rate ,
2015-01-14 01:51:27 +03:00
} ;
static int ti_fapll_synth_enable ( struct clk_hw * hw )
{
struct fapll_synth * synth = to_synth ( hw ) ;
u32 v = readl_relaxed ( synth - > fd - > base + FAPLL_PWD_OFFSET ) ;
v & = ~ ( 1 < < synth - > index ) ;
writel_relaxed ( v , synth - > fd - > base + FAPLL_PWD_OFFSET ) ;
return 0 ;
}
static void ti_fapll_synth_disable ( struct clk_hw * hw )
{
struct fapll_synth * synth = to_synth ( hw ) ;
u32 v = readl_relaxed ( synth - > fd - > base + FAPLL_PWD_OFFSET ) ;
v | = 1 < < synth - > index ;
writel_relaxed ( v , synth - > fd - > base + FAPLL_PWD_OFFSET ) ;
}
static int ti_fapll_synth_is_enabled ( struct clk_hw * hw )
{
struct fapll_synth * synth = to_synth ( hw ) ;
u32 v = readl_relaxed ( synth - > fd - > base + FAPLL_PWD_OFFSET ) ;
return ! ( v & ( 1 < < synth - > index ) ) ;
}
/*
* See dm816x TRM chapter 1.10 .3 Flying Adder PLL fore more info
*/
static unsigned long ti_fapll_synth_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct fapll_synth * synth = to_synth ( hw ) ;
u32 synth_div_m ;
2015-11-04 07:17:11 +03:00
u64 rate ;
2015-01-14 01:51:27 +03:00
/* The audio_pll_clk1 is hardwired to produce 32.768KiHz clock */
if ( ! synth - > div )
return 32768 ;
/*
* PLL in bypass sets the synths in bypass mode too . The PLL rate
* can be also be set to 27 MHz , so we can ' t use parent_rate to
* check for bypass mode .
*/
if ( ti_fapll_clock_is_bypass ( synth - > fd ) )
return parent_rate ;
rate = parent_rate ;
/*
* Synth frequency integer and fractional divider .
* Note that the phase output K is 8 , so the result needs
2015-03-17 04:04:20 +03:00
* to be multiplied by SYNTH_PHASE_K .
2015-01-14 01:51:27 +03:00
*/
if ( synth - > freq ) {
u32 v , synth_int_div , synth_frac_div , synth_div_freq ;
v = readl_relaxed ( synth - > freq ) ;
synth_int_div = ( v > > 24 ) & 0xf ;
synth_frac_div = v & 0xffffff ;
synth_div_freq = ( synth_int_div * 10000000 ) + synth_frac_div ;
rate * = 10000000 ;
do_div ( rate , synth_div_freq ) ;
2015-03-17 04:04:20 +03:00
rate * = SYNTH_PHASE_K ;
2015-01-14 01:51:27 +03:00
}
2015-03-23 01:35:24 +03:00
/* Synth post-divider M */
synth_div_m = readl_relaxed ( synth - > div ) & SYNTH_MAX_DIV_M ;
2015-01-14 01:51:27 +03:00
2015-03-23 01:35:24 +03:00
return DIV_ROUND_UP_ULL ( rate , synth_div_m ) ;
2015-01-14 01:51:27 +03:00
}
2015-03-17 04:04:20 +03:00
static unsigned long ti_fapll_synth_get_frac_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct fapll_synth * synth = to_synth ( hw ) ;
unsigned long current_rate , frac_rate ;
u32 post_div_m ;
current_rate = ti_fapll_synth_recalc_rate ( hw , parent_rate ) ;
post_div_m = readl_relaxed ( synth - > div ) & SYNTH_MAX_DIV_M ;
frac_rate = current_rate * post_div_m ;
return frac_rate ;
}
static u32 ti_fapll_synth_set_frac_rate ( struct fapll_synth * synth ,
unsigned long rate ,
unsigned long parent_rate )
{
u32 post_div_m , synth_int_div = 0 , synth_frac_div = 0 , v ;
post_div_m = DIV_ROUND_UP_ULL ( ( u64 ) parent_rate * SYNTH_PHASE_K , rate ) ;
post_div_m = post_div_m / SYNTH_MAX_INT_DIV ;
if ( post_div_m > SYNTH_MAX_DIV_M )
return - EINVAL ;
if ( ! post_div_m )
post_div_m = 1 ;
for ( ; post_div_m < SYNTH_MAX_DIV_M ; post_div_m + + ) {
synth_int_div = DIV_ROUND_UP_ULL ( ( u64 ) parent_rate *
SYNTH_PHASE_K *
10000000 ,
rate * post_div_m ) ;
synth_frac_div = synth_int_div % 10000000 ;
synth_int_div / = 10000000 ;
if ( synth_int_div < = SYNTH_MAX_INT_DIV )
break ;
}
if ( synth_int_div > SYNTH_MAX_INT_DIV )
return - EINVAL ;
v = readl_relaxed ( synth - > freq ) ;
v & = ~ 0x1fffffff ;
v | = ( synth_int_div & SYNTH_MAX_INT_DIV ) < < 24 ;
v | = ( synth_frac_div & 0xffffff ) ;
v | = SYNTH_LDFREQ ;
writel_relaxed ( v , synth - > freq ) ;
return post_div_m ;
}
static long ti_fapll_synth_round_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long * parent_rate )
{
struct fapll_synth * synth = to_synth ( hw ) ;
struct fapll_data * fd = synth - > fd ;
unsigned long r ;
if ( ti_fapll_clock_is_bypass ( fd ) | | ! synth - > div | | ! rate )
return - EINVAL ;
/* Only post divider m available with no fractional divider? */
if ( ! synth - > freq ) {
unsigned long frac_rate ;
u32 synth_post_div_m ;
frac_rate = ti_fapll_synth_get_frac_rate ( hw , * parent_rate ) ;
synth_post_div_m = DIV_ROUND_UP ( frac_rate , rate ) ;
r = DIV_ROUND_UP ( frac_rate , synth_post_div_m ) ;
goto out ;
}
r = * parent_rate * SYNTH_PHASE_K ;
if ( rate > r )
goto out ;
r = DIV_ROUND_UP_ULL ( r , SYNTH_MAX_INT_DIV * SYNTH_MAX_DIV_M ) ;
if ( rate < r )
goto out ;
r = rate ;
out :
return r ;
}
static int ti_fapll_synth_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct fapll_synth * synth = to_synth ( hw ) ;
struct fapll_data * fd = synth - > fd ;
unsigned long frac_rate , post_rate = 0 ;
u32 post_div_m = 0 , v ;
if ( ti_fapll_clock_is_bypass ( fd ) | | ! synth - > div | | ! rate )
return - EINVAL ;
/* Produce the rate with just post divider M? */
frac_rate = ti_fapll_synth_get_frac_rate ( hw , parent_rate ) ;
if ( frac_rate < rate ) {
if ( ! synth - > freq )
return - EINVAL ;
} else {
post_div_m = DIV_ROUND_UP ( frac_rate , rate ) ;
if ( post_div_m & & ( post_div_m < = SYNTH_MAX_DIV_M ) )
post_rate = DIV_ROUND_UP ( frac_rate , post_div_m ) ;
if ( ! synth - > freq & & ! post_rate )
return - EINVAL ;
}
/* Need to recalculate the fractional divider? */
if ( ( post_rate ! = rate ) & & synth - > freq )
post_div_m = ti_fapll_synth_set_frac_rate ( synth ,
rate ,
parent_rate ) ;
v = readl_relaxed ( synth - > div ) ;
v & = ~ SYNTH_MAX_DIV_M ;
v | = post_div_m ;
v | = SYNTH_LDMDIV1 ;
writel_relaxed ( v , synth - > div ) ;
return 0 ;
2015-01-14 01:51:27 +03:00
}
static struct clk_ops ti_fapll_synt_ops = {
. enable = ti_fapll_synth_enable ,
. disable = ti_fapll_synth_disable ,
. is_enabled = ti_fapll_synth_is_enabled ,
. recalc_rate = ti_fapll_synth_recalc_rate ,
2015-03-17 04:04:20 +03:00
. round_rate = ti_fapll_synth_round_rate ,
. set_rate = ti_fapll_synth_set_rate ,
2015-01-14 01:51:27 +03:00
} ;
static struct clk * __init ti_fapll_synth_setup ( struct fapll_data * fd ,
void __iomem * freq ,
void __iomem * div ,
int index ,
const char * name ,
const char * parent ,
struct clk * pll_clk )
{
struct clk_init_data * init ;
struct fapll_synth * synth ;
init = kzalloc ( sizeof ( * init ) , GFP_KERNEL ) ;
if ( ! init )
return ERR_PTR ( - ENOMEM ) ;
init - > ops = & ti_fapll_synt_ops ;
init - > name = name ;
init - > parent_names = & parent ;
init - > num_parents = 1 ;
synth = kzalloc ( sizeof ( * synth ) , GFP_KERNEL ) ;
if ( ! synth )
goto free ;
synth - > fd = fd ;
synth - > index = index ;
synth - > freq = freq ;
synth - > div = div ;
synth - > name = name ;
synth - > hw . init = init ;
synth - > clk_pll = pll_clk ;
return clk_register ( NULL , & synth - > hw ) ;
free :
kfree ( synth ) ;
kfree ( init ) ;
return ERR_PTR ( - ENOMEM ) ;
}
static void __init ti_fapll_setup ( struct device_node * node )
{
struct fapll_data * fd ;
struct clk_init_data * init = NULL ;
const char * parent_name [ 2 ] ;
struct clk * pll_clk ;
int i ;
fd = kzalloc ( sizeof ( * fd ) , GFP_KERNEL ) ;
if ( ! fd )
return ;
fd - > outputs . clks = kzalloc ( sizeof ( struct clk * ) *
MAX_FAPLL_OUTPUTS + 1 ,
GFP_KERNEL ) ;
if ( ! fd - > outputs . clks )
goto free ;
init = kzalloc ( sizeof ( * init ) , GFP_KERNEL ) ;
if ( ! init )
goto free ;
init - > ops = & ti_fapll_ops ;
init - > name = node - > name ;
init - > num_parents = of_clk_get_parent_count ( node ) ;
if ( init - > num_parents ! = 2 ) {
pr_err ( " %s must have two parents \n " , node - > name ) ;
goto free ;
}
2015-07-07 06:59:06 +03:00
of_clk_parent_fill ( node , parent_name , 2 ) ;
2015-01-14 01:51:27 +03:00
init - > parent_names = parent_name ;
fd - > clk_ref = of_clk_get ( node , 0 ) ;
if ( IS_ERR ( fd - > clk_ref ) ) {
pr_err ( " %s could not get clk_ref \n " , node - > name ) ;
goto free ;
}
fd - > clk_bypass = of_clk_get ( node , 1 ) ;
if ( IS_ERR ( fd - > clk_bypass ) ) {
pr_err ( " %s could not get clk_bypass \n " , node - > name ) ;
goto free ;
}
fd - > base = of_iomap ( node , 0 ) ;
if ( ! fd - > base ) {
pr_err ( " %s could not get IO base \n " , node - > name ) ;
goto free ;
}
if ( fapll_is_ddr_pll ( fd - > base ) )
fd - > bypass_bit_inverted = true ;
fd - > name = node - > name ;
fd - > hw . init = init ;
/* Register the parent PLL */
pll_clk = clk_register ( NULL , & fd - > hw ) ;
if ( IS_ERR ( pll_clk ) )
goto unmap ;
fd - > outputs . clks [ 0 ] = pll_clk ;
fd - > outputs . clk_num + + ;
/*
* Set up the child synthesizers starting at index 1 as the
* PLL output is at index 0. We need to check the clock - indices
* for numbering in case there are holes in the synth mapping ,
* and then probe the synth register to see if it has a FREQ
* register available .
*/
for ( i = 0 ; i < MAX_FAPLL_OUTPUTS ; i + + ) {
const char * output_name ;
void __iomem * freq , * div ;
struct clk * synth_clk ;
int output_instance ;
u32 v ;
if ( of_property_read_string_index ( node , " clock-output-names " ,
i , & output_name ) )
continue ;
if ( of_property_read_u32_index ( node , " clock-indices " , i ,
& output_instance ) )
output_instance = i ;
freq = fd - > base + ( output_instance * 8 ) ;
div = freq + 4 ;
/* Check for hardwired audio_pll_clk1 */
if ( is_audio_pll_clk1 ( freq ) ) {
2015-05-01 22:59:32 +03:00
freq = NULL ;
div = NULL ;
2015-01-14 01:51:27 +03:00
} else {
/* Does the synthesizer have a FREQ register? */
v = readl_relaxed ( freq ) ;
if ( ! v )
2015-05-01 22:59:32 +03:00
freq = NULL ;
2015-01-14 01:51:27 +03:00
}
synth_clk = ti_fapll_synth_setup ( fd , freq , div , output_instance ,
output_name , node - > name ,
pll_clk ) ;
if ( IS_ERR ( synth_clk ) )
continue ;
fd - > outputs . clks [ output_instance ] = synth_clk ;
fd - > outputs . clk_num + + ;
clk_register_clkdev ( synth_clk , output_name , NULL ) ;
}
/* Register the child synthesizers as the FAPLL outputs */
of_clk_add_provider ( node , of_clk_src_onecell_get , & fd - > outputs ) ;
/* Add clock alias for the outputs */
kfree ( init ) ;
return ;
unmap :
iounmap ( fd - > base ) ;
free :
if ( fd - > clk_bypass )
clk_put ( fd - > clk_bypass ) ;
if ( fd - > clk_ref )
clk_put ( fd - > clk_ref ) ;
kfree ( fd - > outputs . clks ) ;
kfree ( fd ) ;
kfree ( init ) ;
}
CLK_OF_DECLARE ( ti_fapll_clock , " ti,dm816-fapll-clock " , ti_fapll_setup ) ;