mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: "Clément Leger" <cleger@kalray.eu>
To: Barebox List <barebox@lists.infradead.org>
Subject: [PATCH] Net: add mdio_i2c driver.
Date: Tue, 14 Nov 2017 14:34:51 +0100 (CET)	[thread overview]
Message-ID: <221136220.35006899.1510666491764.JavaMail.zimbra@kalray.eu> (raw)

From 1238b5c70d29762074bc71ac25623b958af9010a Mon Sep 17 00:00:00 2001
From: Clement Leger <clement.leger@kalray.eu>
Date: Wed, 8 Nov 2017 09:13:10 +0100
Subject: [PATCH] Net: add mdio_i2c driver (i2c to mdio bridge).

Some phys (Marvells) can be connected using and i2c bus instead of a mdio bus.
The communication format is then slightly different than standard mdio.
This patch add a i2c to mdio bridge which allows to communicate with
these phys.

---
 drivers/net/phy/Kconfig       |   8 +++
 drivers/net/phy/Makefile      |   1 +
 drivers/net/phy/mdio-i2c.c    | 148 ++++++++++++++++++++++++++++++++++++++++++
 dts/Bindings/net/mdio-i2c.txt |  19 ++++++
 4 files changed, 176 insertions(+)
 create mode 100644 drivers/net/phy/mdio-i2c.c
 create mode 100644 dts/Bindings/net/mdio-i2c.txt

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index ea2e062..f058f38 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -60,6 +60,14 @@ config MDIO_BITBANG
 
           If in doubt, say N.
 
+config MDIO_I2C
+	bool "Support for I2C based MDIO buses"
+	depends on I2C
+	---help---
+	  Support I2C based PHYs. This provides a MDIO bus bridged
+	  to I2C to allow PHYs connected in I2C mode to be accessed
+	  using the existing infrastructure.
+
 config MDIO_GPIO
 	bool "Support for GPIO lib-based bitbanged MDIO buses"
 	depends on MDIO_BITBANG && GPIOLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 13b8f65..9f61ae6 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_SMSC_PHY)		+= smsc.o
 obj-$(CONFIG_MDIO_MVEBU)	+= mdio-mvebu.o
 obj-$(CONFIG_MDIO_BITBANG)	+= mdio-bitbang.o
 obj-$(CONFIG_MDIO_GPIO)		+= mdio-gpio.o
