2015-06-03 08:25:19 +03:00
/*
2016-12-31 21:04:36 +03:00
* Driver for TI Multi PLL CDCE913 / 925 / 937 / 949 clock synthesizer
2015-06-03 08:25:19 +03:00
*
2016-12-31 21:04:36 +03:00
* This driver always connects the Y1 to the input clock , Y2 / Y3 to PLL1 ,
* Y4 / Y5 to PLL2 , and so on . PLL frequency is set on a first - come - first - serve
2015-06-03 08:25:19 +03:00
* basis . Clients can directly request any frequency that the chip can
* deliver using the standard clk framework . In addition , the device can
* be configured and activated via the devicetree .
*
* Copyright ( C ) 2014 , Topic Embedded Products
* Licenced under GPL
*/
2015-06-11 00:14:28 +03:00
# include <linux/clk.h>
2015-06-03 08:25:19 +03:00
# include <linux/clk-provider.h>
# include <linux/delay.h>
# include <linux/module.h>
# include <linux/i2c.h>
# include <linux/regmap.h>
# include <linux/slab.h>
# include <linux/gcd.h>
2016-12-31 21:04:36 +03:00
/* Each chip has different number of PLLs and outputs, for example:
* The CECE925 has 2 PLLs which can be routed through dividers to 5 outputs .
2015-06-03 08:25:19 +03:00
* Model this as 2 PLL clocks which are parents to the outputs .
*/
2016-12-31 21:04:36 +03:00
enum {
CDCE913 ,
CDCE925 ,
CDCE937 ,
CDCE949 ,
} ;
struct clk_cdce925_chip_info {
int num_plls ;
int num_outputs ;
} ;
static const struct clk_cdce925_chip_info clk_cdce925_chip_info_tbl [ ] = {
[ CDCE913 ] = { . num_plls = 1 , . num_outputs = 3 } ,
[ CDCE925 ] = { . num_plls = 2 , . num_outputs = 5 } ,
[ CDCE937 ] = { . num_plls = 3 , . num_outputs = 7 } ,
[ CDCE949 ] = { . num_plls = 4 , . num_outputs = 9 } ,
} ;
# define MAX_NUMBER_OF_PLLS 4
# define MAX_NUMBER_OF_OUTPUTS 9
2015-06-03 08:25:19 +03:00
# define CDCE925_REG_GLOBAL1 0x01
# define CDCE925_REG_Y1SPIPDIVH 0x02
# define CDCE925_REG_PDIVL 0x03
# define CDCE925_REG_XCSEL 0x05
/* PLL parameters start at 0x10, steps of 0x10 */
# define CDCE925_OFFSET_PLL 0x10
/* Add CDCE925_OFFSET_PLL * (pll) to these registers before sending */
# define CDCE925_PLL_MUX_OUTPUTS 0x14
# define CDCE925_PLL_MULDIV 0x18
# define CDCE925_PLL_FREQUENCY_MIN 80000000ul
# define CDCE925_PLL_FREQUENCY_MAX 230000000ul
struct clk_cdce925_chip ;
struct clk_cdce925_output {
struct clk_hw hw ;
struct clk_cdce925_chip * chip ;
u8 index ;
2016-12-31 21:04:36 +03:00
u16 pdiv ; /* 1..127 for Y2-Y9; 1..1023 for Y1 */
2015-06-03 08:25:19 +03:00
} ;
# define to_clk_cdce925_output(_hw) \
container_of ( _hw , struct clk_cdce925_output , hw )
struct clk_cdce925_pll {
struct clk_hw hw ;
struct clk_cdce925_chip * chip ;
u8 index ;
u16 m ; /* 1..511 */
u16 n ; /* 1..4095 */
} ;
# define to_clk_cdce925_pll(_hw) container_of(_hw, struct clk_cdce925_pll, hw)
struct clk_cdce925_chip {
struct regmap * regmap ;
struct i2c_client * i2c_client ;
2016-12-31 21:04:36 +03:00
const struct clk_cdce925_chip_info * chip_info ;
struct clk_cdce925_pll pll [ MAX_NUMBER_OF_PLLS ] ;
struct clk_cdce925_output clk [ MAX_NUMBER_OF_OUTPUTS ] ;
2015-06-03 08:25:19 +03:00
} ;
/* ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** */
static unsigned long cdce925_pll_calculate_rate ( unsigned long parent_rate ,
u16 n , u16 m )
{
if ( ( ! m | | ! n ) | | ( m = = n ) )
return parent_rate ; /* In bypass mode runs at same frequency */
return mult_frac ( parent_rate , ( unsigned long ) n , ( unsigned long ) m ) ;
}
static unsigned long cdce925_pll_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
/* Output frequency of PLL is Fout = (Fin/Pdiv)*(N/M) */
struct clk_cdce925_pll * data = to_clk_cdce925_pll ( hw ) ;
return cdce925_pll_calculate_rate ( parent_rate , data - > n , data - > m ) ;
}
static void cdce925_pll_find_rate ( unsigned long rate ,
unsigned long parent_rate , u16 * n , u16 * m )
{
unsigned long un ;
unsigned long um ;
unsigned long g ;
if ( rate < = parent_rate ) {
/* Can always deliver parent_rate in bypass mode */
rate = parent_rate ;
* n = 0 ;
* m = 0 ;
} else {
/* In PLL mode, need to apply min/max range */
if ( rate < CDCE925_PLL_FREQUENCY_MIN )
rate = CDCE925_PLL_FREQUENCY_MIN ;
else if ( rate > CDCE925_PLL_FREQUENCY_MAX )
rate = CDCE925_PLL_FREQUENCY_MAX ;
g = gcd ( rate , parent_rate ) ;
um = parent_rate / g ;
un = rate / g ;
/* When outside hw range, reduce to fit (rounding errors) */
while ( ( un > 4095 ) | | ( um > 511 ) ) {
un > > = 1 ;
um > > = 1 ;
}
if ( un = = 0 )
un = 1 ;
if ( um = = 0 )
um = 1 ;
* n = un ;
* m = um ;
}
}
static long cdce925_pll_round_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long * parent_rate )
{
u16 n , m ;
cdce925_pll_find_rate ( rate , * parent_rate , & n , & m ) ;
return ( long ) cdce925_pll_calculate_rate ( * parent_rate , n , m ) ;
}
static int cdce925_pll_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct clk_cdce925_pll * data = to_clk_cdce925_pll ( hw ) ;
if ( ! rate | | ( rate = = parent_rate ) ) {
data - > m = 0 ; /* Bypass mode */
data - > n = 0 ;
return 0 ;
}
if ( ( rate < CDCE925_PLL_FREQUENCY_MIN ) | |
( rate > CDCE925_PLL_FREQUENCY_MAX ) ) {
pr_debug ( " %s: rate %lu outside PLL range. \n " , __func__ , rate ) ;
return - EINVAL ;
}
if ( rate < parent_rate ) {
pr_debug ( " %s: rate %lu less than parent rate %lu. \n " , __func__ ,
rate , parent_rate ) ;
return - EINVAL ;
}
cdce925_pll_find_rate ( rate , parent_rate , & data - > n , & data - > m ) ;
return 0 ;
}
/* calculate p = max(0, 4 - int(log2 (n/m))) */
static u8 cdce925_pll_calc_p ( u16 n , u16 m )
{
u8 p ;
u16 r = n / m ;
if ( r > = 16 )
return 0 ;
p = 4 ;
while ( r > 1 ) {
r > > = 1 ;
- - p ;
}
return p ;
}
/* Returns VCO range bits for VCO1_0_RANGE */
static u8 cdce925_pll_calc_range_bits ( struct clk_hw * hw , u16 n , u16 m )
{
struct clk * parent = clk_get_parent ( hw - > clk ) ;
unsigned long rate = clk_get_rate ( parent ) ;
rate = mult_frac ( rate , ( unsigned long ) n , ( unsigned long ) m ) ;
if ( rate > = 175000000 )
return 0x3 ;
if ( rate > = 150000000 )
return 0x02 ;
if ( rate > = 125000000 )
return 0x01 ;
return 0x00 ;
}
/* I2C clock, hence everything must happen in (un)prepare because this
* may sleep */
static int cdce925_pll_prepare ( struct clk_hw * hw )
{
struct clk_cdce925_pll * data = to_clk_cdce925_pll ( hw ) ;
u16 n = data - > n ;
u16 m = data - > m ;
u16 r ;
u8 q ;
u8 p ;
u16 nn ;
u8 pll [ 4 ] ; /* Bits are spread out over 4 byte registers */
u8 reg_ofs = data - > index * CDCE925_OFFSET_PLL ;
unsigned i ;
if ( ( ! m | | ! n ) | | ( m = = n ) ) {
/* Set PLL mux to bypass mode, leave the rest as is */
regmap_update_bits ( data - > chip - > regmap ,
reg_ofs + CDCE925_PLL_MUX_OUTPUTS , 0x80 , 0x80 ) ;
} else {
/* According to data sheet: */
/* p = max(0, 4 - int(log2 (n/m))) */
p = cdce925_pll_calc_p ( n , m ) ;
/* nn = n * 2^p */
nn = n * BIT ( p ) ;
/* q = int(nn/m) */
q = nn / m ;
2016-11-12 00:49:05 +03:00
if ( ( q < 16 ) | | ( q > 63 ) ) {
2015-06-03 08:25:19 +03:00
pr_debug ( " %s invalid q=%d \n " , __func__ , q ) ;
return - EINVAL ;
}
r = nn - ( m * q ) ;
if ( r > 511 ) {
pr_debug ( " %s invalid r=%d \n " , __func__ , r ) ;
return - EINVAL ;
}
pr_debug ( " %s n=%d m=%d p=%d q=%d r=%d \n " , __func__ ,
n , m , p , q , r ) ;
/* encode into register bits */
pll [ 0 ] = n > > 4 ;
pll [ 1 ] = ( ( n & 0x0F ) < < 4 ) | ( ( r > > 5 ) & 0x0F ) ;
pll [ 2 ] = ( ( r & 0x1F ) < < 3 ) | ( ( q > > 3 ) & 0x07 ) ;
pll [ 3 ] = ( ( q & 0x07 ) < < 5 ) | ( p < < 2 ) |
cdce925_pll_calc_range_bits ( hw , n , m ) ;
/* Write to registers */
for ( i = 0 ; i < ARRAY_SIZE ( pll ) ; + + i )
regmap_write ( data - > chip - > regmap ,
reg_ofs + CDCE925_PLL_MULDIV + i , pll [ i ] ) ;
/* Enable PLL */
regmap_update_bits ( data - > chip - > regmap ,
reg_ofs + CDCE925_PLL_MUX_OUTPUTS , 0x80 , 0x00 ) ;
}
return 0 ;
}
static void cdce925_pll_unprepare ( struct clk_hw * hw )
{
struct clk_cdce925_pll * data = to_clk_cdce925_pll ( hw ) ;
u8 reg_ofs = data - > index * CDCE925_OFFSET_PLL ;
regmap_update_bits ( data - > chip - > regmap ,
reg_ofs + CDCE925_PLL_MUX_OUTPUTS , 0x80 , 0x80 ) ;
}
static const struct clk_ops cdce925_pll_ops = {
. prepare = cdce925_pll_prepare ,
. unprepare = cdce925_pll_unprepare ,
. recalc_rate = cdce925_pll_recalc_rate ,
. round_rate = cdce925_pll_round_rate ,
. set_rate = cdce925_pll_set_rate ,
} ;
static void cdce925_clk_set_pdiv ( struct clk_cdce925_output * data , u16 pdiv )
{
switch ( data - > index ) {
case 0 :
regmap_update_bits ( data - > chip - > regmap ,
CDCE925_REG_Y1SPIPDIVH ,
0x03 , ( pdiv > > 8 ) & 0x03 ) ;
regmap_write ( data - > chip - > regmap , 0x03 , pdiv & 0xFF ) ;
break ;
case 1 :
regmap_update_bits ( data - > chip - > regmap , 0x16 , 0x7F , pdiv ) ;
break ;
case 2 :
regmap_update_bits ( data - > chip - > regmap , 0x17 , 0x7F , pdiv ) ;
break ;
case 3 :
regmap_update_bits ( data - > chip - > regmap , 0x26 , 0x7F , pdiv ) ;
break ;
case 4 :
regmap_update_bits ( data - > chip - > regmap , 0x27 , 0x7F , pdiv ) ;
break ;
2016-12-31 21:04:36 +03:00
case 5 :
regmap_update_bits ( data - > chip - > regmap , 0x36 , 0x7F , pdiv ) ;
break ;
case 6 :
regmap_update_bits ( data - > chip - > regmap , 0x37 , 0x7F , pdiv ) ;
break ;
case 7 :
regmap_update_bits ( data - > chip - > regmap , 0x46 , 0x7F , pdiv ) ;
break ;
case 8 :
regmap_update_bits ( data - > chip - > regmap , 0x47 , 0x7F , pdiv ) ;
break ;
2015-06-03 08:25:19 +03:00
}
}
static void cdce925_clk_activate ( struct clk_cdce925_output * data )
{
switch ( data - > index ) {
case 0 :
regmap_update_bits ( data - > chip - > regmap ,
CDCE925_REG_Y1SPIPDIVH , 0x0c , 0x0c ) ;
break ;
case 1 :
case 2 :
regmap_update_bits ( data - > chip - > regmap , 0x14 , 0x03 , 0x03 ) ;
break ;
case 3 :
case 4 :
regmap_update_bits ( data - > chip - > regmap , 0x24 , 0x03 , 0x03 ) ;
break ;
2016-12-31 21:04:36 +03:00
case 5 :
case 6 :
regmap_update_bits ( data - > chip - > regmap , 0x34 , 0x03 , 0x03 ) ;
break ;
case 7 :
case 8 :
regmap_update_bits ( data - > chip - > regmap , 0x44 , 0x03 , 0x03 ) ;
break ;
2015-06-03 08:25:19 +03:00
}
}
static int cdce925_clk_prepare ( struct clk_hw * hw )
{
struct clk_cdce925_output * data = to_clk_cdce925_output ( hw ) ;
cdce925_clk_set_pdiv ( data , data - > pdiv ) ;
cdce925_clk_activate ( data ) ;
return 0 ;
}
static void cdce925_clk_unprepare ( struct clk_hw * hw )
{
struct clk_cdce925_output * data = to_clk_cdce925_output ( hw ) ;
/* Disable clock by setting divider to "0" */
cdce925_clk_set_pdiv ( data , 0 ) ;
}
static unsigned long cdce925_clk_recalc_rate ( struct clk_hw * hw ,
unsigned long parent_rate )
{
struct clk_cdce925_output * data = to_clk_cdce925_output ( hw ) ;
if ( data - > pdiv )
return parent_rate / data - > pdiv ;
return 0 ;
}
static u16 cdce925_calc_divider ( unsigned long rate ,
unsigned long parent_rate )
{
unsigned long divider ;
if ( ! rate )
return 0 ;
if ( rate > = parent_rate )
return 1 ;
divider = DIV_ROUND_CLOSEST ( parent_rate , rate ) ;
if ( divider > 0x7F )
divider = 0x7F ;
return ( u16 ) divider ;
}
static unsigned long cdce925_clk_best_parent_rate (
struct clk_hw * hw , unsigned long rate )
{
struct clk * pll = clk_get_parent ( hw - > clk ) ;
struct clk * root = clk_get_parent ( pll ) ;
unsigned long root_rate = clk_get_rate ( root ) ;
unsigned long best_rate_error = rate ;
u16 pdiv_min ;
u16 pdiv_max ;
u16 pdiv_best ;
u16 pdiv_now ;
if ( root_rate % rate = = 0 )
return root_rate ; /* Don't need the PLL, use bypass */
pdiv_min = ( u16 ) max ( 1ul , DIV_ROUND_UP ( CDCE925_PLL_FREQUENCY_MIN , rate ) ) ;
pdiv_max = ( u16 ) min ( 127ul , CDCE925_PLL_FREQUENCY_MAX / rate ) ;
if ( pdiv_min > pdiv_max )
return 0 ; /* No can do? */
pdiv_best = pdiv_min ;
for ( pdiv_now = pdiv_min ; pdiv_now < pdiv_max ; + + pdiv_now ) {
unsigned long target_rate = rate * pdiv_now ;
long pll_rate = clk_round_rate ( pll , target_rate ) ;
unsigned long actual_rate ;
unsigned long rate_error ;
if ( pll_rate < = 0 )
continue ;
actual_rate = pll_rate / pdiv_now ;
rate_error = abs ( ( long ) actual_rate - ( long ) rate ) ;
if ( rate_error < best_rate_error ) {
pdiv_best = pdiv_now ;
best_rate_error = rate_error ;
}
/* TODO: Consider PLL frequency based on smaller n/m values
* and pick the better one if the error is equal */
}
return rate * pdiv_best ;
}
static long cdce925_clk_round_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long * parent_rate )
{
unsigned long l_parent_rate = * parent_rate ;
u16 divider = cdce925_calc_divider ( rate , l_parent_rate ) ;
if ( l_parent_rate / divider ! = rate ) {
l_parent_rate = cdce925_clk_best_parent_rate ( hw , rate ) ;
divider = cdce925_calc_divider ( rate , l_parent_rate ) ;
* parent_rate = l_parent_rate ;
}
if ( divider )
return ( long ) ( l_parent_rate / divider ) ;
return 0 ;
}
static int cdce925_clk_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct clk_cdce925_output * data = to_clk_cdce925_output ( hw ) ;
data - > pdiv = cdce925_calc_divider ( rate , parent_rate ) ;
return 0 ;
}
static const struct clk_ops cdce925_clk_ops = {
. prepare = cdce925_clk_prepare ,
. unprepare = cdce925_clk_unprepare ,
. recalc_rate = cdce925_clk_recalc_rate ,
. round_rate = cdce925_clk_round_rate ,
. set_rate = cdce925_clk_set_rate ,
} ;
static u16 cdce925_y1_calc_divider ( unsigned long rate ,
unsigned long parent_rate )
{
unsigned long divider ;
if ( ! rate )
return 0 ;
if ( rate > = parent_rate )
return 1 ;
divider = DIV_ROUND_CLOSEST ( parent_rate , rate ) ;
if ( divider > 0x3FF ) /* Y1 has 10-bit divider */
divider = 0x3FF ;
return ( u16 ) divider ;
}
static long cdce925_clk_y1_round_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long * parent_rate )
{
unsigned long l_parent_rate = * parent_rate ;
u16 divider = cdce925_y1_calc_divider ( rate , l_parent_rate ) ;
if ( divider )
return ( long ) ( l_parent_rate / divider ) ;
return 0 ;
}
static int cdce925_clk_y1_set_rate ( struct clk_hw * hw , unsigned long rate ,
unsigned long parent_rate )
{
struct clk_cdce925_output * data = to_clk_cdce925_output ( hw ) ;
data - > pdiv = cdce925_y1_calc_divider ( rate , parent_rate ) ;
return 0 ;
}
static const struct clk_ops cdce925_clk_y1_ops = {
. prepare = cdce925_clk_prepare ,
. unprepare = cdce925_clk_unprepare ,
. recalc_rate = cdce925_clk_recalc_rate ,
. round_rate = cdce925_clk_y1_round_rate ,
. set_rate = cdce925_clk_y1_set_rate ,
} ;
# define CDCE925_I2C_COMMAND_BLOCK_TRANSFER 0x00
# define CDCE925_I2C_COMMAND_BYTE_TRANSFER 0x80
static int cdce925_regmap_i2c_write (
void * context , const void * data , size_t count )
{
struct device * dev = context ;
struct i2c_client * i2c = to_i2c_client ( dev ) ;
int ret ;
u8 reg_data [ 2 ] ;
if ( count ! = 2 )
return - ENOTSUPP ;
/* First byte is command code */
reg_data [ 0 ] = CDCE925_I2C_COMMAND_BYTE_TRANSFER | ( ( u8 * ) data ) [ 0 ] ;
reg_data [ 1 ] = ( ( u8 * ) data ) [ 1 ] ;
dev_dbg ( & i2c - > dev , " %s(%zu) %#x %#x \n " , __func__ , count ,
reg_data [ 0 ] , reg_data [ 1 ] ) ;
ret = i2c_master_send ( i2c , reg_data , count ) ;
if ( likely ( ret = = count ) )
return 0 ;
else if ( ret < 0 )
return ret ;
else
return - EIO ;
}
static int cdce925_regmap_i2c_read ( void * context ,
const void * reg , size_t reg_size , void * val , size_t val_size )
{
struct device * dev = context ;
struct i2c_client * i2c = to_i2c_client ( dev ) ;
struct i2c_msg xfer [ 2 ] ;
int ret ;
u8 reg_data [ 2 ] ;
if ( reg_size ! = 1 )
return - ENOTSUPP ;
xfer [ 0 ] . addr = i2c - > addr ;
xfer [ 0 ] . flags = 0 ;
xfer [ 0 ] . buf = reg_data ;
if ( val_size = = 1 ) {
reg_data [ 0 ] =
CDCE925_I2C_COMMAND_BYTE_TRANSFER | ( ( u8 * ) reg ) [ 0 ] ;
xfer [ 0 ] . len = 1 ;
} else {
reg_data [ 0 ] =
CDCE925_I2C_COMMAND_BLOCK_TRANSFER | ( ( u8 * ) reg ) [ 0 ] ;
reg_data [ 1 ] = val_size ;
xfer [ 0 ] . len = 2 ;
}
xfer [ 1 ] . addr = i2c - > addr ;
xfer [ 1 ] . flags = I2C_M_RD ;
xfer [ 1 ] . len = val_size ;
xfer [ 1 ] . buf = val ;
ret = i2c_transfer ( i2c - > adapter , xfer , 2 ) ;
if ( likely ( ret = = 2 ) ) {
2015-06-11 00:14:28 +03:00
dev_dbg ( & i2c - > dev , " %s(%zu, %zu) %#x %#x \n " , __func__ ,
2015-06-03 08:25:19 +03:00
reg_size , val_size , reg_data [ 0 ] , * ( ( u8 * ) val ) ) ;
return 0 ;
} else if ( ret < 0 )
return ret ;
else
return - EIO ;
}
2016-06-02 02:15:11 +03:00
static struct clk_hw *
of_clk_cdce925_get ( struct of_phandle_args * clkspec , void * _data )
{
struct clk_cdce925_chip * data = _data ;
unsigned int idx = clkspec - > args [ 0 ] ;
if ( idx > = ARRAY_SIZE ( data - > clk ) ) {
pr_err ( " %s: invalid index %u \n " , __func__ , idx ) ;
return ERR_PTR ( - EINVAL ) ;
}
return & data - > clk [ idx ] . hw ;
}
2015-06-03 08:25:19 +03:00
/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
* just weird , so just use the single byte mode exclusively . */
static struct regmap_bus regmap_cdce925_bus = {
. write = cdce925_regmap_i2c_write ,
. read = cdce925_regmap_i2c_read ,
} ;
static int cdce925_probe ( struct i2c_client * client ,
const struct i2c_device_id * id )
{
struct clk_cdce925_chip * data ;
struct device_node * node = client - > dev . of_node ;
const char * parent_name ;
2016-12-31 21:04:36 +03:00
const char * pll_clk_name [ MAX_NUMBER_OF_PLLS ] = { NULL , } ;
2015-06-03 08:25:19 +03:00
struct clk_init_data init ;
u32 value ;
int i ;
int err ;
struct device_node * np_output ;
char child_name [ 6 ] ;
2016-12-31 21:04:36 +03:00
struct regmap_config config = {
. name = " configuration0 " ,
. reg_bits = 8 ,
. val_bits = 8 ,
. cache_type = REGCACHE_RBTREE ,
} ;
2015-06-03 08:25:19 +03:00
dev_dbg ( & client - > dev , " %s \n " , __func__ ) ;
data = devm_kzalloc ( & client - > dev , sizeof ( * data ) , GFP_KERNEL ) ;
if ( ! data )
return - ENOMEM ;
data - > i2c_client = client ;
2016-12-31 21:04:36 +03:00
data - > chip_info = & clk_cdce925_chip_info_tbl [ id - > driver_data ] ;
config . max_register = CDCE925_OFFSET_PLL +
data - > chip_info - > num_plls * 0x10 - 1 ;
2015-06-03 08:25:19 +03:00
data - > regmap = devm_regmap_init ( & client - > dev , & regmap_cdce925_bus ,
2016-12-31 21:04:36 +03:00
& client - > dev , & config ) ;
2015-06-03 08:25:19 +03:00
if ( IS_ERR ( data - > regmap ) ) {
dev_err ( & client - > dev , " failed to allocate register map \n " ) ;
return PTR_ERR ( data - > regmap ) ;
}
i2c_set_clientdata ( client , data ) ;
parent_name = of_clk_get_parent_name ( node , 0 ) ;
if ( ! parent_name ) {
dev_err ( & client - > dev , " missing parent clock \n " ) ;
return - ENODEV ;
}
dev_dbg ( & client - > dev , " parent is: %s \n " , parent_name ) ;
if ( of_property_read_u32 ( node , " xtal-load-pf " , & value ) = = 0 )
regmap_write ( data - > regmap ,
CDCE925_REG_XCSEL , ( value < < 3 ) & 0xF8 ) ;
/* PWDN bit */
regmap_update_bits ( data - > regmap , CDCE925_REG_GLOBAL1 , BIT ( 4 ) , 0 ) ;
/* Set input source for Y1 to be the XTAL */
regmap_update_bits ( data - > regmap , 0x02 , BIT ( 7 ) , 0 ) ;
init . ops = & cdce925_pll_ops ;
init . flags = 0 ;
init . parent_names = & parent_name ;
init . num_parents = parent_name ? 1 : 0 ;
/* Register PLL clocks */
2016-12-31 21:04:36 +03:00
for ( i = 0 ; i < data - > chip_info - > num_plls ; + + i ) {
2015-06-03 08:25:19 +03:00
pll_clk_name [ i ] = kasprintf ( GFP_KERNEL , " %s.pll%d " ,
client - > dev . of_node - > name , i ) ;
init . name = pll_clk_name [ i ] ;
data - > pll [ i ] . chip = data ;
data - > pll [ i ] . hw . init = & init ;
data - > pll [ i ] . index = i ;
2016-06-02 02:15:11 +03:00
err = devm_clk_hw_register ( & client - > dev , & data - > pll [ i ] . hw ) ;
if ( err ) {
2015-06-03 08:25:19 +03:00
dev_err ( & client - > dev , " Failed register PLL %d \n " , i ) ;
goto error ;
}
sprintf ( child_name , " PLL%d " , i + 1 ) ;
np_output = of_get_child_by_name ( node , child_name ) ;
if ( ! np_output )
continue ;
if ( ! of_property_read_u32 ( np_output ,
" clock-frequency " , & value ) ) {
2016-06-02 02:15:11 +03:00
err = clk_set_rate ( data - > pll [ i ] . hw . clk , value ) ;
2015-06-03 08:25:19 +03:00
if ( err )
dev_err ( & client - > dev ,
" unable to set PLL frequency %ud \n " ,
value ) ;
}
if ( ! of_property_read_u32 ( np_output ,
" spread-spectrum " , & value ) ) {
u8 flag = of_property_read_bool ( np_output ,
" spread-spectrum-center " ) ? 0x80 : 0x00 ;
regmap_update_bits ( data - > regmap ,
0x16 + ( i * CDCE925_OFFSET_PLL ) ,
0x80 , flag ) ;
regmap_update_bits ( data - > regmap ,
0x12 + ( i * CDCE925_OFFSET_PLL ) ,
0x07 , value & 0x07 ) ;
}
}
/* Register output clock Y1 */
init . ops = & cdce925_clk_y1_ops ;
init . flags = 0 ;
init . num_parents = 1 ;
init . parent_names = & parent_name ; /* Mux Y1 to input */
init . name = kasprintf ( GFP_KERNEL , " %s.Y1 " , client - > dev . of_node - > name ) ;
data - > clk [ 0 ] . chip = data ;
data - > clk [ 0 ] . hw . init = & init ;
data - > clk [ 0 ] . index = 0 ;
data - > clk [ 0 ] . pdiv = 1 ;
2016-06-02 02:15:11 +03:00
err = devm_clk_hw_register ( & client - > dev , & data - > clk [ 0 ] . hw ) ;
2015-06-03 08:25:19 +03:00
kfree ( init . name ) ; /* clock framework made a copy of the name */
2016-06-02 02:15:11 +03:00
if ( err ) {
2015-06-03 08:25:19 +03:00
dev_err ( & client - > dev , " clock registration Y1 failed \n " ) ;
goto error ;
}
/* Register output clocks Y2 .. Y5*/
init . ops = & cdce925_clk_ops ;
init . flags = CLK_SET_RATE_PARENT ;
init . num_parents = 1 ;
2016-12-31 21:04:36 +03:00
for ( i = 1 ; i < data - > chip_info - > num_outputs ; + + i ) {
2015-06-03 08:25:19 +03:00
init . name = kasprintf ( GFP_KERNEL , " %s.Y%d " ,
client - > dev . of_node - > name , i + 1 ) ;
data - > clk [ i ] . chip = data ;
data - > clk [ i ] . hw . init = & init ;
data - > clk [ i ] . index = i ;
data - > clk [ i ] . pdiv = 1 ;
switch ( i ) {
case 1 :
case 2 :
/* Mux Y2/3 to PLL1 */
init . parent_names = & pll_clk_name [ 0 ] ;
break ;
case 3 :
case 4 :
/* Mux Y4/5 to PLL2 */
init . parent_names = & pll_clk_name [ 1 ] ;
break ;
2016-12-31 21:04:36 +03:00
case 5 :
case 6 :
/* Mux Y6/7 to PLL3 */
init . parent_names = & pll_clk_name [ 2 ] ;
break ;
case 7 :
case 8 :
/* Mux Y8/9 to PLL4 */
init . parent_names = & pll_clk_name [ 3 ] ;
break ;
2015-06-03 08:25:19 +03:00
}
2016-06-02 02:15:11 +03:00
err = devm_clk_hw_register ( & client - > dev , & data - > clk [ i ] . hw ) ;
2015-06-03 08:25:19 +03:00
kfree ( init . name ) ; /* clock framework made a copy of the name */
2016-06-02 02:15:11 +03:00
if ( err ) {
2015-06-03 08:25:19 +03:00
dev_err ( & client - > dev , " clock registration failed \n " ) ;
goto error ;
}
}
/* Register the output clocks */
2016-06-02 02:15:11 +03:00
err = of_clk_add_hw_provider ( client - > dev . of_node , of_clk_cdce925_get ,
data ) ;
2015-06-03 08:25:19 +03:00
if ( err )
dev_err ( & client - > dev , " unable to add OF clock provider \n " ) ;
err = 0 ;
error :
2016-12-31 21:04:36 +03:00
for ( i = 0 ; i < data - > chip_info - > num_plls ; + + i )
2015-06-03 08:25:19 +03:00
/* clock framework made a copy of the name */
kfree ( pll_clk_name [ i ] ) ;
return err ;
}
static const struct i2c_device_id cdce925_id [ ] = {
2016-12-31 21:04:36 +03:00
{ " cdce913 " , CDCE913 } ,
{ " cdce925 " , CDCE925 } ,
{ " cdce937 " , CDCE937 } ,
{ " cdce949 " , CDCE949 } ,
2015-06-03 08:25:19 +03:00
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , cdce925_id ) ;
static const struct of_device_id clk_cdce925_of_match [ ] = {
2016-12-31 21:04:36 +03:00
{ . compatible = " ti,cdce913 " } ,
2015-06-03 08:25:19 +03:00
{ . compatible = " ti,cdce925 " } ,
2016-12-31 21:04:36 +03:00
{ . compatible = " ti,cdce937 " } ,
{ . compatible = " ti,cdce949 " } ,
2015-06-03 08:25:19 +03:00
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , clk_cdce925_of_match ) ;
static struct i2c_driver cdce925_driver = {
. driver = {
. name = " cdce925 " ,
. of_match_table = of_match_ptr ( clk_cdce925_of_match ) ,
} ,
. probe = cdce925_probe ,
. id_table = cdce925_id ,
} ;
module_i2c_driver ( cdce925_driver ) ;
MODULE_AUTHOR ( " Mike Looijmans <mike.looijmans@topic.nl> " ) ;
2016-12-31 21:04:36 +03:00
MODULE_DESCRIPTION ( " TI CDCE913/925/937/949 driver " ) ;
2015-06-03 08:25:19 +03:00
MODULE_LICENSE ( " GPL " ) ;