@ -742,6 +742,30 @@ static ulong rk3399_mmc_set_clk(struct rk3399_cru *cru,
return rk3399_mmc_get_clk ( cru , clk_id ) ;
}
static ulong rk3399_gmac_set_clk ( struct rk3399_cru * cru , ulong rate )
{
ulong ret ;
/*
* The RGMII CLK can be derived either from an external " clkin "
* or can be generated from internally by a divider from SCLK_MAC .
*/
if ( readl ( & cru - > clksel_con [ 19 ] ) & BIT ( 4 ) ) {
/* An external clock will always generate the right rate... */
ret = rate ;
} else {
/*
* No platform uses an internal clock to date .
* Implement this once it becomes necessary and print an error
* if someone tries to use it ( while it remains unimplemented ) .
*/
pr_err ( " %s: internal clock is UNIMPLEMENTED \n " , __func__ ) ;
ret = 0 ;
}
return ret ;
}
# define PMUSGRF_DDR_RGN_CON16 0xff330040
static ulong rk3399_ddr_set_clk ( struct rk3399_cru * cru ,
ulong set_rate )
@ -865,8 +889,7 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
ret = rk3399_mmc_set_clk ( priv - > cru , clk - > id , rate ) ;
break ;
case SCLK_MAC :
/* nothing to do, as this is an external clock */
ret = rate ;
ret = rk3399_gmac_set_clk ( priv - > cru , rate ) ;
break ;
case SCLK_I2C1 :
case SCLK_I2C2 :
@ -902,6 +925,52 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
return ret ;
}
static int rk3399_gmac_set_parent ( struct clk * clk , struct clk * parent )
{
struct rk3399_clk_priv * priv = dev_get_priv ( clk - > dev ) ;
const char * clock_output_name ;
int ret ;
/*
* If the requested parent is in the same clock - controller and
* the id is SCLK_MAC ( " clk_gmac " ) , switch to the internal clock .
*/
if ( ( parent - > dev = = clk - > dev ) & & ( parent - > id = = SCLK_MAC ) ) {
debug ( " %s: switching RGMII to SCLK_MAC \n " , __func__ ) ;
rk_clrreg ( & priv - > cru - > clksel_con [ 19 ] , BIT ( 4 ) ) ;
return 0 ;
}
/*
* Otherwise , we need to check the clock - output - names of the
* requested parent to see if the requested id is " clkin_gmac " .
*/
ret = dev_read_string_index ( parent - > dev , " clock-output-names " ,
parent - > id , & clock_output_name ) ;
if ( ret < 0 )
return - ENODATA ;
/* If this is "clkin_gmac", switch to the external clock input */
if ( ! strcmp ( clock_output_name , " clkin_gmac " ) ) {
debug ( " %s: switching RGMII to CLKIN \n " , __func__ ) ;
rk_setreg ( & priv - > cru - > clksel_con [ 19 ] , BIT ( 4 ) ) ;
return 0 ;
}
return - EINVAL ;
}
static int rk3399_clk_set_parent ( struct clk * clk , struct clk * parent )
{
switch ( clk - > id ) {
case SCLK_RMII_SRC :
return rk3399_gmac_set_parent ( clk , parent ) ;
}
debug ( " %s: unsupported clk %ld \n " , __func__ , clk - > id ) ;
return - ENOENT ;
}
static int rk3399_clk_enable ( struct clk * clk )
{
switch ( clk - > id ) {
@ -919,6 +988,7 @@ static int rk3399_clk_enable(struct clk *clk)
static struct clk_ops rk3399_clk_ops = {
. get_rate = rk3399_clk_get_rate ,
. set_rate = rk3399_clk_set_rate ,
. set_parent = rk3399_clk_set_parent ,
. enable = rk3399_clk_enable ,
} ;