+obj-$(CONFIG_MDIO_I2C)		+= mdio-i2c.o
diff --git a/drivers/net/phy/mdio-i2c.c b/drivers/net/phy/mdio-i2c.c
new file mode 100644
index 0000000..fcc5562
--- /dev/null
+++ b/drivers/net/phy/mdio-i2c.c
@@ -0,0 +1,148 @@
+/*
+ * MDIO I2C bridge
+ *
+ * Copyright (C) 2017 Clément Léger
+ *
+ * Based on code by Russell King from Linux
+ * Copyright (C) 2015 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <io.h>
+#include <of.h>
+#include <of_gpio.h>
+#include <linux/phy.h>
+#include <gpio.h>
+#include <malloc.h>
+#include <xfuncs.h>
+
+#include <i2c/i2c.h>
+
+/*
+ * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
+ * specified to be present in SFP modules.  These correspond with PHY
+ * addresses 16 and 17.  Disallow access to these "phy" addresses.
+ */
+static bool i2c_mii_valid_phy_id(int phy_id)
+{
+	return phy_id != 0x10 && phy_id != 0x11;
+}
+
+static unsigned int i2c_mii_phy_addr(int phy_id)
+{
+	return phy_id + 0x40;
+}
+
+static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
+{
+	struct i2c_adapter *i2c = bus->priv;
+	struct i2c_msg msgs[2];
+	u8 data[2], dev_addr = reg;
+	int bus_addr, ret;
+
+	if (!i2c_mii_valid_phy_id(phy_id))
+		return 0xffff;
+
+	bus_addr = i2c_mii_phy_addr(phy_id);
+	msgs[0].addr = bus_addr;
+	msgs[0].flags = 0;
+	msgs[0].len = 1;
+	msgs[0].buf = &dev_addr;
+	msgs[1].addr = bus_addr;
+	msgs[1].flags = I2C_M_RD;
+	msgs[1].len = sizeof(data);
+	msgs[1].buf = data;
+
+	ret = i2c_transfer(i2c, msgs, ARRAY_SIZE(msgs));
+	if (ret != ARRAY_SIZE(msgs))
+		return 0xffff;
+
+	return data[0] << 8 | data[1];
+}
+
+static int i2c_mii_write(struct mii_bus *bus, int phy_id, int reg, u16 val)
+{
+	struct i2c_adapter *i2c = bus->priv;
+	struct i2c_msg msg;
+	int ret;
+	u8 data[3];
+
+	if (!i2c_mii_valid_phy_id(phy_id))
+		return 0;
+
+	data[0] = reg;
+	data[1] = val >> 8;
+	data[2] = val;
+
+	msg.addr = i2c_mii_phy_addr(phy_id);
+	msg.flags = 0;
+	msg.len = 3;
+	msg.buf = data;
+
+	ret = i2c_transfer(i2c, &msg, 1);
+
+	return ret < 0 ? ret : 0;
+}
+
+static int mdio_i2c_probe(struct device_d *dev)
+{
+	struct mii_bus *mii;
+	struct i2c_adapter *i2c_adap;
+	struct device_node *i2c_node;
+
+	i2c_node = of_parse_phandle(dev->device_node, "i2c-bus", 0);
+	if (!i2c_node) {
+		dev_err(dev, "Missing i2c-bus property for mdio-i2c\n");
+		return -EINVAL;
+	}
+
+	i2c_adap = of_find_i2c_adapter_by_node(i2c_node);
+	if (!i2c_adap) {
+		dev_dbg(dev, "i2c bus not yet probed\n");
+		return -EPROBE_DEFER;
+	}
+
+	mii = xzalloc(sizeof(*mii));
+
+	mii->parent = dev;
+	mii->dev.device_node = dev->device_node;
+
+	mii->parent = dev;
+	mii->read = i2c_mii_read;
+	mii->write = i2c_mii_write;
+	mii->priv = i2c_adap;
+
+	dev->priv = mii;
+
+	dev_info(dev, "I2C mdio register\n");
+
+	return mdiobus_register(mii);
+}
+
+static void mdio_i2c_remove(struct device_d *dev)
+{
+	struct mii_bus *mii = dev->priv;
+
+	mdiobus_unregister(mii);
+	kfree(mii);
+}
+
+static const struct of_device_id i2c_mdio_dt_ids[] = {
+	{ .compatible = "virtual,mdio-i2c", },
+	{ /* sentinel */ }
+};
+
+static struct driver_d mdio_i2c_driver = {
+	.name = "mdio-i2c",
+	.probe = mdio_i2c_probe,
+	.remove = mdio_i2c_remove,
+	.of_compatible = DRV_OF_COMPAT(i2c_mdio_dt_ids),
+};
+
+device_platform_driver(mdio_i2c_driver);
diff --git a/dts/Bindings/net/mdio-i2c.txt b/dts/Bindings/net/mdio-i2c.txt
new file mode 100644
index 0000000..64e20e1
--- /dev/null
+++ b/dts/Bindings/net/mdio-i2c.txt
@@ -0,0 +1,19 @@
+MDIO on I2C Bus
+This compatible allows to use phy devices connected to an i2c bus
+and expecting to be use with mdio protocol.
+
+Currently defined compatibles:
+- virtual,mdio-i2c
+
+Required properties:
+- i2c-bus: A phandle on the I2C bus acting as a MDIO bridge where phys
+           are connected to.
+
+Example:
+
+mdio0@i2c {
+	compatible = "virtual,mdio-i2c";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	i2c-bus = <&i2c_bus>;
+};
-- 
1.8.3.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

             reply	other threads:[~2017-11-14 13:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-14 13:34 Clément Leger [this message]
2017-11-17  8:33 ` Sascha Hauer
2017-11-17  8:52   ` Clément Leger
2017-11-17  9:06     ` Sascha Hauer
2017-11-17  9:34       ` Clément Leger
2017-11-17  9:39         ` Sascha Hauer
2017-11-17 10:05           ` Clément Leger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=221136220.35006899.1510666491764.JavaMail.zimbra@kalray.eu \
    --to=cleger@kalray.eu \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox