From patchwork Tue Apr 3 17:13:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serge Vailugin X-Patchwork-Id: 894715 X-Patchwork-Delegate: blogic@openwrt.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (helo) smtp.helo=arrakis.dune.hu (client-ip=78.24.191.176; helo=arrakis.dune.hu; envelope-from=openwrt-devel-bounces@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=yandex.ru Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=yandex.ru header.i=@yandex.ru header.b="M28q3SjD"; dkim-atps=neutral Received: from arrakis.dune.hu (arrakis.dune.hu [78.24.191.176]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40Fwfs6L6xz9s1b for ; Wed, 4 Apr 2018 03:13:55 +1000 (AEST) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id 759A3B8051B; Tue, 3 Apr 2018 19:13:45 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on arrakis.dune.hu X-Spam-Level: X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,FREEMAIL_FROM, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.1 Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP; Tue, 3 Apr 2018 19:13:45 +0200 (CEST) Received: from arrakis.dune.hu (localhost [127.0.0.1]) by arrakis.dune.hu (Postfix) with ESMTP id BDA88B80141 for ; Tue, 3 Apr 2018 19:13:43 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 CL_IP_EQ_HELO_IP=-2 (check from: .yandex. - helo: .forward22p.cmail.yandex. - helo-domain: .yandex.) FROM/MX_MATCHES_HELO(DOMAIN)=-2; rate: -7 Received: from forward22p.cmail.yandex.net (forward22p.cmail.yandex.net [77.88.31.53]) by arrakis.dune.hu (Postfix) with ESMTPS for ; Tue, 3 Apr 2018 19:13:42 +0200 (CEST) Received: from mxback10g.mail.yandex.net (mxback10g.mail.yandex.net [IPv6:2a02:6b8:0:1472:2741:0:8b7:171]) by forward22p.cmail.yandex.net (Yandex) with ESMTP id 8A9BD2104F; Tue, 3 Apr 2018 20:13:41 +0300 (MSK) Received: from localhost (localhost [::1]) by mxback10g.mail.yandex.net (nwsmtp/Yandex) with ESMTP id JJpBOfjApL-DdQCNxBx; Tue, 03 Apr 2018 20:13:40 +0300 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1522775620; bh=Xtfk2XcVWjhioCDH4/i88xCecbIaqCyEUin6Fdx84zs=; h=From:To:Subject:Message-Id:Date; b=M28q3SjDMrgaA95kR8dPEcQ1oVGkb0JFPHcXpb62aUfbd5NSyjNcQEUXJZQGjBLZt GTf/z6unADCB9btllzCQIKaVxZIXtGu2K4dfFgetM61Ymzqf/cpEGyvr81EEQqNLsK OcMqr2tXnY33KZU/NYdqFAb085uRDnhMoOArp660= Authentication-Results: mxback10g.mail.yandex.net; dkim=pass header.i=@yandex.ru Received: by web14o.yandex.ru with HTTP; Tue, 03 Apr 2018 20:13:39 +0300 From: =?utf-8?b?0KHQtdGA0LPQtdC5INCS0LDRgdC40LvRjtCz0LjQvQ==?= To: "lede-dev@lists.infradead.org" , OpenWrt Development List MIME-Version: 1.0 Message-Id: <1634581522775619@web14o.yandex.ru> X-Mailer: Yamail [ http://yandex.ru ] 5.0 Date: Tue, 03 Apr 2018 20:13:39 +0300 Subject: [OpenWrt-Devel] [PATCH v2] kernel: rtl8366-smi: add Realtek switch management via mii-bus X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: OpenWrt Development List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: openwrt-devel-bounces@lists.openwrt.org Sender: "openwrt-devel" 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 --- --- serge 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 #include #include +#include #include #include @@ -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 {