2009-10-14 23:04:38 +04:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
2016-03-11 20:53:10 +03:00
* Copyright ( C ) 2009 - 2015 Cavium , Inc .
2009-10-14 23:04:38 +04:00
*/
# include <linux/platform_device.h>
2015-07-29 01:12:11 +03:00
# include <linux/of_address.h>
2012-07-05 20:12:39 +04:00
# include <linux/of_mdio.h>
# include <linux/module.h>
# include <linux/gfp.h>
2009-10-14 23:04:38 +04:00
# include <linux/phy.h>
2012-07-05 20:12:39 +04:00
# include <linux/io.h>
2009-10-14 23:04:38 +04:00
2016-03-11 20:53:10 +03:00
# include "mdio-cavium.h"
2009-10-14 23:04:38 +04:00
2012-12-03 18:24:14 +04:00
static int octeon_mdiobus_probe ( struct platform_device * pdev )
2009-10-14 23:04:38 +04:00
{
2016-03-11 20:53:10 +03:00
struct cavium_mdiobus * bus ;
2016-01-06 22:11:14 +03:00
struct mii_bus * mii_bus ;
2012-07-05 20:12:39 +04:00
struct resource * res_mem ;
2016-03-11 20:53:10 +03:00
resource_size_t mdio_phys ;
resource_size_t regsize ;
2010-04-02 05:17:54 +04:00
union cvmx_smix_en smi_en ;
2009-10-14 23:04:38 +04:00
int err = - ENOENT ;
2016-01-06 22:11:14 +03:00
mii_bus = devm_mdiobus_alloc_size ( & pdev - > dev , sizeof ( * bus ) ) ;
if ( ! mii_bus )
2009-10-14 23:04:38 +04:00
return - ENOMEM ;
2012-07-05 20:12:39 +04:00
res_mem = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
if ( res_mem = = NULL ) {
dev_err ( & pdev - > dev , " found no memory resource \n " ) ;
2015-07-29 01:12:12 +03:00
return - ENXIO ;
2012-07-05 20:12:39 +04:00
}
2015-07-29 01:12:12 +03:00
2016-01-06 22:11:14 +03:00
bus = mii_bus - > priv ;
bus - > mii_bus = mii_bus ;
2016-03-11 20:53:10 +03:00
mdio_phys = res_mem - > start ;
regsize = resource_size ( res_mem ) ;
2015-07-29 01:12:12 +03:00
2016-03-11 20:53:10 +03:00
if ( ! devm_request_mem_region ( & pdev - > dev , mdio_phys , regsize ,
2012-07-05 20:12:39 +04:00
res_mem - > name ) ) {
dev_err ( & pdev - > dev , " request_mem_region failed \n " ) ;
2015-07-29 01:12:12 +03:00
return - ENXIO ;
2012-07-05 20:12:39 +04:00
}
2015-07-29 01:12:12 +03:00
2012-07-05 20:12:39 +04:00
bus - > register_base =
2016-03-11 20:53:10 +03:00
( u64 ) devm_ioremap ( & pdev - > dev , mdio_phys , regsize ) ;
2015-07-29 01:12:12 +03:00
if ( ! bus - > register_base ) {
dev_err ( & pdev - > dev , " dev_ioremap failed \n " ) ;
return - ENOMEM ;
}
2009-10-14 23:04:38 +04:00
2010-04-02 05:17:54 +04:00
smi_en . u64 = 0 ;
smi_en . s . en = 1 ;
2015-07-29 01:12:11 +03:00
oct_mdio_writeq ( smi_en . u64 , bus - > register_base + SMI_EN ) ;
2009-10-14 23:04:38 +04:00
2016-03-11 20:53:10 +03:00
bus - > mii_bus - > name = KBUILD_MODNAME ;
2012-07-05 20:12:39 +04:00
snprintf ( bus - > mii_bus - > id , MII_BUS_ID_SIZE , " %llx " , bus - > register_base ) ;
2009-10-14 23:04:38 +04:00
bus - > mii_bus - > parent = & pdev - > dev ;
2016-03-11 20:53:10 +03:00
bus - > mii_bus - > read = cavium_mdiobus_read ;
bus - > mii_bus - > write = cavium_mdiobus_write ;
2009-10-14 23:04:38 +04:00
2013-08-21 14:15:15 +04:00
platform_set_drvdata ( pdev , bus ) ;
2009-10-14 23:04:38 +04:00
2012-07-05 20:12:39 +04:00
err = of_mdiobus_register ( bus - > mii_bus , pdev - > dev . of_node ) ;
2009-10-14 23:04:38 +04:00
if ( err )
2012-07-05 20:12:39 +04:00
goto fail_register ;
2009-10-14 23:04:38 +04:00
2016-03-11 20:53:10 +03:00
dev_info ( & pdev - > dev , " Probed \n " ) ;
2009-10-14 23:04:38 +04:00
return 0 ;
2012-07-05 20:12:39 +04:00
fail_register :
2009-10-14 23:04:38 +04:00
mdiobus_free ( bus - > mii_bus ) ;
2010-04-02 05:17:54 +04:00
smi_en . u64 = 0 ;
2015-07-29 01:12:11 +03:00
oct_mdio_writeq ( smi_en . u64 , bus - > register_base + SMI_EN ) ;
2009-10-14 23:04:38 +04:00
return err ;
}
2012-12-03 18:24:14 +04:00
static int octeon_mdiobus_remove ( struct platform_device * pdev )
2009-10-14 23:04:38 +04:00
{
2016-03-11 20:53:10 +03:00
struct cavium_mdiobus * bus ;
2010-04-02 05:17:54 +04:00
union cvmx_smix_en smi_en ;
2009-10-14 23:04:38 +04:00
2013-09-02 12:10:09 +04:00
bus = platform_get_drvdata ( pdev ) ;
2009-10-14 23:04:38 +04:00
mdiobus_unregister ( bus - > mii_bus ) ;
mdiobus_free ( bus - > mii_bus ) ;
2010-04-02 05:17:54 +04:00
smi_en . u64 = 0 ;
2015-07-29 01:12:11 +03:00
oct_mdio_writeq ( smi_en . u64 , bus - > register_base + SMI_EN ) ;
2009-10-14 23:04:38 +04:00
return 0 ;
}
2015-03-17 21:40:23 +03:00
static const struct of_device_id octeon_mdiobus_match [ ] = {
2012-07-05 20:12:39 +04:00
{
. compatible = " cavium,octeon-3860-mdio " ,
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , octeon_mdiobus_match ) ;
2009-10-14 23:04:38 +04:00
static struct platform_driver octeon_mdiobus_driver = {
. driver = {
2016-03-11 20:53:10 +03:00
. name = KBUILD_MODNAME ,
2012-07-05 20:12:39 +04:00
. of_match_table = octeon_mdiobus_match ,
2009-10-14 23:04:38 +04:00
} ,
. probe = octeon_mdiobus_probe ,
2012-12-03 18:24:14 +04:00
. remove = octeon_mdiobus_remove ,
2009-10-14 23:04:38 +04:00
} ;
void octeon_mdiobus_force_mod_depencency ( void )
{
/* Let ethernet drivers force us to be loaded. */
}
EXPORT_SYMBOL ( octeon_mdiobus_force_mod_depencency ) ;
2013-03-20 05:41:32 +04:00
module_platform_driver ( octeon_mdiobus_driver ) ;
2009-10-14 23:04:38 +04:00
2016-03-11 20:53:10 +03:00
MODULE_DESCRIPTION ( " Cavium OCTEON MDIO bus driver " ) ;
2009-10-14 23:04:38 +04:00
MODULE_AUTHOR ( " David Daney " ) ;
MODULE_LICENSE ( " GPL " ) ;