@ -225,6 +225,18 @@ struct cpdma_chan {
void * hdp , * cp , * rxfree ;
} ;
/* AM33xx SoC specific definitions for the CONTROL port */
# define AM33XX_GMII_SEL_MODE_MII 0
# define AM33XX_GMII_SEL_MODE_RMII 1
# define AM33XX_GMII_SEL_MODE_RGMII 2
# define AM33XX_GMII_SEL_RGMII1_IDMODE BIT(4)
# define AM33XX_GMII_SEL_RGMII2_IDMODE BIT(5)
# define AM33XX_GMII_SEL_RMII1_IO_CLK_EN BIT(6)
# define AM33XX_GMII_SEL_RMII2_IO_CLK_EN BIT(7)
# define GMII_SEL_MODE_MASK 0x3
# define desc_write(desc, fld, val) __raw_writel((u32)(val), &(desc)->fld)
# define desc_read(desc, fld) __raw_readl(&(desc)->fld)
# define desc_read_ptr(desc, fld) ((void *)__raw_readl(&(desc)->fld))
@ -1150,12 +1162,129 @@ static inline fdt_addr_t cpsw_get_addr_by_node(const void *fdt, int node)
false ) ;
}
static void cpsw_gmii_sel_am3352 ( struct cpsw_priv * priv ,
phy_interface_t phy_mode )
{
u32 reg ;
u32 mask ;
u32 mode = 0 ;
bool rgmii_id = false ;
int slave = priv - > data . active_slave ;
reg = readl ( priv - > data . gmii_sel ) ;
switch ( phy_mode ) {
case PHY_INTERFACE_MODE_RMII :
mode = AM33XX_GMII_SEL_MODE_RMII ;
break ;
case PHY_INTERFACE_MODE_RGMII :
mode = AM33XX_GMII_SEL_MODE_RGMII ;
break ;
case PHY_INTERFACE_MODE_RGMII_ID :
case PHY_INTERFACE_MODE_RGMII_RXID :
case PHY_INTERFACE_MODE_RGMII_TXID :
mode = AM33XX_GMII_SEL_MODE_RGMII ;
rgmii_id = true ;
break ;
case PHY_INTERFACE_MODE_MII :
default :
mode = AM33XX_GMII_SEL_MODE_MII ;
break ;
} ;
mask = GMII_SEL_MODE_MASK < < ( slave * 2 ) | BIT ( slave + 6 ) ;
mode < < = slave * 2 ;
if ( priv - > data . rmii_clock_external ) {
if ( slave = = 0 )
mode | = AM33XX_GMII_SEL_RMII1_IO_CLK_EN ;
else
mode | = AM33XX_GMII_SEL_RMII2_IO_CLK_EN ;
}
if ( rgmii_id ) {
if ( slave = = 0 )
mode | = AM33XX_GMII_SEL_RGMII1_IDMODE ;
else
mode | = AM33XX_GMII_SEL_RGMII2_IDMODE ;
}
reg & = ~ mask ;
reg | = mode ;
writel ( reg , priv - > data . gmii_sel ) ;
}
static void cpsw_gmii_sel_dra7xx ( struct cpsw_priv * priv ,
phy_interface_t phy_mode )
{
u32 reg ;
u32 mask ;
u32 mode = 0 ;
int slave = priv - > data . active_slave ;
reg = readl ( priv - > data . gmii_sel ) ;
switch ( phy_mode ) {
case PHY_INTERFACE_MODE_RMII :
mode = AM33XX_GMII_SEL_MODE_RMII ;
break ;
case PHY_INTERFACE_MODE_RGMII :
case PHY_INTERFACE_MODE_RGMII_ID :
case PHY_INTERFACE_MODE_RGMII_RXID :
case PHY_INTERFACE_MODE_RGMII_TXID :
mode = AM33XX_GMII_SEL_MODE_RGMII ;
break ;
case PHY_INTERFACE_MODE_MII :
default :
mode = AM33XX_GMII_SEL_MODE_MII ;
break ;
} ;
switch ( slave ) {
case 0 :
mask = GMII_SEL_MODE_MASK ;
break ;
case 1 :
mask = GMII_SEL_MODE_MASK < < 4 ;
mode < < = 4 ;
break ;
default :
dev_err ( priv - > dev , " invalid slave number... \n " ) ;
return ;
}
if ( priv - > data . rmii_clock_external )
dev_err ( priv - > dev , " RMII External clock is not supported \n " ) ;
reg & = ~ mask ;
reg | = mode ;
writel ( reg , priv - > data . gmii_sel ) ;
}
static void cpsw_phy_sel ( struct cpsw_priv * priv , const char * compat ,
phy_interface_t phy_mode )
{
if ( ! strcmp ( compat , " ti,am3352-cpsw-phy-sel " ) )
cpsw_gmii_sel_am3352 ( priv , phy_mode ) ;
if ( ! strcmp ( compat , " ti,am43xx-cpsw-phy-sel " ) )
cpsw_gmii_sel_am3352 ( priv , phy_mode ) ;
else if ( ! strcmp ( compat , " ti,dra7xx-cpsw-phy-sel " ) )
cpsw_gmii_sel_dra7xx ( priv , phy_mode ) ;
}
static int cpsw_eth_ofdata_to_platdata ( struct udevice * dev )
{
struct eth_pdata * pdata = dev_get_platdata ( dev ) ;
struct cpsw_priv * priv = dev_get_priv ( dev ) ;
struct gpio_desc * mode_gpios ;
const char * phy_mode ;
const char * phy_sel_compat = NULL ;
const void * fdt = gd - > fdt_blob ;
int node = dev - > of_offset ;
int subnode ;
@ -1271,6 +1400,17 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
error ( " Not able to get gmii_sel reg address \n " ) ;
return - ENOENT ;
}
if ( fdt_get_property ( fdt , subnode , " rmii-clock-ext " ,
NULL ) )
priv - > data . rmii_clock_external = true ;
phy_sel_compat = fdt_getprop ( fdt , subnode , " compatible " ,
NULL ) ;
if ( ! phy_sel_compat ) {
error ( " Not able to get gmii_sel compatible \n " ) ;
return - ENOENT ;
}
}
}
@ -1293,20 +1433,9 @@ static int cpsw_eth_ofdata_to_platdata(struct udevice *dev)
debug ( " %s: Invalid PHY interface '%s' \n " , __func__ , phy_mode ) ;
return - EINVAL ;
}
switch ( pdata - > phy_interface ) {
case PHY_INTERFACE_MODE_MII :
writel ( MII_MODE_ENABLE , priv - > data . gmii_sel ) ;
break ;
case PHY_INTERFACE_MODE_RMII :
writel ( RMII_MODE_ENABLE , priv - > data . gmii_sel ) ;
break ;
case PHY_INTERFACE_MODE_RGMII :
case PHY_INTERFACE_MODE_RGMII_ID :
case PHY_INTERFACE_MODE_RGMII_RXID :
case PHY_INTERFACE_MODE_RGMII_TXID :
writel ( RGMII_MODE_ENABLE , priv - > data . gmii_sel ) ;
break ;
}
/* Select phy interface in control module */
cpsw_phy_sel ( priv , phy_sel_compat , pdata - > phy_interface ) ;
return 0 ;
}