Some microchip phys support the Serial Management Interface Protocol
(SMI) for the configuration of the extended register set. We add
MII_ADDR_SMI0 as an availabe interface to the mdiobb write and read
functions, as this interface can be easy realized using the bitbang mdio
driver.

Signed-off-by: Sam Ravnborg <s...@ravnborg.org>
Signed-off-by: Michael Grzeschik <m.grzesc...@pengutronix.de>
---
 drivers/net/phy/mdio-bitbang.c | 10 ++++++++++
 include/linux/phy.h            | 12 ++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c
index 5136275c8e739..a978f8a9a172b 100644
--- a/drivers/net/phy/mdio-bitbang.c
+++ b/drivers/net/phy/mdio-bitbang.c
@@ -22,6 +22,10 @@
 #define MDIO_READ 2
 #define MDIO_WRITE 1
 
+#define SMI0_RW_OPCODE 0
+#define SMI0_READ_PHY  (1 << 4)
+#define SMI0_WRITE_PHY (0 << 4)
+
 #define MDIO_C45 (1<<15)
 #define MDIO_C45_ADDR (MDIO_C45 | 0)
 #define MDIO_C45_READ (MDIO_C45 | 3)
@@ -157,6 +161,9 @@ static int mdiobb_read(struct mii_bus *bus, int phy, int 
reg)
        if (reg & MII_ADDR_C45) {
                reg = mdiobb_cmd_addr(ctrl, phy, reg);
                mdiobb_cmd(ctrl, MDIO_C45_READ, phy, reg);
+       } else if (reg & MII_ADDR_SMI0) {
+               mdiobb_cmd(ctrl, SMI0_RW_OPCODE,
+                          (reg & 0xE0) >> 5 | SMI0_READ_PHY, reg);
        } else
                mdiobb_cmd(ctrl, MDIO_READ, phy, reg);
 
@@ -188,6 +195,9 @@ static int mdiobb_write(struct mii_bus *bus, int phy, int 
reg, u16 val)
        if (reg & MII_ADDR_C45) {
                reg = mdiobb_cmd_addr(ctrl, phy, reg);
                mdiobb_cmd(ctrl, MDIO_C45_WRITE, phy, reg);
+       } else if (reg & MII_ADDR_SMI0) {
+               mdiobb_cmd(ctrl, SMI0_RW_OPCODE,
+                          (reg & 0xE0) >> 5 | SMI0_WRITE_PHY, reg);
        } else
                mdiobb_cmd(ctrl, MDIO_WRITE, phy, reg);
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 073fb151b5a99..f011722fbd5c2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -199,6 +199,18 @@ static inline const char *phy_modes(phy_interface_t 
interface)
    IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips. */
 #define MII_ADDR_C45 (1<<30)
 
+/* Serial Management Interface (SMI) uses the following frame format:
+ *
+ *       preamble|start|Read/Write|  PHY   |  REG  |TA|   Data bits      | Idle
+ *               |frame| OP code  |address |address|  |                  |
+ * read | 32x1´s | 01  |    00    | 1xRRR  | RRRRR |Z0| 00000000DDDDDDDD |  Z
+ * write| 32x1´s | 01  |    00    | 0xRRR  | RRRRR |10| xxxxxxxxDDDDDDDD |  Z
+ *
+ * The register number is encoded with the 5 least significant bits in REG
+ * and the 3 most significant bits in PHY
+ */
+#define MII_ADDR_SMI0 (1<<31)
+
 struct device;
 struct phylink;
 struct sk_buff;
-- 
2.20.1

Reply via email to