@ -311,15 +311,43 @@ static ulong rk3368_ddr_set_clk(struct rk3368_cru *cru, ulong set_rate)
# endif
# endif
# if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
# if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
static ulong rk3368_gmac_set_clk ( struct rk3368_cru * cru ,
static ulong rk3368_gmac_set_clk ( struct rk3368_cru * cru , ulong set_rate )
ulong clk_id , ulong set_rate )
{
{
ulong ret ;
/*
/*
* This models the ' assigned - clock - parents = < & ext_gmac > ' from
* The gmac clock can be derived either from an external clock
* the DTS and switches to the ' ext_gmac ' clock parent .
* or can be generated from internally by a divider from SCLK_MAC .
*/
*/
rk_setreg ( & cru - > clksel_con [ 43 ] , GMAC_MUX_SEL_EXTCLK ) ;
if ( readl ( & cru - > clksel_con [ 43 ] ) & GMAC_MUX_SEL_EXTCLK ) {
return set_rate ;
/* An external clock will always generate the right rate... */
ret = set_rate ;
} else {
u32 con = readl ( & cru - > clksel_con [ 43 ] ) ;
ulong pll_rate ;
u8 div ;
if ( ( ( con > > GMAC_PLL_SHIFT ) & GMAC_PLL_MASK ) = =
GMAC_PLL_SELECT_GENERAL )
pll_rate = GPLL_HZ ;
else if ( ( ( con > > GMAC_PLL_SHIFT ) & GMAC_PLL_MASK ) = =
GMAC_PLL_SELECT_CODEC )
pll_rate = CPLL_HZ ;
else
/* CPLL is not set */
return - EPERM ;
div = DIV_ROUND_UP ( pll_rate , set_rate ) - 1 ;
if ( div < = 0x1f )
rk_clrsetreg ( & cru - > clksel_con [ 43 ] , GMAC_DIV_CON_MASK ,
div < < GMAC_DIV_CON_SHIFT ) ;
else
debug ( " Unsupported div for gmac:%d \n " , div ) ;
return DIV_TO_RATE ( pll_rate , div ) ;
}
return ret ;
}
}
# endif
# endif
@ -479,7 +507,7 @@ static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate)
# if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
# if CONFIG_IS_ENABLED(GMAC_ROCKCHIP)
case SCLK_MAC :
case SCLK_MAC :
/* select the external clock */
/* select the external clock */
ret = rk3368_gmac_set_clk ( priv - > cru , clk - > id , rate ) ;
ret = rk3368_gmac_set_clk ( priv - > cru , rate ) ;
break ;
break ;
# endif
# endif
case SCLK_SARADC :
case SCLK_SARADC :
@ -492,9 +520,58 @@ static ulong rk3368_clk_set_rate(struct clk *clk, ulong rate)
return ret ;
return ret ;
}
}
static int rk3368_gmac_set_parent ( struct clk * clk , struct clk * parent )
{
struct rk3368_clk_priv * priv = dev_get_priv ( clk - > dev ) ;
struct rk3368_cru * cru = priv - > cru ;
const char * clock_output_name ;
int ret ;
/*
* If the requested parent is in the same clock - controller and
* the id is SCLK_MAC ( " sclk_mac " ) , switch to the internal
* clock .
*/
if ( ( parent - > dev = = clk - > dev ) & & ( parent - > id = = SCLK_MAC ) ) {
debug ( " %s: switching GAMC to SCLK_MAC \n " , __func__ ) ;
rk_clrreg ( & cru - > clksel_con [ 43 ] , GMAC_MUX_SEL_EXTCLK ) ;
return 0 ;
}
/*
* Otherwise , we need to check the clock - output - names of the
* requested parent to see if the requested id is " ext_gmac " .
*/
ret = dev_read_string_index ( parent - > dev , " clock-output-names " ,
parent - > id , & clock_output_name ) ;
if ( ret < 0 )
return - ENODATA ;
/* If this is "ext_gmac", switch to the external clock input */
if ( ! strcmp ( clock_output_name , " ext_gmac " ) ) {
debug ( " %s: switching GMAC to external clock \n " , __func__ ) ;
rk_setreg ( & cru - > clksel_con [ 43 ] , GMAC_MUX_SEL_EXTCLK ) ;
return 0 ;
}
return - EINVAL ;
}
static int rk3368_clk_set_parent ( struct clk * clk , struct clk * parent )
{
switch ( clk - > id ) {
case SCLK_MAC :
return rk3368_gmac_set_parent ( clk , parent ) ;
}
debug ( " %s: unsupported clk %ld \n " , __func__ , clk - > id ) ;
return - ENOENT ;
}
static struct clk_ops rk3368_clk_ops = {
static struct clk_ops rk3368_clk_ops = {
. get_rate = rk3368_clk_get_rate ,
. get_rate = rk3368_clk_get_rate ,
. set_rate = rk3368_clk_set_rate ,
. set_rate = rk3368_clk_set_rate ,
. set_parent = rk3368_clk_set_parent ,
} ;
} ;
static int rk3368_clk_probe ( struct udevice * dev )
static int rk3368_clk_probe ( struct udevice * dev )