2020-06-29 15:03:41 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2020-06-29 15:03:43 +03:00
# include <linux/device.h>
2020-06-29 15:03:45 +03:00
# include <linux/of_mdio.h>
2020-06-29 15:03:41 +03:00
# include <linux/phy.h>
2020-06-29 15:03:43 +03:00
# include <linux/stddef.h>
struct mdiobus_devres {
struct mii_bus * mii ;
} ;
static void devm_mdiobus_free ( struct device * dev , void * this )
{
struct mdiobus_devres * dr = this ;
mdiobus_free ( dr - > mii ) ;
}
/**
* devm_mdiobus_alloc_size - Resource - managed mdiobus_alloc_size ( )
* @ dev : Device to allocate mii_bus for
* @ sizeof_priv : Space to allocate for private structure
*
* Managed mdiobus_alloc_size . mii_bus allocated with this function is
* automatically freed on driver detach .
*
* RETURNS :
* Pointer to allocated mii_bus on success , NULL on out - of - memory error .
*/
struct mii_bus * devm_mdiobus_alloc_size ( struct device * dev , int sizeof_priv )
{
struct mdiobus_devres * dr ;
dr = devres_alloc ( devm_mdiobus_free , sizeof ( * dr ) , GFP_KERNEL ) ;
if ( ! dr )
return NULL ;
dr - > mii = mdiobus_alloc_size ( sizeof_priv ) ;
if ( ! dr - > mii ) {
devres_free ( dr ) ;
return NULL ;
}
devres_add ( dev , dr ) ;
return dr - > mii ;
}
EXPORT_SYMBOL ( devm_mdiobus_alloc_size ) ;
static void devm_mdiobus_unregister ( struct device * dev , void * this )
{
struct mdiobus_devres * dr = this ;
mdiobus_unregister ( dr - > mii ) ;
}
static int mdiobus_devres_match ( struct device * dev ,
void * this , void * match_data )
{
struct mdiobus_devres * res = this ;
struct mii_bus * mii = match_data ;
return mii = = res - > mii ;
}
2020-06-29 15:03:41 +03:00
2020-06-29 15:03:42 +03:00
/**
* __devm_mdiobus_register - Resource - managed variant of mdiobus_register ( )
2020-06-29 15:03:43 +03:00
* @ dev : Device to register mii_bus for
2020-06-29 15:03:42 +03:00
* @ bus : MII bus structure to register
* @ owner : Owning module
*
* Returns 0 on success , negative error number on failure .
*/
2020-06-29 15:03:43 +03:00
int __devm_mdiobus_register ( struct device * dev , struct mii_bus * bus ,
struct module * owner )
2020-06-29 15:03:41 +03:00
{
2020-06-29 15:03:43 +03:00
struct mdiobus_devres * dr ;
2020-06-29 15:03:41 +03:00
int ret ;
2020-06-29 15:03:43 +03:00
if ( WARN_ON ( ! devres_find ( dev , devm_mdiobus_free ,
mdiobus_devres_match , bus ) ) )
return - EINVAL ;
dr = devres_alloc ( devm_mdiobus_unregister , sizeof ( * dr ) , GFP_KERNEL ) ;
if ( ! dr )
return - ENOMEM ;
2020-06-29 15:03:41 +03:00
ret = __mdiobus_register ( bus , owner ) ;
2020-06-29 15:03:43 +03:00
if ( ret ) {
devres_free ( dr ) ;
return ret ;
}
2020-06-29 15:03:41 +03:00
2020-06-29 15:03:43 +03:00
dr - > mii = bus ;
devres_add ( dev , dr ) ;
return 0 ;
2020-06-29 15:03:41 +03:00
}
EXPORT_SYMBOL ( __devm_mdiobus_register ) ;
2020-06-29 15:03:45 +03:00
# if IS_ENABLED(CONFIG_OF_MDIO)
/**
* devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register ( )
* @ dev : Device to register mii_bus for
* @ mdio : MII bus structure to register
* @ np : Device node to parse
*/
int devm_of_mdiobus_register ( struct device * dev , struct mii_bus * mdio ,
struct device_node * np )
{
struct mdiobus_devres * dr ;
int ret ;
if ( WARN_ON ( ! devres_find ( dev , devm_mdiobus_free ,
mdiobus_devres_match , mdio ) ) )
return - EINVAL ;
dr = devres_alloc ( devm_mdiobus_unregister , sizeof ( * dr ) , GFP_KERNEL ) ;
if ( ! dr )
return - ENOMEM ;
ret = of_mdiobus_register ( mdio , np ) ;
if ( ret ) {
devres_free ( dr ) ;
return ret ;
}
dr - > mii = mdio ;
devres_add ( dev , dr ) ;
return 0 ;
}
EXPORT_SYMBOL ( devm_of_mdiobus_register ) ;
# endif /* CONFIG_OF_MDIO */
MODULE_LICENSE ( " GPL " ) ;