@ -20,7 +20,7 @@
static int bus_count ;
static int ag71xx_mdio_wait_busy ( struct ag71xx * ag )
static int ag71xx_mdio_wait_busy ( struct ag71xx_mdio * am )
{
int i ;
@ -29,57 +29,57 @@ static int ag71xx_mdio_wait_busy(struct ag71xx *ag)
udelay ( AG71XX_MDIO_DELAY ) ;
regmap_read ( ag - > mii_regmap , AG71XX_REG_MII_IND , & busy ) ;
regmap_read ( am - > mii_regmap , AG71XX_REG_MII_IND , & busy ) ;
if ( ! busy )
return 0 ;
udelay ( AG71XX_MDIO_DELAY ) ;
}
pr_err ( " %s: MDIO operation timed out \n " , ag - > mii_bus - > name ) ;
pr_err ( " %s: MDIO operation timed out \n " , am - > mii_bus - > name ) ;
return - ETIMEDOUT ;
}
int ag71xx_mdio_mii_read ( struct mii_bus * bus , int addr , int reg )
static int ag71xx_mdio_mii_read ( struct mii_bus * bus , int addr , int reg )
{
struct ag71xx * ag = bus - > priv ;
struct ag71xx_mdio * am = bus - > priv ;
int err ;
int ret ;
err = ag71xx_mdio_wait_busy ( ag ) ;
err = ag71xx_mdio_wait_busy ( am ) ;
if ( err )
return 0xffff ;
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_CMD , MII_CMD_WRITE ) ;
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_ADDR ,
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_CMD , MII_CMD_WRITE ) ;
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_ADDR ,
( ( addr & 0xff ) < < MII_ADDR_SHIFT ) | ( reg & 0xff ) ) ;
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_CMD , MII_CMD_READ ) ;
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_CMD , MII_CMD_READ ) ;
err = ag71xx_mdio_wait_busy ( ag ) ;
err = ag71xx_mdio_wait_busy ( am ) ;
if ( err )
return 0xffff ;
regmap_read ( ag - > mii_regmap , AG71XX_REG_MII_STATUS , & ret ) ;
regmap_read ( am - > mii_regmap , AG71XX_REG_MII_STATUS , & ret ) ;
ret & = 0xffff ;
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_CMD , MII_CMD_WRITE ) ;
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_CMD , MII_CMD_WRITE ) ;
DBG ( " mii_read: addr=%04x, reg=%04x, value=%04x \n " , addr , reg , ret ) ;
return ret ;
}
int ag71xx_mdio_mii_write ( struct mii_bus * bus , int addr , int reg , u16 val )
static int ag71xx_mdio_mii_write ( struct mii_bus * bus , int addr , int reg , u16 val )
{
struct ag71xx * ag = bus - > priv ;
struct ag71xx_mdio * am = bus - > priv ;
DBG ( " mii_write: addr=%04x, reg=%04x, value=%04x \n " , addr , reg , val ) ;
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_ADDR ,
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_ADDR ,
( ( addr & 0xff ) < < MII_ADDR_SHIFT ) | ( reg & 0xff ) ) ;
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_CTRL , val ) ;
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_CTRL , val ) ;
ag71xx_mdio_wait_busy ( ag ) ;
ag71xx_mdio_wait_busy ( am ) ;
return 0 ;
}
@ -97,23 +97,22 @@ static int ar934x_mdio_clock_div(unsigned int rate)
static int ag71xx_mdio_reset ( struct mii_bus * bus )
{
struct device_node * np = bus - > dev . of_node ;
struct ag71xx * ag = bus - > priv ;
struct device_node * np_ag = ag - > pdev - > dev . of_node ;
struct ag71xx_mdio * am = bus - > priv ;
bool builtin_switch ;
u32 t ;
builtin_switch = of_property_read_bool ( np , " builtin-switch " ) ;
if ( of_device_is_compatible ( np_ag , " qca,ar7240-eth " ) )
if ( of_device_is_compatible ( np , " qca,ar7240-mdio " ) )
t = MII_CFG_CLK_DIV_6 ;
else if ( of_device_is_compatible ( np_ag , " qca,ar9340-eth " ) )
else if ( of_device_is_compatible ( np , " qca,ar9340-mdio " ) )
t = MII_CFG_CLK_DIV_58 ;
else if ( builtin_switch )
t = MII_CFG_CLK_DIV_10 ;
else
t = MII_CFG_CLK_DIV_28 ;
if ( builtin_switch & & of_device_is_compatible ( np_ag , " qca,ar9340-eth " ) ) {
if ( builtin_switch & & of_device_is_compatible ( np , " qca,ar9340-mdio " ) ) {
struct clk * ref_clk = of_clk_get ( np , 0 ) ;
int clock_rate ;
@ -126,56 +125,45 @@ static int ag71xx_mdio_reset(struct mii_bus *bus)
clk_put ( ref_clk ) ;
}
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_CFG , t | MII_CFG_RESET ) ;
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_CFG , t | MII_CFG_RESET ) ;
udelay ( 100 ) ;
regmap_write ( ag - > mii_regmap , AG71XX_REG_MII_CFG , t ) ;
regmap_write ( am - > mii_regmap , AG71XX_REG_MII_CFG , t ) ;
udelay ( 100 ) ;
return 0 ;
}
int ag71xx_mdio_init ( struct ag71xx * ag )
static int ag71xx_mdio_probe ( struct platform_device * pdev )
{
struct device * parent = & ag - > pdev - > dev ;
struct device_node * np ;
struct device * amdev = & pdev - > dev ;
struct device_node * np = pdev - > dev . of_node ;
struct ag71xx_mdio * am ;
struct mii_bus * mii_bus ;
bool builtin_switch ;
int i , err ;
np = of_get_child_by_name ( parent - > of_node , " mdio-bus " ) ;
if ( ! np )
return - ENODEV ;
am = devm_kzalloc ( amdev , sizeof ( * am ) , GFP_KERNEL ) ;
if ( ! am )
return - ENOMEM ;
if ( ! of_device_is_available ( np ) ) {
err = 0 ;
goto err_out ;
}
ag - > mii_regmap = syscon_regmap_lookup_by_phandle ( np , " regmap " ) ;
if ( ! ag - > mii_regmap )
am - > mii_regmap = syscon_regmap_lookup_by_phandle ( np , " regmap " ) ;
if ( ! am - > mii_regmap )
return - ENOENT ;
mii_bus = devm_mdiobus_alloc ( parent ) ;
if ( ! mii_bus ) {
err = - ENOMEM ;
goto err_out ;
}
mii_bus = devm_mdiobus_alloc ( amdev ) ;
if ( ! mii_bus )
return - ENOMEM ;
ag - > mdio_reset = of_reset_control_get_exclusive ( np , " mdio " ) ;
am - > mdio_reset = of_reset_control_get_exclusive ( np , " mdio " ) ;
builtin_switch = of_property_read_bool ( np , " builtin-switch " ) ;
mii_bus - > name = " mdio " ;
if ( builtin_switch ) {
mii_bus - > read = ar7240sw_phy_read ;
mii_bus - > write = ar7240sw_phy_write ;
} else {
mii_bus - > read = ag71xx_mdio_mii_read ;
mii_bus - > write = ag71xx_mdio_mii_write ;
}
mii_bus - > name = " ag71xx_mdio " ;
mii_bus - > read = ag71xx_mdio_mii_read ;
mii_bus - > write = ag71xx_mdio_mii_write ;
mii_bus - > reset = ag71xx_mdio_reset ;
mii_bus - > priv = ag ;
mii_bus - > parent = parent ;
mii_bus - > priv = am ;
mii_bus - > parent = amdev ;
snprintf ( mii_bus - > id , MII_BUS_ID_SIZE , " %s.%d " , np - > name , bus_count + + ) ;
if ( ! builtin_switch & &
@ -185,34 +173,46 @@ int ag71xx_mdio_init(struct ag71xx *ag)
for ( i = 0 ; i < PHY_MAX_ADDR ; i + + )
mii_bus - > irq [ i ] = PHY_POLL ;
if ( ! IS_ERR ( ag - > mdio_reset ) ) {
reset_control_assert ( ag - > mdio_reset ) ;
if ( ! IS_ERR ( am - > mdio_reset ) ) {
reset_control_assert ( am - > mdio_reset ) ;
msleep ( 100 ) ;
reset_control_deassert ( ag - > mdio_reset ) ;
reset_control_deassert ( am - > mdio_reset ) ;
msleep ( 200 ) ;
}
err = of_mdiobus_register ( mii_bus , np ) ;
if ( err )
goto err_out ;
ag - > mii_bus = mii_bus ;
return err ;
if ( builtin_switch )
ag71xx_ar7240_init ( ag , np ) ;
am - > mii_bus = mii_bus ;
platform_set_drvdata ( pdev , am ) ;
return 0 ;
err_out :
of_node_put ( np ) ;
return err ;
}
void ag71xx_mdio_cleanup ( struct ag71xx * ag )
static int ag71xx_mdio_remove ( struct platform_device * pdev )
{
if ( ! ag - > mii_bus )
return ;
struct ag71xx_mdio * am = platform_get_drvdata ( pdev ) ;
ag71xx_ar7240_cleanup ( ag ) ;
mdiobus_unregister ( ag - > mii_bus ) ;
mdiobus_unregister ( am - > mii_bus ) ;
return 0 ;
}
static const struct of_device_id ag71xx_mdio_match [ ] = {
{ . compatible = " qca,ar7240-mdio " } ,
{ . compatible = " qca,ar9340-mdio " } ,
{ . compatible = " qca,ath79-mdio " } ,
{ }
} ;
static struct platform_driver ag71xx_mdio_driver = {
. probe = ag71xx_mdio_probe ,
. remove = ag71xx_mdio_remove ,
. driver = {
. name = " ag71xx-mdio " ,
. of_match_table = ag71xx_mdio_match ,
}
} ;
module_platform_driver ( ag71xx_mdio_driver ) ;
MODULE_LICENSE ( " GPL " ) ;