2012-05-02 19:16:39 +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 .
*
* Copyright ( C ) 2011 , 2012 Cavium , Inc .
*/
# include <linux/platform_device.h>
# include <linux/device.h>
# include <linux/of_mdio.h>
# include <linux/module.h>
# include <linux/phy.h>
# include <linux/mdio-mux.h>
2015-04-27 11:37:31 +03:00
# include <linux/gpio/consumer.h>
2012-05-02 19:16:39 +04:00
2014-11-25 12:31:18 +03:00
# define DRV_VERSION "1.1"
2012-05-02 19:16:39 +04:00
# define DRV_DESCRIPTION "GPIO controlled MDIO bus multiplexer driver"
struct mdio_mux_gpio_state {
2015-04-27 11:37:31 +03:00
struct gpio_descs * gpios ;
2012-05-02 19:16:39 +04:00
void * mux_handle ;
} ;
static int mdio_mux_gpio_switch_fn ( int current_child , int desired_child ,
void * data )
{
struct mdio_mux_gpio_state * s = data ;
2015-04-27 11:37:31 +03:00
int values [ s - > gpios - > ndescs ] ;
unsigned int n ;
2012-05-02 19:16:39 +04:00
if ( current_child = = desired_child )
return 0 ;
2015-04-27 11:37:31 +03:00
for ( n = 0 ; n < s - > gpios - > ndescs ; n + + )
2014-11-25 12:31:18 +03:00
values [ n ] = ( desired_child > > n ) & 1 ;
2015-04-27 11:37:31 +03:00
2015-05-13 12:04:56 +03:00
gpiod_set_array_value_cansleep ( s - > gpios - > ndescs , s - > gpios - > desc ,
values ) ;
2012-05-02 19:16:39 +04:00
return 0 ;
}
2012-12-03 18:24:14 +04:00
static int mdio_mux_gpio_probe ( struct platform_device * pdev )
2012-05-02 19:16:39 +04:00
{
struct mdio_mux_gpio_state * s ;
int r ;
s = devm_kzalloc ( & pdev - > dev , sizeof ( * s ) , GFP_KERNEL ) ;
if ( ! s )
return - ENOMEM ;
2015-04-27 11:37:31 +03:00
s - > gpios = gpiod_get_array ( & pdev - > dev , NULL , GPIOD_OUT_LOW ) ;
if ( IS_ERR ( s - > gpios ) )
return PTR_ERR ( s - > gpios ) ;
2012-05-02 19:16:39 +04:00
2017-09-04 19:30:14 +03:00
r = mdio_mux_init ( & pdev - > dev , pdev - > dev . of_node ,
2016-06-10 08:33:45 +03:00
mdio_mux_gpio_switch_fn , & s - > mux_handle , s , NULL ) ;
2012-05-02 19:16:39 +04:00
2015-04-27 11:37:31 +03:00
if ( r ! = 0 ) {
gpiod_put_array ( s - > gpios ) ;
return r ;
2012-05-02 19:16:39 +04:00
}
2015-04-27 11:37:31 +03:00
pdev - > dev . platform_data = s ;
return 0 ;
2012-05-02 19:16:39 +04:00
}
2012-12-03 18:24:14 +04:00
static int mdio_mux_gpio_remove ( struct platform_device * pdev )
2012-05-02 19:16:39 +04:00
{
2013-08-30 09:09:26 +04:00
struct mdio_mux_gpio_state * s = dev_get_platdata ( & pdev - > dev ) ;
2012-05-02 19:16:39 +04:00
mdio_mux_uninit ( s - > mux_handle ) ;
2015-04-27 11:37:31 +03:00
gpiod_put_array ( s - > gpios ) ;
2012-05-02 19:16:39 +04:00
return 0 ;
}
2015-03-17 21:40:23 +03:00
static const struct of_device_id mdio_mux_gpio_match [ ] = {
2012-05-02 19:16:39 +04:00
{
. compatible = " mdio-mux-gpio " ,
} ,
{
/* Legacy compatible property. */
. compatible = " cavium,mdio-mux-sn74cbtlv3253 " ,
} ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , mdio_mux_gpio_match ) ;
static struct platform_driver mdio_mux_gpio_driver = {
. driver = {
. name = " mdio-mux-gpio " ,
. of_match_table = mdio_mux_gpio_match ,
} ,
. probe = mdio_mux_gpio_probe ,
2012-12-03 18:24:14 +04:00
. remove = mdio_mux_gpio_remove ,
2012-05-02 19:16:39 +04:00
} ;
module_platform_driver ( mdio_mux_gpio_driver ) ;
MODULE_DESCRIPTION ( DRV_DESCRIPTION ) ;
MODULE_VERSION ( DRV_VERSION ) ;
MODULE_AUTHOR ( " David Daney " ) ;
MODULE_LICENSE ( " GPL " ) ;