[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20190221182516.4700-1-pankaj.bansal@nxp.com>
Date: Thu, 21 Feb 2019 13:00:44 +0000
From: Pankaj Bansal <pankaj.bansal@....com>
To: Leo Li <leoyang.li@....com>, Peter Rosin <peda@...ntia.se>,
Andrew Lunn <andrew@...n.ch>,
Florian Fainelli <f.fainelli@...il.com>,
Heiner Kallweit <hkallweit1@...il.com>
CC: "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
Pankaj Bansal <pankaj.bansal@....com>
Subject: [PATCH] drivers: net: phy: mdio-mux: Add support for Generic Mux
controls
Add support for Generic Mux controls, when Mdio mux node is a consumer
of mux produced by some other device.
Signed-off-by: Pankaj Bansal <pankaj.bansal@....com>
---
drivers/net/phy/Kconfig | 1 +
drivers/net/phy/mdio-mux.c | 81 ++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 3d187cd50eb0..e0e6b2b33d6d 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -47,6 +47,7 @@ config MDIO_BITBANG
config MDIO_BUS_MUX
tristate
depends on OF_MDIO
+ select MULTIPLEXER
help
This module provides a driver framework for MDIO bus
multiplexers which connect one of several child MDIO busses
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c
index 0a86f1e4c02f..c49e4ae9c174 100644
--- a/drivers/net/phy/mdio-mux.c
+++ b/drivers/net/phy/mdio-mux.c
@@ -11,6 +11,7 @@
#include <linux/of_mdio.h>
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/mux/consumer.h>
#include <linux/phy.h>
#define DRV_DESCRIPTION "MDIO bus multiplexer driver"
@@ -35,6 +36,11 @@ struct mdio_mux_child_bus {
int bus_number;
};
+struct mdio_mux_state {
+ struct mux_control *muxc;
+ void *mux_handle;
+};
+
/*
* The parent bus' lock is used to order access to the switch_fn.
*/
@@ -208,6 +214,81 @@ void mdio_mux_uninit(void *mux_handle)
}
EXPORT_SYMBOL_GPL(mdio_mux_uninit);
+static int mdio_mux_switch_fn(int current_child, int desired_child, void *data)
+{
+ struct platform_device *pdev;
+ struct mdio_mux_state *s;
+ int ret = 0;
+
+ pdev = (struct platform_device *)data;
+ s = (struct mdio_mux_state *)platform_get_drvdata(pdev);
+ if (current_child ^ desired_child) {
+ if (current_child != -1)
+ ret = mux_control_deselect(s->muxc);
+ if (ret)
+ return ret;
+
+ ret = mux_control_select(s->muxc, desired_child);
+ if (!ret)
+ dev_dbg(&pdev->dev, "%s %d -> %d\n", __func__,
+ current_child, desired_child);
+ }
+
+ return ret;
+}
+
+static int mdio_mux_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mdio_mux_state *s;
+ int ret = 0;
+
+ s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
+ if (!s)
+ return -ENOMEM;
+
+ s->muxc = devm_mux_control_get(dev, NULL);
+ if (IS_ERR(s->muxc)) {
+ ret = PTR_ERR(s->muxc);
+ if (ret != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "Failed to get mux: %d\n", ret);
+ return ret;
+ }
+
+ platform_set_drvdata(pdev, s);
+
+ ret = mdio_mux_init(&pdev->dev, pdev->dev.of_node, mdio_mux_switch_fn,
+ &s->mux_handle, pdev, NULL);
+
+ return ret;
+}
+
+static int mdio_mux_remove(struct platform_device *pdev)
+{
+ struct mdio_mux_state *s = platform_get_drvdata(pdev);
+
+ mdio_mux_uninit(s->mux_handle);
+
+ return 0;
+}
+
+static const struct of_device_id mdio_mux_match[] = {
+ { .compatible = "mdio-mux", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, mdio_mux_match);
+
+static struct platform_driver mdio_mux_driver = {
+ .driver = {
+ .name = "mdio-mux",
+ .of_match_table = mdio_mux_match,
+ },
+ .probe = mdio_mux_probe,
+ .remove = mdio_mux_remove,
+};
+
+module_platform_driver(mdio_mux_driver);
+
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_AUTHOR("David Daney");
MODULE_LICENSE("GPL");
--
2.17.1
Powered by blists - more mailing lists