mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-25 08:21:14 +00:00
169 lines
4.7 KiB
Diff
169 lines
4.7 KiB
Diff
|
From d585c55b9f70cf9e8c66820d7efe7130c683f19e Mon Sep 17 00:00:00 2001
|
||
|
From: Antoine Tenart <antoine.tenart@bootlin.com>
|
||
|
Date: Fri, 21 Feb 2020 11:51:27 +0100
|
||
|
Subject: [PATCH 2/3] net: phy: add an MDIO SMBus library
|
||
|
|
||
|
Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
|
||
|
---
|
||
|
drivers/net/mdio/Kconfig | 11 +++++++
|
||
|
drivers/net/mdio/Makefile | 1 +
|
||
|
drivers/net/mdio/mdio-smbus.c | 62 +++++++++++++++++++++++++++++++++++
|
||
|
drivers/net/phy/Kconfig | 1 +
|
||
|
include/linux/mdio/mdio-i2c.h | 16 +++++++++
|
||
|
5 files changed, 91 insertions(+)
|
||
|
create mode 100644 drivers/net/mdio/mdio-smbus.c
|
||
|
|
||
|
--- a/drivers/net/mdio/Kconfig
|
||
|
+++ b/drivers/net/mdio/Kconfig
|
||
|
@@ -40,6 +40,17 @@ config MDIO_SUN4I
|
||
|
interface units of the Allwinner SoC that have an EMAC (A10,
|
||
|
A12, A10s, etc.)
|
||
|
|
||
|
+config MDIO_SMBUS
|
||
|
+ tristate
|
||
|
+ depends on I2C_SMBUS
|
||
|
+ help
|
||
|
+ Support SMBus based PHYs. This provides a MDIO bus bridged
|
||
|
+ to SMBus to allow PHYs connected in SMBus mode to be accessed
|
||
|
+ using the existing infrastructure.
|
||
|
+
|
||
|
+ This is library mode.
|
||
|
+
|
||
|
+
|
||
|
config MDIO_XGENE
|
||
|
tristate "APM X-Gene SoC MDIO bus controller"
|
||
|
depends on ARCH_XGENE || COMPILE_TEST
|
||
|
--- a/drivers/net/mdio/Makefile
|
||
|
+++ b/drivers/net/mdio/Makefile
|
||
|
@@ -17,6 +17,7 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxar
|
||
|
obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
|
||
|
obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
|
||
|
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
|
||
|
+obj-$(CONFIG_MDIO_SMBUS) += mdio-smbus.o
|
||
|
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
|
||
|
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
|
||
|
obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
|
||
|
--- /dev/null
|
||
|
+++ b/drivers/net/mdio/mdio-smbus.c
|
||
|
@@ -0,0 +1,62 @@
|
||
|
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
+/*
|
||
|
+ * MDIO SMBus bridge
|
||
|
+ *
|
||
|
+ * Copyright (C) 2020 Antoine Tenart
|
||
|
+ *
|
||
|
+ * Network PHYs can appear on SMBus when they are part of SFP modules.
|
||
|
+ */
|
||
|
+#include <linux/i2c.h>
|
||
|
+#include <linux/phy.h>
|
||
|
+#include <linux/mdio/mdio-i2c.h>
|
||
|
+
|
||
|
+static int smbus_mii_read(struct mii_bus *mii, int phy_id, int reg)
|
||
|
+{
|
||
|
+ struct i2c_adapter *i2c = mii->priv;
|
||
|
+ union i2c_smbus_data data;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ ret = i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, I2C_SMBUS_READ,
|
||
|
+ reg, I2C_SMBUS_BYTE_DATA, &data);
|
||
|
+ if (ret < 0)
|
||
|
+ return 0xff;
|
||
|
+
|
||
|
+ return data.byte;
|
||
|
+}
|
||
|
+
|
||
|
+static int smbus_mii_write(struct mii_bus *mii, int phy_id, int reg, u16 val)
|
||
|
+{
|
||
|
+ struct i2c_adapter *i2c = mii->priv;
|
||
|
+ union i2c_smbus_data data;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ data.byte = val;
|
||
|
+
|
||
|
+ ret = i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, I2C_SMBUS_WRITE,
|
||
|
+ reg, I2C_SMBUS_BYTE_DATA, &data);
|
||
|
+ return ret < 0 ? ret : 0;
|
||
|
+}
|
||
|
+
|
||
|
+struct mii_bus *mdio_smbus_alloc(struct device *parent, struct i2c_adapter *i2c)
|
||
|
+{
|
||
|
+ struct mii_bus *mii;
|
||
|
+
|
||
|
+ if (!i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA))
|
||
|
+ return ERR_PTR(-EINVAL);
|
||
|
+
|
||
|
+ mii = mdiobus_alloc();
|
||
|
+ if (!mii)
|
||
|
+ return ERR_PTR(-ENOMEM);
|
||
|
+
|
||
|
+ snprintf(mii->id, MII_BUS_ID_SIZE, "smbus:%s", dev_name(parent));
|
||
|
+ mii->parent = parent;
|
||
|
+ mii->read = smbus_mii_read;
|
||
|
+ mii->write = smbus_mii_write;
|
||
|
+ mii->priv = i2c;
|
||
|
+
|
||
|
+ return mii;
|
||
|
+}
|
||
|
+
|
||
|
+MODULE_AUTHOR("Antoine Tenart");
|
||
|
+MODULE_DESCRIPTION("MDIO SMBus bridge library");
|
||
|
+MODULE_LICENSE("GPL");
|
||
|
--- a/drivers/net/phy/Kconfig
|
||
|
+++ b/drivers/net/phy/Kconfig
|
||
|
@@ -60,6 +60,7 @@ config SFP
|
||
|
depends on I2C && PHYLINK
|
||
|
depends on HWMON || HWMON=n
|
||
|
select MDIO_I2C
|
||
|
+ select MDIO_SMBUS
|
||
|
|
||
|
comment "Switch configuration API + drivers"
|
||
|
|
||
|
--- a/include/linux/mdio/mdio-i2c.h
|
||
|
+++ b/include/linux/mdio/mdio-i2c.h
|
||
|
@@ -12,5 +12,21 @@ struct i2c_adapter;
|
||
|
struct mii_bus;
|
||
|
|
||
|
struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
|
||
|
+struct mii_bus *mdio_smbus_alloc(struct device *parent, struct i2c_adapter *i2c);
|
||
|
+
|
||
|
+/*
|
||
|
+ * 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;
|
||
|
+}
|
||
|
|
||
|
#endif
|
||
|
--- a/drivers/net/mdio/mdio-i2c.c
|
||
|
+++ b/drivers/net/mdio/mdio-i2c.c
|
||
|
@@ -13,21 +13,6 @@
|
||
|
#include <linux/mdio/mdio-i2c.h>
|
||
|
#include <linux/phy.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;
|