@ -295,15 +295,42 @@ static int pll_para_config(ulong freq_hz, struct pll_div *div, uint *ext_div)
return 0 ;
}
static int rockchip_mac_set_clk ( struct rk3288_cru * cru ,
int periph , uint freq )
static int rockchip_mac_set_clk ( struct rk3288_cru * cru , uint freq )
{
/* Assuming mac_clk is fed by an external clock */
rk_clrsetreg ( & cru - > cru_clksel_con [ 21 ] ,
RMII_EXTCLK_MASK ,
RMII_EXTCLK_SELECT_EXT_CLK < < RMII_EXTCLK_SHIFT ) ;
ulong ret ;
return 0 ;
/*
* The gmac clock can be derived either from an external clock
* or can be generated from internally by a divider from SCLK_MAC .
*/
if ( readl ( & cru - > cru_clksel_con [ 21 ] ) & RMII_EXTCLK_MASK ) {
/* An external clock will always generate the right rate... */
ret = freq ;
} else {
u32 con = readl ( & cru - > cru_clksel_con [ 21 ] ) ;
ulong pll_rate ;
u8 div ;
if ( ( ( con > > EMAC_PLL_SHIFT ) & EMAC_PLL_MASK ) = =
EMAC_PLL_SELECT_GENERAL )
pll_rate = GPLL_HZ ;
else if ( ( ( con > > EMAC_PLL_SHIFT ) & EMAC_PLL_MASK ) = =
EMAC_PLL_SELECT_CODEC )
pll_rate = CPLL_HZ ;
else
pll_rate = NPLL_HZ ;
div = DIV_ROUND_UP ( pll_rate , freq ) - 1 ;
if ( div < = 0x1f )
rk_clrsetreg ( & cru - > cru_clksel_con [ 21 ] , MAC_DIV_CON_MASK ,
div < < MAC_DIV_CON_SHIFT ) ;
else
debug ( " Unsupported div for gmac:%d \n " , div ) ;
return DIV_TO_RATE ( pll_rate , div ) ;
}
return ret ;
}
static int rockchip_vop_set_clk ( struct rk3288_cru * cru , struct rk3288_grf * grf ,
@ -744,7 +771,7 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
break ;
# ifndef CONFIG_SPL_BUILD
case SCLK_MAC :
new_rate = rockchip_mac_set_clk ( priv - > cru , clk - > id , rate ) ;
new_rate = rockchip_mac_set_clk ( priv - > cru , rate ) ;
break ;
case DCLK_VOP0 :
case DCLK_VOP1 :
@ -797,6 +824,17 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_SARADC :
new_rate = rockchip_saradc_set_clk ( priv - > cru , rate ) ;
break ;
case PLL_GPLL :
case PLL_CPLL :
case PLL_NPLL :
case ACLK_CPU :
case HCLK_CPU :
case PCLK_CPU :
case ACLK_PERI :
case HCLK_PERI :
case PCLK_PERI :
case SCLK_UART0 :
return 0 ;
default :
return - ENOENT ;
}
@ -804,9 +842,61 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate)
return new_rate ;
}
static int rk3288_gmac_set_parent ( struct clk * clk , struct clk * parent )
{
struct rk3288_clk_priv * priv = dev_get_priv ( clk - > dev ) ;
struct rk3288_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_PLL ( " mac_pll_src " ) , switch to the internal
* clock .
*/
if ( ( parent - > dev = = clk - > dev ) & & ( parent - > id = = SCLK_MAC_PLL ) ) {
debug ( " %s: switching GAMC to SCLK_MAC_PLL \n " , __func__ ) ;
rk_clrsetreg ( & cru - > cru_clksel_con [ 21 ] , RMII_EXTCLK_MASK , 0 ) ;
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_clrsetreg ( & cru - > cru_clksel_con [ 21 ] , RMII_EXTCLK_MASK ,
RMII_EXTCLK_SELECT_EXT_CLK < < RMII_EXTCLK_SHIFT ) ;
return 0 ;
}
return - EINVAL ;
}
static int rk3288_clk_set_parent ( struct clk * clk , struct clk * parent )
{
switch ( clk - > id ) {
case SCLK_MAC :
return rk3288_gmac_set_parent ( clk , parent ) ;
case SCLK_USBPHY480M_SRC :
return 0 ;
}
debug ( " %s: unsupported clk %ld \n " , __func__ , clk - > id ) ;
return - ENOENT ;
}
static struct clk_ops rk3288_clk_ops = {
. get_rate = rk3288_clk_get_rate ,
. set_rate = rk3288_clk_set_rate ,
. set_parent = rk3288_clk_set_parent ,
} ;
static int rk3288_clk_ofdata_to_platdata ( struct udevice * dev )