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