<div><div>Current version of rtl8366-smi module support Realtek switch</div><div>managment via two gpio lines only. This patch add Realtek switch</div><div>management via mii_bus. For my board Tp-link Archer C2 v1 (Mediatek</div><div>SoC mt7620a based) dts-file configuration looks like:</div><div> </div><div>    rtl8367rb {</div><div>        compatible = "realtek,rtl8367b", "rtl8367b";</div><div>        realtek,extif1 = <1 0 1 1 1 1 1 1 2>;</div><div>        mii-bus = <&mdio0>;</div><div>    };</div><div> </div><div>&ethernet {</div><div>    status = "okay";</div><div>    mtd-mac-address = <&rom 0xf100>;</div><div>    pinctrl-names = "default";</div><div>    pinctrl-0 = <&rgmii1_pins &rgmii2_pins &mdio_pins>;</div><div> </div><div>    port@5 {</div><div>        status = "okay";</div><div>        mediatek,fixed-link = <1000 1 1 1>;</div><div>        phy-mode = "rgmii";</div><div>    };</div><div> </div><div>    mdio0: mdio-bus {</div><div>        status = "okay";</div><div>    };</div><div>};</div><div> </div><div>Realtek rtl8367rb switch is ok.</div><div>Other Realtek switches and archs are untested but must work too.</div><div> </div><div>Signed-off-by: Serge Vasilugin <vasilugin@yandex.ru></div><div> </div><div>diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c</div><div>index ae04597..1951627 100644</div><div>--- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c</div><div>+++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.c</div><div>@@ -18,6 +18,7 @@</div><div> #include <linux/of.h></div><div> #include <linux/of_platform.h></div><div> #include <linux/of_gpio.h></div><div>+#include <linux/of_mdio.h></div><div> #include <linux/rtl8366.h></div><div> #include <linux/version.h></div><div> </div><div>@@ -198,7 +199,7 @@ static int rtl8366_smi_read_byte1(struct rtl8366_smi *smi, u8 *data)</div><div>     return 0;</div><div> }</div><div> </div><div>-int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data)</div><div>+static int __rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data)</div><div> {</div><div>     unsigned long flags;</div><div>     u8 lo = 0;</div><div>@@ -239,6 +240,89 @@ int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data)</div><div> </div><div>     return ret;</div><div> }</div><div>+/* Read/write via mdiobus */</div><div>+#define MDC_MDIO_CTRL0_REG        31</div><div>+#define MDC_MDIO_START_REG        29</div><div>+#define MDC_MDIO_CTRL1_REG        21</div><div>+#define MDC_MDIO_ADDRESS_REG        23</div><div>+#define MDC_MDIO_DATA_WRITE_REG        24</div><div>+#define MDC_MDIO_DATA_READ_REG        25</div><div>+</div><div>+#define MDC_MDIO_START_OP        0xFFFF</div><div>+#define MDC_MDIO_ADDR_OP        0x000E</div><div>+#define MDC_MDIO_READ_OP        0x0001</div><div>+#define MDC_MDIO_WRITE_OP        0x0003</div><div>+#define MDC_REALTEK_PHY_ADDR        0x0</div><div>+</div><div>+int __rtl8366_mdio_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data)</div><div>+{</div><div>+    u32 g_phy_id = MDC_REALTEK_PHY_ADDR;</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Write address control code to register 31 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP);</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Write address to register 23 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_ADDRESS_REG, addr);</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Write read control code to register 21 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_CTRL1_REG, MDC_MDIO_READ_OP);</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Read data from register 25 */</div><div>+    *data = smi->ext_mbus->read(smi->ext_mbus,g_phy_id, MDC_MDIO_DATA_READ_REG);//???</div><div>+</div><div>+    return 0;</div><div>+}</div><div>+</div><div>+static int __rtl8366_mdio_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data)</div><div>+{</div><div>+    u32 g_phy_id = MDC_REALTEK_PHY_ADDR;</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus, g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Write address control code to register 31 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_CTRL0_REG, MDC_MDIO_ADDR_OP);</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Write address to register 23 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_ADDRESS_REG, addr);</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Write data to register 24 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_DATA_WRITE_REG, data);</div><div>+</div><div>+    /* Write Start command to register 29 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_START_REG, MDC_MDIO_START_OP);</div><div>+</div><div>+    /* Write data control code to register 21 */</div><div>+    smi->ext_mbus->write(smi->ext_mbus,g_phy_id, MDC_MDIO_CTRL1_REG, MDC_MDIO_WRITE_OP);</div><div>+</div><div>+    return 0;</div><div>+}</div><div>+</div><div>+int rtl8366_smi_read_reg(struct rtl8366_smi *smi, u32 addr, u32 *data)</div><div>+{</div><div>+    if(smi->ext_mbus)</div><div>+    return __rtl8366_mdio_read_reg(smi, addr, data);</div><div>+    else</div><div>+    return __rtl8366_smi_read_reg(smi, addr, data);</div><div>+}</div><div> EXPORT_SYMBOL_GPL(rtl8366_smi_read_reg);</div><div> </div><div> static int __rtl8366_smi_write_reg(struct rtl8366_smi *smi,</div><div>@@ -290,6 +374,9 @@ static int __rtl8366_smi_write_reg(struct rtl8366_smi *smi,</div><div> </div><div> int rtl8366_smi_write_reg(struct rtl8366_smi *smi, u32 addr, u32 data)</div><div> {</div><div>+    if(smi->ext_mbus)</div><div>+    return __rtl8366_mdio_write_reg(smi, addr, data);</div><div>+    else</div><div>     return __rtl8366_smi_write_reg(smi, addr, data, true);</div><div> }</div><div> EXPORT_SYMBOL_GPL(rtl8366_smi_write_reg);</div><div>@@ -1269,20 +1356,21 @@ static int __rtl8366_smi_init(struct rtl8366_smi *smi, const char *name)</div><div> {</div><div>     int err;</div><div> </div><div>-    err = gpio_request(smi->gpio_sda, name);</div><div>-    if (err) {</div><div>-        printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n",</div><div>-            smi->gpio_sda, err);</div><div>-        goto err_out;</div><div>-    }</div><div>+    if(!smi->ext_mbus) {</div><div>+        err = gpio_request(smi->gpio_sda, name);</div><div>+        if (err) {</div><div>+            printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n",</div><div>+                smi->gpio_sda, err);</div><div>+            goto err_out;</div><div>+        }</div><div> </div><div>-    err = gpio_request(smi->gpio_sck, name);</div><div>-    if (err) {</div><div>-        printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n",</div><div>-            smi->gpio_sck, err);</div><div>-        goto err_free_sda;</div><div>+        err = gpio_request(smi->gpio_sck, name);</div><div>+        if (err) {</div><div>+            printk(KERN_ERR "rtl8366_smi: gpio_request failed for %u, err=%d\n",</div><div>+                smi->gpio_sck, err);</div><div>+            goto err_free_sda;</div><div>+        }</div><div>     }</div><div>-</div><div>     spin_lock_init(&smi->lock);</div><div> </div><div>     /* start the switch */</div><div>@@ -1303,9 +1391,10 @@ static void __rtl8366_smi_cleanup(struct rtl8366_smi *smi)</div><div> {</div><div>     if (smi->hw_reset)</div><div>         smi->hw_reset(true);</div><div>-</div><div>-    gpio_free(smi->gpio_sck);</div><div>-    gpio_free(smi->gpio_sda);</div><div>+    if(!smi->ext_mbus) {</div><div>+        gpio_free(smi->gpio_sck);</div><div>+        gpio_free(smi->gpio_sda);</div><div>+    }</div><div> }</div><div> </div><div> enum rtl8366_type rtl8366_smi_detect(struct rtl8366_platform_data *pdata)</div><div>@@ -1358,8 +1447,11 @@ int rtl8366_smi_init(struct rtl8366_smi *smi)</div><div>     if (err)</div><div>         goto err_out;</div><div> </div><div>-    dev_info(smi->parent, "using GPIO pins %u (SDA) and %u (SCK)\n",</div><div>+    if(!smi->ext_mbus)</div><div>+        dev_info(smi->parent, "using GPIO pins %u (SDA) and %u (SCK)\n",</div><div>          smi->gpio_sda, smi->gpio_sck);</div><div>+    else</div><div>+        dev_info(smi->parent, "using MDIO bus '%s'\n", smi->ext_mbus->name);</div><div> </div><div>     err = smi->ops->detect(smi);</div><div>     if (err) {</div><div>@@ -1416,7 +1508,24 @@ int rtl8366_smi_probe_of(struct platform_device *pdev, struct rtl8366_smi *smi)</div><div> {</div><div>     int sck = of_get_named_gpio(pdev->dev.of_node, "gpio-sck", 0);</div><div>     int sda = of_get_named_gpio(pdev->dev.of_node, "gpio-sda", 0);</div><div>+    struct device_node *np = pdev->dev.of_node;;</div><div>+    struct device_node *mdio_node = NULL;</div><div>+</div><div>+    mdio_node = of_parse_phandle(np, "mii-bus", 0);</div><div>+    if (!mdio_node) {</div><div>+        dev_err(&pdev->dev, "cannot find mdio node phandle");</div><div>+        goto try_gpio;</div><div>+    }</div><div>+</div><div>+    smi->ext_mbus = of_mdio_find_bus(mdio_node);</div><div>+    if (!smi->ext_mbus) {</div><div>+        dev_err(&pdev->dev,</div><div>+            "cannot find mdio bus from bus handle");</div><div>+        goto try_gpio;</div><div>+    }</div><div>+    return 0;</div><div> </div><div>+try_gpio:</div><div>     if (!gpio_is_valid(sck) || !gpio_is_valid(sda)) {</div><div>         dev_err(&pdev->dev, "gpios missing in devictree\n");</div><div>         return -EINVAL;</div><div>diff --git a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h</div><div>index 4bb9e9a..79f0114 100644</div><div>--- a/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h</div><div>+++ b/target/linux/generic/files/drivers/net/phy/rtl8366_smi.h</div><div>@@ -59,6 +59,7 @@ struct rtl8366_smi {</div><div>     u16            dbg_reg;</div><div>     u8            dbg_vlan_4k_page;</div><div> #endif</div><div>+    struct mii_bus        *ext_mbus;</div><div> };</div><div> </div><div> struct rtl8366_vlan_mc {</div></div><div> </div><div>---</div><div>serge</div><div> </div>