[PATCH net 1/2] net: dsa: mt7530: remove redundant MODULE_ALIAS entries

2018-03-26 Thread sean.wang
From: Sean Wang 

MODULE_ALIAS exports information to allow the module to be auto-loaded at
boot for the drivers registered using legacy platform registration.

However, currently the driver is always used by DT-only platform,
MODULE_ALIAS is redundant and should be removed properly.

Signed-off-by: Sean Wang 
---
 drivers/net/dsa/mt7530.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 8a0bb00..d31246c 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1424,4 +1424,3 @@ mdio_module_driver(mt7530_mdio_driver);
 MODULE_AUTHOR("Sean Wang ");
 MODULE_DESCRIPTION("Driver for Mediatek MT7530 Switch");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:mediatek-mt7530");
-- 
2.7.4



[PATCH net 2/2] net: dsa: mt7530: fix module autoloading for OF platform drivers

2018-03-26 Thread sean.wang
From: Sean Wang 

It's required to create a modules.alias via MODULE_DEVICE_TABLE helper
for the OF platform driver. Otherwise, module autoloading cannot work.

Signed-off-by: Sean Wang 
---
 drivers/net/dsa/mt7530.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index d31246c..4e53c5c 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1409,6 +1409,7 @@ static const struct of_device_id mt7530_of_match[] = {
{ .compatible = "mediatek,mt7530" },
{ /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, mt7530_of_match);
 
 static struct mdio_driver mt7530_mdio_driver = {
.probe  = mt7530_probe,
-- 
2.7.4



[PATCH net 1/2] dt-bindings: net: mediatek: add condition to property mediatek,pctl

2017-12-20 Thread sean.wang
From: Sean Wang 

The property "mediatek,pctl" is only required for SoCs such as MT2701 and
MT7623, so adding a few words for stating the condition.

Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/mediatek-net.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index 214eaa9..53c13ee 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -28,7 +28,7 @@ Required properties:
 - mediatek,sgmiisys: phandle to the syscon node that handles the SGMII setup
which is required for those SoCs equipped with SGMII such as MT7622 SoC.
 - mediatek,pctl: phandle to the syscon node that handles the ports slew rate
-   and driver current
+   and driver current: only for MT2701 and MT7623 SoC
 
 Optional properties:
 - interrupt-parent: Should be the phandle for the interrupt controller
-- 
2.7.4



[PATCH net 2/2] net: mediatek: remove superfluous pin setup for MT7622 SoC

2017-12-20 Thread sean.wang
From: Sean Wang 

Remove superfluous pin setup to get out of accessing invalid I/O pin
registers because the way for pin configuring tends to be different from
various SoCs and thus it should be better being managed and controlled by
the pinctrl driver which MT7622 already can support.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 35 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 +++
 2 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index fc67e35..29826dd 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1952,14 +1952,16 @@ static int mtk_hw_init(struct mtk_eth *eth)
}
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
 
-   /* Set GE2 driving and slew rate */
-   regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00);
+   if (eth->pctl) {
+   /* Set GE2 driving and slew rate */
+   regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00);
 
-   /* set GE2 TDSEL */
-   regmap_write(eth->pctl, GPIO_OD33_CTRL8, 0x5);
+   /* set GE2 TDSEL */
+   regmap_write(eth->pctl, GPIO_OD33_CTRL8, 0x5);
 
-   /* set GE2 TUNE */
-   regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0);
+   /* set GE2 TUNE */
+   regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0);
+   }
 
/* Set linkdown as the default for each GMAC. Its own MCR would be set
 * up with the more appropriate value when mtk_phy_link_adjust call is
@@ -2538,11 +2540,13 @@ static int mtk_probe(struct platform_device *pdev)
}
}
 
-   eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-   "mediatek,pctl");
-   if (IS_ERR(eth->pctl)) {
-   dev_err(>dev, "no pctl regmap found\n");
-   return PTR_ERR(eth->pctl);
+   if (eth->soc->required_pctl) {
+   eth->pctl = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+   "mediatek,pctl");
+   if (IS_ERR(eth->pctl)) {
+   dev_err(>dev, "no pctl regmap found\n");
+   return PTR_ERR(eth->pctl);
+   }
}
 
for (i = 0; i < 3; i++) {
@@ -2668,17 +2672,20 @@ static int mtk_remove(struct platform_device *pdev)
 
 static const struct mtk_soc_data mt2701_data = {
.caps = MTK_GMAC1_TRGMII,
-   .required_clks = MT7623_CLKS_BITMAP
+   .required_clks = MT7623_CLKS_BITMAP,
+   .required_pctl = true,
 };
 
 static const struct mtk_soc_data mt7622_data = {
.caps = MTK_DUAL_GMAC_SHARED_SGMII | MTK_GMAC1_ESW,
-   .required_clks = MT7622_CLKS_BITMAP
+   .required_clks = MT7622_CLKS_BITMAP,
+   .required_pctl = false,
 };
 
 static const struct mtk_soc_data mt7623_data = {
.caps = MTK_GMAC1_TRGMII,
-   .required_clks = MT7623_CLKS_BITMAP
+   .required_clks = MT7623_CLKS_BITMAP,
+   .required_pctl = true,
 };
 
 const struct of_device_id of_mtk_match[] = {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index a3af466..672b8c3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -573,10 +573,13 @@ struct mtk_rx_ring {
  * @caps   Flags shown the extra capability for the SoC
  * @required_clks  Flags shown the bitmap for required clocks on
  * the target SoC
+ * @required_pctl  A bool value to show whether the SoC requires
+ * the extra setup for those pins used by GMAC.
  */
 struct mtk_soc_data {
u32 caps;
u32 required_clks;
+   boolrequired_pctl;
 };
 
 /* currently no SoC has more than 2 macs */
-- 
2.7.4



[PATCH net] net: mediatek: setup proper state for disabled GMAC on the default

2017-12-18 Thread sean.wang
From: Sean Wang 

The current solution would setup fixed and force link of 1Gbps to the both
GMAC on the default. However, The GMAC should always be put to link down
state when the GMAC is disabled on certain target boards. Otherwise,
the driver possibly receives unexpected data from the floating hardware
connection through the unused GMAC. Although the driver had been added
certain protection in RX path to get rid of such kind of unexpected data
sent to the upper stack.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 54adfd9..fc67e35 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1961,11 +1961,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
/* set GE2 TUNE */
regmap_write(eth->pctl, GPIO_BIAS_CTRL, 0x0);
 
-   /* GE1, Force 1000M/FD, FC ON */
-   mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(0));
-
-   /* GE2, Force 1000M/FD, FC ON */
-   mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1));
+   /* Set linkdown as the default for each GMAC. Its own MCR would be set
+* up with the more appropriate value when mtk_phy_link_adjust call is
+* being invoked.
+*/
+   for (i = 0; i < MTK_MAC_COUNT; i++)
+   mtk_w32(eth, 0, MTK_MAC_MCR(i));
 
/* Indicates CDM to parse the MTK special tag from CPU
 * which also is working out for untag packets.
-- 
2.7.4



[PATCH v3 net-next 1/3] net: dsa: mediatek: add VLAN support for MT7530

2017-12-14 Thread sean.wang
From: Sean Wang 

MT7530 can treat each port as either VLAN-unaware port or VLAN-aware port
through the implementation of port matrix mode or port security mode on
the ingress port, respectively. On one hand, Each port has been acting as
the VLAN-unaware one whenever the device is created in the initial or
certain port joins or leaves into/from the bridge at the runtime. On the
other hand, the patch just filling the required callbacks for VLAN
operations is achieved via extending the port to be into port security
mode when the port is configured as VLAN-aware port. Which mode can make
the port be able to recognize VID from incoming packets and look up VLAN
table to validate and judge which port it should be going to. And the
range for VID from 1 to 4094 is valid for the hardware.

Signed-off-by: Sean Wang 
Reviewed-by: Andrew Lunn 
---
 drivers/net/dsa/mt7530.c | 288 ++-
 drivers/net/dsa/mt7530.h |  83 +-
 2 files changed, 364 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 2820d69..8a0bb00 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -805,6 +805,69 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
 }
 
 static void
+mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
+{
+   struct mt7530_priv *priv = ds->priv;
+   bool all_user_ports_removed = true;
+   int i;
+
+   /* When a port is removed from the bridge, the port would be set up
+* back to the default as is at initial boot which is a VLAN-unaware
+* port.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+  MT7530_PORT_MATRIX_MODE);
+   mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
+  VLAN_ATTR(MT7530_VLAN_TRANSPARENT));
+
+   priv->ports[port].vlan_filtering = false;
+
+   for (i = 0; i < MT7530_NUM_PORTS; i++) {
+   if (dsa_is_user_port(ds, i) &&
+   priv->ports[i].vlan_filtering) {
+   all_user_ports_removed = false;
+   break;
+   }
+   }
+
+   /* CPU port also does the same thing until all user ports belonging to
+* the CPU port get out of VLAN filtering mode.
+*/
+   if (all_user_ports_removed) {
+   mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT),
+PCR_MATRIX(dsa_user_ports(priv->ds)));
+   mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT),
+PORT_SPEC_TAG);
+   }
+}
+
+static void
+mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port)
+{
+   struct mt7530_priv *priv = ds->priv;
+
+   /* The real fabric path would be decided on the membership in the
+* entry of VLAN table. PCR_MATRIX set up here with ALL_MEMBERS
+* means potential VLAN can be consisting of certain subset of all
+* ports.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port),
+  PCR_MATRIX_MASK, PCR_MATRIX(MT7530_ALL_MEMBERS));
+
+   /* Trapped into security mode allows packet forwarding through VLAN
+* table lookup.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+  MT7530_PORT_SECURITY_MODE);
+
+   /* Set the port as a user port which is to be able to recognize VID
+* from incoming packets before fetching entry within the VLAN table.
+*/
+   mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
+  VLAN_ATTR(MT7530_VLAN_USER));
+}
+
+static void
 mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
 struct net_device *bridge)
 {
@@ -817,8 +880,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
/* Remove this port from the port matrix of the other ports
 * in the same bridge. If the port is disabled, port matrix
 * is kept and not being setup until the port becomes enabled.
+* And the other port's port matrix cannot be broken when the
+* other port is still a VLAN-aware port.
 */
-   if (dsa_is_user_port(ds, i) && i != port) {
+   if (!priv->ports[i].vlan_filtering &&
+   dsa_is_user_port(ds, i) && i != port) {
if (dsa_to_port(ds, i)->bridge_dev != bridge)
continue;
if (priv->ports[i].enable)
@@ -836,6 +902,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
   PCR_MATRIX(BIT(MT7530_CPU_PORT)));
priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));
 
+   mt7530_port_set_vlan_unaware(ds, port);
+
mutex_unlock(>reg_mutex);
 }
 
@@ -906,6 +974,220 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
   

[PATCH v3 net-next 3/3] net: dsa: mediatek: update MAINTAINERS entry with MediaTek switch driver

2017-12-14 Thread sean.wang
From: Sean Wang 

I work for MediaTek and maintain SoC targeting to home gateway and
also will keep extending and testing the function from MediaTek
switch.

Signed-off-by: Sean Wang 
Reviewed-by: Andrew Lunn 
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index c86781b..90ca7f8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8728,6 +8728,13 @@ L:   netdev@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/mediatek/
 
+MEDIATEK SWITCH DRIVER
+M: Sean Wang 
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/dsa/mt7530.*
+F: net/dsa/tag_mtk.c
+
 MEDIATEK JPEG DRIVER
 M: Rick Chang 
 M: Bin Liu 
-- 
2.7.4



[PATCH v3 net-next 0/3] add VLAN support to DSA MT7530

2017-12-14 Thread sean.wang
From: Sean Wang 

Changes sicne v2:
update to the latest code base from net-next and fix up all building
errors with -Werror.

Changes since v1:
- fix up the typo
- prefer ordering declarations longest to shortest
- update that vlan_prepare callback should not change any state
- use lower case letter for function naming

The patchset extends DSA MT7530 to VLAN support through filling required
callbacks in patch 1 and merging the special tag with VLAN tag in patch 2
for allowing that the hardware can handle these packets with VID from the
CPU port.

Sean Wang (3):
  net: dsa: mediatek: add VLAN support for MT7530
  net: dsa: mediatek: combine MediaTek tag with VLAN tag
  net: dsa: mediatek: update MAINTAINERS entry with MediaTek switch
driver

 MAINTAINERS  |   7 ++
 drivers/net/dsa/mt7530.c | 288 ++-
 drivers/net/dsa/mt7530.h |  83 +-
 net/dsa/tag_mtk.c|  38 +--
 4 files changed, 400 insertions(+), 16 deletions(-)

-- 
2.7.4



[PATCH v3 net-next 2/3] net: dsa: mediatek: combine MediaTek tag with VLAN tag

2017-12-14 Thread sean.wang
From: Sean Wang 

In order to let MT7530 switch can recognize well those egress packets
having both special tag and VLAN tag, the information about the special
tag should be carried on the existing VLAN tag. On the other hand, it's
unnecessary for extra handling for ingress packets when VLAN tag is
present since it is able to put the VLAN tag after the special tag and
then follow the existing way to parse.

Signed-off-by: Sean Wang 
Reviewed-by: Andrew Lunn 
---
 net/dsa/tag_mtk.c | 38 +-
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 8475434..11535bc 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -13,10 +13,13 @@
  */
 
 #include 
+#include 
 
 #include "dsa_priv.h"
 
 #define MTK_HDR_LEN4
+#define MTK_HDR_XMIT_UNTAGGED  0
+#define MTK_HDR_XMIT_TAGGED_TPID_8100  1
 #define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
 #define MTK_HDR_XMIT_DP_BIT_MASK   GENMASK(5, 0)
 
@@ -25,20 +28,37 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
 {
struct dsa_port *dp = dsa_slave_to_port(dev);
u8 *mtk_tag;
+   bool is_vlan_skb = true;
 
-   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
-   return NULL;
-
-   skb_push(skb, MTK_HDR_LEN);
+   /* Build the special tag after the MAC Source Address. If VLAN header
+* is present, it's required that VLAN header and special tag is
+* being combined. Only in this way we can allow the switch can parse
+* the both special and VLAN tag at the same time and then look up VLAN
+* table with VID.
+*/
+   if (!skb_vlan_tagged(skb)) {
+   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+   return NULL;
 
-   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+   skb_push(skb, MTK_HDR_LEN);
+   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+   is_vlan_skb = false;
+   }
 
-   /* Build the tag after the MAC Source Address */
mtk_tag = skb->data + 2 * ETH_ALEN;
-   mtk_tag[0] = 0;
+
+   /* Mark tag attribute on special tag insertion to notify hardware
+* whether that's a combined special tag with 802.1Q header.
+*/
+   mtk_tag[0] = is_vlan_skb ? MTK_HDR_XMIT_TAGGED_TPID_8100 :
+MTK_HDR_XMIT_UNTAGGED;
mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
-   mtk_tag[2] = 0;
-   mtk_tag[3] = 0;
+
+   /* Tag control information is kept for 802.1Q */
+   if (!is_vlan_skb) {
+   mtk_tag[2] = 0;
+   mtk_tag[3] = 0;
+   }
 
return skb;
 }
-- 
2.7.4



[PATCH v2 net-next 0/3] add VLAN support to DSA MT7530

2017-12-12 Thread sean.wang
From: Sean Wang 

Changes since v1:
- fix up the typo
- prefer ordering declarations longest to shortest
- update that vlan_prepare callback should not change any state
- use lower case letter for function naming

The patchset extends DSA MT7530 to VLAN support through filling required
callbacks in patch 1 and merging the special tag with VLAN tag in patch 2
for allowing that the hardware can handle these packets with VID from the
CPU port.

Sean Wang (3):
  net: dsa: mediatek: add VLAN support for MT7530
  net: dsa: mediatek: combine MediaTek tag with VLAN tag
  net: dsa: mediatek: update MAINTAINERS entry with MediaTek switch
driver

 MAINTAINERS  |   7 ++
 drivers/net/dsa/mt7530.c | 291 ++-
 drivers/net/dsa/mt7530.h |  83 +-
 net/dsa/tag_mtk.c|  38 +--
 4 files changed, 403 insertions(+), 16 deletions(-)

-- 
2.7.4



[PATCH v2 net-next 2/3] net: dsa: mediatek: combine MediaTek tag with VLAN tag

2017-12-12 Thread sean.wang
From: Sean Wang 

In order to let MT7530 switch can recognize well those egress packets
having both special tag and VLAN tag, the information about the special
tag should be carried on the existing VLAN tag. On the other hand, it's
unnecessary for extra handling for ingress packets when VLAN tag is
present since it is able to put the VLAN tag after the special tag and
then follow the existing way to parse.

Signed-off-by: Sean Wang 
---
 net/dsa/tag_mtk.c | 38 +-
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 8475434..11535bc 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -13,10 +13,13 @@
  */
 
 #include 
+#include 
 
 #include "dsa_priv.h"
 
 #define MTK_HDR_LEN4
+#define MTK_HDR_XMIT_UNTAGGED  0
+#define MTK_HDR_XMIT_TAGGED_TPID_8100  1
 #define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
 #define MTK_HDR_XMIT_DP_BIT_MASK   GENMASK(5, 0)
 
@@ -25,20 +28,37 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
 {
struct dsa_port *dp = dsa_slave_to_port(dev);
u8 *mtk_tag;
+   bool is_vlan_skb = true;
 
-   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
-   return NULL;
-
-   skb_push(skb, MTK_HDR_LEN);
+   /* Build the special tag after the MAC Source Address. If VLAN header
+* is present, it's required that VLAN header and special tag is
+* being combined. Only in this way we can allow the switch can parse
+* the both special and VLAN tag at the same time and then look up VLAN
+* table with VID.
+*/
+   if (!skb_vlan_tagged(skb)) {
+   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+   return NULL;
 
-   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+   skb_push(skb, MTK_HDR_LEN);
+   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+   is_vlan_skb = false;
+   }
 
-   /* Build the tag after the MAC Source Address */
mtk_tag = skb->data + 2 * ETH_ALEN;
-   mtk_tag[0] = 0;
+
+   /* Mark tag attribute on special tag insertion to notify hardware
+* whether that's a combined special tag with 802.1Q header.
+*/
+   mtk_tag[0] = is_vlan_skb ? MTK_HDR_XMIT_TAGGED_TPID_8100 :
+MTK_HDR_XMIT_UNTAGGED;
mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
-   mtk_tag[2] = 0;
-   mtk_tag[3] = 0;
+
+   /* Tag control information is kept for 802.1Q */
+   if (!is_vlan_skb) {
+   mtk_tag[2] = 0;
+   mtk_tag[3] = 0;
+   }
 
return skb;
 }
-- 
2.7.4



[PATCH v2 net-next 3/3] net: dsa: mediatek: update MAINTAINERS entry with MediaTek switch driver

2017-12-12 Thread sean.wang
From: Sean Wang 

I work for MediaTek and maintain SoC targeting to home gateway and
also will keep extending and testing the function from MediaTek
switch.

Signed-off-by: Sean Wang 
Reviewed-by: Andrew Lunn 
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index c0edf30..070fd91 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8723,6 +8723,13 @@ L:   netdev@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/mediatek/
 
+MEDIATEK SWITCH DRIVER
+M: Sean Wang 
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/dsa/mt7530.*
+F: net/dsa/tag_mtk.c
+
 MEDIATEK JPEG DRIVER
 M: Rick Chang 
 M: Bin Liu 
-- 
2.7.4



[PATCH v2 net-next 1/3] net: dsa: mediatek: add VLAN support for MT7530

2017-12-12 Thread sean.wang
From: Sean Wang 

MT7530 can treat each port as either VLAN-unaware port or VLAN-aware port
through the implementation of port matrix mode or port security mode on
the ingress port, respectively. On one hand, Each port has been acting as
the VLAN-unaware one whenever the device is created in the initial or
certain port joins or leaves into/from the bridge at the runtime. On the
other hand, the patch just filling the required callbacks for VLAN
operations is achieved via extending the port to be into port security
mode when the port is configured as VLAN-aware port. Which mode can make
the port be able to recognize VID from incoming packets and look up VLAN
table to validate and judge which port it should be going to. And the
range for VID from 1 to 4094 is valid for the hardware.

Signed-off-by: Sean Wang 
---
 drivers/net/dsa/mt7530.c | 291 ++-
 drivers/net/dsa/mt7530.h |  83 +-
 2 files changed, 367 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 2820d69..252e8ba 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -805,6 +805,69 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
 }
 
 static void
+mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
+{
+   struct mt7530_priv *priv = ds->priv;
+   bool all_user_ports_removed = true;
+   int i;
+
+   /* When a port is removed from the bridge, the port would be set up
+* back to the default as is at initial boot which is a VLAN-unaware
+* port.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+  MT7530_PORT_MATRIX_MODE);
+   mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
+  VLAN_ATTR(MT7530_VLAN_TRANSPARENT));
+
+   priv->ports[port].vlan_filtering = false;
+
+   for (i = 0; i < MT7530_NUM_PORTS; i++) {
+   if (dsa_is_user_port(ds, i) &&
+   priv->ports[i].vlan_filtering) {
+   all_user_ports_removed = false;
+   break;
+   }
+   }
+
+   /* CPU port also does the same thing until all user ports belonging to
+* the CPU port get out of VLAN filtering mode.
+*/
+   if (all_user_ports_removed) {
+   mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT),
+PCR_MATRIX(dsa_user_ports(priv->ds)));
+   mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT),
+PORT_SPEC_TAG);
+   }
+}
+
+static void
+mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port)
+{
+   struct mt7530_priv *priv = ds->priv;
+
+   /* The real fabric path would be decided on the membership in the
+* entry of VLAN table. PCR_MATRIX set up here with ALL_MEMBERS
+* means potential VLAN can be consisting of certain subset of all
+* ports.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port),
+  PCR_MATRIX_MASK, PCR_MATRIX(MT7530_ALL_MEMBERS));
+
+   /* Trapped into security mode allows packet forwarding through VLAN
+* table lookup.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+  MT7530_PORT_SECURITY_MODE);
+
+   /* Set the port as a user port which is to be able to recognize VID
+* from incoming packets before fetching entry within the VLAN table.
+*/
+   mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
+  VLAN_ATTR(MT7530_VLAN_USER));
+}
+
+static void
 mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
 struct net_device *bridge)
 {
@@ -817,8 +880,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
/* Remove this port from the port matrix of the other ports
 * in the same bridge. If the port is disabled, port matrix
 * is kept and not being setup until the port becomes enabled.
+* And the other port's port matrix cannot be broken when the
+* other port is still a VLAN-aware port.
 */
-   if (dsa_is_user_port(ds, i) && i != port) {
+   if (!priv->ports[i].vlan_filtering &&
+   dsa_is_user_port(ds, i) && i != port) {
if (dsa_to_port(ds, i)->bridge_dev != bridge)
continue;
if (priv->ports[i].enable)
@@ -836,6 +902,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
   PCR_MATRIX(BIT(MT7530_CPU_PORT)));
priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));
 
+   mt7530_port_set_vlan_unaware(ds, port);
+
mutex_unlock(>reg_mutex);
 }
 
@@ -906,6 +974,223 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
return 0;
 }
 
+static int

[PATCH net-next 3/3] net: dsa: mediatek: update MAINTAINERS entry with MediaTek switch driver

2017-12-06 Thread sean.wang
From: Sean Wang 

I work for MediaTek and maintain SoC targeting to home gateway and
also will keep extending and testing the function from MediaTek
switch.

Signed-off-by: Sean Wang 
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index c0edf30..070fd91 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8723,6 +8723,13 @@ L:   netdev@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/mediatek/
 
+MEDIATEK SWITCH DRIVER
+M: Sean Wang 
+L: netdev@vger.kernel.org
+S: Maintained
+F: drivers/net/dsa/mt7530.*
+F: net/dsa/tag_mtk.c
+
 MEDIATEK JPEG DRIVER
 M: Rick Chang 
 M: Bin Liu 
-- 
2.7.4



[PATCH net-next 1/3] net: dsa: mediatek: add VLAN support for MT7530

2017-12-06 Thread sean.wang
From: Sean Wang 

MT7530 can treat each port as either VLAN-unware port or VLAN-ware port
through the implementation of port matrix mode or port security mode on
the ingress port, respectively. On one hand, Each port has been acting as
the VLAN-unware one whenever the device is created in the initial or
certain port joins or leaves into/from the bridge at the runtime. On the
other hand, the patch just filling the required callbacks for VLAN
operations is achieved via extending the port to be into port security
mode when the port is configured as VLAN-ware port. Which mode can make
the port be able to recognize VID from incoming packets and look up VLAN
table to validate and judge which port it should be going to. And the
range for VID from 1 to 4094 is valid for the hardware.

Signed-off-by: Sean Wang 
---
 drivers/net/dsa/mt7530.c | 292 ++-
 drivers/net/dsa/mt7530.h |  83 +-
 2 files changed, 368 insertions(+), 7 deletions(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 2820d69..a7c5370 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -805,6 +805,69 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
 }
 
 static void
+mt7530_port_set_vlan_unware(struct dsa_switch *ds, int port)
+{
+   struct mt7530_priv *priv = ds->priv;
+   int i;
+   bool all_user_ports_removed = true;
+
+   /* When a port is removed from the bridge, the port would be set up
+* back to the default as is at initial boot which is a VLAN-unware
+* port.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+  MT7530_PORT_MATRIX_MODE);
+   mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
+  VLAN_ATTR(MT7530_VLAN_TRANSPARENT));
+
+   priv->ports[port].vlan_filtering = false;
+
+   for (i = 0; i < MT7530_NUM_PORTS; i++) {
+   if (dsa_is_user_port(ds, i) &&
+   priv->ports[i].vlan_filtering) {
+   all_user_ports_removed = false;
+   break;
+   }
+   }
+
+   /* CPU port also does the same thing until all user ports belonging to
+* the CPU port get out of VLAN filtering mode.
+*/
+   if (all_user_ports_removed) {
+   mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT),
+PCR_MATRIX(dsa_user_ports(priv->ds)));
+   mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT),
+PORT_SPEC_TAG);
+   }
+}
+
+static void
+mt7530_port_set_vlan_ware(struct dsa_switch *ds, int port)
+{
+   struct mt7530_priv *priv = ds->priv;
+
+   /* The real fabric path would be decided on the membership in the
+* entry of VLAN table. PCR_MATRIX set up here with ALL_MEMBERS
+* means potential VLAN can be consisting of certain subset of all
+* ports.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port),
+  PCR_MATRIX_MASK, PCR_MATRIX(MT7530_ALL_MEMBERS));
+
+   /* Trapped into security mode allows packet forwarding through VLAN
+* table lookup.
+*/
+   mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+  MT7530_PORT_SECURITY_MODE);
+
+   /* Set the port as a user port which is to be able to recognize VID
+* from incoming packets before fetching entry within the VLAN table.
+*/
+   mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK,
+  VLAN_ATTR(MT7530_VLAN_USER));
+}
+
+static void
 mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
 struct net_device *bridge)
 {
@@ -817,8 +880,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
/* Remove this port from the port matrix of the other ports
 * in the same bridge. If the port is disabled, port matrix
 * is kept and not being setup until the port becomes enabled.
+* And the other port's port matrix cannot be broken when the
+* other port is still a VLAN-ware port.
 */
-   if (dsa_is_user_port(ds, i) && i != port) {
+   if (!priv->ports[i].vlan_filtering &&
+   dsa_is_user_port(ds, i) && i != port) {
if (dsa_to_port(ds, i)->bridge_dev != bridge)
continue;
if (priv->ports[i].enable)
@@ -836,6 +902,8 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
   PCR_MATRIX(BIT(MT7530_CPU_PORT)));
priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));
 
+   mt7530_port_set_vlan_unware(ds, port);
+
mutex_unlock(>reg_mutex);
 }
 
@@ -906,6 +974,224 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
return 0;
 }
 
+static int

[PATCH net-next 0/3] add VLAN support to DSA MT7530

2017-12-06 Thread sean.wang
From: Sean Wang 

The patchset extends DSA MT7530 to VLAN support through filling required
callbacks in patch 1 and merging the special tag with VLAN tag in patch 2
for allowing that the hardware can handle these packets with VID from the
CPU port.

Sean Wang (3):
  net: dsa: mediatek: add VLAN support for MT7530
  net: dsa: mediatek: combine MediaTek tag with VLAN tag
  net: dsa: mediatek: update MAINTAINERS entry with MediaTek switch
driver

 MAINTAINERS  |   7 ++
 drivers/net/dsa/mt7530.c | 292 ++-
 drivers/net/dsa/mt7530.h |  83 +-
 net/dsa/tag_mtk.c|  38 --
 4 files changed, 404 insertions(+), 16 deletions(-)

-- 
2.7.4



[PATCH net-next 2/3] net: dsa: mediatek: combine MediaTek tag with VLAN tag

2017-12-06 Thread sean.wang
From: Sean Wang 

In order to let MT7530 switch can recognize well those packets
having both special tag and VLAN tag, the information about
the special tag should be carried on the existing VLAN tag.

Signed-off-by: Sean Wang 
---
 net/dsa/tag_mtk.c | 38 +-
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
index 8475434..11535bc 100644
--- a/net/dsa/tag_mtk.c
+++ b/net/dsa/tag_mtk.c
@@ -13,10 +13,13 @@
  */
 
 #include 
+#include 
 
 #include "dsa_priv.h"
 
 #define MTK_HDR_LEN4
+#define MTK_HDR_XMIT_UNTAGGED  0
+#define MTK_HDR_XMIT_TAGGED_TPID_8100  1
 #define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
 #define MTK_HDR_XMIT_DP_BIT_MASK   GENMASK(5, 0)
 
@@ -25,20 +28,37 @@ static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
 {
struct dsa_port *dp = dsa_slave_to_port(dev);
u8 *mtk_tag;
+   bool is_vlan_skb = true;
 
-   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
-   return NULL;
-
-   skb_push(skb, MTK_HDR_LEN);
+   /* Build the special tag after the MAC Source Address. If VLAN header
+* is present, it's required that VLAN header and special tag is
+* being combined. Only in this way we can allow the switch can parse
+* the both special and VLAN tag at the same time and then look up VLAN
+* table with VID.
+*/
+   if (!skb_vlan_tagged(skb)) {
+   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+   return NULL;
 
-   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+   skb_push(skb, MTK_HDR_LEN);
+   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+   is_vlan_skb = false;
+   }
 
-   /* Build the tag after the MAC Source Address */
mtk_tag = skb->data + 2 * ETH_ALEN;
-   mtk_tag[0] = 0;
+
+   /* Mark tag attribute on special tag insertion to notify hardware
+* whether that's a combined special tag with 802.1Q header.
+*/
+   mtk_tag[0] = is_vlan_skb ? MTK_HDR_XMIT_TAGGED_TPID_8100 :
+MTK_HDR_XMIT_UNTAGGED;
mtk_tag[1] = (1 << dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
-   mtk_tag[2] = 0;
-   mtk_tag[3] = 0;
+
+   /* Tag control information is kept for 802.1Q */
+   if (!is_vlan_skb) {
+   mtk_tag[2] = 0;
+   mtk_tag[3] = 0;
+   }
 
return skb;
 }
-- 
2.7.4



[PATCH net-next v3 0/4] net-next: mediatek: add support for ethernet on MT7622 SoC

2017-07-31 Thread sean.wang
From: Sean Wang 

Changes since v2:
- update John's mail

Changes since v1:
- add refinement for ethernet clock management
- take out the code block for ESW, add it until ESW driver is actually 
introduced

The series adds the driver for ethernet controller found on MT7622 SoC.
There are additions against with previous MT7623 SoC such as shared SGMII
given for the dual GMACs and built-in 5-ports 10/100 embedded switch support
(ESW). Thus more clocks consumers and SGMII hardware setup for the extra
features are all introduced here and as for the support for ESW that would be
planned to add in the separate patch integrating with DSA infrastructure
in the future.

Currently testing successfully is done with those patches for the conditions
such as GMAC2 with IP1001 PHY via RGMII and GMAC1/2 with RTL8211F PHY via SGMII.


Sean Wang (4):
  dt-bindings: net: mediatek: add support for MediaTek MT7623 and MT7622
SoC
  net-next: mediatek: add platform data to adapt into various hardware
  net-next: mediatek: add support for MediaTek MT7622 SoC
  MAINTAINERS: add Sean/Nelson as MediaTek ethernet maintainers

 .../devicetree/bindings/net/mediatek-net.txt   |  12 +-
 MAINTAINERS|   4 +-
 drivers/net/ethernet/mediatek/Kconfig  |   6 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c| 142 +++--
 drivers/net/ethernet/mediatek/mtk_eth_soc.h|  73 ++-
 5 files changed, 215 insertions(+), 22 deletions(-)

-- 
2.7.4



[PATCH net-next v3 4/4] MAINTAINERS: add Sean/Nelson as MediaTek ethernet maintainers

2017-07-31 Thread sean.wang
From: Sean Wang 

Sean and Nelson work for MediaTek on maintaining the MediaTek ethernet
driver for the existing SoCs and adding support for the following SoCs.
In the past, Sean has been active at making most of the qualifications
, stress test and submitting a lot of patches for the driver while
Nelson was looking into the aspects more on hardware additions and details
such as introducing PDMA with Hardware LRO to the driver. Also update
John's up-to-date mail address in the patch.

Cc: John Crispin 
Signed-off-by: Sean Wang 
Signed-off-by: Nelson Chang 
---
 MAINTAINERS | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index bd22d07..22faf704 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8431,7 +8431,9 @@ F:include/uapi/linux/uvcvideo.h
 
 MEDIATEK ETHERNET DRIVER
 M: Felix Fietkau 
-M: John Crispin 
+M: John Crispin 
+M: Sean Wang 
+M: Nelson Chang 
 L: netdev@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/mediatek/
-- 
2.7.4



[PATCH net-next v3 1/4] dt-bindings: net: mediatek: add support for MediaTek MT7623 and MT7622 SoC

2017-07-31 Thread sean.wang
From: Sean Wang 

The patch adds the supplements in the dt-binding document for MediaTek
MT7622 SoC with extra SGMII system controller and relevant clock consumers
listed as the requirements for those SoCs equipped with the SGMII circuit.
Also, add the missing binding information for MT7623 SoC here which relies
on the fallback binding of MT2701.

Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/mediatek-net.txt | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index c7194e8..1d1168b 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -7,24 +7,30 @@ have dual GMAC each represented by a child node..
 * Ethernet controller node
 
 Required properties:
-- compatible: Should be "mediatek,mt2701-eth"
+- compatible: Should be
+   "mediatek,mt2701-eth": for MT2701 SoC
+   "mediatek,mt7623-eth", "mediatek,mt2701-eth": for MT7623 SoC
+   "mediatek,mt7622-eth": for MT7622 SoC
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the three frame engines interrupts in numeric
order. These are fe_int0, fe_int1 and fe_int2.
 - clocks: the clock used by the core
 - clock-names: the names of the clock listed in the clocks property. These are
-   "ethif", "esw", "gp2", "gp1"
+   "ethif", "esw", "gp2", "gp1" : For MT2701 and MT7623 SoC
+"ethif", "esw", "gp0", "gp1", "gp2", "sgmii_tx250m", "sgmii_rx250m",
+   "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll" : For MT7622 SoC
 - power-domains: phandle to the power domain that the ethernet is part of
 - resets: Should contain a phandle to the ethsys reset signal
 - reset-names: Should contain the reset signal name "eth"
 - mediatek,ethsys: phandle to the syscon node that handles the port setup
+- mediatek,sgmiisys: phandle to the syscon node that handles the SGMII setup
+   which is required for those SoCs equipped with SGMII such as MT7622 SoC.
 - mediatek,pctl: phandle to the syscon node that handles the ports slew rate
and driver current
 
 Optional properties:
 - interrupt-parent: Should be the phandle for the interrupt controller
   that services interrupts for this device
-
 * Ethernet MAC node
 
 Required properties:
-- 
2.7.4



[PATCH net-next v3 3/4] net-next: mediatek: add support for MediaTek MT7622 SoC

2017-07-31 Thread sean.wang
From: Sean Wang 

This patch adds the driver for ethernet controller on MT7622 SoC. It has
the similar handling logic as the previously MT7623 does, but there are
additions against with MT7623 SoC, the shared SGMII given for the dual
GMACs and including 5-ports 10/100 embedded switch support (ESW) as the
GMAC1 option, thus more clocks consumers for the extra feature are
introduced here. So for ease portability and maintenance, those
differences all are being kept inside the platform data as other drivers
usually do. Currently testing successfully is done with those patches for
the conditions such as GMAC2 with IP1001 PHY via RGMII and GMAC1/2 with
RTL8211F PHY via SGMII.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 67 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 54 ++-
 2 files changed, 117 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ad48623..9f44246 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -52,7 +52,8 @@ static const struct mtk_ethtool_stats {
 };
 
 static const char * const mtk_clks_source_name[] = {
-   "ethif", "esw", "gp1", "gp2", "trgpll"
+   "ethif", "esw", "gp0", "gp1", "gp2", "trgpll", "sgmii_tx250m",
+   "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll"
 };
 
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -162,6 +163,47 @@ static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, 
int speed)
mtk_w32(eth, val, TRGMII_TCK_CTRL);
 }
 
+static void mtk_gmac_sgmii_hw_setup(struct mtk_eth *eth, int mac_id)
+{
+   u32 val;
+
+   /* Setup the link timer and QPHY power up inside SGMIISYS */
+   regmap_write(eth->sgmiisys, SGMSYS_PCS_LINK_TIMER,
+SGMII_LINK_TIMER_DEFAULT);
+
+   regmap_read(eth->sgmiisys, SGMSYS_SGMII_MODE, );
+   val |= SGMII_REMOTE_FAULT_DIS;
+   regmap_write(eth->sgmiisys, SGMSYS_SGMII_MODE, val);
+
+   regmap_read(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, );
+   val |= SGMII_AN_RESTART;
+   regmap_write(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, val);
+
+   regmap_read(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, );
+   val &= ~SGMII_PHYA_PWD;
+   regmap_write(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+
+   /* Determine MUX for which GMAC uses the SGMII interface */
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_DUAL_GMAC_SHARED_SGMII)) {
+   regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
+   val &= ~SYSCFG0_SGMII_MASK;
+   val |= !mac_id ? SYSCFG0_SGMII_GMAC1 : SYSCFG0_SGMII_GMAC2;
+   regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
+
+   dev_info(eth->dev, "setup shared sgmii for gmac=%d\n",
+mac_id);
+   }
+
+   /* Setup the GMAC1 going through SGMII path when SoC also support
+* ESW on GMAC1
+*/
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_ESW | MTK_GMAC1_SGMII) &&
+   !mac_id) {
+   mtk_w32(eth, 0, MTK_MAC_MISC);
+   dev_info(eth->dev, "setup gmac1 going through sgmii");
+   }
+}
+
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
@@ -269,6 +311,7 @@ static int mtk_phy_connect(struct net_device *dev)
if (!np)
return -ENODEV;
 
+   mac->ge_mode = 0;
switch (of_get_phy_mode(np)) {
case PHY_INTERFACE_MODE_TRGMII:
mac->trgmii = true;
@@ -276,7 +319,10 @@ static int mtk_phy_connect(struct net_device *dev)
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
-   mac->ge_mode = 0;
+   break;
+   case PHY_INTERFACE_MODE_SGMII:
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII))
+   mtk_gmac_sgmii_hw_setup(eth, mac->id);
break;
case PHY_INTERFACE_MODE_MII:
mac->ge_mode = 1;
@@ -2421,6 +2467,7 @@ static int mtk_get_chip_id(struct mtk_eth *eth, u32 
*chip_id)
 static bool mtk_is_hwlro_supported(struct mtk_eth *eth)
 {
switch (eth->chip_id) {
+   case MT7622_ETH:
case MT7623_ETH:
return true;
}
@@ -2460,6 +2507,16 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->ethsys);
}
 
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
+   eth->sgmiisys =
+   syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+   "mediatek,sgmiisys");
+   if (IS_ERR(eth->sgmiisys)) {
+   dev_err(>dev, "no sgmiisys regmap found\n");
+   return PTR_ERR(eth->sgmiisys);
+ 

[PATCH net-next v3 2/4] net-next: mediatek: add platform data to adapt into various hardware

2017-07-31 Thread sean.wang
From: Sean Wang 

This patch is the preparation patch in order to adapt into various
hardware through adding platform data which holds specific characteristics
among MediaTek SoCs and introducing the unified clock handler for those
distinct clock requirements depending on different features such as
TRGMII and SGMII getting support on the target SoC. And finally, add
enhancement with given the generic description for Kconfig and remove the
unnecessary machine type dependency in Makefile.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/Kconfig   |  6 +--
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 75 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 23 -
 3 files changed, 88 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/Kconfig 
b/drivers/net/ethernet/mediatek/Kconfig
index 698bb89..f9149d2 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -7,11 +7,11 @@ config NET_VENDOR_MEDIATEK
 if NET_VENDOR_MEDIATEK
 
 config NET_MEDIATEK_SOC
-   tristate "MediaTek MT7623 Gigabit ethernet support"
-   depends on NET_VENDOR_MEDIATEK && (MACH_MT7623 || MACH_MT2701)
+   tristate "MediaTek SoC Gigabit Ethernet support"
+   depends on NET_VENDOR_MEDIATEK
select PHYLIB
---help---
  This driver supports the gigabit ethernet MACs in the
- MediaTek MT2701/MT7623 chipset family.
+ MediaTek SoC family.
 
 endif #NET_VENDOR_MEDIATEK
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b3d0c2e..ad48623 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -184,7 +184,8 @@ static void mtk_phy_link_adjust(struct net_device *dev)
break;
};
 
-   if (mac->id == 0 && !mac->trgmii)
+   if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
+   !mac->id && !mac->trgmii)
mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
 
if (dev->phydev->link)
@@ -1832,9 +1833,36 @@ static void ethsys_reset(struct mtk_eth *eth, u32 
reset_bits)
mdelay(10);
 }
 
+static void mtk_clk_disable(struct mtk_eth *eth)
+{
+   int clk;
+
+   for (clk = MTK_CLK_MAX - 1; clk >= 0; clk--)
+   clk_disable_unprepare(eth->clks[clk]);
+}
+
+static int mtk_clk_enable(struct mtk_eth *eth)
+{
+   int clk, ret;
+
+   for (clk = 0; clk < MTK_CLK_MAX ; clk++) {
+   ret = clk_prepare_enable(eth->clks[clk]);
+   if (ret)
+   goto err_disable_clks;
+   }
+
+   return 0;
+
+err_disable_clks:
+   while (--clk >= 0)
+   clk_disable_unprepare(eth->clks[clk]);
+
+   return ret;
+}
+
 static int mtk_hw_init(struct mtk_eth *eth)
 {
-   int i, val;
+   int i, val, ret;
 
if (test_and_set_bit(MTK_HW_INIT, >state))
return 0;
@@ -1842,10 +1870,10 @@ static int mtk_hw_init(struct mtk_eth *eth)
pm_runtime_enable(eth->dev);
pm_runtime_get_sync(eth->dev);
 
-   clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
-   clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
+   ret = mtk_clk_enable(eth);
+   if (ret)
+   goto err_disable_pm;
+
ethsys_reset(eth, RSTCTRL_FE);
ethsys_reset(eth, RSTCTRL_PPE);
 
@@ -1913,6 +1941,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
}
 
return 0;
+
+err_disable_pm:
+   pm_runtime_put_sync(eth->dev);
+   pm_runtime_disable(eth->dev);
+
+   return ret;
 }
 
 static int mtk_hw_deinit(struct mtk_eth *eth)
@@ -1920,10 +1954,7 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
if (!test_and_clear_bit(MTK_HW_INIT, >state))
return 0;
 
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+   mtk_clk_disable(eth);
 
pm_runtime_put_sync(eth->dev);
pm_runtime_disable(eth->dev);
@@ -2401,6 +2432,7 @@ static int mtk_probe(struct platform_device *pdev)
 {
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct device_node *mac_np;
+   const struct of_device_id *match;
struct mtk_eth *eth;
int err;
int i;
@@ -2409,6 +2441,9 @@ static int mtk_probe(struct platform_device *pdev)
if (!eth)
return -ENOMEM;
 
+   match = of_match_device(of_mtk_match, >dev);
+   eth->soc = (struct mtk_soc_data *)match->data;
+
eth->dev = >dev;
eth->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(eth->base))
@@ -2445,7 +2480,12 @@ static int 

[PATCH] net: dsa: fixup fail to get tag in mtk_get_tag_protocol

2017-07-24 Thread sean.wang
From: Sean Wang 

dsa_is_cpu_port() checking ds->cpu_port_mask is not available in
ds->ops->get_tag_protocol

Since commit 14be36c2c96c ("net: dsa: Initialize all CPU and enabled
ports masks in dsa_ds_parse()") So force returning DSA_TAG_PROTO_MTK
inside mtk_get_tag_protocol call after that.

Cc: Florian Fainelli 
Signed-off-by: Sean Wang 
---
 drivers/net/dsa/mt7530.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 1e46418..c265e7e 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -892,15 +892,7 @@ mt7530_port_fdb_dump(struct dsa_switch *ds, int port,
 static enum dsa_tag_protocol
 mtk_get_tag_protocol(struct dsa_switch *ds)
 {
-   struct mt7530_priv *priv = ds->priv;
-
-   if (!dsa_is_cpu_port(ds, MT7530_CPU_PORT)) {
-   dev_warn(priv->dev,
-"port not matched with tagging CPU port\n");
-   return DSA_TAG_PROTO_NONE;
-   } else {
-   return DSA_TAG_PROTO_MTK;
-   }
+   return DSA_TAG_PROTO_MTK;
 }
 
 static int
-- 
2.7.4



[PATCH v2 net] net: ethernet: mediatek: avoid potential invalid memory access

2017-07-22 Thread sean.wang
From: Sean Wang 

Potential dangerous invalid memory might be accessed if invalid mac value
reflected from the forward port field in rxd4 caused by possible potential
hardware defects. So added a simple sanity checker to avoid the kind of
situation happening.

Signed-off-by: Sean Wang 
Acked-by: John Crispin 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c1dc08c..e69524c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -999,6 +999,10 @@ static int mtk_poll_rx(struct napi_struct *napi, int 
budget,
  RX_DMA_FPORT_MASK;
mac--;
 
+   if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
+!eth->netdev[mac]))
+   goto release_desc;
+
netdev = eth->netdev[mac];
 
if (unlikely(test_bit(MTK_RESETTING, >state)))
-- 
2.7.4



[PATCH net] net: ethernet: mediatek: avoid potential invalid memory access

2017-07-20 Thread sean.wang
From: Sean Wang 

Potential dangerous invalid memory might be accessed if invalid mac value
reflected from the forward port field in rxd4 caused by possible potential
hardware defects. So added a simple sanity checker to avoid the kind of
situation happening.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c1dc08c..8175433 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -999,6 +999,12 @@ static int mtk_poll_rx(struct napi_struct *napi, int 
budget,
  RX_DMA_FPORT_MASK;
mac--;
 
+   if (unlikely(mac < 0 || mac >= MTK_MAC_COUNT ||
+!eth->netdev[mac])) {
+   netdev->stats.rx_dropped++;
+   goto release_desc;
+   }
+
netdev = eth->netdev[mac];
 
if (unlikely(test_bit(MTK_RESETTING, >state)))
-- 
2.7.4



[PATCH net-next v2 0/4] net-next: mediatek: add support for ethernet on MT7622 SoC

2017-07-17 Thread sean.wang
From: Sean Wang 

Changes since v1:
- add refinement for ethernet clock management
- take out the code block for ESW, add it until ESW driver is actually 
introduced

The series adds the driver for ethernet controller found on MT7622 SoC.
There are additions against with previous MT7623 SoC such as shared SGMII
given for the dual GMACs and built-in 5-ports 10/100 embedded switch support
(ESW). Thus more clocks consumers and SGMII hardware setup for the extra
features are all introduced here and as for the support for ESW that would be
planned to add in the separate patch integrating with DSA infrastructure
in the future.

Currently testing successfully is done with those patches for the conditions
such as GMAC2 with IP1001 PHY via RGMII and GMAC1/2 with RTL8211F PHY via SGMII.

Sean Wang (4):
  dt-bindings: net: mediatek: add support for MediaTek MT7623 and MT7622
SoC
  net-next: mediatek: add platform data to adapt into various hardware
  net-next: mediatek: add support for MediaTek MT7622 SoC
  MAINTAINERS: add Sean/Nelson as MediaTek ethernet maintainers

 .../devicetree/bindings/net/mediatek-net.txt   |  12 +-
 MAINTAINERS|   2 +
 drivers/net/ethernet/mediatek/Kconfig  |   6 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c| 142 +++--
 drivers/net/ethernet/mediatek/mtk_eth_soc.h|  73 ++-
 5 files changed, 214 insertions(+), 21 deletions(-)

-- 
2.7.4



[PATCH net-next v2 2/4] net-next: mediatek: add platform data to adapt into various hardware

2017-07-17 Thread sean.wang
From: Sean Wang 

This patch is the preparation patch in order to adapt into various
hardware through adding platform data which holds specific characteristics
among MediaTek SoCs and introducing the unified clock handler for those
distinct clock requirements depending on different features such as
TRGMII and SGMII getting support on the target SoC. And finally, add
enhancement with given the generic description for Kconfig and remove the
unnecessary machine type dependency in Makefile.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/Kconfig   |  6 +--
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 75 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 23 -
 3 files changed, 88 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/Kconfig 
b/drivers/net/ethernet/mediatek/Kconfig
index 698bb89..f9149d2 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -7,11 +7,11 @@ config NET_VENDOR_MEDIATEK
 if NET_VENDOR_MEDIATEK
 
 config NET_MEDIATEK_SOC
-   tristate "MediaTek MT7623 Gigabit ethernet support"
-   depends on NET_VENDOR_MEDIATEK && (MACH_MT7623 || MACH_MT2701)
+   tristate "MediaTek SoC Gigabit Ethernet support"
+   depends on NET_VENDOR_MEDIATEK
select PHYLIB
---help---
  This driver supports the gigabit ethernet MACs in the
- MediaTek MT2701/MT7623 chipset family.
+ MediaTek SoC family.
 
 endif #NET_VENDOR_MEDIATEK
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b3d0c2e..ad48623 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -184,7 +184,8 @@ static void mtk_phy_link_adjust(struct net_device *dev)
break;
};
 
-   if (mac->id == 0 && !mac->trgmii)
+   if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
+   !mac->id && !mac->trgmii)
mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
 
if (dev->phydev->link)
@@ -1832,9 +1833,36 @@ static void ethsys_reset(struct mtk_eth *eth, u32 
reset_bits)
mdelay(10);
 }
 
+static void mtk_clk_disable(struct mtk_eth *eth)
+{
+   int clk;
+
+   for (clk = MTK_CLK_MAX - 1; clk >= 0; clk--)
+   clk_disable_unprepare(eth->clks[clk]);
+}
+
+static int mtk_clk_enable(struct mtk_eth *eth)
+{
+   int clk, ret;
+
+   for (clk = 0; clk < MTK_CLK_MAX ; clk++) {
+   ret = clk_prepare_enable(eth->clks[clk]);
+   if (ret)
+   goto err_disable_clks;
+   }
+
+   return 0;
+
+err_disable_clks:
+   while (--clk >= 0)
+   clk_disable_unprepare(eth->clks[clk]);
+
+   return ret;
+}
+
 static int mtk_hw_init(struct mtk_eth *eth)
 {
-   int i, val;
+   int i, val, ret;
 
if (test_and_set_bit(MTK_HW_INIT, >state))
return 0;
@@ -1842,10 +1870,10 @@ static int mtk_hw_init(struct mtk_eth *eth)
pm_runtime_enable(eth->dev);
pm_runtime_get_sync(eth->dev);
 
-   clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
-   clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
+   ret = mtk_clk_enable(eth);
+   if (ret)
+   goto err_disable_pm;
+
ethsys_reset(eth, RSTCTRL_FE);
ethsys_reset(eth, RSTCTRL_PPE);
 
@@ -1913,6 +1941,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
}
 
return 0;
+
+err_disable_pm:
+   pm_runtime_put_sync(eth->dev);
+   pm_runtime_disable(eth->dev);
+
+   return ret;
 }
 
 static int mtk_hw_deinit(struct mtk_eth *eth)
@@ -1920,10 +1954,7 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
if (!test_and_clear_bit(MTK_HW_INIT, >state))
return 0;
 
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+   mtk_clk_disable(eth);
 
pm_runtime_put_sync(eth->dev);
pm_runtime_disable(eth->dev);
@@ -2401,6 +2432,7 @@ static int mtk_probe(struct platform_device *pdev)
 {
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct device_node *mac_np;
+   const struct of_device_id *match;
struct mtk_eth *eth;
int err;
int i;
@@ -2409,6 +2441,9 @@ static int mtk_probe(struct platform_device *pdev)
if (!eth)
return -ENOMEM;
 
+   match = of_match_device(of_mtk_match, >dev);
+   eth->soc = (struct mtk_soc_data *)match->data;
+
eth->dev = >dev;
eth->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(eth->base))
@@ -2445,7 +2480,12 @@ static int 

[PATCH net-next v2 3/4] net-next: mediatek: add support for MediaTek MT7622 SoC

2017-07-17 Thread sean.wang
From: Sean Wang 

This patch adds the driver for ethernet controller on MT7622 SoC. It has
the similar handling logic as the previously MT7623 does, but there are
additions against with MT7623 SoC, the shared SGMII given for the dual
GMACs and including 5-ports 10/100 embedded switch support (ESW) as the
GMAC1 option, thus more clocks consumers for the extra feature are
introduced here. So for ease portability and maintenance, those
differences all are being kept inside the platform data as other drivers
usually do. Currently testing successfully is done with those patches for
the conditions such as GMAC2 with IP1001 PHY via RGMII and GMAC1/2 with
RTL8211F PHY via SGMII.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 67 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 54 ++-
 2 files changed, 117 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ad48623..9f44246 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -52,7 +52,8 @@ static const struct mtk_ethtool_stats {
 };
 
 static const char * const mtk_clks_source_name[] = {
-   "ethif", "esw", "gp1", "gp2", "trgpll"
+   "ethif", "esw", "gp0", "gp1", "gp2", "trgpll", "sgmii_tx250m",
+   "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll"
 };
 
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -162,6 +163,47 @@ static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, 
int speed)
mtk_w32(eth, val, TRGMII_TCK_CTRL);
 }
 
+static void mtk_gmac_sgmii_hw_setup(struct mtk_eth *eth, int mac_id)
+{
+   u32 val;
+
+   /* Setup the link timer and QPHY power up inside SGMIISYS */
+   regmap_write(eth->sgmiisys, SGMSYS_PCS_LINK_TIMER,
+SGMII_LINK_TIMER_DEFAULT);
+
+   regmap_read(eth->sgmiisys, SGMSYS_SGMII_MODE, );
+   val |= SGMII_REMOTE_FAULT_DIS;
+   regmap_write(eth->sgmiisys, SGMSYS_SGMII_MODE, val);
+
+   regmap_read(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, );
+   val |= SGMII_AN_RESTART;
+   regmap_write(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, val);
+
+   regmap_read(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, );
+   val &= ~SGMII_PHYA_PWD;
+   regmap_write(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+
+   /* Determine MUX for which GMAC uses the SGMII interface */
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_DUAL_GMAC_SHARED_SGMII)) {
+   regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
+   val &= ~SYSCFG0_SGMII_MASK;
+   val |= !mac_id ? SYSCFG0_SGMII_GMAC1 : SYSCFG0_SGMII_GMAC2;
+   regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
+
+   dev_info(eth->dev, "setup shared sgmii for gmac=%d\n",
+mac_id);
+   }
+
+   /* Setup the GMAC1 going through SGMII path when SoC also support
+* ESW on GMAC1
+*/
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_ESW | MTK_GMAC1_SGMII) &&
+   !mac_id) {
+   mtk_w32(eth, 0, MTK_MAC_MISC);
+   dev_info(eth->dev, "setup gmac1 going through sgmii");
+   }
+}
+
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
@@ -269,6 +311,7 @@ static int mtk_phy_connect(struct net_device *dev)
if (!np)
return -ENODEV;
 
+   mac->ge_mode = 0;
switch (of_get_phy_mode(np)) {
case PHY_INTERFACE_MODE_TRGMII:
mac->trgmii = true;
@@ -276,7 +319,10 @@ static int mtk_phy_connect(struct net_device *dev)
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
-   mac->ge_mode = 0;
+   break;
+   case PHY_INTERFACE_MODE_SGMII:
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII))
+   mtk_gmac_sgmii_hw_setup(eth, mac->id);
break;
case PHY_INTERFACE_MODE_MII:
mac->ge_mode = 1;
@@ -2421,6 +2467,7 @@ static int mtk_get_chip_id(struct mtk_eth *eth, u32 
*chip_id)
 static bool mtk_is_hwlro_supported(struct mtk_eth *eth)
 {
switch (eth->chip_id) {
+   case MT7622_ETH:
case MT7623_ETH:
return true;
}
@@ -2460,6 +2507,16 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->ethsys);
}
 
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
+   eth->sgmiisys =
+   syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+   "mediatek,sgmiisys");
+   if (IS_ERR(eth->sgmiisys)) {
+   dev_err(>dev, "no sgmiisys regmap found\n");
+   return PTR_ERR(eth->sgmiisys);
+ 

[PATCH net-next v2 1/4] dt-bindings: net: mediatek: add support for MediaTek MT7623 and MT7622 SoC

2017-07-17 Thread sean.wang
From: Sean Wang 

The patch adds the supplements in the dt-binding document for MediaTek
MT7622 SoC with extra SGMII system controller and relevant clock consumers
listed as the requirements for those SoCs equipped with the SGMII circuit.
Also, add the missing binding information for MT7623 SoC here which relies
on the fallback binding of MT2701.

Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/mediatek-net.txt | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index c7194e8..1d1168b 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -7,24 +7,30 @@ have dual GMAC each represented by a child node..
 * Ethernet controller node
 
 Required properties:
-- compatible: Should be "mediatek,mt2701-eth"
+- compatible: Should be
+   "mediatek,mt2701-eth": for MT2701 SoC
+   "mediatek,mt7623-eth", "mediatek,mt2701-eth": for MT7623 SoC
+   "mediatek,mt7622-eth": for MT7622 SoC
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the three frame engines interrupts in numeric
order. These are fe_int0, fe_int1 and fe_int2.
 - clocks: the clock used by the core
 - clock-names: the names of the clock listed in the clocks property. These are
-   "ethif", "esw", "gp2", "gp1"
+   "ethif", "esw", "gp2", "gp1" : For MT2701 and MT7623 SoC
+"ethif", "esw", "gp0", "gp1", "gp2", "sgmii_tx250m", "sgmii_rx250m",
+   "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll" : For MT7622 SoC
 - power-domains: phandle to the power domain that the ethernet is part of
 - resets: Should contain a phandle to the ethsys reset signal
 - reset-names: Should contain the reset signal name "eth"
 - mediatek,ethsys: phandle to the syscon node that handles the port setup
+- mediatek,sgmiisys: phandle to the syscon node that handles the SGMII setup
+   which is required for those SoCs equipped with SGMII such as MT7622 SoC.
 - mediatek,pctl: phandle to the syscon node that handles the ports slew rate
and driver current
 
 Optional properties:
 - interrupt-parent: Should be the phandle for the interrupt controller
   that services interrupts for this device
-
 * Ethernet MAC node
 
 Required properties:
-- 
2.7.4



[PATCH net-next v2 4/4] MAINTAINERS: add Sean/Nelson as MediaTek ethernet maintainers

2017-07-17 Thread sean.wang
From: Sean Wang 

Sean and Nelson work for MediaTek on maintaining the MediaTek ethernet
driver for the existing SoCs and adding support for the following SoCs.
In the past, Sean has been active at making most of the qualifications
, stress test and submitting a lot of patches for the driver while
Nelson was looking into the aspects more on hardware additions and details
such as introducing PDMA with Hardware LRO to the driver.

Cc: John Crispin 
Signed-off-by: Sean Wang 
Signed-off-by: Nelson Chang 
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4f4057c..3b2dd4b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8385,6 +8385,8 @@ F:include/uapi/linux/uvcvideo.h
 MEDIATEK ETHERNET DRIVER
 M: Felix Fietkau 
 M: John Crispin 
+M: Sean Wang 
+M: Nelson Chang 
 L: netdev@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/mediatek/
-- 
2.7.4



[PATCH net-next 2/4] net-next: mediatek: add platform data to adapt into various hardware

2017-07-11 Thread sean.wang
From: Sean Wang 

This patch is the preparation patch in order to adapt into various
hardware through adding platform data which holds specific characteristics
among MediaTek SoCs and introducing the unified clock handler for those
distinct clock requirements depending on different features such as
TRGMII and SGMII getting support on the target SoC. And finally, add
enhancement with given the generic description for Kconfig and remove the
unnecessary machine type dependency in Makefile.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/Kconfig   |  6 +--
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 71 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 23 +-
 3 files changed, 85 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/Kconfig 
b/drivers/net/ethernet/mediatek/Kconfig
index 698bb89..f9149d2 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -7,11 +7,11 @@ config NET_VENDOR_MEDIATEK
 if NET_VENDOR_MEDIATEK
 
 config NET_MEDIATEK_SOC
-   tristate "MediaTek MT7623 Gigabit ethernet support"
-   depends on NET_VENDOR_MEDIATEK && (MACH_MT7623 || MACH_MT2701)
+   tristate "MediaTek SoC Gigabit Ethernet support"
+   depends on NET_VENDOR_MEDIATEK
select PHYLIB
---help---
  This driver supports the gigabit ethernet MACs in the
- MediaTek MT2701/MT7623 chipset family.
+ MediaTek SoC family.
 
 endif #NET_VENDOR_MEDIATEK
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b8068ce..51ca79f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -184,7 +184,8 @@ static void mtk_phy_link_adjust(struct net_device *dev)
break;
};
 
-   if (mac->id == 0 && !mac->trgmii)
+   if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII) &&
+   !mac->id && !mac->trgmii)
mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
 
if (dev->phydev->link)
@@ -1837,6 +1838,39 @@ static void ethsys_reset(struct mtk_eth *eth, u32 
reset_bits)
mdelay(10);
 }
 
+static void mtk_clk_disable(struct mtk_eth *eth)
+{
+   int clk;
+
+   for (clk = MTK_CLK_MAX - 1; clk >= 0; clk--) {
+   if (eth->clks[clk])
+   clk_disable_unprepare(eth->clks[clk]);
+   }
+}
+
+static int mtk_clk_enable(struct mtk_eth *eth)
+{
+   int clk, ret;
+
+   for (clk = 0; clk < MTK_CLK_MAX ; clk++) {
+   if (eth->clks[clk]) {
+   ret = clk_prepare_enable(eth->clks[clk]);
+   if (ret)
+   goto err_disable_clks;
+   }
+   }
+
+   return 0;
+
+err_disable_clks:
+   while (--clk >= 0) {
+   if (eth->clks[clk])
+   clk_disable_unprepare(eth->clks[clk]);
+   }
+
+   return ret;
+}
+
 static int mtk_hw_init(struct mtk_eth *eth)
 {
int i, val;
@@ -1847,10 +1881,8 @@ static int mtk_hw_init(struct mtk_eth *eth)
pm_runtime_enable(eth->dev);
pm_runtime_get_sync(eth->dev);
 
-   clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
-   clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
+   mtk_clk_enable(eth);
+
ethsys_reset(eth, RSTCTRL_FE);
ethsys_reset(eth, RSTCTRL_PPE);
 
@@ -1925,10 +1957,7 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
if (!test_and_clear_bit(MTK_HW_INIT, >state))
return 0;
 
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+   mtk_clk_disable(eth);
 
pm_runtime_put_sync(eth->dev);
pm_runtime_disable(eth->dev);
@@ -2406,6 +2435,7 @@ static int mtk_probe(struct platform_device *pdev)
 {
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct device_node *mac_np;
+   const struct of_device_id *match;
struct mtk_eth *eth;
int err;
int i;
@@ -2414,6 +2444,9 @@ static int mtk_probe(struct platform_device *pdev)
if (!eth)
return -ENOMEM;
 
+   match = of_match_device(of_mtk_match, >dev);
+   eth->soc = (struct mtk_soc_data *)match->data;
+
eth->dev = >dev;
eth->base = devm_ioremap_resource(>dev, res);
if (IS_ERR(eth->base))
@@ -2450,7 +2483,12 @@ static int mtk_probe(struct platform_device *pdev)
if (IS_ERR(eth->clks[i])) {
if (PTR_ERR(eth->clks[i]) == -EPROBE_DEFER)
return -EPROBE_DEFER;
-   return 

[PATCH net-next 4/4] MAINTAINERS: add Sean/Nelson as MediaTek ethernet maintainers

2017-07-11 Thread sean.wang
From: Sean Wang 

Sean and Nelson work for MediaTek on maintaining the MediaTek ethernet
driver for the existing SoCs and adding support for the following SoCs.
In the past, Sean has been active at making most of the qualifications
, stress test and submitting a lot of patches for the driver while
Nelson was looking into the aspects more on hardware additions and details
such as introducing PDMA with Hardware LRO to the driver.

Cc: John Crispin 
Signed-off-by: Sean Wang 
Signed-off-by: Nelson Chang 
---
 MAINTAINERS | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4f4057c..3b2dd4b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8385,6 +8385,8 @@ F:include/uapi/linux/uvcvideo.h
 MEDIATEK ETHERNET DRIVER
 M: Felix Fietkau 
 M: John Crispin 
+M: Sean Wang 
+M: Nelson Chang 
 L: netdev@vger.kernel.org
 S: Maintained
 F: drivers/net/ethernet/mediatek/
-- 
2.7.4



[PATCH net-next 1/4] dt-bindings: net: mediatek: add support for MediaTek MT7623 and MT7622 SoC

2017-07-11 Thread sean.wang
From: Sean Wang 

The patch adds the supplements in the dt-binding document for MediaTek
MT7622 SoC with extra SGMII system controller and relevant clock consumers
listed as the requirements for those SoCs equipped with the SGMII circuit.
Also, add the missing binding information for MT7623 SoC here which relies
on the fallback binding of MT2701.

Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/mediatek-net.txt | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index c7194e8..1d1168b 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -7,24 +7,30 @@ have dual GMAC each represented by a child node..
 * Ethernet controller node
 
 Required properties:
-- compatible: Should be "mediatek,mt2701-eth"
+- compatible: Should be
+   "mediatek,mt2701-eth": for MT2701 SoC
+   "mediatek,mt7623-eth", "mediatek,mt2701-eth": for MT7623 SoC
+   "mediatek,mt7622-eth": for MT7622 SoC
 - reg: Address and length of the register set for the device
 - interrupts: Should contain the three frame engines interrupts in numeric
order. These are fe_int0, fe_int1 and fe_int2.
 - clocks: the clock used by the core
 - clock-names: the names of the clock listed in the clocks property. These are
-   "ethif", "esw", "gp2", "gp1"
+   "ethif", "esw", "gp2", "gp1" : For MT2701 and MT7623 SoC
+"ethif", "esw", "gp0", "gp1", "gp2", "sgmii_tx250m", "sgmii_rx250m",
+   "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll" : For MT7622 SoC
 - power-domains: phandle to the power domain that the ethernet is part of
 - resets: Should contain a phandle to the ethsys reset signal
 - reset-names: Should contain the reset signal name "eth"
 - mediatek,ethsys: phandle to the syscon node that handles the port setup
+- mediatek,sgmiisys: phandle to the syscon node that handles the SGMII setup
+   which is required for those SoCs equipped with SGMII such as MT7622 SoC.
 - mediatek,pctl: phandle to the syscon node that handles the ports slew rate
and driver current
 
 Optional properties:
 - interrupt-parent: Should be the phandle for the interrupt controller
   that services interrupts for this device
-
 * Ethernet MAC node
 
 Required properties:
-- 
2.7.4



[PATCH net-next 3/4] net-next: mediatek: add support for MediaTek MT7622 SoC

2017-07-11 Thread sean.wang
From: Sean Wang 

This patch adds the driver for ethernet controller on MT7622 SoC. It has
the similar handling logic as the previously MT7623 does, but there are
additions against with MT7623 SoC, the shared SGMII given for the dual
GMACs and including 5-ports 10/100 embedded switch support (ESW) as the
GMAC1 option, thus more clocks consumers for the extra feature are
introduced here. So for ease portability and maintenance, those
differences all are being kept inside the platform data as other drivers
usually do. Currently testing successfully is done with those patches for
the conditions such as GMAC2 with IP1001 PHY via RGMII and GMAC1/2 with
RTL8211F PHY via SGMII.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 72 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 54 +-
 2 files changed, 122 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 51ca79f..e3dbea1 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -52,7 +52,8 @@ static const struct mtk_ethtool_stats {
 };
 
 static const char * const mtk_clks_source_name[] = {
-   "ethif", "esw", "gp1", "gp2", "trgpll"
+   "ethif", "esw", "gp0", "gp1", "gp2", "trgpll", "sgmii_tx250m",
+   "sgmii_rx250m", "sgmii_cdr_ref", "sgmii_cdr_fb", "sgmii_ck", "eth2pll"
 };
 
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -162,6 +163,47 @@ static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, 
int speed)
mtk_w32(eth, val, TRGMII_TCK_CTRL);
 }
 
+static void mtk_gmac_sgmii_hw_setup(struct mtk_eth *eth, int mac_id)
+{
+   u32 val;
+
+   /* Setup the link timer and QPHY power up inside SGMIISYS */
+   regmap_write(eth->sgmiisys, SGMSYS_PCS_LINK_TIMER,
+SGMII_LINK_TIMER_DEFAULT);
+
+   regmap_read(eth->sgmiisys, SGMSYS_SGMII_MODE, );
+   val |= SGMII_REMOTE_FAULT_DIS;
+   regmap_write(eth->sgmiisys, SGMSYS_SGMII_MODE, val);
+
+   regmap_read(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, );
+   val |= SGMII_AN_RESTART;
+   regmap_write(eth->sgmiisys, SGMSYS_PCS_CONTROL_1, val);
+
+   regmap_read(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, );
+   val &= ~SGMII_PHYA_PWD;
+   regmap_write(eth->sgmiisys, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+
+   /* Determine MUX for which GMAC uses the SGMII interface */
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_DUAL_GMAC_SHARED_SGMII)) {
+   regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
+   val &= ~SYSCFG0_SGMII_MASK;
+   val |= !mac_id ? SYSCFG0_SGMII_GMAC1 : SYSCFG0_SGMII_GMAC2;
+   regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
+
+   dev_info(eth->dev, "setup shared sgmii for gmac=%d\n",
+mac_id);
+   }
+
+   /* Setup the GMAC1 going through SGMII path when SoC also support
+* ESW on GMAC1
+*/
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_ESW | MTK_GMAC1_SGMII) &&
+   !mac_id) {
+   mtk_w32(eth, 0, MTK_MAC_MISC);
+   dev_info(eth->dev, "setup gmac1 going through sgmii");
+   }
+}
+
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
@@ -269,6 +311,7 @@ static int mtk_phy_connect(struct net_device *dev)
if (!np)
return -ENODEV;
 
+   mac->ge_mode = 0;
switch (of_get_phy_mode(np)) {
case PHY_INTERFACE_MODE_TRGMII:
mac->trgmii = true;
@@ -276,7 +319,15 @@ static int mtk_phy_connect(struct net_device *dev)
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
-   mac->ge_mode = 0;
+   break;
+   case PHY_INTERFACE_MODE_SGMII:
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII))
+   mtk_gmac_sgmii_hw_setup(eth, mac->id);
+   break;
+   case PHY_INTERFACE_MODE_INTERNAL:
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_GMAC1_ESW) && !mac->id)
+   /* Setup the path through ESW internal switch */
+   mtk_w32(eth, MTK_MUX_TO_ESW, MTK_MAC_MISC);
break;
case PHY_INTERFACE_MODE_MII:
mac->ge_mode = 1;
@@ -2424,6 +2475,7 @@ static int mtk_get_chip_id(struct mtk_eth *eth, u32 
*chip_id)
 static bool mtk_is_hwlro_supported(struct mtk_eth *eth)
 {
switch (eth->chip_id) {
+   case MT7622_ETH:
case MT7623_ETH:
return true;
}
@@ -2463,6 +2515,16 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->ethsys);
}
 
+   if (MTK_HAS_CAPS(eth->soc->caps, MTK_SGMII)) {
+   eth->sgmiisys =
+   

[PATCH net-next 0/4] net-next: mediatek: add support for ethernet on MT7622 SoC

2017-07-11 Thread sean.wang
From: Sean Wang 

The series adds the driver for ethernet controller found on MT7622 SoC.
There are additions against with previous MT7623 SoC such as shared SGMII
given for the dual GMACs and built-in 5-ports 10/100 embedded switch support
(ESW). Thus more clocks consumers and SGMII hardware setup for the extra
features are all introduced here and as for the support for ESW that would be
planned to add in the separate patch integrating with DSA infrastructure
in the future.

Currently testing successfully is done with those patches for the conditions
such as GMAC2 with IP1001 PHY via RGMII and GMAC1/2 with RTL8211F PHY via SGMII.

Sean Wang (4):
  dt-bindings: net: mediatek: add support for MediaTek MT7623 and MT7622
SoC
  net-next: mediatek: add platform data to adapt into various hardware
  net-next: mediatek: add support for MediaTek MT7622 SoC
  MAINTAINERS: add Sean/Nelson as MediaTek ethernet maintainers

 .../devicetree/bindings/net/mediatek-net.txt   |  12 +-
 MAINTAINERS|   2 +
 drivers/net/ethernet/mediatek/Kconfig  |   6 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c| 143 +++--
 drivers/net/ethernet/mediatek/mtk_eth_soc.h|  73 ++-
 5 files changed, 216 insertions(+), 20 deletions(-)

-- 
2.7.4



[PATCH] net: ethernet: mediatek: fixed deadlock captured by lockdep

2017-07-03 Thread sean.wang
From: Sean Wang 

Lockdep found an inconsistent lock state when mtk_get_stats64 is called
in user context while NAPI updates MAC statistics in softirq.

Use spin_trylock_bh/spin_unlock_bh fix following lockdep warning.

[   81.321030] WARNING: inconsistent lock state
[   81.325266] 4.12.0-rc1-00035-gd9dda65 #32 Not tainted
[   81.330273] 
[   81.334505] inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage.
[   81.340464] ksoftirqd/0/7 [HC0[0]:SC1[1]:HE1:SE0] takes:
[   81.345731]  (>seq#2){+.?...}, at: [] 
mtk_handle_status_irq.part.6+0x70/0x84
[   81.354219] {SOFTIRQ-ON-W} state was registered at:
[   81.359062]   lock_acquire+0xfc/0x2b0
[   81.362696]   mtk_stats_update_mac+0x60/0x2c0
[   81.367017]   mtk_get_stats64+0x17c/0x18c
[   81.370995]   dev_get_stats+0x48/0xbc
[   81.374628]   rtnl_fill_stats+0x48/0x128
[   81.378520]   rtnl_fill_ifinfo+0x4ac/0xd1c
[   81.382584]   rtmsg_ifinfo_build_skb+0x7c/0xe0
[   81.386991]   rtmsg_ifinfo.part.5+0x24/0x54
[   81.391139]   rtmsg_ifinfo+0x24/0x28
[   81.394685]   __dev_notify_flags+0xa4/0xac
[   81.398749]   dev_change_flags+0x50/0x58
[   81.402640]   devinet_ioctl+0x768/0x85c
[   81.406444]   inet_ioctl+0x1a4/0x1d0
[   81.409990]   sock_ioctl+0x16c/0x33c
[   81.413538]   do_vfs_ioctl+0xb4/0xa34
[   81.417169]   SyS_ioctl+0x44/0x6c
[   81.420458]   ret_fast_syscall+0x0/0x1c
[   81.424260] irq event stamp: 3354692
[   81.427806] hardirqs last  enabled at (3354692): [] 
net_rx_action+0xc0/0x504
[   81.435660] hardirqs last disabled at (3354691): [] 
net_rx_action+0x8c/0x504
[   81.443515] softirqs last  enabled at (3354106): [] 
__do_softirq+0x4b4/0x614
[   81.451370] softirqs last disabled at (3354109): [] 
run_ksoftirqd+0x44/0x80
[   81.459134]
[   81.459134] other info that might help us debug this:
[   81.465608]  Possible unsafe locking scenario:
[   81.465608]
[   81.471478]CPU0
[   81.473900]
[   81.476321]   lock(>seq#2);
[   81.479701]   
[   81.482294] lock(>seq#2);
[   81.485847]
[   81.485847]  *** DEADLOCK ***
[   81.485847]
[   81.491720] 1 lock held by ksoftirqd/0/7:
[   81.495693]  #0:  (&(>hw_stats->stats_lock)->rlock){+.+...}, at: 
[] mtk_handle_status_irq.part.6+0x48/0x84
[   81.506579]
[   81.506579] stack backtrace:
[   81.510904] CPU: 0 PID: 7 Comm: ksoftirqd/0 Not tainted 
4.12.0-rc1-00035-gd9dda65 #32
[   81.518668] Hardware name: Mediatek Cortex-A7 (Device Tree)
[   81.524208] [] (unwind_backtrace) from [] 
(show_stack+0x20/0x24)
[   81.531899] [] (show_stack) from [] 
(dump_stack+0xb4/0xe0)
[   81.539072] [] (dump_stack) from [] 
(print_usage_bug+0x234/0x2e0)
[   81.546846] [] (print_usage_bug) from [] 
(mark_lock+0x63c/0x7bc)
[   81.554532] [] (mark_lock) from [] 
(__lock_acquire+0x654/0x1bfc)
[   81.562217] [] (__lock_acquire) from [] 
(lock_acquire+0xfc/0x2b0)
[   81.569990] [] (lock_acquire) from [] 
(mtk_stats_update_mac+0x60/0x2c0)
[   81.578283] [] (mtk_stats_update_mac) from [] 
(mtk_handle_status_irq.part.6+0x70/0x84)
[   81.587865] [] (mtk_handle_status_irq.part.6) from [] 
(mtk_napi_tx+0x358/0x37c)
[   81.596845] [] (mtk_napi_tx) from [] 
(net_rx_action+0x244/0x504)
[   81.604533] [] (net_rx_action) from [] 
(__do_softirq+0x134/0x614)
[   81.612306] [] (__do_softirq) from [] 
(run_ksoftirqd+0x44/0x80)
[   81.619907] [] (run_ksoftirqd) from [] 
(smpboot_thread_fn+0x14c/0x25c)
[   81.628110] [] (smpboot_thread_fn) from [] 
(kthread+0x150/0x180)
[   81.635798] [] (kthread) from [] 
(ret_from_fork+0x14/0x24)

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 16f9755..8a2acb8 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -470,9 +470,9 @@ static void mtk_get_stats64(struct net_device *dev,
unsigned int start;
 
if (netif_running(dev) && netif_device_present(dev)) {
-   if (spin_trylock(_stats->stats_lock)) {
+   if (spin_trylock_bh(_stats->stats_lock)) {
mtk_stats_update_mac(mac);
-   spin_unlock(_stats->stats_lock);
+   spin_unlock_bh(_stats->stats_lock);
}
}
 
@@ -2156,9 +2156,9 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
return;
 
if (netif_running(dev) && netif_device_present(dev)) {
-   if (spin_trylock(>stats_lock)) {
+   if (spin_trylock_bh(>stats_lock)) {
mtk_stats_update_mac(mac);
-   spin_unlock(>stats_lock);
+   spin_unlock_bh(>stats_lock);
}
}
 
-- 
2.7.4



[PATCH v2 net 2/2] net: ethernet: mediatek: fix inconsistency of port number carried in TXD

2017-04-13 Thread sean.wang
From: Sean Wang 

Fix port inconsistency on TXD due to hardware BUG that would cause
different port number is carried on the same TXD between tx_map()
and tx_unmap() with the iperf test. It would cause confusing BQL
logic which leads to kernel panic when dual GMAC runs concurrently.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 +---
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 48ba617..6313c53 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -648,6 +648,8 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
 
WRITE_ONCE(itxd->txd1, mapped_addr);
itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
+   itx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
+ MTK_TX_FLAGS_FPORT1;
dma_unmap_addr_set(itx_buf, dma_addr0, mapped_addr);
dma_unmap_len_set(itx_buf, dma_len0, skb_headlen(skb));
 
@@ -689,6 +691,9 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
+   tx_buf->flags |= (!mac->id) ? MTK_TX_FLAGS_FPORT0 :
+MTK_TX_FLAGS_FPORT1;
+
dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
dma_unmap_len_set(tx_buf, dma_len0, frag_map_size);
frag_size -= frag_map_size;
@@ -1011,17 +1016,16 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
 
while ((cpu != dma) && budget) {
u32 next_cpu = desc->txd2;
-   int mac;
+   int mac = 0;
 
desc = mtk_qdma_phys_to_virt(ring, desc->txd2);
if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0)
break;
 
-   mac = (desc->txd4 >> TX_DMA_FPORT_SHIFT) &
-  TX_DMA_FPORT_MASK;
-   mac--;
-
tx_buf = mtk_desc_to_tx_buf(ring, desc);
+   if (tx_buf->flags & MTK_TX_FLAGS_FPORT1)
+   mac = 1;
+
skb = tx_buf->skb;
if (!skb) {
condition = 1;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 996024d..3c46a3b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -410,12 +410,18 @@ struct mtk_hw_stats {
struct u64_stats_sync   syncp;
 };
 
-/* PDMA descriptor can point at 1-2 segments. This enum allows us to track how
- * memory was allocated so that it can be freed properly
- */
 enum mtk_tx_flags {
+   /* PDMA descriptor can point at 1-2 segments. This enum allows us to
+* track how memory was allocated so that it can be freed properly.
+*/
MTK_TX_FLAGS_SINGLE0= 0x01,
MTK_TX_FLAGS_PAGE0  = 0x02,
+
+   /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted
+* SKB out instead of looking up through hardware TX descriptor.
+*/
+   MTK_TX_FLAGS_FPORT0 = 0x04,
+   MTK_TX_FLAGS_FPORT1 = 0x08,
 };
 
 /* This enum allows us to identify how the clock is defined on the array of the
-- 
1.9.1



[PATCH v2 net 1/2] net: ethernet: mediatek: fix inconsistency between TXD and the used buffer

2017-04-13 Thread sean.wang
From: Sean Wang 

Fix inconsistency between the TXD descriptor and the used buffer that
would cause unexpected logic at mtk_tx_unmap() during skb housekeeping.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 14e1bd1..48ba617 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -613,7 +613,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
struct mtk_tx_dma *itxd, *txd;
-   struct mtk_tx_buf *tx_buf;
+   struct mtk_tx_buf *itx_buf, *tx_buf;
dma_addr_t mapped_addr;
unsigned int nr_frags;
int i, n_desc = 1;
@@ -627,8 +627,8 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
txd4 |= fport;
 
-   tx_buf = mtk_desc_to_tx_buf(ring, itxd);
-   memset(tx_buf, 0, sizeof(*tx_buf));
+   itx_buf = mtk_desc_to_tx_buf(ring, itxd);
+   memset(itx_buf, 0, sizeof(*itx_buf));
 
if (gso)
txd4 |= TX_DMA_TSO;
@@ -647,9 +647,9 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
return -ENOMEM;
 
WRITE_ONCE(itxd->txd1, mapped_addr);
-   tx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
-   dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
-   dma_unmap_len_set(tx_buf, dma_len0, skb_headlen(skb));
+   itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
+   dma_unmap_addr_set(itx_buf, dma_addr0, mapped_addr);
+   dma_unmap_len_set(itx_buf, dma_len0, skb_headlen(skb));
 
/* TX SG offload */
txd = itxd;
@@ -685,10 +685,9 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
   last_frag * TX_DMA_LS0));
WRITE_ONCE(txd->txd4, fport);
 
-   tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf = mtk_desc_to_tx_buf(ring, txd);
memset(tx_buf, 0, sizeof(*tx_buf));
-
+   tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
dma_unmap_len_set(tx_buf, dma_len0, frag_map_size);
@@ -698,7 +697,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
}
 
/* store skb to cleanup */
-   tx_buf->skb = skb;
+   itx_buf->skb = skb;
 
WRITE_ONCE(itxd->txd4, txd4);
WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
-- 
1.9.1



[PATCH v2 net 0/2] Fix crash caused by reporting inconsistent skb->len to BQL

2017-04-13 Thread sean.wang
From: Sean Wang 

Changes since v1:
- fix inconsistent enumeration which easily causes the potential bug

The series fixes kernel BUG caused by inconsistent SKB length reported
into BQL. The reason for inconsistent length comes from hardware BUG which
results in different port number carried on the TXD within the lifecycle of
SKB. So patch 2) is proposed for use a software way to track which port
the SKB involving instead of hardware way. And patch 1) is given for another
issue I found which causes TXD and SKB inconsistency that is not expected
in the initial logic, so it is also being corrected it in the series.

The log for the kernel BUG caused by the issue is posted as below.

[  120.825955] kernel BUG at ... lib/dynamic_queue_limits.c:26!
[  120.837684] Internal error: Oops - BUG: 0 [#1] SMP ARM
[  120.842778] Modules linked in:
[  120.845811] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 
4.11.0-rc1-191576-gdbcef47 #35
[  120.853488] Hardware name: Mediatek Cortex-A7 (Device Tree)
[  120.859012] task: c1007480 task.stack: c100
[  120.863510] PC is at dql_completed+0x108/0x17c
[  120.867915] LR is at 0x46
[  120.870512] pc : []lr : [<0046>]psr: 8113
[  120.870512] sp : c1001d58  ip : c1001d80  fp : c1001d7c
[  120.881895] r10: 003e  r9 : df6b3400  r8 : 0ed86506
[  120.887075] r7 : 0001  r6 : 0001  r5 : 0ed8654c  r4 : df0135d8
[  120.893546] r3 : 0001  r2 : df016800  r1 : fece  r0 : df6b3480
[  120.900018] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  120.907093] Control: 10c5387d  Table: 9e27806a  DAC: 0051
[  120.912789] Process swapper/0 (pid: 0, stack limit = 0xc1000218)
[  120.918744] Stack: (0xc1001d58 to 0xc1002000)



121.085331] 1fc0:  c0a52a28  c10855d4 c1003c58 c0a52a24 
c100885c 8000406a
[  121.093444] 1fe0: 410fc073   c1001ff8 8000807c c0a009cc 
 
[  121.101575] [] (dql_completed) from [] 
(mtk_napi_tx+0x1d0/0x37c)
[  121.109263] [] (mtk_napi_tx) from [] 
(net_rx_action+0x24c/0x3b8)
[  121.116951] [] (net_rx_action) from [] 
(__do_softirq+0xe4/0x35c)
[  121.124638] [] (__do_softirq) from [] 
(irq_exit+0xe8/0x150)
[  121.131895] [] (irq_exit) from [] 
(__handle_domain_irq+0x70/0xc4)
[  121.139666] [] (__handle_domain_irq) from [] 
(gic_handle_irq+0x58/0x9c)
[  121.147953] [] (gic_handle_irq) from [] 
(__irq_svc+0x6c/0x90)
[  121.155373] Exception stack(0xc1001ef8 to 0xc1001f40)

Sean Wang (2):
  net: ethernet: mediatek: fix inconsistency between TXD and the used
buffer
  net: ethernet: mediatek: fix inconsistency of port number carried in
TXD

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 31 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ---
 2 files changed, 26 insertions(+), 17 deletions(-)

-- 
1.9.1



[PATCH net-next] net: ethernet: mediatek: enhance TX path with recycling more SKBs in one poll

2017-04-11 Thread sean.wang
From: Sean Wang 

The patch adds the enhancement for recycling more TX completed SKBs in
one NAPI polling handler if NAPI budgets are still available and hardware
raises status bit shown for certain SKBs are aready done.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 14e1bd1..ac8f1b9 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1074,10 +1074,13 @@ static int mtk_napi_tx(struct napi_struct *napi, int 
budget)
struct mtk_eth *eth = container_of(napi, struct mtk_eth, tx_napi);
u32 status, mask;
int tx_done = 0;
+   int remain_budget = budget;
 
mtk_handle_status_irq(eth);
+
+poll_again:
mtk_w32(eth, MTK_TX_DONE_INT, MTK_QMTK_INT_STATUS);
-   tx_done = mtk_poll_tx(eth, budget);
+   tx_done = mtk_poll_tx(eth, remain_budget);
 
if (unlikely(netif_msg_intr(eth))) {
status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
@@ -1087,17 +1090,19 @@ static int mtk_napi_tx(struct napi_struct *napi, int 
budget)
 tx_done, status, mask);
}
 
-   if (tx_done == budget)
+   if (tx_done == remain_budget)
return budget;
 
status = mtk_r32(eth, MTK_QMTK_INT_STATUS);
-   if (status & MTK_TX_DONE_INT)
-   return budget;
+   if (status & MTK_TX_DONE_INT) {
+   remain_budget -= tx_done;
+   goto poll_again;
+   }
 
napi_complete(napi);
mtk_irq_enable(eth, MTK_QDMA_INT_MASK, MTK_TX_DONE_INT);
 
-   return tx_done;
+   return tx_done + budget - remain_budget;
 }
 
 static int mtk_napi_rx(struct napi_struct *napi, int budget)
-- 
1.9.1



[PATCH net 2/2] net: ethernet: mediatek: fix inconsistency of port number carried in TXD

2017-04-11 Thread sean.wang
From: Sean Wang 

Fix port inconsistency on TXD due to hardware BUG that would cause
different port number is carried on the same TXD between tx_map()
and tx_unmap() with the iperf test. It would cause confusing BQL
logic which leads to kernel panic when dual GMAC runs concurrently.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 14 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 +---
 2 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 48ba617..502956c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -648,6 +648,8 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
 
WRITE_ONCE(itxd->txd1, mapped_addr);
itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
+   itx_buf->flags |= (!mac->id) ? BIT(MTK_TX_FLAGS_FPORT0) :
+ BIT(MTK_TX_FLAGS_FPORT1);
dma_unmap_addr_set(itx_buf, dma_addr0, mapped_addr);
dma_unmap_len_set(itx_buf, dma_len0, skb_headlen(skb));
 
@@ -689,6 +691,9 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
memset(tx_buf, 0, sizeof(*tx_buf));
tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
+   tx_buf->flags |= (!mac->id) ? BIT(MTK_TX_FLAGS_FPORT0) :
+BIT(MTK_TX_FLAGS_FPORT1);
+
dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
dma_unmap_len_set(tx_buf, dma_len0, frag_map_size);
frag_size -= frag_map_size;
@@ -1011,17 +1016,16 @@ static int mtk_poll_tx(struct mtk_eth *eth, int budget)
 
while ((cpu != dma) && budget) {
u32 next_cpu = desc->txd2;
-   int mac;
+   int mac = 0;
 
desc = mtk_qdma_phys_to_virt(ring, desc->txd2);
if ((desc->txd3 & TX_DMA_OWNER_CPU) == 0)
break;
 
-   mac = (desc->txd4 >> TX_DMA_FPORT_SHIFT) &
-  TX_DMA_FPORT_MASK;
-   mac--;
-
tx_buf = mtk_desc_to_tx_buf(ring, desc);
+   if (tx_buf->flags & BIT(MTK_TX_FLAGS_FPORT1))
+   mac = 1;
+
skb = tx_buf->skb;
if (!skb) {
condition = 1;
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 996024d..7327b23 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -410,12 +410,18 @@ struct mtk_hw_stats {
struct u64_stats_sync   syncp;
 };
 
-/* PDMA descriptor can point at 1-2 segments. This enum allows us to track how
- * memory was allocated so that it can be freed properly
- */
 enum mtk_tx_flags {
+   /* PDMA descriptor can point at 1-2 segments. This enum allows us to
+* track how memory was allocated so that it can be freed properly.
+*/
MTK_TX_FLAGS_SINGLE0= 0x01,
MTK_TX_FLAGS_PAGE0  = 0x02,
+
+   /* MTK_TX_FLAGS_FPORTx allows tracking which port the transmitted
+* SKB out instead of looking up through hardware TX descriptor.
+*/
+   MTK_TX_FLAGS_FPORT1 = 0x03,
+   MTK_TX_FLAGS_FPORT0 = 0x04,
 };
 
 /* This enum allows us to identify how the clock is defined on the array of the
-- 
1.9.1



[PATCH net 0/2] Fix crash caused by reporting inconsistent skb->len to BQL

2017-04-11 Thread sean.wang
From: Sean Wang 

The series fixes kernel BUG caused by inconsistent SKB length reported
into BQL. The reason for inconsistent length comes from hardware BUG which
results in different port number carried on the TXD within the lifecycle of
SKB. So patch 2) is proposed for use a software way to track which port
the SKB involving instead of hardware way. And patch 1) is given for another
issue I found which causes TXD and SKB inconsistency that is not expected
in the initial logic, so it is also being corrected it in the series.

The log for the kernel BUG caused by the issue is shown as below.

[  120.825955] kernel BUG at ... lib/dynamic_queue_limits.c:26!
[  120.837684] Internal error: Oops - BUG: 0 [#1] SMP ARM
[  120.842778] Modules linked in:
[  120.845811] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 
4.11.0-rc1-191576-gdbcef47 #35
[  120.853488] Hardware name: Mediatek Cortex-A7 (Device Tree)
[  120.859012] task: c1007480 task.stack: c100
[  120.863510] PC is at dql_completed+0x108/0x17c
[  120.867915] LR is at 0x46
[  120.870512] pc : []lr : [<0046>]psr: 8113
[  120.870512] sp : c1001d58  ip : c1001d80  fp : c1001d7c
[  120.881895] r10: 003e  r9 : df6b3400  r8 : 0ed86506
[  120.887075] r7 : 0001  r6 : 0001  r5 : 0ed8654c  r4 : df0135d8
[  120.893546] r3 : 0001  r2 : df016800  r1 : fece  r0 : df6b3480
[  120.900018] Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
[  120.907093] Control: 10c5387d  Table: 9e27806a  DAC: 0051
[  120.912789] Process swapper/0 (pid: 0, stack limit = 0xc1000218)
[  120.918744] Stack: (0xc1001d58 to 0xc1002000)



121.085331] 1fc0:  c0a52a28  c10855d4 c1003c58 c0a52a24 
c100885c 8000406a
[  121.093444] 1fe0: 410fc073   c1001ff8 8000807c c0a009cc 
 
[  121.101575] [] (dql_completed) from [] 
(mtk_napi_tx+0x1d0/0x37c)
[  121.109263] [] (mtk_napi_tx) from [] 
(net_rx_action+0x24c/0x3b8)
[  121.116951] [] (net_rx_action) from [] 
(__do_softirq+0xe4/0x35c)
[  121.124638] [] (__do_softirq) from [] 
(irq_exit+0xe8/0x150)
[  121.131895] [] (irq_exit) from [] 
(__handle_domain_irq+0x70/0xc4)
[  121.139666] [] (__handle_domain_irq) from [] 
(gic_handle_irq+0x58/0x9c)
[  121.147953] [] (gic_handle_irq) from [] 
(__irq_svc+0x6c/0x90)
[  121.155373] Exception stack(0xc1001ef8 to 0xc1001f40)

Sean Wang (2):
  net: ethernet: mediatek: fix inconsistency between TXD and the used
buffer
  net: ethernet: mediatek: fix inconsistency of port number carried in
TXD

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 31 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 12 ---
 2 files changed, 26 insertions(+), 17 deletions(-)

-- 
1.9.1



[PATCH net 1/2] net: ethernet: mediatek: fix inconsistency between TXD and the used buffer

2017-04-11 Thread sean.wang
From: Sean Wang 

Fix inconsistency between the TXD descriptor and the used buffer that
would cause unexpected logic at mtk_tx_unmap() during skb housekeeping.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 14e1bd1..48ba617 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -613,7 +613,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
struct mtk_tx_dma *itxd, *txd;
-   struct mtk_tx_buf *tx_buf;
+   struct mtk_tx_buf *itx_buf, *tx_buf;
dma_addr_t mapped_addr;
unsigned int nr_frags;
int i, n_desc = 1;
@@ -627,8 +627,8 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
fport = (mac->id + 1) << TX_DMA_FPORT_SHIFT;
txd4 |= fport;
 
-   tx_buf = mtk_desc_to_tx_buf(ring, itxd);
-   memset(tx_buf, 0, sizeof(*tx_buf));
+   itx_buf = mtk_desc_to_tx_buf(ring, itxd);
+   memset(itx_buf, 0, sizeof(*itx_buf));
 
if (gso)
txd4 |= TX_DMA_TSO;
@@ -647,9 +647,9 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
return -ENOMEM;
 
WRITE_ONCE(itxd->txd1, mapped_addr);
-   tx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
-   dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
-   dma_unmap_len_set(tx_buf, dma_len0, skb_headlen(skb));
+   itx_buf->flags |= MTK_TX_FLAGS_SINGLE0;
+   dma_unmap_addr_set(itx_buf, dma_addr0, mapped_addr);
+   dma_unmap_len_set(itx_buf, dma_len0, skb_headlen(skb));
 
/* TX SG offload */
txd = itxd;
@@ -685,10 +685,9 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
   last_frag * TX_DMA_LS0));
WRITE_ONCE(txd->txd4, fport);
 
-   tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf = mtk_desc_to_tx_buf(ring, txd);
memset(tx_buf, 0, sizeof(*tx_buf));
-
+   tx_buf->skb = (struct sk_buff *)MTK_DMA_DUMMY_DESC;
tx_buf->flags |= MTK_TX_FLAGS_PAGE0;
dma_unmap_addr_set(tx_buf, dma_addr0, mapped_addr);
dma_unmap_len_set(tx_buf, dma_len0, frag_map_size);
@@ -698,7 +697,7 @@ static int mtk_tx_map(struct sk_buff *skb, struct 
net_device *dev,
}
 
/* store skb to cleanup */
-   tx_buf->skb = skb;
+   itx_buf->skb = skb;
 
WRITE_ONCE(itxd->txd4, txd4);
WRITE_ONCE(itxd->txd3, (TX_DMA_SWC | TX_DMA_PLEN0(skb_headlen(skb)) |
-- 
1.9.1



[PATCH net-next v4 0/5] net-next: dsa: add Mediatek MT7530 support

2017-04-07 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N which includes 7-port
Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY. Among these ports,
The port from 0 to 4 are the user ports connecting with the remote devices
while the port 5 and 6 are the CPU ports connecting into Mediatek Ethernet
GMAC.

The patch series integrated Mediatek MT7530 into DSA support which
includes the most of the essential callbacks such as tag insertion for
port distinguishing, port control, bridge offloading, STP setup and
ethtool operations to allow DSA to model each user port into independently
standalone netdevice as the other DSA driver had done.

Changes since v1:
- rebased into 4.11-rc1
- refined binding document including below five items 
- changed the type of mediatek,mcm into bool
- used reset controller binding for MCM reset and removed "mediatek,ethsys"
  property from binding
- reused CPU port's ethernet Phandle instead of creating new one and removed
  "mediatek,ethernet" property from binding
- aligned naming for GPIO reset with dsa/marvell.txt
- added phy-mode as required property child nodes within ports container
- handled gpio reset with devm_gpiod_* API
- refined comment words
- removed condition for CDM setting since the setup looks both fine for all 
cases
- allowed of_find_net_device_by_node() working with pointing the device node 
into
  real netdev instance
- fixed Kbuild warnings

Changes since v2:
- reuse readx_poll_timeout() to poll
- add proper macro instead of hard coding
- treat inconsistent cpu port as warning
- remove the usage for regmap-debugfs
- show error message when invalid id is found
- put the logic for the setup of trgmii into adjut_link()
- refine and reuse logic between port_[disable,enable], and default port setup 
- correct typo

Changes since v3:
- used struct as the parameter for readx_poll_timeout() and kill 
  extra lpriv defined
- moved around function to get out of an additional declaration
- fixed kbuild errors caused by missing proper include in the latest tree

Sean Wang (5):
  dt-bindings: net: dsa: add Mediatek MT7530 binding
  net-next: dsa: add Mediatek tag RX/TX handler
  net-next: ethernet: mediatek: add CDM able to recognize the tag for
DSA
  net-next: ethernet: mediatek: add device_node of GMAC pointing into
the netdev instance
  net-next: dsa: add dsa support for Mediatek MT7530 switch

 .../devicetree/bindings/net/dsa/mt7530.txt |   92 ++
 drivers/net/dsa/Kconfig|8 +
 drivers/net/dsa/Makefile   |2 +-
 drivers/net/dsa/mt7530.c   | 1125 
 drivers/net/dsa/mt7530.h   |  402 +++
 drivers/net/ethernet/mediatek/mtk_eth_soc.c|8 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h|4 +
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|2 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |3 +
 net/dsa/tag_mtk.c  |  118 ++
 13 files changed, 1768 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h
 create mode 100644 net/dsa/tag_mtk.c

-- 
1.9.1



[PATCH net-next v4 3/5] net-next: ethernet: mediatek: add CDM able to recognize the tag for DSA

2017-04-07 Thread sean.wang
From: Sean Wang 

The patch adds the setup for allowing CDM can recognize these packets with
carrying port-distinguishing tag. Otherwise, these tagging packets will be
handled incorrectly by CDM. The setup is also working out for general
untag packets as well.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
Reviewed-by: Andrew Lunn 
Reviewed-by: Florian Fainelli 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 
 2 files changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 9e75768..c21ed99 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1846,6 +1846,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
/* GE2, Force 1000M/FD, FC ON */
mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1));
 
+   /* Indicates CDM to parse the MTK special tag from CPU
+* which also is working out for untag packets.
+*/
+   val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+   mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 99b1c8e..996024d 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -70,6 +70,10 @@
 /* Frame Engine Interrupt Grouping Register */
 #define MTK_FE_INT_GRP 0x20
 
+/* CDMP Ingress Control Register */
+#define MTK_CDMQ_IG_CTRL   0x1400
+#define MTK_CDMQ_STAG_EN   BIT(0)
+
 /* CDMP Exgress Control Register */
 #define MTK_CDMP_EG_CTRL   0x404
 
-- 
1.9.1



[PATCH net-next v4 2/5] net-next: dsa: add Mediatek tag RX/TX handler

2017-04-07 Thread sean.wang
From: Sean Wang 

Add the support for the 4-bytes tag for DSA port distinguishing inserted
allowing receiving and transmitting the packet via the particular port.
The tag is being added after the source MAC address in the ethernet
header.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
Reviewed-by: Andrew Lunn 
Reviewed-by: Florian Fainelli 
---
 include/net/dsa.h  |   1 +
 net/dsa/Kconfig|   2 +
 net/dsa/Makefile   |   1 +
 net/dsa/dsa.c  |   3 ++
 net/dsa/dsa_priv.h |   3 ++
 net/dsa/tag_mtk.c  | 118 +
 6 files changed, 128 insertions(+)
 create mode 100644 net/dsa/tag_mtk.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 4e13e69..3276547 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -31,6 +31,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
DSA_TAG_PROTO_QCA,
+   DSA_TAG_PROTO_MTK,
DSA_TAG_LAST,   /* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 9649238..d78789b 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -31,4 +31,6 @@ config NET_DSA_TAG_TRAILER
 config NET_DSA_TAG_QCA
bool
 
+config NET_DSA_TAG_MTK
+   bool
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 31d3437..9b1d478 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -8,3 +8,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
 dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
+dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index b6d4f6a..617f736 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -53,6 +53,9 @@ static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff 
*skb,
 #ifdef CONFIG_NET_DSA_TAG_QCA
[DSA_TAG_PROTO_QCA] = _netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_MTK
+   [DSA_TAG_PROTO_MTK] = _netdev_ops,
+#endif
[DSA_TAG_PROTO_NONE] = _ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 0706a51..2a31399 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -85,4 +85,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device 
*parent,
 /* tag_qca.c */
 extern const struct dsa_device_ops qca_netdev_ops;
 
+/* tag_mtk.c */
+extern const struct dsa_device_ops mtk_netdev_ops;
+
 #endif
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
new file mode 100644
index 000..44ae635
--- /dev/null
+++ b/net/dsa/tag_mtk.c
@@ -0,0 +1,118 @@
+/*
+ * Mediatek DSA Tag support
+ * Copyright (C) 2017 Landen Chao 
+ *   Sean Wang 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include "dsa_priv.h"
+
+#define MTK_HDR_LEN4
+#define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
+#define MTK_HDR_XMIT_DP_BIT_MASK   GENMASK(5, 0)
+
+static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+   struct net_device *dev)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   u8 *mtk_tag;
+
+   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+   goto out_free;
+
+   skb_push(skb, MTK_HDR_LEN);
+
+   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+
+   /* Build the tag after the MAC Source Address */
+   mtk_tag = skb->data + 2 * ETH_ALEN;
+   mtk_tag[0] = 0;
+   mtk_tag[1] = (1 << p->dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
+   mtk_tag[2] = 0;
+   mtk_tag[3] = 0;
+
+   return skb;
+
+out_free:
+   kfree_skb(skb);
+   return NULL;
+}
+
+static int mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+  struct packet_type *pt, struct net_device *orig_dev)
+{
+   struct dsa_switch_tree *dst = dev->dsa_ptr;
+   struct dsa_switch *ds;
+   int port;
+   __be16 *phdr, hdr;
+
+   if (unlikely(!dst))
+   goto out_drop;
+
+   skb = skb_unshare(skb, GFP_ATOMIC);
+   if (!skb)
+   goto out;
+
+   if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
+   goto out_drop;
+
+   /* The MTK header is added by the switch between src addr
+* and ethertype at this point, skb->data points to 2 bytes
+* after src addr so header should be 2 bytes right before.
+*/
+   phdr = (__be16 *)(skb->data - 2);
+   hdr = ntohs(*phdr);
+

[PATCH net-next v4 1/5] dt-bindings: net: dsa: add Mediatek MT7530 binding

2017-04-07 Thread sean.wang
From: Sean Wang 

Add device-tree binding for Mediatek MT7530 switch.

Cc: devicet...@vger.kernel.org
Signed-off-by: Sean Wang 
Acked-by: Rob Herring 
---
 .../devicetree/bindings/net/dsa/mt7530.txt | 92 ++
 1 file changed, 92 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/mt7530.txt 
b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
new file mode 100644
index 000..a9bc27b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
@@ -0,0 +1,92 @@
+Mediatek MT7530 Ethernet switch
+
+
+Required properties:
+
+- compatible: Must be compatible = "mediatek,mt7530";
+- #address-cells: Must be 1.
+- #size-cells: Must be 0.
+- mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part
+   on multi-chip module belong to MT7623A has or the remotely standalone
+   chip as the function MT7623N reference board provided for.
+- core-supply: Phandle to the regulator node necessary for the core power.
+- io-supply: Phandle to the regulator node necessary for the I/O power.
+   See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
+   for details for the regulator setup on these boards.
+
+If the property mediatek,mcm isn't defined, following property is required
+
+- reset-gpios: Should be a gpio specifier for a reset line.
+
+Else, following properties are required
+
+- resets : Phandle pointing to the system reset controller with
+   line index for the ethsys.
+- reset-names : Should be set to "mcm".
+
+Required properties for the child nodes within ports container:
+
+- reg: Port address described must be 6 for CPU port and from 0 to 5 for
+   user ports.
+- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled
+"cpu".
+
+See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+required, optional properties and how the integrated switch subnodes must
+be specified.
+
+Example:
+
+{
+   switch@0 {
+   compatible = "mediatek,mt7530";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+
+   core-supply = <_vpa_reg>;
+   io-supply = <_vemc3v3_reg>;
+   reset-gpios = < 33 0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+   port@0 {
+   reg = <0>;
+   label = "lan0";
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan1";
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "lan3";
+   };
+
+   port@4 {
+   reg = <4>;
+   label = "wan";
+   };
+
+   port@6 {
+   reg = <6>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "trgmii";
+   fixed-link {
+   speed = <1000>;
+   full-duplex;
+   };
+   };
+   };
+   };
+   };
-- 
1.9.1



[PATCH net-next v4 4/5] net-next: ethernet: mediatek: add device_node of GMAC pointing into the netdev instance

2017-04-07 Thread sean.wang
From: Sean Wang 

the patch adds the setup of the corresponding device node of GMAC into the
netdev instance which could allow other modules such as DSA to find the
instance through the node in dt-bindings using of_find_net_device_by_node()
call.

Signed-off-by: Sean Wang 
Reviewed-by: Andrew Lunn 
Reviewed-by: Florian Fainelli 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c21ed99..84b09a4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2323,6 +2323,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct 
device_node *np)
eth->netdev[id]->ethtool_ops = _ethtool_ops;
 
eth->netdev[id]->irq = eth->irq[0];
+   eth->netdev[id]->dev.of_node = np;
+
return 0;
 
 free_netdev:
-- 
1.9.1



[PATCH net-next v4 5/5] net-next: dsa: add dsa support for Mediatek MT7530 switch

2017-04-07 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N platform which
includes 7-port Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY.
Among these ports, The port from 0 to 4 are the user ports connecting
with the remote devices while the port 5 and 6 are the CPU ports
connecting into Mediatek Ethernet GMAC.

For port 6, it can communicate with the CPU via Mediatek Ethernet GMAC
through either the TRGMII or RGMII which could be controlled by phy-mode
in the dt-bindings to specify which mode is preferred to use. And for
port 5, only RGMII can be specified. However, currently, only port 6 is
being supported in this DSA driver.

The driver is made with the reference to qca8k and other existing DSA
driver. The most of the essential callbacks of the DSA are already
support in the driver, including tag insert for user port distinguishing,
port control, bridge offloading, STP setup and ethtool operation to allow
DSA to model each user port into a standalone netdevice as the other DSA
driver had done.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
---
 drivers/net/dsa/Kconfig  |8 +
 drivers/net/dsa/Makefile |2 +-
 drivers/net/dsa/mt7530.c | 1125 ++
 drivers/net/dsa/mt7530.h |  402 +
 4 files changed, 1536 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 0659846..5b322b4 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -34,4 +34,12 @@ config NET_DSA_QCA8K
  This enables support for the Qualcomm Atheros QCA8K Ethernet
  switch chips.
 
+config NET_DSA_MT7530
+   tristate "Mediatek MT7530 Ethernet switch support"
+   depends on NET_DSA
+   select NET_DSA_TAG_MTK
+   ---help---
+ This enables support for the Mediatek MT7530 Ethernet switch
+ chip.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index a3c9416..8e629c1 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -2,6 +2,6 @@ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)  += bcm-sf2.o
 bcm-sf2-objs   := bcm_sf2.o bcm_sf2_cfp.o
 obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
-
+obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
 obj-y  += b53/
 obj-y  += mv88e6xxx/
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
new file mode 100644
index 000..a4f3b0b
--- /dev/null
+++ b/drivers/net/dsa/mt7530.c
@@ -0,0 +1,1125 @@
+/*
+ * Mediatek MT7530 DSA Switch driver
+ * Copyright (C) 2017 Sean Wang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mt7530.h"
+
+/* String, offset, and register size in bytes if different from 4 bytes */
+static const struct mt7530_mib_desc mt7530_mib[] = {
+   MIB_DESC(1, 0x00, "TxDrop"),
+   MIB_DESC(1, 0x04, "TxCrcErr"),
+   MIB_DESC(1, 0x08, "TxUnicast"),
+   MIB_DESC(1, 0x0c, "TxMulticast"),
+   MIB_DESC(1, 0x10, "TxBroadcast"),
+   MIB_DESC(1, 0x14, "TxCollision"),
+   MIB_DESC(1, 0x18, "TxSingleCollision"),
+   MIB_DESC(1, 0x1c, "TxMultipleCollision"),
+   MIB_DESC(1, 0x20, "TxDeferred"),
+   MIB_DESC(1, 0x24, "TxLateCollision"),
+   MIB_DESC(1, 0x28, "TxExcessiveCollistion"),
+   MIB_DESC(1, 0x2c, "TxPause"),
+   MIB_DESC(1, 0x30, "TxPktSz64"),
+   MIB_DESC(1, 0x34, "TxPktSz65To127"),
+   MIB_DESC(1, 0x38, "TxPktSz128To255"),
+   MIB_DESC(1, 0x3c, "TxPktSz256To511"),
+   MIB_DESC(1, 0x40, "TxPktSz512To1023"),
+   MIB_DESC(1, 0x44, "Tx1024ToMax"),
+   MIB_DESC(2, 0x48, "TxBytes"),
+   MIB_DESC(1, 0x60, "RxDrop"),
+   MIB_DESC(1, 0x64, "RxFiltering"),
+   MIB_DESC(1, 0x6c, "RxMulticast"),
+   MIB_DESC(1, 0x70, "RxBroadcast"),
+   MIB_DESC(1, 0x74, "RxAlignErr"),
+   MIB_DESC(1, 0x78, "RxCrcErr"),
+   MIB_DESC(1, 0x7c, "RxUnderSizeErr"),
+   MIB_DESC(1, 0x80, "RxFragErr"),
+   MIB_DESC(1, 0x84, "RxOverSzErr"),
+   MIB_DESC(1, 0x88, "RxJabberErr"),
+   MIB_DESC(1, 0x8c, "RxPause"),
+   MIB_DESC(1, 0x90, "RxPktSz64"),

[PATCH net-next v3 3/5] net-next: ethernet: mediatek: add CDM able to recognize the tag for DSA

2017-03-29 Thread sean.wang
From: Sean Wang 

The patch adds the setup for allowing CDM can recognize these packets with
carrying port-distinguishing tag. Otherwise, these tagging packets will be
handled incorrectly by CDM. The setup is also working out for general
untag packets as well.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
Reviewed-by: Andrew Lunn 
Reviewed-by: Florian Fainelli 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 
 2 files changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 9e75768..c21ed99 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1846,6 +1846,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
/* GE2, Force 1000M/FD, FC ON */
mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1));
 
+   /* Indicates CDM to parse the MTK special tag from CPU
+* which also is working out for untag packets.
+*/
+   val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+   mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 99b1c8e..996024d 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -70,6 +70,10 @@
 /* Frame Engine Interrupt Grouping Register */
 #define MTK_FE_INT_GRP 0x20
 
+/* CDMP Ingress Control Register */
+#define MTK_CDMQ_IG_CTRL   0x1400
+#define MTK_CDMQ_STAG_EN   BIT(0)
+
 /* CDMP Exgress Control Register */
 #define MTK_CDMP_EG_CTRL   0x404
 
-- 
1.9.1



[PATCH net-next v3 2/5] net-next: dsa: add Mediatek tag RX/TX handler

2017-03-29 Thread sean.wang
From: Sean Wang 

Add the support for the 4-bytes tag for DSA port distinguishing inserted
allowing receiving and transmitting the packet via the particular port.
The tag is being added after the source MAC address in the ethernet
header.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
Reviewed-by: Andrew Lunn 
Reviewed-by: Florian Fainelli 
---
 include/net/dsa.h  |   1 +
 net/dsa/Kconfig|   2 +
 net/dsa/Makefile   |   1 +
 net/dsa/dsa.c  |   3 ++
 net/dsa/dsa_priv.h |   3 ++
 net/dsa/tag_mtk.c  | 117 +
 6 files changed, 127 insertions(+)
 create mode 100644 net/dsa/tag_mtk.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 4e13e69..3276547 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -31,6 +31,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
DSA_TAG_PROTO_QCA,
+   DSA_TAG_PROTO_MTK,
DSA_TAG_LAST,   /* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 9649238..d78789b 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -31,4 +31,6 @@ config NET_DSA_TAG_TRAILER
 config NET_DSA_TAG_QCA
bool
 
+config NET_DSA_TAG_MTK
+   bool
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 31d3437..9b1d478 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -8,3 +8,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
 dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
+dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index b6d4f6a..617f736 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -53,6 +53,9 @@ static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff 
*skb,
 #ifdef CONFIG_NET_DSA_TAG_QCA
[DSA_TAG_PROTO_QCA] = _netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_MTK
+   [DSA_TAG_PROTO_MTK] = _netdev_ops,
+#endif
[DSA_TAG_PROTO_NONE] = _ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 0706a51..2a31399 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -85,4 +85,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device 
*parent,
 /* tag_qca.c */
 extern const struct dsa_device_ops qca_netdev_ops;
 
+/* tag_mtk.c */
+extern const struct dsa_device_ops mtk_netdev_ops;
+
 #endif
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
new file mode 100644
index 000..833a9d6
--- /dev/null
+++ b/net/dsa/tag_mtk.c
@@ -0,0 +1,117 @@
+/*
+ * Mediatek DSA Tag support
+ * Copyright (C) 2017 Landen Chao 
+ *   Sean Wang 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include "dsa_priv.h"
+
+#define MTK_HDR_LEN4
+#define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
+#define MTK_HDR_XMIT_DP_BIT_MASK   GENMASK(5, 0)
+
+static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+   struct net_device *dev)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   u8 *mtk_tag;
+
+   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+   goto out_free;
+
+   skb_push(skb, MTK_HDR_LEN);
+
+   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+
+   /* Build the tag after the MAC Source Address */
+   mtk_tag = skb->data + 2 * ETH_ALEN;
+   mtk_tag[0] = 0;
+   mtk_tag[1] = (1 << p->dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
+   mtk_tag[2] = 0;
+   mtk_tag[3] = 0;
+
+   return skb;
+
+out_free:
+   kfree_skb(skb);
+   return NULL;
+}
+
+static int mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+  struct packet_type *pt, struct net_device *orig_dev)
+{
+   struct dsa_switch_tree *dst = dev->dsa_ptr;
+   struct dsa_switch *ds;
+   int port;
+   __be16 *phdr, hdr;
+
+   if (unlikely(!dst))
+   goto out_drop;
+
+   skb = skb_unshare(skb, GFP_ATOMIC);
+   if (!skb)
+   goto out;
+
+   if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
+   goto out_drop;
+
+   /* The MTK header is added by the switch between src addr
+* and ethertype at this point, skb->data points to 2 bytes
+* after src addr so header should be 2 bytes right before.
+*/
+   phdr = (__be16 *)(skb->data - 2);
+   hdr = ntohs(*phdr);
+
+   /* 

[PATCH net-next v3 4/5] net-next: ethernet: mediatek: add device_node of GMAC pointing into the netdev instance

2017-03-29 Thread sean.wang
From: Sean Wang 

the patch adds the setup of the corresponding device node of GMAC into the
netdev instance which could allow other modules such as DSA to find the
instance through the node in dt-bindings using of_find_net_device_by_node()
call.

Signed-off-by: Sean Wang 
Reviewed-by: Andrew Lunn 
Reviewed-by: Florian Fainelli 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c21ed99..84b09a4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2323,6 +2323,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct 
device_node *np)
eth->netdev[id]->ethtool_ops = _ethtool_ops;
 
eth->netdev[id]->irq = eth->irq[0];
+   eth->netdev[id]->dev.of_node = np;
+
return 0;
 
 free_netdev:
-- 
1.9.1



[PATCH net-next v3 5/5] net-next: dsa: add dsa support for Mediatek MT7530 switch

2017-03-29 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N platform which
includes 7-port Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY.
Among these ports, The port from 0 to 4 are the user ports connecting
with the remote devices while the port 5 and 6 are the CPU ports
connecting into Mediatek Ethernet GMAC.

For port 6, it can communicate with the CPU via Mediatek Ethernet GMAC
through either the TRGMII or RGMII which could be controlled by phy-mode
in the dt-bindings to specify which mode is preferred to use. And for
port 5, only RGMII can be specified. However, currently, only port 6 is
being supported in this DSA driver.

The driver is made with the reference to qca8k and other existing DSA
driver. The most of the essential callbacks of the DSA are already
support in the driver, including tag insert for user port distinguishing,
port control, bridge offloading, STP setup and ethtool operation to allow
DSA to model each user port into a standalone netdevice as the other DSA
driver had done.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
---
 drivers/net/dsa/Kconfig  |8 +
 drivers/net/dsa/Makefile |2 +-
 drivers/net/dsa/mt7530.c | 1126 ++
 drivers/net/dsa/mt7530.h |  390 
 4 files changed, 1525 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 0659846..5b322b4 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -34,4 +34,12 @@ config NET_DSA_QCA8K
  This enables support for the Qualcomm Atheros QCA8K Ethernet
  switch chips.
 
+config NET_DSA_MT7530
+   tristate "Mediatek MT7530 Ethernet switch support"
+   depends on NET_DSA
+   select NET_DSA_TAG_MTK
+   ---help---
+ This enables support for the Mediatek MT7530 Ethernet switch
+ chip.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index a3c9416..8e629c1 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -2,6 +2,6 @@ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)  += bcm-sf2.o
 bcm-sf2-objs   := bcm_sf2.o bcm_sf2_cfp.o
 obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
-
+obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
 obj-y  += b53/
 obj-y  += mv88e6xxx/
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
new file mode 100644
index 000..ad2e6f8
--- /dev/null
+++ b/drivers/net/dsa/mt7530.c
@@ -0,0 +1,1126 @@
+/*
+ * Mediatek MT7530 DSA Switch driver
+ * Copyright (C) 2017 Sean Wang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mt7530.h"
+
+/* String, offset, and register size in bytes if different from 4 bytes */
+static const struct mt7530_mib_desc mt7530_mib[] = {
+   MIB_DESC(1, 0x00, "TxDrop"),
+   MIB_DESC(1, 0x04, "TxCrcErr"),
+   MIB_DESC(1, 0x08, "TxUnicast"),
+   MIB_DESC(1, 0x0c, "TxMulticast"),
+   MIB_DESC(1, 0x10, "TxBroadcast"),
+   MIB_DESC(1, 0x14, "TxCollision"),
+   MIB_DESC(1, 0x18, "TxSingleCollision"),
+   MIB_DESC(1, 0x1c, "TxMultipleCollision"),
+   MIB_DESC(1, 0x20, "TxDeferred"),
+   MIB_DESC(1, 0x24, "TxLateCollision"),
+   MIB_DESC(1, 0x28, "TxExcessiveCollistion"),
+   MIB_DESC(1, 0x2c, "TxPause"),
+   MIB_DESC(1, 0x30, "TxPktSz64"),
+   MIB_DESC(1, 0x34, "TxPktSz65To127"),
+   MIB_DESC(1, 0x38, "TxPktSz128To255"),
+   MIB_DESC(1, 0x3c, "TxPktSz256To511"),
+   MIB_DESC(1, 0x40, "TxPktSz512To1023"),
+   MIB_DESC(1, 0x44, "Tx1024ToMax"),
+   MIB_DESC(2, 0x48, "TxBytes"),
+   MIB_DESC(1, 0x60, "RxDrop"),
+   MIB_DESC(1, 0x64, "RxFiltering"),
+   MIB_DESC(1, 0x6c, "RxMulticast"),
+   MIB_DESC(1, 0x70, "RxBroadcast"),
+   MIB_DESC(1, 0x74, "RxAlignErr"),
+   MIB_DESC(1, 0x78, "RxCrcErr"),
+   MIB_DESC(1, 0x7c, "RxUnderSizeErr"),
+   MIB_DESC(1, 0x80, "RxFragErr"),
+   MIB_DESC(1, 0x84, "RxOverSzErr"),
+   MIB_DESC(1, 0x88, "RxJabberErr"),
+   MIB_DESC(1, 0x8c, "RxPause"),
+   MIB_DESC(1, 0x90, "RxPktSz64"),
+ 

[PATCH net-next v3 1/5] dt-bindings: net: dsa: add Mediatek MT7530 binding

2017-03-29 Thread sean.wang
From: Sean Wang 

Add device-tree binding for Mediatek MT7530 switch.

Cc: devicet...@vger.kernel.org
Signed-off-by: Sean Wang 
Acked-by: Rob Herring 
---
 .../devicetree/bindings/net/dsa/mt7530.txt | 92 ++
 1 file changed, 92 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/mt7530.txt 
b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
new file mode 100644
index 000..a9bc27b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
@@ -0,0 +1,92 @@
+Mediatek MT7530 Ethernet switch
+
+
+Required properties:
+
+- compatible: Must be compatible = "mediatek,mt7530";
+- #address-cells: Must be 1.
+- #size-cells: Must be 0.
+- mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part
+   on multi-chip module belong to MT7623A has or the remotely standalone
+   chip as the function MT7623N reference board provided for.
+- core-supply: Phandle to the regulator node necessary for the core power.
+- io-supply: Phandle to the regulator node necessary for the I/O power.
+   See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
+   for details for the regulator setup on these boards.
+
+If the property mediatek,mcm isn't defined, following property is required
+
+- reset-gpios: Should be a gpio specifier for a reset line.
+
+Else, following properties are required
+
+- resets : Phandle pointing to the system reset controller with
+   line index for the ethsys.
+- reset-names : Should be set to "mcm".
+
+Required properties for the child nodes within ports container:
+
+- reg: Port address described must be 6 for CPU port and from 0 to 5 for
+   user ports.
+- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled
+"cpu".
+
+See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+required, optional properties and how the integrated switch subnodes must
+be specified.
+
+Example:
+
+{
+   switch@0 {
+   compatible = "mediatek,mt7530";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+
+   core-supply = <_vpa_reg>;
+   io-supply = <_vemc3v3_reg>;
+   reset-gpios = < 33 0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+   port@0 {
+   reg = <0>;
+   label = "lan0";
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan1";
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "lan3";
+   };
+
+   port@4 {
+   reg = <4>;
+   label = "wan";
+   };
+
+   port@6 {
+   reg = <6>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "trgmii";
+   fixed-link {
+   speed = <1000>;
+   full-duplex;
+   };
+   };
+   };
+   };
+   };
-- 
1.9.1



[PATCH net-next v3 0/5] net-next: dsa: add Mediatek MT7530 support

2017-03-29 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N which includes 7-port
Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY. Among these ports,
The port from 0 to 4 are the user ports connecting with the remote devices
while the port 5 and 6 are the CPU ports connecting into Mediatek Ethernet
GMAC.

The patch series integrated Mediatek MT7530 into DSA support which
includes the most of the essential callbacks such as tag insertion for
port distinguishing, port control, bridge offloading, STP setup and
ethtool operations to allow DSA to model each user port into independently
standalone netdevice as the other DSA driver had done.

Changes since v1:
- rebased into 4.11-rc1
- refined binding document including below five items 
- changed the type of mediatek,mcm into bool
- used reset controller binding for MCM reset and removed "mediatek,ethsys"
  property from binding
- reused CPU port's ethernet Phandle instead of creating new one and removed
  "mediatek,ethernet" property from binding
- aligned naming for GPIO reset with dsa/marvell.txt
- added phy-mode as required property child nodes within ports container
- handled gpio reset with devm_gpiod_* API
- refined comment words
- removed condition for CDM setting since the setup looks both fine for all 
cases
- allowed of_find_net_device_by_node() working with pointing the device node 
into
  real netdev instance
- fixed Kbuild warnings

Changes since v2:
- reuse readx_poll_timeout() to poll
- add proper macro instead of hard coding
- treat inconsistent cpu port as warning
- remove the usage for regmap-debugfs
- show error message when invalid id is found
- put the logic for the setup of trgmii into adjut_link()
- refine and reuse logic between port_[disable,enable], and default port setup 
- correct typo

Sean Wang (5):
  dt-bindings: net: dsa: add Mediatek MT7530 binding
  net-next: dsa: add Mediatek tag RX/TX handler
  net-next: ethernet: mediatek: add CDM able to recognize the tag for
DSA
  net-next: ethernet: mediatek: add device_node of GMAC pointing into
the netdev instance
  net-next: dsa: add dsa support for Mediatek MT7530 switch

 .../devicetree/bindings/net/dsa/mt7530.txt |   92 ++
 drivers/net/dsa/Kconfig|8 +
 drivers/net/dsa/Makefile   |2 +-
 drivers/net/dsa/mt7530.c   | 1126 
 drivers/net/dsa/mt7530.h   |  390 +++
 drivers/net/ethernet/mediatek/mtk_eth_soc.c|8 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h|4 +
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|2 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |3 +
 net/dsa/tag_mtk.c  |  117 ++
 13 files changed, 1756 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h
 create mode 100644 net/dsa/tag_mtk.c

-- 
1.9.1



[PATCH net-next v2 2/5] net-next: dsa: add Mediatek tag RX/TX handler

2017-03-21 Thread sean.wang
From: Sean Wang 

Add the support for the 4-bytes tag for DSA port distinguishing inserted
allowing receiving and transmitting the packet via the particular port.
The tag is being added after the source MAC address in the ethernet
header.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
Reviewed-by: Andrew Lunn 
Reviewed-by: Florian Fainelli 
---
 include/net/dsa.h  |   1 +
 net/dsa/Kconfig|   2 +
 net/dsa/Makefile   |   1 +
 net/dsa/dsa.c  |   3 ++
 net/dsa/dsa_priv.h |   3 ++
 net/dsa/tag_mtk.c  | 117 +
 6 files changed, 127 insertions(+)
 create mode 100644 net/dsa/tag_mtk.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 4e13e69..3276547 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -31,6 +31,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
DSA_TAG_PROTO_QCA,
+   DSA_TAG_PROTO_MTK,
DSA_TAG_LAST,   /* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 9649238..d78789b 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -31,4 +31,6 @@ config NET_DSA_TAG_TRAILER
 config NET_DSA_TAG_QCA
bool
 
+config NET_DSA_TAG_MTK
+   bool
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index 31d3437..9b1d478 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -8,3 +8,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
 dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
+dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index b6d4f6a..617f736 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -53,6 +53,9 @@ static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff 
*skb,
 #ifdef CONFIG_NET_DSA_TAG_QCA
[DSA_TAG_PROTO_QCA] = _netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_MTK
+   [DSA_TAG_PROTO_MTK] = _netdev_ops,
+#endif
[DSA_TAG_PROTO_NONE] = _ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 0706a51..2a31399 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -85,4 +85,7 @@ int dsa_slave_create(struct dsa_switch *ds, struct device 
*parent,
 /* tag_qca.c */
 extern const struct dsa_device_ops qca_netdev_ops;
 
+/* tag_mtk.c */
+extern const struct dsa_device_ops mtk_netdev_ops;
+
 #endif
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
new file mode 100644
index 000..833a9d6
--- /dev/null
+++ b/net/dsa/tag_mtk.c
@@ -0,0 +1,117 @@
+/*
+ * Mediatek DSA Tag support
+ * Copyright (C) 2017 Landen Chao 
+ *   Sean Wang 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include "dsa_priv.h"
+
+#define MTK_HDR_LEN4
+#define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
+#define MTK_HDR_XMIT_DP_BIT_MASK   GENMASK(5, 0)
+
+static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+   struct net_device *dev)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   u8 *mtk_tag;
+
+   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+   goto out_free;
+
+   skb_push(skb, MTK_HDR_LEN);
+
+   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+
+   /* Build the tag after the MAC Source Address */
+   mtk_tag = skb->data + 2 * ETH_ALEN;
+   mtk_tag[0] = 0;
+   mtk_tag[1] = (1 << p->dp->index) & MTK_HDR_XMIT_DP_BIT_MASK;
+   mtk_tag[2] = 0;
+   mtk_tag[3] = 0;
+
+   return skb;
+
+out_free:
+   kfree_skb(skb);
+   return NULL;
+}
+
+static int mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+  struct packet_type *pt, struct net_device *orig_dev)
+{
+   struct dsa_switch_tree *dst = dev->dsa_ptr;
+   struct dsa_switch *ds;
+   int port;
+   __be16 *phdr, hdr;
+
+   if (unlikely(!dst))
+   goto out_drop;
+
+   skb = skb_unshare(skb, GFP_ATOMIC);
+   if (!skb)
+   goto out;
+
+   if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
+   goto out_drop;
+
+   /* The MTK header is added by the switch between src addr
+* and ethertype at this point, skb->data points to 2 bytes
+* after src addr so header should be 2 bytes right before.
+*/
+   phdr = (__be16 *)(skb->data - 2);
+   hdr = ntohs(*phdr);
+
+   /* 

[PATCH net-next v2 3/5] net-next: ethernet: mediatek: add CDM able to recognize the tag for DSA

2017-03-21 Thread sean.wang
From: Sean Wang 

The patch adds the setup for allowing CDM can recognize these packets with
carrying port-distinguishing tag. Otherwise, these tagging packets will be
handled incorrectly by CDM. The setup is working out for general untag
packets as well.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 ++
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 4 
 2 files changed, 10 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 9e75768..c21ed99 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1846,6 +1846,12 @@ static int mtk_hw_init(struct mtk_eth *eth)
/* GE2, Force 1000M/FD, FC ON */
mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1));
 
+   /* Indicates CDM to parse the MTK special tag from CPU
+* which also is working out for untag packets.
+*/
+   val = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+   mtk_w32(eth, val | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 99b1c8e..996024d 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -70,6 +70,10 @@
 /* Frame Engine Interrupt Grouping Register */
 #define MTK_FE_INT_GRP 0x20
 
+/* CDMP Ingress Control Register */
+#define MTK_CDMQ_IG_CTRL   0x1400
+#define MTK_CDMQ_STAG_EN   BIT(0)
+
 /* CDMP Exgress Control Register */
 #define MTK_CDMP_EG_CTRL   0x404
 
-- 
1.9.1



[PATCH net-next v2 4/5] net-next: ethernet: mediatek: add device_node of GMAC pointing into the netdev instance

2017-03-21 Thread sean.wang
From: Sean Wang 

the patch adds the setup of the corresponding device node of GMAC into the
netdev instance which could allow other modules such as DSA to find the
instance through the node in dt-bindings using of_find_net_device_by_node()
call.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c21ed99..84b09a4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2323,6 +2323,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct 
device_node *np)
eth->netdev[id]->ethtool_ops = _ethtool_ops;
 
eth->netdev[id]->irq = eth->irq[0];
+   eth->netdev[id]->dev.of_node = np;
+
return 0;
 
 free_netdev:
-- 
1.9.1



[PATCH net-next v2 0/5] net-next: dsa: add Mediatek MT7530 support

2017-03-21 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N which includes 7-port
Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY. Among these ports,
The port from 0 to 4 are the user ports connecting with the remote devices
while the port 5 and 6 are the CPU ports connecting into Mediatek Ethernet
GMAC.

The patch series integrated Mediatek MT7530 into DSA support which
includes the most of the essential callbacks such as tag insertion for
port distinguishing, port control, bridge offloading, STP setup and
ethtool operations to allow DSA to model each user port into independently
standalone netdevice as the other DSA driver had done.

Changes since v1:
- rebased into 4.11-rc1
- refined binding document including below five items 
- changed the type of mediatek,mcm into bool
- used reset controller binding for MCM reset and removed "mediatek,ethsys"
  property from binding
- reused CPU port's ethernet Phandle instead of creating new one and removed
  "mediatek,ethernet" property from binding
- aligned naming for GPIO reset with dsa/marvell.txt
- added phy-mode as required property child nodes within ports container
- handled gpio reset with devm_gpiod_* API
- refined comment words
- removed condition for CDM setting since the setup looks both fine for all 
cases
- allowed of_find_net_device_by_node() working with pointing the device node 
into
  real netdev instance
- fixed Kbuild warnings

Sean Wang (5):
  dt-bindings: net: dsa: add Mediatek MT7530 binding
  net-next: dsa: add Mediatek tag RX/TX handler
  net-next: ethernet: mediatek: add CDM able to recognize the tag for
DSA
  net-next: ethernet: mediatek: add device_node of GMAC pointing into
the netdev instance
  net-next: dsa: add dsa support for Mediatek MT7530 switch

 .../devicetree/bindings/net/dsa/mt7530.txt |   92 ++
 drivers/net/dsa/Kconfig|8 +
 drivers/net/dsa/Makefile   |2 +-
 drivers/net/dsa/mt7530.c   | 1172 
 drivers/net/dsa/mt7530.h   |  382 +++
 drivers/net/ethernet/mediatek/mtk_eth_soc.c|8 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h|4 +
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|2 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |3 +
 net/dsa/tag_mtk.c  |  117 ++
 13 files changed, 1794 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h
 create mode 100644 net/dsa/tag_mtk.c

-- 
1.9.1



[PATCH net-next v2 5/5] net-next: dsa: add dsa support for Mediatek MT7530 switch

2017-03-21 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N platform which
includes 7-port Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY.
Among these ports, The port from 0 to 4 are the user ports connecting
with the remote devices while the port 5 and 6 are the CPU ports
connecting into Mediatek Ethernet GMAC.

For port 6, it can communicate with the CPU via Mediatek Ethernet GMAC
through either the TRGMII or RGMII which could be controlled by phy-mode
in the dt-bindings to specify which mode is preferred to use. And for
port 5, only RGMII can be specified. However, currently, only port 6 is
being supported in this DSA driver.

The driver is made with the reference to qca8k and other existing DSA
driver. The most of the essential callbacks of the DSA are already
support in the driver, including tag insert for user port distinguishing,
port control, bridge offloading, STP setup and ethtool operation to allow
DSA to model each user port into a standalone netdevice as the other DSA
driver had done.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
---
 drivers/net/dsa/Kconfig  |8 +
 drivers/net/dsa/Makefile |2 +-
 drivers/net/dsa/mt7530.c | 1172 ++
 drivers/net/dsa/mt7530.h |  382 +++
 4 files changed, 1563 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 0659846..5b322b4 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -34,4 +34,12 @@ config NET_DSA_QCA8K
  This enables support for the Qualcomm Atheros QCA8K Ethernet
  switch chips.
 
+config NET_DSA_MT7530
+   tristate "Mediatek MT7530 Ethernet switch support"
+   depends on NET_DSA
+   select NET_DSA_TAG_MTK
+   ---help---
+ This enables support for the Mediatek MT7530 Ethernet switch
+ chip.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index a3c9416..8e629c1 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -2,6 +2,6 @@ obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)  += bcm-sf2.o
 bcm-sf2-objs   := bcm_sf2.o bcm_sf2_cfp.o
 obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
-
+obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
 obj-y  += b53/
 obj-y  += mv88e6xxx/
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
new file mode 100644
index 000..99e5485
--- /dev/null
+++ b/drivers/net/dsa/mt7530.c
@@ -0,0 +1,1172 @@
+/*
+ * Mediatek MT7530 DSA Switch driver
+ * Copyright (C) 2017 Sean Wang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mt7530.h"
+
+/* String, offset, and register size in bytes if different from 4 bytes */
+static const struct mt7530_mib_desc mt7530_mib[] = {
+   MIB_DESC(1, 0x00, "TxDrop"),
+   MIB_DESC(1, 0x04, "TxCrcErr"),
+   MIB_DESC(1, 0x08, "TxUnicast"),
+   MIB_DESC(1, 0x0c, "TxMulticast"),
+   MIB_DESC(1, 0x10, "TxBroadcast"),
+   MIB_DESC(1, 0x14, "TxCollision"),
+   MIB_DESC(1, 0x18, "TxSingleCollision"),
+   MIB_DESC(1, 0x1c, "TxMultipleCollision"),
+   MIB_DESC(1, 0x20, "TxDeferred"),
+   MIB_DESC(1, 0x24, "TxLateCollision"),
+   MIB_DESC(1, 0x28, "TxExcessiveCollistion"),
+   MIB_DESC(1, 0x2c, "TxPause"),
+   MIB_DESC(1, 0x30, "TxPktSz64"),
+   MIB_DESC(1, 0x34, "TxPktSz65To127"),
+   MIB_DESC(1, 0x38, "TxPktSz128To255"),
+   MIB_DESC(1, 0x3c, "TxPktSz256To511"),
+   MIB_DESC(1, 0x40, "TxPktSz512To1023"),
+   MIB_DESC(1, 0x44, "Tx1024ToMax"),
+   MIB_DESC(2, 0x48, "TxBytes"),
+   MIB_DESC(1, 0x60, "RxDrop"),
+   MIB_DESC(1, 0x64, "RxFiltering"),
+   MIB_DESC(1, 0x6c, "RxMulticast"),
+   MIB_DESC(1, 0x70, "RxBroadcast"),
+   MIB_DESC(1, 0x74, "RxAlignErr"),
+   MIB_DESC(1, 0x78, "RxCrcErr"),
+   MIB_DESC(1, 0x7c, "RxUnderSizeErr"),
+   MIB_DESC(1, 0x80, "RxFragErr"),
+   MIB_DESC(1, 0x84, "RxOverSzErr"),
+   MIB_DESC(1, 0x88, "RxJabberErr"),
+   MIB_DESC(1, 0x8c, "RxPause"),
+   MIB_DESC(1, 0x90, "RxPktSz64"),
+   

[PATCH net-next v2 1/5] dt-bindings: net: dsa: add Mediatek MT7530 binding

2017-03-21 Thread sean.wang
From: Sean Wang 

Add device-tree binding for Mediatek MT7530 switch.

Cc: devicet...@vger.kernel.org
Signed-off-by: Sean Wang 
---
 .../devicetree/bindings/net/dsa/mt7530.txt | 92 ++
 1 file changed, 92 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/mt7530.txt 
b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
new file mode 100644
index 000..a9bc27b
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
@@ -0,0 +1,92 @@
+Mediatek MT7530 Ethernet switch
+
+
+Required properties:
+
+- compatible: Must be compatible = "mediatek,mt7530";
+- #address-cells: Must be 1.
+- #size-cells: Must be 0.
+- mediatek,mcm: Boolean; if defined, indicates that either MT7530 is the part
+   on multi-chip module belong to MT7623A has or the remotely standalone
+   chip as the function MT7623N reference board provided for.
+- core-supply: Phandle to the regulator node necessary for the core power.
+- io-supply: Phandle to the regulator node necessary for the I/O power.
+   See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
+   for details for the regulator setup on these boards.
+
+If the property mediatek,mcm isn't defined, following property is required
+
+- reset-gpios: Should be a gpio specifier for a reset line.
+
+Else, following properties are required
+
+- resets : Phandle pointing to the system reset controller with
+   line index for the ethsys.
+- reset-names : Should be set to "mcm".
+
+Required properties for the child nodes within ports container:
+
+- reg: Port address described must be 6 for CPU port and from 0 to 5 for
+   user ports.
+- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled
+"cpu".
+
+See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+required, optional properties and how the integrated switch subnodes must
+be specified.
+
+Example:
+
+{
+   switch@0 {
+   compatible = "mediatek,mt7530";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+
+   core-supply = <_vpa_reg>;
+   io-supply = <_vemc3v3_reg>;
+   reset-gpios = < 33 0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+   port@0 {
+   reg = <0>;
+   label = "lan0";
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan1";
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "lan3";
+   };
+
+   port@4 {
+   reg = <4>;
+   label = "wan";
+   };
+
+   port@6 {
+   reg = <6>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "trgmii";
+   fixed-link {
+   speed = <1000>;
+   full-duplex;
+   };
+   };
+   };
+   };
+   };
-- 
1.9.1



[PATCH net-next 4/4] net-next: dsa: add dsa support for Mediatek MT7530 switch

2017-03-13 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N platform which
includes 7-port Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY.
Among these ports, The port from 0 to 4 are the user ports connecting
with the remote devices while the port 5 and 6 are the CPU ports
connecting into Mediatek Ethernet GMAC.

For port 6, it can communicate with the CPU via Mediatek Ethernet GMAC
through either the TRGMII or RGMII which could be controlled by phy-mode
in the dt-bindings to specify which mode is preferred to use. And for
port 5, only RGMII can be specified. However, currently, only port 6 is
being supported in this DSA driver.

The driver is made with the reference to qca8k and other existing DSA
driver. The most of the essential callbacks of the DSA are already
support in the driver, including tag insert for user port distinguishing,
port control, bridge offloading, STP setup and ethtool operation to allow
DSA to model each user port into a standalone netdevice as the other DSA
driver had done.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
---
 drivers/net/dsa/Kconfig  |8 +
 drivers/net/dsa/Makefile |2 +-
 drivers/net/dsa/mt7530.c | 1195 ++
 drivers/net/dsa/mt7530.h |  387 +++
 4 files changed, 1591 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h

diff --git a/drivers/net/dsa/Kconfig b/drivers/net/dsa/Kconfig
index 0659846..5b322b4 100644
--- a/drivers/net/dsa/Kconfig
+++ b/drivers/net/dsa/Kconfig
@@ -34,4 +34,12 @@ config NET_DSA_QCA8K
  This enables support for the Qualcomm Atheros QCA8K Ethernet
  switch chips.
 
+config NET_DSA_MT7530
+   tristate "Mediatek MT7530 Ethernet switch support"
+   depends on NET_DSA
+   select NET_DSA_TAG_MTK
+   ---help---
+ This enables support for the Mediatek MT7530 Ethernet switch
+ chip.
+
 endmenu
diff --git a/drivers/net/dsa/Makefile b/drivers/net/dsa/Makefile
index 8346e4f..84e734e 100644
--- a/drivers/net/dsa/Makefile
+++ b/drivers/net/dsa/Makefile
@@ -1,6 +1,6 @@
 obj-$(CONFIG_NET_DSA_MV88E6060) += mv88e6060.o
 obj-$(CONFIG_NET_DSA_BCM_SF2)  += bcm_sf2.o
 obj-$(CONFIG_NET_DSA_QCA8K)+= qca8k.o
-
+obj-$(CONFIG_NET_DSA_MT7530) += mt7530.o
 obj-y  += b53/
 obj-y  += mv88e6xxx/
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
new file mode 100644
index 000..e316b9b
--- /dev/null
+++ b/drivers/net/dsa/mt7530.c
@@ -0,0 +1,1195 @@
+/*
+ * Mediatek MT7530 DSA Switch driver
+ * Copyright (C) 2017 Sean Wang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "mt7530.h"
+
+/* String, offset, and register size in bytes if different from 4 bytes */
+static const struct mt7530_mib_desc mt7530_mib[] = {
+   MIB_DESC(1, 0x00, "TxDrop"),
+   MIB_DESC(1, 0x04, "TxCrcErr"),
+   MIB_DESC(1, 0x08, "TxUnicast"),
+   MIB_DESC(1, 0x0c, "TxMulticast"),
+   MIB_DESC(1, 0x10, "TxBroadcast"),
+   MIB_DESC(1, 0x14, "TxCollision"),
+   MIB_DESC(1, 0x18, "TxSingleCollision"),
+   MIB_DESC(1, 0x1c, "TxMultipleCollision"),
+   MIB_DESC(1, 0x20, "TxDeferred"),
+   MIB_DESC(1, 0x24, "TxLateCollision"),
+   MIB_DESC(1, 0x28, "TxExcessiveCollistion"),
+   MIB_DESC(1, 0x2c, "TxPause"),
+   MIB_DESC(1, 0x30, "TxPktSz64"),
+   MIB_DESC(1, 0x34, "TxPktSz65To127"),
+   MIB_DESC(1, 0x38, "TxPktSz128To255"),
+   MIB_DESC(1, 0x3c, "TxPktSz256To511"),
+   MIB_DESC(1, 0x40, "TxPktSz512To1023"),
+   MIB_DESC(1, 0x44, "Tx1024ToMax"),
+   MIB_DESC(2, 0x48, "TxBytes"),
+   MIB_DESC(1, 0x60, "RxDrop"),
+   MIB_DESC(1, 0x64, "RxFiltering"),
+   MIB_DESC(1, 0x6c, "RxMulticast"),
+   MIB_DESC(1, 0x70, "RxBroadcast"),
+   MIB_DESC(1, 0x74, "RxAlignErr"),
+   MIB_DESC(1, 0x78, "RxCrcErr"),
+   MIB_DESC(1, 0x7c, "RxUnderSizeErr"),
+   MIB_DESC(1, 0x80, "RxFragErr"),
+   MIB_DESC(1, 0x84, "RxOverSzErr"),
+   MIB_DESC(1, 0x88, "RxJabberErr"),
+   MIB_DESC(1, 0x8c, "RxPause"),
+   MIB_DESC(1, 0x90, "RxPktSz64"),
+   MIB_DESC(1, 0x94, "RxPktSz65To127"),
+   MIB_DESC(1, 0x98, 

[PATCH net-next 2/4] net-next: dsa: add Mediatek tag RX/TX handler

2017-03-13 Thread sean.wang
From: Sean Wang 

Add the support for the 4-bytes tag for DSA port distinguishing inserted
allowing receiving and transmitting the packet via the particular port.
The tag is being added after the source MAC address in the ethernet
header.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
---
 include/net/dsa.h  |   1 +
 net/dsa/Kconfig|   2 +
 net/dsa/Makefile   |   1 +
 net/dsa/dsa.c  |   3 ++
 net/dsa/dsa_priv.h |   3 ++
 net/dsa/tag_mtk.c  | 121 +
 6 files changed, 131 insertions(+)
 create mode 100644 net/dsa/tag_mtk.c

diff --git a/include/net/dsa.h b/include/net/dsa.h
index b122196..954cff2 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -27,6 +27,7 @@ enum dsa_tag_protocol {
DSA_TAG_PROTO_EDSA,
DSA_TAG_PROTO_BRCM,
DSA_TAG_PROTO_QCA,
+   DSA_TAG_PROTO_MTK,
DSA_TAG_LAST,   /* MUST BE LAST */
 };
 
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig
index 96e47c5..43b67e8 100644
--- a/net/dsa/Kconfig
+++ b/net/dsa/Kconfig
@@ -41,4 +41,6 @@ config NET_DSA_TAG_TRAILER
 config NET_DSA_TAG_QCA
bool
 
+config NET_DSA_TAG_MTK
+   bool
 endif
diff --git a/net/dsa/Makefile b/net/dsa/Makefile
index a3380ed..97c9891 100644
--- a/net/dsa/Makefile
+++ b/net/dsa/Makefile
@@ -8,3 +8,4 @@ dsa_core-$(CONFIG_NET_DSA_TAG_DSA) += tag_dsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_EDSA) += tag_edsa.o
 dsa_core-$(CONFIG_NET_DSA_TAG_TRAILER) += tag_trailer.o
 dsa_core-$(CONFIG_NET_DSA_TAG_QCA) += tag_qca.o
+dsa_core-$(CONFIG_NET_DSA_TAG_MTK) += tag_mtk.o
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c
index 7899919..3586b1e 100644
--- a/net/dsa/dsa.c
+++ b/net/dsa/dsa.c
@@ -57,6 +57,9 @@ static struct sk_buff *dsa_slave_notag_xmit(struct sk_buff 
*skb,
 #ifdef CONFIG_NET_DSA_TAG_QCA
[DSA_TAG_PROTO_QCA] = _netdev_ops,
 #endif
+#ifdef CONFIG_NET_DSA_TAG_MTK
+   [DSA_TAG_PROTO_MTK] = _dsa_netdev_ops,
+#endif
[DSA_TAG_PROTO_NONE] = _ops,
 };
 
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 6cfd738..de61e8f 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -84,4 +84,7 @@ int dsa_slave_netdevice_event(struct notifier_block *unused,
 /* tag_qca.c */
 extern const struct dsa_device_ops qca_netdev_ops;
 
+/* tag_mtk.c */
+extern const struct dsa_device_ops mtk_dsa_netdev_ops;
+
 #endif
diff --git a/net/dsa/tag_mtk.c b/net/dsa/tag_mtk.c
new file mode 100644
index 000..a2dc014
--- /dev/null
+++ b/net/dsa/tag_mtk.c
@@ -0,0 +1,121 @@
+/*
+ * Mediatek DSA Tag support
+ * Copyright (C) 2017 Landen Chao 
+ *   Sean Wang 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include "dsa_priv.h"
+
+#define MTK_HDR_LEN4
+#define MTK_HDR_RECV_SOURCE_PORT_MASK  GENMASK(2, 0)
+#define MTK_HDR_XMIT_DP_BIT_MASK   GENMASK(5, 0)
+
+static struct sk_buff *mtk_tag_xmit(struct sk_buff *skb,
+   struct net_device *dev)
+{
+   struct dsa_slave_priv *p = netdev_priv(dev);
+   u8 *mtk_tag;
+
+   if (skb_cow_head(skb, MTK_HDR_LEN) < 0)
+   goto out_free;
+
+   skb_push(skb, MTK_HDR_LEN);
+
+   memmove(skb->data, skb->data + MTK_HDR_LEN, 2 * ETH_ALEN);
+
+   /* Build the tag after the MAC Source Address */
+   mtk_tag = skb->data + 2 * ETH_ALEN;
+
+   /* Set the ingress opcode, traffic class, tag enforcment is
+* deprecated
+*/
+   mtk_tag[0] = 0;
+   mtk_tag[1] = (1 << p->port) & MTK_HDR_XMIT_DP_BIT_MASK;
+   mtk_tag[2] = 0;
+   mtk_tag[3] = 0;
+
+   return skb;
+
+out_free:
+   kfree_skb(skb);
+   return NULL;
+}
+
+static int mtk_tag_rcv(struct sk_buff *skb, struct net_device *dev,
+  struct packet_type *pt, struct net_device *orig_dev)
+{
+   struct dsa_switch_tree *dst = dev->dsa_ptr;
+   struct dsa_switch *ds;
+   int port;
+   __be16 *phdr, hdr;
+
+   if (unlikely(!dst))
+   goto out_drop;
+
+   skb = skb_unshare(skb, GFP_ATOMIC);
+   if (!skb)
+   goto out;
+
+   if (unlikely(!pskb_may_pull(skb, MTK_HDR_LEN)))
+   goto out_drop;
+
+   /* The MTK header is added by the switch between src addr
+* and ethertype at this point, skb->data points to 2bytes
+* after src addr so header should be 2 bytes right before.
+*/
+   phdr = (__be16 *)(skb->data - 2);
+   hdr = ntohs(*phdr);
+
+  

[PATCH net-next 1/4] dt-bindings: net: dsa: add Mediatek MT7530 binding

2017-03-13 Thread sean.wang
From: Sean Wang 

Add device-tree binding for Mediatek MT7530 switch.

Cc: devicet...@vger.kernel.org
Signed-off-by: Sean Wang 
---
 .../devicetree/bindings/net/dsa/mt7530.txt | 94 ++
 1 file changed, 94 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt

diff --git a/Documentation/devicetree/bindings/net/dsa/mt7530.txt 
b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
new file mode 100644
index 000..0e50dbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
@@ -0,0 +1,94 @@
+Mediatek MT7530 Ethernet switch
+
+
+Required properties:
+
+- compatible: Must be compatible = "mediatek,mt7530";
+- #address-cells: Must be 1
+- #size-cells: Must be 0
+- mediatek,ethsys: Phandle to the syscon node that handles the reset.
+- mediatek,ethernet: Phandle to the syscon node that Mediatek ethernet driver
+   provides that handles the TRGMII setup used by the switch.
+   See
+   Documentation/devicetree/bindings/net/mediatek-net.txt for the detailed
+   setup on mediatek ethernet.
+- mediatek,mcm: String, should be "enabled" or "disabled" to indicate that
+   either MT7530 is the part on multi-chip module belong to MT7623A has
+   or the remotely standalone chip as the function MT7623N reference board
+   provided for.
+- core-supply: Phandle to the regulator node necessary for the core power.
+- io-supply: Phandle to the regulator node necessary for the I/O power
+   See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
+   for details for the regulator setup on these boards.
+- mediatek,reset-pin: Phandle to the pinctrl node used for the reset. Which
+   must be required if the property mediatek,mcm of specified as
+   "disabled". See
+   Documentation/devicetree/bindings/pinctrl/pinctrl-mt65xx.txt for
+   the mediatek pintcrl setting for the details.
+
+Each port children node within ports container must have the following
+mandatory properties:
+- reg  : Port address described must be 6 for CPU port
+   and from 0 to 5 for user ports.
+
+See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+required, optional properties and how the integrated switch subnodes must
+be specified.
+
+Example:
+
+{
+   switch@0 {
+   compatible = "mediatek,mt7530";
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+
+   mediatek,ethsys = <>;
+   mediatek,ethernet = <>;
+   mediatek,mcm = "enabled";
+   core-supply = <_vpa_reg>;
+   io-supply = <_vemc3v3_reg>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   reg = <0>;
+   port@0 {
+   reg = <0>;
+   label = "lan0";
+   };
+
+   port@1 {
+   reg = <1>;
+   label = "lan1";
+   };
+
+   port@2 {
+   reg = <2>;
+   label = "lan2";
+   };
+
+   port@3 {
+   reg = <3>;
+   label = "lan3";
+   };
+
+   port@4 {
+   reg = <4>;
+   label = "wan";
+   };
+
+   port@6 {
+   reg = <6>;
+   label = "cpu";
+   ethernet = <>;
+   phy-mode = "trgmii";
+   fixed-link {
+   speed = <1000>;
+   full-duplex;
+   };
+   };
+   };
+   };
+   };
-- 
1.9.1



[PATCH net-next 3/4] net-next: ethernet: mediatek: add CDM able to recognize the tag for DSA

2017-03-13 Thread sean.wang
From: Sean Wang 

Allowing CDM can recognize these packets with carrying port-distinguishing
tag when CONFIG_NET_DSA_TAG_MTK is enabled. Otherwise, these packets will
be dropped by CDM ingress.

Signed-off-by: Sean Wang 
Signed-off-by: Landen Chao 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 5 +
 2 files changed, 13 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 3dd8788..19944e0 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1848,6 +1848,14 @@ static int mtk_hw_init(struct mtk_eth *eth)
/* GE2, Force 1000M/FD, FC ON */
mtk_w32(eth, MAC_MCR_FIXED_LINK, MTK_MAC_MCR(1));
 
+#if defined(CONFIG_NET_DSA_TAG_MTK)
+   /* Tell CDMQ to parse the MTK special tag from CPU  */
+   /* QDMA Tx Use CDMQ */
+   u32 val2 = mtk_r32(eth, MTK_CDMQ_IG_CTRL);
+
+   mtk_w32(eth, val2 | MTK_CDMQ_STAG_EN, MTK_CDMQ_IG_CTRL);
+#endif
+
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 99b1c8e..79606db 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -70,11 +70,16 @@
 /* Frame Engine Interrupt Grouping Register */
 #define MTK_FE_INT_GRP 0x20
 
+/* CDMP Ingress Control Register */
+#define MTK_CDMQ_IG_CTRL   0x1400
+#define MTK_CDMQ_STAG_EN   BIT(0)
+
 /* CDMP Exgress Control Register */
 #define MTK_CDMP_EG_CTRL   0x404
 
 /* GDM Exgress Control Register */
 #define MTK_GDMA_FWD_CFG(x)(0x500 + (x * 0x1000))
+#define MTK_GDMA_STAG_EN   BIT(24)
 #define MTK_GDMA_ICS_ENBIT(22)
 #define MTK_GDMA_TCS_ENBIT(21)
 #define MTK_GDMA_UCS_ENBIT(20)
-- 
1.9.1



[PATCH net-next 0/4] net-next: dsa: add Mediatek MT7530 support

2017-03-13 Thread sean.wang
From: Sean Wang 

MT7530 is a 7-ports Gigabit Ethernet Switch that could be found on
Mediatek router platforms such as MT7623A or MT7623N which includes 7-port
Gigabit Ethernet MAC and 5-port Gigabit Ethernet PHY. Among these ports,
The port from 0 to 4 are the user ports connecting with the remote devices
while the port 5 and 6 are the CPU ports connecting into Mediatek Ethernet
GMAC.

The patch series integrated Mediatek MT7530 into DSA support which
includes the most of the essential callbacks such as tag insertion for
port distinguishing, port control, bridge offloading, STP setup and
ethtool operations to allow DSA to model each user port into independently
standalone netdevice as the other DSA driver had done.

Sean Wang (4):
  dt-bindings: net: dsa: add mt7530 binding
  net-next: dsa: add Mediatek tag RX/TX handler
  net-next: ethernet: mediatek: add CMD ingress recognize the special
tag
  net-next: dsa: add dsa support for Mediatek MT7530 switch

 .../devicetree/bindings/net/dsa/mt7530.txt |   96 ++
 drivers/net/dsa/Kconfig|8 +
 drivers/net/dsa/Makefile   |2 +-
 drivers/net/dsa/mt7530.c   | 1195 
 drivers/net/dsa/mt7530.h   |  387 +++
 drivers/net/ethernet/mediatek/mtk_eth_soc.c|8 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h|5 +
 include/net/dsa.h  |1 +
 net/dsa/Kconfig|2 +
 net/dsa/Makefile   |1 +
 net/dsa/dsa.c  |3 +
 net/dsa/dsa_priv.h |3 +
 net/dsa/tag_mtk.c  |  121 ++
 13 files changed, 1831 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/net/dsa/mt7530.txt
 create mode 100644 drivers/net/dsa/mt7530.c
 create mode 100644 drivers/net/dsa/mt7530.h
 create mode 100644 net/dsa/tag_mtk.c

-- 
1.9.1



[PATCH net-next] Documentation: devicetree: fix typo in MediaTek ethernet device-tree binding

2016-09-23 Thread sean.wang
From: Sean Wang 

fix typo in
Documentation/devicetree/bindings/net/mediatek-net.txt

Cc: devicet...@vger.kernel.org
Reported-by: Sergei Shtylyov 
Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/mediatek-net.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index 7111278..f095257 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -34,7 +34,7 @@ Required properties:
 - phy-handle: see ethernet.txt file in the same directory and
the phy-mode "trgmii" required being provided when reg
is equal to 0 and the MAC uses fixed-link to connect
-   with inernal switch such as MT7530.
+   with internal switch such as MT7530.
 
 Example:
 
-- 
1.9.1



[PATCH net-next v2] Documentation: devicetree: revise ethernet device-tree binding about TRGMII

2016-09-23 Thread sean.wang
From: Sean Wang 

add phy-mode "trgmii" to
Documentation/devicetree/bindings/net/ethernet.txt

Cc: devicet...@vger.kernel.org
Reported-by: Sergei Shtylyov 
Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/ethernet.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/ethernet.txt 
b/Documentation/devicetree/bindings/net/ethernet.txt
index 5d88f37..e1d7681 100644
--- a/Documentation/devicetree/bindings/net/ethernet.txt
+++ b/Documentation/devicetree/bindings/net/ethernet.txt
@@ -11,8 +11,8 @@ The following properties are common to the Ethernet 
controllers:
   the maximum frame size (there's contradiction in ePAPR).
 - phy-mode: string, operation mode of the PHY interface; supported values are
   "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", 
"rgmii-id",
-  "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto
-  standard property;
+  "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii", "trgmii"; this is now a
+  de-facto standard property;
 - phy-connection-type: the same as "phy-mode" property but described in ePAPR;
 - phy-handle: phandle, specifies a reference to a node representing a PHY
   device; this property is described in ePAPR and so preferred;
-- 
1.9.1



[PATCH net-next] Documentation: devicetree: revise ethernet device-tree binding about TRGMII

2016-09-22 Thread sean.wang
From: Sean Wang 

fix typo in mediatek-net.txt and add phy-mode "trgmii" to ethernet.txt

Cc: devicet...@vger.kernel.org
Reported-by: Sergei Shtylyov 
Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/ethernet.txt | 4 ++--
 Documentation/devicetree/bindings/net/mediatek-net.txt | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/ethernet.txt 
b/Documentation/devicetree/bindings/net/ethernet.txt
index 5d88f37..e1d7681 100644
--- a/Documentation/devicetree/bindings/net/ethernet.txt
+++ b/Documentation/devicetree/bindings/net/ethernet.txt
@@ -11,8 +11,8 @@ The following properties are common to the Ethernet 
controllers:
   the maximum frame size (there's contradiction in ePAPR).
 - phy-mode: string, operation mode of the PHY interface; supported values are
   "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", 
"rgmii-id",
-  "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto
-  standard property;
+  "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii", "trgmii"; this is now a
+  de-facto standard property;
 - phy-connection-type: the same as "phy-mode" property but described in ePAPR;
 - phy-handle: phandle, specifies a reference to a node representing a PHY
   device; this property is described in ePAPR and so preferred;
diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index bae848e..da05f8b 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -34,7 +34,7 @@ Required properties:
 - phy-handle: see ethernet.txt file in the same directory and
the phy-mode "trgmii" required being provided when reg
is equal to 0 and the MAC uses fixed-link to connect
-   with inernal switch such as MT7530.
+   with internal switch such as MT7530.
 
 Example:
 
-- 
1.9.1



[PATCH net-next] net: ethernet: mediatek: get out of potential invalid pointer access

2016-09-22 Thread sean.wang
From: Sean Wang 

Potential dangerous invalid pointer might be accessed if
the error happens when couple phy_device to net_device so
cleanup the error path.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a65801a..3d7e0cb 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -296,7 +296,9 @@ static int mtk_phy_connect(struct net_device *dev)
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
 
/* couple phydev to net_device */
-   mtk_phy_connect_node(eth, mac, np);
+   if (mtk_phy_connect_node(eth, mac, np))
+   goto err_phy;
+
dev->phydev->autoneg = AUTONEG_ENABLE;
dev->phydev->speed = 0;
dev->phydev->duplex = 0;
@@ -317,7 +319,7 @@ static int mtk_phy_connect(struct net_device *dev)
 
 err_phy:
of_node_put(np);
-   dev_err(eth->dev, "invalid phy_mode\n");
+   dev_err(eth->dev, "%s: invalid phy\n", __func__);
return -EINVAL;
 }
 
-- 
1.9.1



[PATCH net-next] net: ethernet: mediatek: use [get|set]_link_ksettings

2016-09-22 Thread sean.wang
From: Sean Wang 

1) use new api [get|set]_link_ksettings instead
of [get|set]_settings old ones.

2) dev->phydev is sure being ready before calling
these callbacks, so removing all the sanity check
if it is existing.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 33 +++--
 1 file changed, 12 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 1918c39..a65801a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2034,35 +2034,26 @@ static int mtk_cleanup(struct mtk_eth *eth)
return 0;
 }
 
-static int mtk_get_settings(struct net_device *dev,
-   struct ethtool_cmd *cmd)
+int mtk_get_link_ksettings(struct net_device *ndev,
+  struct ethtool_link_ksettings *cmd)
 {
-   struct mtk_mac *mac = netdev_priv(dev);
-   int err;
+   struct mtk_mac *mac = netdev_priv(ndev);
 
if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
return -EBUSY;
 
-   err = phy_read_status(dev->phydev);
-   if (err)
-   return -ENODEV;
-
-   return phy_ethtool_gset(dev->phydev, cmd);
+   return phy_ethtool_ksettings_get(ndev->phydev, cmd);
 }
 
-static int mtk_set_settings(struct net_device *dev,
-   struct ethtool_cmd *cmd)
+int mtk_set_link_ksettings(struct net_device *ndev,
+  const struct ethtool_link_ksettings *cmd)
 {
-   struct mtk_mac *mac = netdev_priv(dev);
+   struct mtk_mac *mac = netdev_priv(ndev);
 
-   if (cmd->phy_address != dev->phydev->mdio.addr) {
-   dev->phydev = mdiobus_get_phy(mac->hw->mii_bus,
-  cmd->phy_address);
-   if (!dev->phydev)
-   return -ENODEV;
-   }
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
 
-   return phy_ethtool_sset(dev->phydev, cmd);
+   return phy_ethtool_ksettings_set(ndev->phydev, cmd);
 }
 
 static void mtk_get_drvinfo(struct net_device *dev,
@@ -2225,8 +2216,8 @@ static int mtk_set_rxnfc(struct net_device *dev, struct 
ethtool_rxnfc *cmd)
 }
 
 static const struct ethtool_ops mtk_ethtool_ops = {
-   .get_settings   = mtk_get_settings,
-   .set_settings   = mtk_set_settings,
+   .get_link_ksettings = mtk_get_link_ksettings,
+   .set_link_ksettings = mtk_set_link_ksettings,
.get_drvinfo= mtk_get_drvinfo,
.get_msglevel   = mtk_get_msglevel,
.set_msglevel   = mtk_set_msglevel,
-- 
1.9.1



[PATCH net-next] net: ethernet: mediatek: remove superfluous local variable for phy address

2016-09-22 Thread sean.wang
From: Sean Wang 

remove the unused variable for parsing PHY address
and the related logic for sanity test which would
be all already handled done when of_mdiobus_register
was called

Reported-by: Nelson Chang 
Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 10 +-
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 6b7acf4..1918c39 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -226,17 +226,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
 static int mtk_phy_connect_node(struct mtk_eth *eth, struct mtk_mac *mac,
struct device_node *phy_node)
 {
-   const __be32 *_addr = NULL;
struct phy_device *phydev;
-   int phy_mode, addr;
+   int phy_mode;
 
-   _addr = of_get_property(phy_node, "reg", NULL);
-
-   if (!_addr || (be32_to_cpu(*_addr) >= 0x20)) {
-   pr_err("%s: invalid phy address\n", phy_node->name);
-   return -EINVAL;
-   }
-   addr = be32_to_cpu(*_addr);
phy_mode = of_get_phy_mode(phy_node);
if (phy_mode < 0) {
dev_err(eth->dev, "incorrect phy-mode %d\n", phy_mode);
-- 
1.9.1



[PATCH net-next] net: ethernet: mediatek: use phydev from struct net_device

2016-09-22 Thread sean.wang
From: Sean Wang 

reuse phydev already in struct net_device instead of creating
another new one in private structure.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 73 ++---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  2 -
 2 files changed, 36 insertions(+), 39 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ec60794..6b7acf4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -175,7 +175,7 @@ static void mtk_phy_link_adjust(struct net_device *dev)
if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
return;
 
-   switch (mac->phy_dev->speed) {
+   switch (dev->phydev->speed) {
case SPEED_1000:
mcr |= MAC_MCR_SPEED_1000;
break;
@@ -185,22 +185,22 @@ static void mtk_phy_link_adjust(struct net_device *dev)
};
 
if (mac->id == 0 && !mac->trgmii)
-   mtk_gmac0_rgmii_adjust(mac->hw, mac->phy_dev->speed);
+   mtk_gmac0_rgmii_adjust(mac->hw, dev->phydev->speed);
 
-   if (mac->phy_dev->link)
+   if (dev->phydev->link)
mcr |= MAC_MCR_FORCE_LINK;
 
-   if (mac->phy_dev->duplex) {
+   if (dev->phydev->duplex) {
mcr |= MAC_MCR_FORCE_DPX;
 
-   if (mac->phy_dev->pause)
+   if (dev->phydev->pause)
rmt_adv = LPA_PAUSE_CAP;
-   if (mac->phy_dev->asym_pause)
+   if (dev->phydev->asym_pause)
rmt_adv |= LPA_PAUSE_ASYM;
 
-   if (mac->phy_dev->advertising & ADVERTISED_Pause)
+   if (dev->phydev->advertising & ADVERTISED_Pause)
lcl_adv |= ADVERTISE_PAUSE_CAP;
-   if (mac->phy_dev->advertising & ADVERTISED_Asym_Pause)
+   if (dev->phydev->advertising & ADVERTISED_Asym_Pause)
lcl_adv |= ADVERTISE_PAUSE_ASYM;
 
flowctrl = mii_resolve_flowctrl_fdx(lcl_adv, rmt_adv);
@@ -217,7 +217,7 @@ static void mtk_phy_link_adjust(struct net_device *dev)
 
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
-   if (mac->phy_dev->link)
+   if (dev->phydev->link)
netif_carrier_on(dev);
else
netif_carrier_off(dev);
@@ -255,17 +255,17 @@ static int mtk_phy_connect_node(struct mtk_eth *eth, 
struct mtk_mac *mac,
 mac->id, phydev_name(phydev), phydev->phy_id,
 phydev->drv->name);
 
-   mac->phy_dev = phydev;
-
return 0;
 }
 
-static int mtk_phy_connect(struct mtk_mac *mac)
+static int mtk_phy_connect(struct net_device *dev)
 {
-   struct mtk_eth *eth = mac->hw;
+   struct mtk_mac *mac = netdev_priv(dev);
+   struct mtk_eth *eth;
struct device_node *np;
u32 val;
 
+   eth = mac->hw;
np = of_parse_phandle(mac->of_node, "phy-handle", 0);
if (!np && of_phy_is_fixed_link(mac->of_node))
if (!of_phy_register_fixed_link(mac->of_node))
@@ -303,20 +303,21 @@ static int mtk_phy_connect(struct mtk_mac *mac)
val |= SYSCFG0_GE_MODE(mac->ge_mode, mac->id);
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
 
+   /* couple phydev to net_device */
mtk_phy_connect_node(eth, mac, np);
-   mac->phy_dev->autoneg = AUTONEG_ENABLE;
-   mac->phy_dev->speed = 0;
-   mac->phy_dev->duplex = 0;
+   dev->phydev->autoneg = AUTONEG_ENABLE;
+   dev->phydev->speed = 0;
+   dev->phydev->duplex = 0;
 
if (of_phy_is_fixed_link(mac->of_node))
-   mac->phy_dev->supported |=
+   dev->phydev->supported |=
SUPPORTED_Pause | SUPPORTED_Asym_Pause;
 
-   mac->phy_dev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
+   dev->phydev->supported &= PHY_GBIT_FEATURES | SUPPORTED_Pause |
   SUPPORTED_Asym_Pause;
-   mac->phy_dev->advertising = mac->phy_dev->supported |
+   dev->phydev->advertising = dev->phydev->supported |
ADVERTISED_Autoneg;
-   phy_start_aneg(mac->phy_dev);
+   phy_start_aneg(dev->phydev);
 
of_node_put(np);
 
@@ -1742,7 +1743,7 @@ static int mtk_open(struct net_device *dev)
}
atomic_inc(>dma_refcnt);
 
-   phy_start(mac->phy_dev);
+   phy_start(dev->phydev);
netif_start_queue(dev);
 
return 0;
@@ -1777,7 +1778,7 @@ static int mtk_stop(struct net_device *dev)
struct mtk_eth *eth = mac->hw;
 
netif_tx_disable(dev);
-   phy_stop(mac->phy_dev);
+   phy_stop(dev->phydev);
 
/* only shutdown DMA if this is the last user */
if (!atomic_dec_and_test(>dma_refcnt))
@@ -1917,7 +1918,7 @@ static int __init mtk_init(struct net_device *dev)

[PATCH net-next v2 3/3] net: ethernet: mediatek: add the dts property to set if TRGMII supported on GMAC0

2016-09-21 Thread sean.wang
From: Sean Wang 

Add the dts property for the capability if TRGMII supported on GAMC0

Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/mediatek-net.txt | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index 6103e55..7111278 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -31,7 +31,10 @@ Optional properties:
 Required properties:
 - compatible: Should be "mediatek,eth-mac"
 - reg: The number of the MAC
-- phy-handle: see ethernet.txt file in the same directory.
+- phy-handle: see ethernet.txt file in the same directory and
+   the phy-mode "trgmii" required being provided when reg
+   is equal to 0 and the MAC uses fixed-link to connect
+   with inernal switch such as MT7530.
 
 Example:
 
-- 
1.9.1



[PATCH net-next v2 1/3] net: ethernet: mediatek: add extension of phy-mode for TRGMII

2016-09-21 Thread sean.wang
From: Sean Wang 

adds PHY-mode "trgmii" as an extension for the operation
mode of the PHY interface for PHY_INTERFACE_MODE_TRGMII.
and adds a variable trgmii inside mtk_mac as the indication
to make the difference between the MAC connected to internal
switch or connected to external PHY by the given configuration
on the board and then to perform the corresponding setup on
TRGMII hardware module.

Signed-off-by: Sean Wang 
Cc: Florian Fainelli 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 ++
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 3 +++
 include/linux/phy.h | 3 +++
 3 files changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ca6b501..827f4bd 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -244,6 +244,8 @@ static int mtk_phy_connect(struct mtk_mac *mac)
return -ENODEV;
 
switch (of_get_phy_mode(np)) {
+   case PHY_INTERFACE_MODE_TRGMII:
+   mac->trgmii = true;
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7c5e534..e3b9525 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -529,6 +529,8 @@ struct mtk_eth {
  * @hw:Backpointer to our main datastruture
  * @hw_stats:  Packet statistics counter
  * @phy_dev:   The attached PHY if available
+ * @trgmii Indicate if the MAC uses TRGMII connected to internal
+   switch
  */
 struct mtk_mac {
int id;
@@ -539,6 +541,7 @@ struct mtk_mac {
struct phy_device   *phy_dev;
__be32  hwlro_ip[MTK_MAX_LRO_IP_CNT];
int hwlro_ip_cnt;
+   booltrgmii;
 };
 
 /* the struct describing the SoC. these are declared in the soc_xyz.c files */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 2d24b28..e25f183 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -80,6 +80,7 @@ typedef enum {
PHY_INTERFACE_MODE_XGMII,
PHY_INTERFACE_MODE_MOCA,
PHY_INTERFACE_MODE_QSGMII,
+   PHY_INTERFACE_MODE_TRGMII,
PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
@@ -123,6 +124,8 @@ static inline const char *phy_modes(phy_interface_t 
interface)
return "moca";
case PHY_INTERFACE_MODE_QSGMII:
return "qsgmii";
+   case PHY_INTERFACE_MODE_TRGMII:
+   return "trgmii";
default:
return "unknown";
}
-- 
1.9.1



[PATCH net-next v2 2/3] net: ethernet: mediatek: add support for GMAC0 connecting with external PHY through TRGMII

2016-09-21 Thread sean.wang
From: Sean Wang 

Changing dynamically source clock, TX/RX delay and interface mode
used by TRGMII hardware module inside PHY capability polling routine
for adapting to the various speed of RGMII used by external PHY for
GMAC0.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 32 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 31 +++-
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 827f4bd..73c7904 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -52,7 +52,7 @@ static const struct mtk_ethtool_stats {
 };
 
 static const char * const mtk_clks_source_name[] = {
-   "ethif", "esw", "gp1", "gp2"
+   "ethif", "esw", "gp1", "gp2", "trgpll"
 };
 
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -135,6 +135,33 @@ static int mtk_mdio_read(struct mii_bus *bus, int 
phy_addr, int phy_reg)
return _mtk_mdio_read(eth, phy_addr, phy_reg);
 }
 
+static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, int speed)
+{
+   u32 val;
+   int ret;
+
+   val = (speed == SPEED_1000) ?
+   INTF_MODE_RGMII_1000 : INTF_MODE_RGMII_10_100;
+   mtk_w32(eth, val, INTF_MODE);
+
+   regmap_update_bits(eth->ethsys, ETHSYS_CLKCFG0,
+  ETHSYS_TRGMII_CLK_SEL362_5,
+  ETHSYS_TRGMII_CLK_SEL362_5);
+
+   val = (speed == SPEED_1000) ? 25000 : 5;
+   ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], val);
+   if (ret)
+   dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret);
+
+   val = (speed == SPEED_1000) ?
+   RCK_CTRL_RGMII_1000 : RCK_CTRL_RGMII_10_100;
+   mtk_w32(eth, val, TRGMII_RCK_CTRL);
+
+   val = (speed == SPEED_1000) ?
+   TCK_CTRL_RGMII_1000 : TCK_CTRL_RGMII_10_100;
+   mtk_w32(eth, val, TRGMII_TCK_CTRL);
+}
+
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
@@ -157,6 +184,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
break;
};
 
+   if (mac->id == 0 && !mac->trgmii)
+   mtk_gmac0_rgmii_adjust(mac->hw, mac->phy_dev->speed);
+
if (mac->phy_dev->link)
mcr |= MAC_MCR_FORCE_LINK;
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index e3b9525..e521156 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -313,6 +313,30 @@
 MAC_MCR_FORCE_TX_FC | MAC_MCR_SPEED_1000 | \
 MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_LINK)
 
+/* TRGMII RXC control register */
+#define TRGMII_RCK_CTRL0x10300
+#define DQSI0(x)   ((x << 0) & GENMASK(6, 0))
+#define DQSI1(x)   ((x << 8) & GENMASK(14, 8))
+#define RXCTL_DMWTLAT(x)   ((x << 16) & GENMASK(18, 16))
+#define RXC_DQSISELBIT(30)
+#define RCK_CTRL_RGMII_1000(RXC_DQSISEL | RXCTL_DMWTLAT(2) | DQSI1(16))
+#define RCK_CTRL_RGMII_10_100  RXCTL_DMWTLAT(2)
+
+/* TRGMII RXC control register */
+#define TRGMII_TCK_CTRL0x10340
+#define TXCTL_DMWTLAT(x)   ((x << 16) & GENMASK(18, 16))
+#define TXC_INVBIT(30)
+#define TCK_CTRL_RGMII_1000TXCTL_DMWTLAT(2)
+#define TCK_CTRL_RGMII_10_100  (TXC_INV | TXCTL_DMWTLAT(2))
+
+/* TRGMII Interface mode register */
+#define INTF_MODE  0x10390
+#define TRGMII_INTF_DISBIT(0)
+#define TRGMII_MODEBIT(1)
+#define TRGMII_CENTRAL_ALIGNED BIT(2)
+#define INTF_MODE_RGMII_1000(TRGMII_MODE | TRGMII_CENTRAL_ALIGNED)
+#define INTF_MODE_RGMII_10_100  0
+
 /* GPIO port control registers for GMAC 2*/
 #define GPIO_OD33_CTRL80x4c0
 #define GPIO_BIAS_CTRL 0xed0
@@ -323,7 +347,11 @@
 #define SYSCFG0_GE_MASK0x3
 #define SYSCFG0_GE_MODE(x, y)  (x << (12 + (y * 2)))
 
-/*ethernet reset control register*/
+/* ethernet subsystem clock register */
+#define ETHSYS_CLKCFG0 0x2c
+#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11)
+
+/* ethernet reset control register */
 #define ETHSYS_RSTCTRL 0x34
 #define RSTCTRL_FE BIT(6)
 #define RSTCTRL_PPEBIT(31)
@@ -389,6 +417,7 @@ enum mtk_clks_map {
MTK_CLK_ESW,
MTK_CLK_GP1,
MTK_CLK_GP2,
+   MTK_CLK_TRGPLL,
MTK_CLK_MAX
 };
 
-- 
1.9.1



[PATCH net-next v2 0/3] add support for RGMII on GMAC0 through TRGMII hardware module

2016-09-21 Thread sean.wang
From: Sean Wang 

By default, GMAC0 is connected to built-in switch called
MT7530 through the proprietary interface called Turbo RGMII
(TRGMII). TRGMII also supports well for RGMII as generic external
PHY uses but requires some slight changes to the setup of TRGMII 
and doesn't have well support on current driver.

So this patchset
1) provides the slight changes of the setup for RGMII can work
   through TRGMII
2) adds additional setting "trgmii" as PHY_INTERFACE_MODE_TRGMII 
   about phy-mode on device tree to make GMAC0 distinguish which
   mode it runs
3) changes dynamically source clock, TX/RX delay and interface
   mode on TRGMII for adapting various link

Changes since v1:
- fixed the style of comment which doesn't have a space at 
   the beginning and end of comment lines
- add support for phy-mode "trgmii" as PHY_INTERFACE_MODE_TRGMII 
   into linux/phy.h
- enhance the Documentation about device tree binding for trgmii
  which is applicable only for GMAC0 which uses fixed-link

Sean Wang (3):
  net: ethernet: mediatek: add extension of phy-mode for TRGMII
  net: ethernet: mediatek: add support for GMAC0 connecting with
external PHY through TRGMII
  net: ethernet: mediatek: add the dts property to set if TRGMII
supported on GMAC0

 .../devicetree/bindings/net/mediatek-net.txt   |  5 +++-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c| 34 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.h| 34 +-
 include/linux/phy.h|  3 ++
 4 files changed, 73 insertions(+), 3 deletions(-)

-- 
1.9.1



[PATCH net-next] net: ethernet: mediatek: fix missing changes merged for conflicts overlapping commits

2016-09-20 Thread sean.wang
From: Sean Wang 

add the missing commits about
1)
Commit d3bd1ce4db8e843dce421e2f8f123e5251a9c7d3
("remove redundant free_irq for devm_request_ir allocated irq")
2)
Commit 7c6b0d76fa02213393815e3b6d5e4a415bf3f0e2
("fix logic unbalance between probe and remove")

during merge for conflicts overlapping commits by
Commit b20b378d49926b82c0a131492fa8842156e0e8a9
("Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net")

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 609fd2b..b831a8b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1945,11 +1945,8 @@ static void mtk_uninit(struct net_device *dev)
struct mtk_eth *eth = mac->hw;
 
phy_disconnect(mac->phy_dev);
-   mtk_mdio_cleanup(eth);
mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
-   free_irq(eth->irq[1], dev);
-   free_irq(eth->irq[2], dev);
 }
 
 static int mtk_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -2505,6 +2502,7 @@ static int mtk_remove(struct platform_device *pdev)
netif_napi_del(>tx_napi);
netif_napi_del(>rx_napi);
mtk_cleanup(eth);
+   mtk_mdio_cleanup(eth);
 
return 0;
 }
-- 
1.9.1



[PATCH net-next 1/3] net: ethernet: mediatek: add extension of phy-mode for TRGMII

2016-09-20 Thread sean.wang
From: Sean Wang 

adds PHY-mode "trgmii" as an extension for the operation
mode of the PHY interface, TRGMII can be compatible with
RGMII, so the extended mode doesn't really have effects on
the target MAC and PHY, is used as the indication if the
current MAC is connected to an internal switch or external
PHY respectively by the given configuration on the board and
then to perform the corresponding setup on TRGMII hardware
module.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 24 ++--
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 +++
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ca6b501..a0e338b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -135,6 +135,26 @@ static int mtk_mdio_read(struct mii_bus *bus, int 
phy_addr, int phy_reg)
return _mtk_mdio_read(eth, phy_addr, phy_reg);
 }
 
+static int mtk_of_get_phy_mode(struct mtk_mac *mac, struct device_node *np)
+{
+   int phy_mode, err;
+   const char *pm;
+
+   phy_mode = of_get_phy_mode(np);
+
+   if (phy_mode >= 0)
+   return phy_mode;
+   err = of_property_read_string(np, "phy-mode", );
+   if (err < 0)
+   return err;
+   if (!strcasecmp(pm, "trgmii")) {
+   mac->trgmii = true;
+   /* TRGMII could be compatible with RGMII */
+   return PHY_INTERFACE_MODE_RGMII;
+   } else
+   return -ENODEV;
+}
+
 static void mtk_phy_link_adjust(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
@@ -207,7 +227,7 @@ static int mtk_phy_connect_node(struct mtk_eth *eth, struct 
mtk_mac *mac,
return -EINVAL;
}
addr = be32_to_cpu(*_addr);
-   phy_mode = of_get_phy_mode(phy_node);
+   phy_mode = mtk_of_get_phy_mode(mac, phy_node);
if (phy_mode < 0) {
dev_err(eth->dev, "incorrect phy-mode %d\n", phy_mode);
return -EINVAL;
@@ -243,7 +263,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
if (!np)
return -ENODEV;
 
-   switch (of_get_phy_mode(np)) {
+   switch (mtk_of_get_phy_mode(mac, np)) {
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7c5e534..e3b9525 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -529,6 +529,8 @@ struct mtk_eth {
  * @hw:Backpointer to our main datastruture
  * @hw_stats:  Packet statistics counter
  * @phy_dev:   The attached PHY if available
+ * @trgmii Indicate if the MAC uses TRGMII connected to internal
+   switch
  */
 struct mtk_mac {
int id;
@@ -539,6 +541,7 @@ struct mtk_mac {
struct phy_device   *phy_dev;
__be32  hwlro_ip[MTK_MAX_LRO_IP_CNT];
int hwlro_ip_cnt;
+   booltrgmii;
 };
 
 /* the struct describing the SoC. these are declared in the soc_xyz.c files */
-- 
1.9.1



[PATCH net-next 0/3] add support for RGMII on GMAC0 through TRGMII hardware module

2016-09-20 Thread sean.wang
From: Sean Wang 

By default, GMAC0 is connected to built-in switch called
MT7530 through the proprietary interface called Turbo RGMII
(TRGMII). TRGMII also supports well for RGMII as generic external
PHY uses but requires some slight changes to the setup of TRGMII 
and doesn't have well support on current driver.

So this patchset
1) provides the slight changes of the setup for RGMII can work
   through TRGMII
2) adds additional setting "trgmii" about phy-mode on device tree
   to make GMAC0 distinguish which mode it runs
3) changes dynamically source clock, TX/RX delay and interface
   mode on TRGMII for adapting various link

Sean Wang (3):
  net: ethernet: mediatek: add extension of phy-mode for TRGMII
  net: ethernet: mediatek: add support for GMAC0 connecting with
external PHY through TRGMII
  net: ethernet: mediatek: add the dts property to set if TRGMII
supported on GMAC0

 .../devicetree/bindings/net/mediatek-net.txt   |  5 +-
 drivers/net/ethernet/mediatek/mtk_eth_soc.c| 57 --
 drivers/net/ethernet/mediatek/mtk_eth_soc.h| 32 
 3 files changed, 90 insertions(+), 4 deletions(-)

-- 
1.9.1



[PATCH net-next 3/3] net: ethernet: mediatek: add the dts property to set if TRGMII supported on GMAC0

2016-09-20 Thread sean.wang
From: Sean Wang 

Add the dts property for the capability if TRGMII supported on GAMC0

Signed-off-by: Sean Wang 
---
 Documentation/devicetree/bindings/net/mediatek-net.txt | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt 
b/Documentation/devicetree/bindings/net/mediatek-net.txt
index 6103e55..32f79d8 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -31,7 +31,10 @@ Optional properties:
 Required properties:
 - compatible: Should be "mediatek,eth-mac"
 - reg: The number of the MAC
-- phy-handle: see ethernet.txt file in the same directory.
+- phy-handle: see ethernet.txt file in the same directory and
+   the additional phy-mode "tgrmii" is provided in order to connect
+   with the internal switch MT7530 which is only applicable when reg
+   is equal to 0.
 
 Example:
 
-- 
1.9.1



[PATCH net-next 2/3] net: ethernet: mediatek: add support for GMAC0 connecting with external PHY through TRGMII

2016-09-20 Thread sean.wang
From: Sean Wang 

Changing dynamically source clock, TX/RX delay and interface mode
used by TRGMII hardware module inside PHY capability polling routine
for adapting to the various speed of RGMII used by external PHY for
GMAC0.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 33 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h | 29 +
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a0e338b..609fd2b 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -52,7 +52,7 @@ static const struct mtk_ethtool_stats {
 };
 
 static const char * const mtk_clks_source_name[] = {
-   "ethif", "esw", "gp1", "gp2"
+   "ethif", "esw", "gp1", "gp2", "trgpll"
 };
 
 void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg)
@@ -135,6 +135,33 @@ static int mtk_mdio_read(struct mii_bus *bus, int 
phy_addr, int phy_reg)
return _mtk_mdio_read(eth, phy_addr, phy_reg);
 }
 
+static void mtk_gmac0_rgmii_adjust(struct mtk_eth *eth, int speed)
+{
+   u32 val;
+   int ret;
+
+   val = (speed == SPEED_1000) ?
+   INTF_MODE_RGMII_1000 : INTF_MODE_RGMII_10_100;
+   mtk_w32(eth, val, INTF_MODE);
+
+   regmap_update_bits(eth->ethsys, ETHSYS_CLKCFG0,
+  ETHSYS_TRGMII_CLK_SEL362_5,
+  ETHSYS_TRGMII_CLK_SEL362_5);
+
+   val = (speed == SPEED_1000) ? 25000 : 5;
+   ret = clk_set_rate(eth->clks[MTK_CLK_TRGPLL], val);
+   if (ret)
+   dev_err(eth->dev, "Failed to set trgmii pll: %d\n", ret);
+
+   val = (speed == SPEED_1000) ?
+   RCK_CTRL_RGMII_1000 : RCK_CTRL_RGMII_10_100;
+   mtk_w32(eth, val, TRGMII_RCK_CTRL);
+
+   val = (speed == SPEED_1000) ?
+   TCK_CTRL_RGMII_1000 : TCK_CTRL_RGMII_10_100;
+   mtk_w32(eth, val, TRGMII_TCK_CTRL);
+}
+
 static int mtk_of_get_phy_mode(struct mtk_mac *mac, struct device_node *np)
 {
int phy_mode, err;
@@ -149,6 +176,7 @@ static int mtk_of_get_phy_mode(struct mtk_mac *mac, struct 
device_node *np)
return err;
if (!strcasecmp(pm, "trgmii")) {
mac->trgmii = true;
+
/* TRGMII could be compatible with RGMII */
return PHY_INTERFACE_MODE_RGMII;
} else
@@ -177,6 +205,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
break;
};
 
+   if (mac->id == 0 && !mac->trgmii)
+   mtk_gmac0_rgmii_adjust(mac->hw, mac->phy_dev->speed);
+
if (mac->phy_dev->link)
mcr |= MAC_MCR_FORCE_LINK;
 
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index e3b9525..f1f44de 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -313,6 +313,30 @@
 MAC_MCR_FORCE_TX_FC | MAC_MCR_SPEED_1000 | \
 MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_LINK)
 
+/*TRGMII RXC control register*/
+#define TRGMII_RCK_CTRL0x10300
+#define DQSI0(x)   ((x << 0) & GENMASK(6, 0))
+#define DQSI1(x)   ((x << 8) & GENMASK(14, 8))
+#define RXCTL_DMWTLAT(x)   ((x << 16) & GENMASK(18, 16))
+#define RXC_DQSISELBIT(30)
+#define RCK_CTRL_RGMII_1000(RXC_DQSISEL | RXCTL_DMWTLAT(2) | DQSI1(16))
+#define RCK_CTRL_RGMII_10_100  RXCTL_DMWTLAT(2)
+
+/*TRGMII RXC control register*/
+#define TRGMII_TCK_CTRL0x10340
+#define TXCTL_DMWTLAT(x)   ((x << 16) & GENMASK(18, 16))
+#define TXC_INVBIT(30)
+#define TCK_CTRL_RGMII_1000TXCTL_DMWTLAT(2)
+#define TCK_CTRL_RGMII_10_100  (TXC_INV | TXCTL_DMWTLAT(2))
+
+/*TRGMII Interface mode register*/
+#define INTF_MODE  0x10390
+#define TRGMII_INTF_DISBIT(0)
+#define TRGMII_MODEBIT(1)
+#define TRGMII_CENTRAL_ALIGNED BIT(2)
+#define INTF_MODE_RGMII_1000(TRGMII_MODE | TRGMII_CENTRAL_ALIGNED)
+#define INTF_MODE_RGMII_10_100  0
+
 /* GPIO port control registers for GMAC 2*/
 #define GPIO_OD33_CTRL80x4c0
 #define GPIO_BIAS_CTRL 0xed0
@@ -323,6 +347,10 @@
 #define SYSCFG0_GE_MASK0x3
 #define SYSCFG0_GE_MODE(x, y)  (x << (12 + (y * 2)))
 
+/* ethernet subsystem clock register */
+#define ETHSYS_CLKCFG0 0x2c
+#define ETHSYS_TRGMII_CLK_SEL362_5 BIT(11)
+
 /*ethernet reset control register*/
 #define ETHSYS_RSTCTRL 0x34
 #define RSTCTRL_FE BIT(6)
@@ -389,6 +417,7 @@ enum mtk_clks_map {
MTK_CLK_ESW,
MTK_CLK_GP1,
MTK_CLK_GP2,
+   MTK_CLK_TRGPLL,
MTK_CLK_MAX
 };
 
-- 
1.9.1



[PATCH net-next] net: ethernet: mediatek: enhance with avoiding superfluous assignment inside mtk_get_ethtool_stats

2016-09-19 Thread sean.wang
From: Sean Wang 

data_src is unchanged inside the loop, so this patch moves
the assignment to outside the loop to avoid unnecessarily
assignment

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 481f360..ca6b501 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2137,8 +2137,9 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
}
}
 
+   data_src = (u64 *)hwstats;
+
do {
-   data_src = (u64 *)hwstats;
data_dst = data;
start = u64_stats_fetch_begin_irq(>syncp);
 
-- 
1.9.1



[PATCH net-next v2 3/7] net: ethernet: mediatek: cleanup error path inside mtk_hw_init

2016-09-14 Thread sean.wang
From: Sean Wang 

This cleans up the error path inside mtk_hw_init call, causing it able
to exit appropriately when something fails and also includes refactoring
mtk_cleanup call to make the partial logic reusable on the error path.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 -
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c71b0b3..917a49c6 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1564,17 +1564,36 @@ static void mtk_pending_work(struct work_struct *work)
rtnl_unlock();
 }
 
-static int mtk_cleanup(struct mtk_eth *eth)
+static int mtk_free_dev(struct mtk_eth *eth)
 {
int i;
 
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
continue;
+   free_netdev(eth->netdev[i]);
+   }
+
+   return 0;
+}
 
+static int mtk_unreg_dev(struct mtk_eth *eth)
+{
+   int i;
+
+   for (i = 0; i < MTK_MAC_COUNT; i++) {
+   if (!eth->netdev[i])
+   continue;
unregister_netdev(eth->netdev[i]);
-   free_netdev(eth->netdev[i]);
}
+
+   return 0;
+}
+
+static int mtk_cleanup(struct mtk_eth *eth)
+{
+   mtk_unreg_dev(eth);
+   mtk_free_dev(eth);
cancel_work_sync(>pending_work);
 
return 0;
@@ -1872,7 +1891,7 @@ static int mtk_probe(struct platform_device *pdev)
 
err = mtk_add_mac(eth, mac_np);
if (err)
-   goto err_free_dev;
+   goto err_deinit_hw;
}
 
err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
@@ -1896,7 +1915,7 @@ static int mtk_probe(struct platform_device *pdev)
err = register_netdev(eth->netdev[i]);
if (err) {
dev_err(eth->dev, "error bringing up device\n");
-   goto err_free_dev;
+   goto err_deinit_mdio;
} else
netif_info(eth, probe, eth->netdev[i],
   "mediatek frame engine at 0x%08lx, irq %d\n",
@@ -1916,8 +1935,13 @@ static int mtk_probe(struct platform_device *pdev)
 
return 0;
 
+err_deinit_mdio:
+   mtk_mdio_cleanup(eth);
 err_free_dev:
-   mtk_cleanup(eth);
+   mtk_free_dev(eth);
+err_deinit_hw:
+   mtk_hw_deinit(eth);
+
return err;
 }
 
-- 
1.9.1



[PATCH net-next v2 5/7] net: ethernet: mediatek: add the whole ethernet reset into the reset process

2016-09-14 Thread sean.wang
From: Sean Wang 

1) original driver only resets DMA used by descriptor rings
which can't guarantee it can recover all various kinds of fatal
errors, so the patch tries to reset the underlying hardware
resource from scratch on Mediatek SoC required for ethernet
running, including power, pin mux control, clock and internal
circuits on the ethernet in order to restore into the initial
state which the rebooted machine gives.

2) add state variable inside structure mtk_eth to help distinguish
mtk_hw_init is called between the initialization during boot time
or re-initialization during the reset process.

3) add ge_mode variable inside structure mtk_mac for restoring
the interface mode of the current setup for the target MAC.

4) remove __init attribute from mtk_hw_init definition

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 51 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  8 +
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index fd5d064..a7e2e77 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -231,7 +231,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
 {
struct mtk_eth *eth = mac->hw;
struct device_node *np;
-   u32 val, ge_mode;
+   u32 val;
 
np = of_parse_phandle(mac->of_node, "phy-handle", 0);
if (!np && of_phy_is_fixed_link(mac->of_node))
@@ -245,18 +245,18 @@ static int mtk_phy_connect(struct mtk_mac *mac)
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
-   ge_mode = 0;
+   mac->ge_mode = 0;
break;
case PHY_INTERFACE_MODE_MII:
-   ge_mode = 1;
+   mac->ge_mode = 1;
break;
case PHY_INTERFACE_MODE_REVMII:
-   ge_mode = 2;
+   mac->ge_mode = 2;
break;
case PHY_INTERFACE_MODE_RMII:
if (!mac->id)
goto err_phy;
-   ge_mode = 3;
+   mac->ge_mode = 3;
break;
default:
goto err_phy;
@@ -265,7 +265,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
/* put the gmac into the right mode */
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id);
-   val |= SYSCFG0_GE_MODE(ge_mode, mac->id);
+   val |= SYSCFG0_GE_MODE(mac->ge_mode, mac->id);
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
 
mtk_phy_connect_node(eth, mac, np);
@@ -1414,9 +1414,12 @@ static int mtk_stop(struct net_device *dev)
return 0;
 }
 
-static int __init mtk_hw_init(struct mtk_eth *eth)
+static int mtk_hw_init(struct mtk_eth *eth)
 {
-   int i;
+   int i, val;
+
+   if (test_and_set_bit(MTK_HW_INIT, >state))
+   return 0;
 
pm_runtime_enable(eth->dev);
pm_runtime_get_sync(eth->dev);
@@ -1432,6 +1435,15 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
reset_control_deassert(eth->rstc);
usleep_range(10, 20);
 
+   regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
+   for (i = 0; i < MTK_MAC_COUNT; i++) {
+   if (!eth->mac[i])
+   continue;
+   val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, eth->mac[i]->id);
+   val |= SYSCFG0_GE_MODE(eth->mac[i]->ge_mode, eth->mac[i]->id);
+   }
+   regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
+
/* Set GE2 driving and slew rate */
regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00);
 
@@ -1483,6 +1495,9 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
 
 static int mtk_hw_deinit(struct mtk_eth *eth)
 {
+   if (!test_and_clear_bit(MTK_HW_INIT, >state))
+   return 0;
+
clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
@@ -1557,6 +1572,26 @@ static void mtk_pending_work(struct work_struct *work)
__set_bit(i, );
}
 
+   /* restart underlying hardware such as power, clock, pin mux
+* and the connected phy
+*/
+   mtk_hw_deinit(eth);
+
+   if (eth->dev->pins)
+   pinctrl_select_state(eth->dev->pins->p,
+eth->dev->pins->default_state);
+   mtk_hw_init(eth);
+
+   for (i = 0; i < MTK_MAC_COUNT; i++) {
+   if (!eth->mac[i] ||
+   of_phy_is_fixed_link(eth->mac[i]->of_node))
+   continue;
+   err = phy_init_hw(eth->mac[i]->phy_dev);
+   if (err)
+   dev_err(eth->dev, "%s: PHY init failed.\n",
+   

[PATCH net-next v2 7/7] net: ethernet: mediatek: avoid race condition during the reset process

2016-09-14 Thread sean.wang
From: Sean Wang 

add the protection of the race condition between
the reset process and hardware access happening
on the related callbacks.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 ++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index cde9cd6..b46b08a 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -145,6 +145,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
  MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN |
  MAC_MCR_BACKPR_EN;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return;
+
switch (mac->phy_dev->speed) {
case SPEED_1000:
mcr |= MAC_MCR_SPEED_1000;
@@ -370,6 +373,9 @@ static int mtk_set_mac_address(struct net_device *dev, void 
*p)
if (ret)
return ret;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
spin_lock_bh(>hw->page_lock);
mtk_w32(mac->hw, (macaddr[0] << 8) | macaddr[1],
MTK_GDMA_MAC_ADRH(mac->id));
@@ -770,6 +776,9 @@ static int mtk_start_xmit(struct sk_buff *skb, struct 
net_device *dev)
 */
spin_lock(>page_lock);
 
+   if (unlikely(test_bit(MTK_RESETTING, >state)))
+   goto drop;
+
tx_num = mtk_cal_txd_req(skb);
if (unlikely(atomic_read(>free_count) <= tx_num)) {
mtk_stop_queue(eth);
@@ -842,6 +851,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 
netdev = eth->netdev[mac];
 
+   if (unlikely(test_bit(MTK_RESETTING, >state)))
+   goto release_desc;
+
/* alloc new buffer */
new_data = napi_alloc_frag(ring->frag_size);
if (unlikely(!new_data)) {
@@ -1573,6 +1585,12 @@ static void mtk_pending_work(struct work_struct *work)
 
rtnl_lock();
 
+   dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__);
+
+   while (test_and_set_bit_lock(MTK_RESETTING, >state))
+   cpu_relax();
+
+   dev_dbg(eth->dev, "[%s][%d] mtk_stop starts\n", __func__, __LINE__);
/* stop all devices to make sure that dma is properly shut down */
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
@@ -1580,6 +1598,7 @@ static void mtk_pending_work(struct work_struct *work)
mtk_stop(eth->netdev[i]);
__set_bit(i, );
}
+   dev_dbg(eth->dev, "[%s][%d] mtk_stop ends\n", __func__, __LINE__);
 
/* restart underlying hardware such as power, clock, pin mux
 * and the connected phy
@@ -1612,6 +1631,11 @@ static void mtk_pending_work(struct work_struct *work)
dev_close(eth->netdev[i]);
}
}
+
+   dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__);
+
+   clear_bit_unlock(MTK_RESETTING, >state);
+
rtnl_unlock();
 }
 
@@ -1656,6 +1680,9 @@ static int mtk_get_settings(struct net_device *dev,
struct mtk_mac *mac = netdev_priv(dev);
int err;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
err = phy_read_status(mac->phy_dev);
if (err)
return -ENODEV;
@@ -1706,6 +1733,9 @@ static int mtk_nway_reset(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
return genphy_restart_aneg(mac->phy_dev);
 }
 
@@ -1714,6 +1744,9 @@ static u32 mtk_get_link(struct net_device *dev)
struct mtk_mac *mac = netdev_priv(dev);
int err;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
err = genphy_update_link(mac->phy_dev);
if (err)
return ethtool_op_get_link(dev);
@@ -1754,6 +1787,9 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
unsigned int start;
int i;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return;
+
if (netif_running(dev) && netif_device_present(dev)) {
if (spin_trylock(>stats_lock)) {
mtk_stats_update_mac(mac);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7efa00f..79954b4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -336,7 +336,8 @@ enum mtk_clks_map {
 };
 
 enum mtk_dev_state {
-   MTK_HW_INIT
+   MTK_HW_INIT,
+   MTK_RESETTING
 };
 
 /* struct mtk_tx_buf - This struct holds the pointers to 

[PATCH net-next v2 2/7] net: ethernet: mediatek: add mtk_hw_deinit call as the opposite to mtk_hw_init call

2016-09-14 Thread sean.wang
From: Sean Wang 

grouping things related to the deinitialization of what
mtk_hw_init call does that help to be reused by the reset
process and the error path handling.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ca46e82..c71b0b3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1477,6 +1477,16 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
return 0;
 }
 
+static int mtk_hw_deinit(struct mtk_eth *eth)
+{
+   clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+   clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
+   clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
+   clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+
+   return 0;
+}
+
 static int __init mtk_init(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
@@ -1923,10 +1933,7 @@ static int mtk_remove(struct platform_device *pdev)
mtk_stop(eth->netdev[i]);
}
 
-   clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+   mtk_hw_deinit(eth);
 
netif_napi_del(>tx_napi);
netif_napi_del(>rx_napi);
-- 
1.9.1



[PATCH net-next v2 1/7] net: ethernet: mediatek: refactoring mtk_hw_init to be reused

2016-09-14 Thread sean.wang
From: Sean Wang 

the existing mtk_hw_init includes hardware and software
initialization inside so that it is slightly hard to reuse
them for the process of the reset recovery, so some splitting
is made here for keeping hardware initializing relevant thing
and the else such as IRQ registration and MDIO initialization
what are all about to the interface of core driver moved to the
other proper place because they have no needs to register IRQ and
re-initialize structure again during the reset process.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 62 -
 1 file changed, 34 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 66fd45a..ca46e82 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1415,7 +1415,12 @@ static int mtk_stop(struct net_device *dev)
 
 static int __init mtk_hw_init(struct mtk_eth *eth)
 {
-   int err, i;
+   int i;
+
+   clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
+   clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
+   clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
+   clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
 
/* reset the frame engine */
reset_control_assert(eth->rstc);
@@ -1441,19 +1446,6 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
-   err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
-  dev_name(eth->dev), eth);
-   if (err)
-   return err;
-   err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
-  dev_name(eth->dev), eth);
-   if (err)
-   return err;
-
-   err = mtk_mdio_init(eth);
-   if (err)
-   return err;
-
/* disable delay and normal interrupt */
mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
mtk_w32(eth, 0, MTK_PDMA_DELAY_INT);
@@ -1783,16 +1775,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct 
device_node *np)
eth->netdev[id]->features |= MTK_HW_FEATURES;
eth->netdev[id]->ethtool_ops = _ethtool_ops;
 
-   err = register_netdev(eth->netdev[id]);
-   if (err) {
-   dev_err(eth->dev, "error bringing up device\n");
-   goto free_netdev;
-   }
eth->netdev[id]->irq = eth->irq[0];
-   netif_info(eth, probe, eth->netdev[id],
-  "mediatek frame engine at 0x%08lx, irq %d\n",
-  eth->netdev[id]->base_addr, eth->irq[0]);
-
return 0;
 
 free_netdev:
@@ -1862,11 +1845,6 @@ static int mtk_probe(struct platform_device *pdev)
}
}
 
-   clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
-   clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
-
eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE);
INIT_WORK(>pending_work, mtk_pending_work);
 
@@ -1887,6 +1865,34 @@ static int mtk_probe(struct platform_device *pdev)
goto err_free_dev;
}
 
+   err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
+  dev_name(eth->dev), eth);
+   if (err)
+   goto err_free_dev;
+
+   err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
+  dev_name(eth->dev), eth);
+   if (err)
+   goto err_free_dev;
+
+   err = mtk_mdio_init(eth);
+   if (err)
+   goto err_free_dev;
+
+   for (i = 0; i < MTK_MAX_DEVS; i++) {
+   if (!eth->netdev[i])
+   continue;
+
+   err = register_netdev(eth->netdev[i]);
+   if (err) {
+   dev_err(eth->dev, "error bringing up device\n");
+   goto err_free_dev;
+   } else
+   netif_info(eth, probe, eth->netdev[i],
+  "mediatek frame engine at 0x%08lx, irq %d\n",
+  eth->netdev[i]->base_addr, eth->irq[0]);
+   }
+
/* we run 2 devices on the same DMA ring so we need a dummy device
 * for NAPI to work
 */
-- 
1.9.1



[PATCH net-next v2 6/7] net: ethernet: mediatek: add more resets for internal ethernet circuit block

2016-09-14 Thread sean.wang
From: Sean Wang 

struct mtk_eth has already contained struct regmap ethsys pointer
to the address range of the internal circuit reset, so we reuse it
to reset more internal blocks on ethernet hardware such as packet
processing engine (PPE) and frame engine (FE) instead of rstc which
deals with FE only.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 27 +++
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  6 +-
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a7e2e77..cde9cd6 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1414,6 +1414,19 @@ static int mtk_stop(struct net_device *dev)
return 0;
 }
 
+static void ethsys_reset(struct mtk_eth *eth, u32 reset_bits)
+{
+   regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL,
+  reset_bits,
+  reset_bits);
+
+   usleep_range(1000, 1100);
+   regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL,
+  reset_bits,
+  ~reset_bits);
+   mdelay(10);
+}
+
 static int mtk_hw_init(struct mtk_eth *eth)
 {
int i, val;
@@ -1428,12 +1441,8 @@ static int mtk_hw_init(struct mtk_eth *eth)
clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
-
-   /* reset the frame engine */
-   reset_control_assert(eth->rstc);
-   usleep_range(10, 20);
-   reset_control_deassert(eth->rstc);
-   usleep_range(10, 20);
+   ethsys_reset(eth, RSTCTRL_FE);
+   ethsys_reset(eth, RSTCTRL_PPE);
 
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
for (i = 0; i < MTK_MAC_COUNT; i++) {
@@ -1893,12 +1902,6 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->pctl);
}
 
-   eth->rstc = devm_reset_control_get(>dev, "eth");
-   if (IS_ERR(eth->rstc)) {
-   dev_err(>dev, "no eth reset found\n");
-   return PTR_ERR(eth->rstc);
-   }
-
for (i = 0; i < 3; i++) {
eth->irq[i] = platform_get_irq(pdev, i);
if (eth->irq[i] < 0) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 388cbe7..7efa00f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -266,6 +266,11 @@
 #define SYSCFG0_GE_MASK0x3
 #define SYSCFG0_GE_MODE(x, y)  (x << (12 + (y * 2)))
 
+/*ethernet reset control register*/
+#define ETHSYS_RSTCTRL 0x34
+#define RSTCTRL_FE BIT(6)
+#define RSTCTRL_PPEBIT(31)
+
 struct mtk_rx_dma {
unsigned int rxd1;
unsigned int rxd2;
@@ -423,7 +428,6 @@ struct mtk_rx_ring {
 struct mtk_eth {
struct device   *dev;
void __iomem*base;
-   struct reset_control*rstc;
spinlock_t  page_lock;
spinlock_t  irq_lock;
struct net_device   dummy_dev;
-- 
1.9.1



[PATCH net-next v2 4/7] net: ethernet: mediatek: add controlling power domain the ethernet belongs to

2016-09-14 Thread sean.wang
From: Sean Wang 

introduce power domain control which the digital circuit of
the ethernet belongs to inside the flow of hardware initialization
and deinitialization which helps the entire ethernet hardware block
could restart cleanly and completely as being back to the initial
state when the whole machine reboot.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 917a49c6..fd5d064 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1417,6 +1418,9 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
 {
int i;
 
+   pm_runtime_enable(eth->dev);
+   pm_runtime_get_sync(eth->dev);
+
clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
@@ -1484,6 +1488,9 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
 
+   pm_runtime_put_sync(eth->dev);
+   pm_runtime_disable(eth->dev);
+
return 0;
 }
 
-- 
1.9.1



[PATCH net-next v2 0/7] add enhancement into the existing reset flow

2016-09-14 Thread sean.wang
From: Sean Wang 

Current driver only resets DMA used by descriptor rings which
can't guarantee it can recover all various kinds of fatal
errors, so the patch
1) tries to reset the underlying hardware resource from scratch on
Mediatek SoC required for ethernet running.
2) refactors code in order to the reusability of existing code.
3) considers handling for race condition between the reset flow and
callbacks registered into core driver called about hardware accessing.
4) introduces power domain usage to hardware setup which leads to have
cleanly and completely restore to the state as the initial.

Changes since v1:
- fix the build error with module built causing undefined symbol for
  pinctrl_bind_pins, so using pinctrl_select_state instead accomplishes
  the pin mux setup during the reset process.

Sean Wang (7):
  net: ethernet: mediatek: refactoring mtk_hw_init to be reused
  net: ethernet: mediatek: add mtk_hw_deinit call as the opposite to
mtk_hw_init call
  net: ethernet: mediatek: cleanup error path inside mtk_hw_init
  net: ethernet: mediatek: add controlling power domain the ethernet
belongs to
  net: ethernet: mediatek: add the whole ethernet reset into the reset
process
  net: ethernet: mediatek: add more resets for internal ethernet circuit
block
  net: ethernet: mediatek: avoid race condition during the reset process

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 226 +---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  15 +-
 2 files changed, 186 insertions(+), 55 deletions(-)

-- 
1.9.1



[PATCH net] net: ethernet: mediatek: fix module loading automatically based on MODULE_DEVICE_TABLE

2016-09-14 Thread sean.wang
From: Sean Wang 

The device table is required to load modules based on
modaliases. After adding MODULE_DEVICE_TABLE, below entries
for example will be added to modules.alias:
alias of:N*T*Cmediatek,mt7623-ethC* mtk_eth_soc

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index a6a9a2f..b44ff3c 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -2053,6 +2053,7 @@ const struct of_device_id of_mtk_match[] = {
{ .compatible = "mediatek,mt7623-eth" },
{},
 };
+MODULE_DEVICE_TABLE(of, of_mtk_match);
 
 static struct platform_driver mtk_driver = {
.probe = mtk_probe,
-- 
1.9.1



[PATCH net-next 3/7] net: ethernet: mediatek: cleanup error path inside mtk_hw_init

2016-09-13 Thread sean.wang
From: Sean Wang 

This cleans up the error path inside mtk_hw_init call, causing it able
to exit appropriately when something fails and also includes refactoring
mtk_cleanup call to make the partial logic reusable on the error path.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 -
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index c71b0b3..917a49c6 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1564,17 +1564,36 @@ static void mtk_pending_work(struct work_struct *work)
rtnl_unlock();
 }
 
-static int mtk_cleanup(struct mtk_eth *eth)
+static int mtk_free_dev(struct mtk_eth *eth)
 {
int i;
 
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
continue;
+   free_netdev(eth->netdev[i]);
+   }
+
+   return 0;
+}
 
+static int mtk_unreg_dev(struct mtk_eth *eth)
+{
+   int i;
+
+   for (i = 0; i < MTK_MAC_COUNT; i++) {
+   if (!eth->netdev[i])
+   continue;
unregister_netdev(eth->netdev[i]);
-   free_netdev(eth->netdev[i]);
}
+
+   return 0;
+}
+
+static int mtk_cleanup(struct mtk_eth *eth)
+{
+   mtk_unreg_dev(eth);
+   mtk_free_dev(eth);
cancel_work_sync(>pending_work);
 
return 0;
@@ -1872,7 +1891,7 @@ static int mtk_probe(struct platform_device *pdev)
 
err = mtk_add_mac(eth, mac_np);
if (err)
-   goto err_free_dev;
+   goto err_deinit_hw;
}
 
err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
@@ -1896,7 +1915,7 @@ static int mtk_probe(struct platform_device *pdev)
err = register_netdev(eth->netdev[i]);
if (err) {
dev_err(eth->dev, "error bringing up device\n");
-   goto err_free_dev;
+   goto err_deinit_mdio;
} else
netif_info(eth, probe, eth->netdev[i],
   "mediatek frame engine at 0x%08lx, irq %d\n",
@@ -1916,8 +1935,13 @@ static int mtk_probe(struct platform_device *pdev)
 
return 0;
 
+err_deinit_mdio:
+   mtk_mdio_cleanup(eth);
 err_free_dev:
-   mtk_cleanup(eth);
+   mtk_free_dev(eth);
+err_deinit_hw:
+   mtk_hw_deinit(eth);
+
return err;
 }
 
-- 
1.9.1



[PATCH net-next 7/7] net: ethernet: mediatek: avoid race condition during the reset process

2016-09-13 Thread sean.wang
From: Sean Wang 

add the protection of the race condition between
the reset process and hardware access happening
on the related callbacks.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 36 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  3 ++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 48cddf9..a6a9a2f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -145,6 +145,9 @@ static void mtk_phy_link_adjust(struct net_device *dev)
  MAC_MCR_RX_EN | MAC_MCR_BACKOFF_EN |
  MAC_MCR_BACKPR_EN;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return;
+
switch (mac->phy_dev->speed) {
case SPEED_1000:
mcr |= MAC_MCR_SPEED_1000;
@@ -370,6 +373,9 @@ static int mtk_set_mac_address(struct net_device *dev, void 
*p)
if (ret)
return ret;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
spin_lock_bh(>hw->page_lock);
mtk_w32(mac->hw, (macaddr[0] << 8) | macaddr[1],
MTK_GDMA_MAC_ADRH(mac->id));
@@ -770,6 +776,9 @@ static int mtk_start_xmit(struct sk_buff *skb, struct 
net_device *dev)
 */
spin_lock(>page_lock);
 
+   if (unlikely(test_bit(MTK_RESETTING, >state)))
+   goto drop;
+
tx_num = mtk_cal_txd_req(skb);
if (unlikely(atomic_read(>free_count) <= tx_num)) {
mtk_stop_queue(eth);
@@ -842,6 +851,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
 
netdev = eth->netdev[mac];
 
+   if (unlikely(test_bit(MTK_RESETTING, >state)))
+   goto release_desc;
+
/* alloc new buffer */
new_data = napi_alloc_frag(ring->frag_size);
if (unlikely(!new_data)) {
@@ -1573,6 +1585,12 @@ static void mtk_pending_work(struct work_struct *work)
 
rtnl_lock();
 
+   dev_dbg(eth->dev, "[%s][%d] reset\n", __func__, __LINE__);
+
+   while (test_and_set_bit_lock(MTK_RESETTING, >state))
+   cpu_relax();
+
+   dev_dbg(eth->dev, "[%s][%d] mtk_stop starts\n", __func__, __LINE__);
/* stop all devices to make sure that dma is properly shut down */
for (i = 0; i < MTK_MAC_COUNT; i++) {
if (!eth->netdev[i])
@@ -1580,6 +1598,7 @@ static void mtk_pending_work(struct work_struct *work)
mtk_stop(eth->netdev[i]);
__set_bit(i, );
}
+   dev_dbg(eth->dev, "[%s][%d] mtk_stop ends\n", __func__, __LINE__);
 
/* restart underlying hardware such as power, clock, pin mux
 * and the connected phy
@@ -1613,6 +1632,11 @@ static void mtk_pending_work(struct work_struct *work)
dev_close(eth->netdev[i]);
}
}
+
+   dev_dbg(eth->dev, "[%s][%d] reset done\n", __func__, __LINE__);
+
+   clear_bit_unlock(MTK_RESETTING, >state);
+
rtnl_unlock();
 }
 
@@ -1657,6 +1681,9 @@ static int mtk_get_settings(struct net_device *dev,
struct mtk_mac *mac = netdev_priv(dev);
int err;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
err = phy_read_status(mac->phy_dev);
if (err)
return -ENODEV;
@@ -1707,6 +1734,9 @@ static int mtk_nway_reset(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
return genphy_restart_aneg(mac->phy_dev);
 }
 
@@ -1715,6 +1745,9 @@ static u32 mtk_get_link(struct net_device *dev)
struct mtk_mac *mac = netdev_priv(dev);
int err;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return -EBUSY;
+
err = genphy_update_link(mac->phy_dev);
if (err)
return ethtool_op_get_link(dev);
@@ -1755,6 +1788,9 @@ static void mtk_get_ethtool_stats(struct net_device *dev,
unsigned int start;
int i;
 
+   if (unlikely(test_bit(MTK_RESETTING, >hw->state)))
+   return;
+
if (netif_running(dev) && netif_device_present(dev)) {
if (spin_trylock(>stats_lock)) {
mtk_stats_update_mac(mac);
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 7efa00f..79954b4 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -336,7 +336,8 @@ enum mtk_clks_map {
 };
 
 enum mtk_dev_state {
-   MTK_HW_INIT
+   MTK_HW_INIT,
+   MTK_RESETTING
 };
 
 /* struct mtk_tx_buf - This struct holds the pointers to 

[PATCH net-next 0/7] add enhancement into the existing reset flow

2016-09-13 Thread sean.wang
From: Sean Wang 

Current driver only resets DMA used by descriptor rings which
can't guarantee it can recover all various kinds of fatal
errors, so the patch
1) tries to reset the underlying hardware resource from scratch on
Mediatek SoC required for ethernet running.
2) refactors code in order to the reusability of existing code.
3) considers handling for race condition between the reset flow and
callbacks registered into core driver called about hardware accessing.
4) introduces power domain usage to hardware setup which leads to have
cleanly and completely restore to the state as the initial.

Sean Wang (7):
  net: ethernet: mediatek: refactoring mtk_hw_init to be reused
  net: ethernet: mediatek: add mtk_hw_deinit call as the opposite to
mtk_hw_init call
  net: ethernet: mediatek: cleanup error path inside mtk_hw_init
  net: ethernet: mediatek: add controlling power domain the ethernet
belongs to
  net: ethernet: mediatek: add the whole ethernet reset into the reset
process
  net: ethernet: mediatek: add more resets for internal ethernet circuit
block
  net: ethernet: mediatek: avoid race condition during the reset process

 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 227 +---
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  15 +-
 2 files changed, 187 insertions(+), 55 deletions(-)

-- 
1.9.1



[PATCH net-next 2/7] net: ethernet: mediatek: add mtk_hw_deinit call as the opposite to mtk_hw_init call

2016-09-13 Thread sean.wang
From: Sean Wang 

grouping things related to the deinitialization of what
mtk_hw_init call does that help to be reused by the reset
process and the error path handling.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index ca46e82..c71b0b3 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1477,6 +1477,16 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
return 0;
 }
 
+static int mtk_hw_deinit(struct mtk_eth *eth)
+{
+   clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+   clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
+   clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
+   clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
+
+   return 0;
+}
+
 static int __init mtk_init(struct net_device *dev)
 {
struct mtk_mac *mac = netdev_priv(dev);
@@ -1923,10 +1933,7 @@ static int mtk_remove(struct platform_device *pdev)
mtk_stop(eth->netdev[i]);
}
 
-   clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
-   clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
+   mtk_hw_deinit(eth);
 
netif_napi_del(>tx_napi);
netif_napi_del(>rx_napi);
-- 
1.9.1



[PATCH net-next 6/7] net: ethernet: mediatek: add more resets for internal ethernet circuit block

2016-09-13 Thread sean.wang
From: Sean Wang 

struct mtk_eth has already contained struct regmap ethsys pointer
to the address range of the internal circuit reset, so we reuse it
to reset more internal blocks on ethernet hardware such as packet
processing engine (PPE) and frame engine (FE) instead of rstc which
deals with FE only.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 27 +++
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  6 +-
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index b9ddbcb..48cddf9 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1414,6 +1414,19 @@ static int mtk_stop(struct net_device *dev)
return 0;
 }
 
+static void ethsys_reset(struct mtk_eth *eth, u32 reset_bits)
+{
+   regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL,
+  reset_bits,
+  reset_bits);
+
+   usleep_range(1000, 1100);
+   regmap_update_bits(eth->ethsys, ETHSYS_RSTCTRL,
+  reset_bits,
+  ~reset_bits);
+   mdelay(10);
+}
+
 static int mtk_hw_init(struct mtk_eth *eth)
 {
int i, val;
@@ -1428,12 +1441,8 @@ static int mtk_hw_init(struct mtk_eth *eth)
clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
-
-   /* reset the frame engine */
-   reset_control_assert(eth->rstc);
-   usleep_range(10, 20);
-   reset_control_deassert(eth->rstc);
-   usleep_range(10, 20);
+   ethsys_reset(eth, RSTCTRL_FE);
+   ethsys_reset(eth, RSTCTRL_PPE);
 
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
for (i = 0; i < MTK_MAC_COUNT; i++) {
@@ -1894,12 +1903,6 @@ static int mtk_probe(struct platform_device *pdev)
return PTR_ERR(eth->pctl);
}
 
-   eth->rstc = devm_reset_control_get(>dev, "eth");
-   if (IS_ERR(eth->rstc)) {
-   dev_err(>dev, "no eth reset found\n");
-   return PTR_ERR(eth->rstc);
-   }
-
for (i = 0; i < 3; i++) {
eth->irq[i] = platform_get_irq(pdev, i);
if (eth->irq[i] < 0) {
diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.h 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index 388cbe7..7efa00f 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -266,6 +266,11 @@
 #define SYSCFG0_GE_MASK0x3
 #define SYSCFG0_GE_MODE(x, y)  (x << (12 + (y * 2)))
 
+/*ethernet reset control register*/
+#define ETHSYS_RSTCTRL 0x34
+#define RSTCTRL_FE BIT(6)
+#define RSTCTRL_PPEBIT(31)
+
 struct mtk_rx_dma {
unsigned int rxd1;
unsigned int rxd2;
@@ -423,7 +428,6 @@ struct mtk_rx_ring {
 struct mtk_eth {
struct device   *dev;
void __iomem*base;
-   struct reset_control*rstc;
spinlock_t  page_lock;
spinlock_t  irq_lock;
struct net_device   dummy_dev;
-- 
1.9.1



[PATCH net-next 5/7] net: ethernet: mediatek: add the whole ethernet reset into the reset process

2016-09-13 Thread sean.wang
From: Sean Wang 

1) original driver only resets DMA used by descriptor rings
which can't guarantee it can recover all various kinds of fatal
errors, so the patch tries to reset the underlying hardware
resource from scratch on Mediatek SoC required for ethernet
running, including power, pin mux control, clock and internal
circuits on the ethernet in order to restore into the initial
state which the rebooted machine gives.

2) add state variable inside structure mtk_eth to help distinguish
mtk_hw_init is called between the initialization during boot time
or re-initialization during the reset process.

3) add ge_mode variable inside structure mtk_mac for restoring
the interface mode of the current setup for the target MAC.

4) remove __init attribute from mtk_hw_init definition

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 52 -
 drivers/net/ethernet/mediatek/mtk_eth_soc.h |  8 +
 2 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index fd5d064..b9ddbcb 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -231,7 +231,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
 {
struct mtk_eth *eth = mac->hw;
struct device_node *np;
-   u32 val, ge_mode;
+   u32 val;
 
np = of_parse_phandle(mac->of_node, "phy-handle", 0);
if (!np && of_phy_is_fixed_link(mac->of_node))
@@ -245,18 +245,18 @@ static int mtk_phy_connect(struct mtk_mac *mac)
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
-   ge_mode = 0;
+   mac->ge_mode = 0;
break;
case PHY_INTERFACE_MODE_MII:
-   ge_mode = 1;
+   mac->ge_mode = 1;
break;
case PHY_INTERFACE_MODE_REVMII:
-   ge_mode = 2;
+   mac->ge_mode = 2;
break;
case PHY_INTERFACE_MODE_RMII:
if (!mac->id)
goto err_phy;
-   ge_mode = 3;
+   mac->ge_mode = 3;
break;
default:
goto err_phy;
@@ -265,7 +265,7 @@ static int mtk_phy_connect(struct mtk_mac *mac)
/* put the gmac into the right mode */
regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, mac->id);
-   val |= SYSCFG0_GE_MODE(ge_mode, mac->id);
+   val |= SYSCFG0_GE_MODE(mac->ge_mode, mac->id);
regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
 
mtk_phy_connect_node(eth, mac, np);
@@ -1414,9 +1414,12 @@ static int mtk_stop(struct net_device *dev)
return 0;
 }
 
-static int __init mtk_hw_init(struct mtk_eth *eth)
+static int mtk_hw_init(struct mtk_eth *eth)
 {
-   int i;
+   int i, val;
+
+   if (test_and_set_bit(MTK_HW_INIT, >state))
+   return 0;
 
pm_runtime_enable(eth->dev);
pm_runtime_get_sync(eth->dev);
@@ -1432,6 +1435,15 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
reset_control_deassert(eth->rstc);
usleep_range(10, 20);
 
+   regmap_read(eth->ethsys, ETHSYS_SYSCFG0, );
+   for (i = 0; i < MTK_MAC_COUNT; i++) {
+   if (!eth->mac[i])
+   continue;
+   val &= ~SYSCFG0_GE_MODE(SYSCFG0_GE_MASK, eth->mac[i]->id);
+   val |= SYSCFG0_GE_MODE(eth->mac[i]->ge_mode, eth->mac[i]->id);
+   }
+   regmap_write(eth->ethsys, ETHSYS_SYSCFG0, val);
+
/* Set GE2 driving and slew rate */
regmap_write(eth->pctl, GPIO_DRV_SEL10, 0xa00);
 
@@ -1483,6 +1495,9 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
 
 static int mtk_hw_deinit(struct mtk_eth *eth)
 {
+   if (!test_and_clear_bit(MTK_HW_INIT, >state))
+   return 0;
+
clk_disable_unprepare(eth->clks[MTK_CLK_GP2]);
clk_disable_unprepare(eth->clks[MTK_CLK_GP1]);
clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
@@ -1557,6 +1572,27 @@ static void mtk_pending_work(struct work_struct *work)
__set_bit(i, );
}
 
+   /* restart underlying hardware such as power, clock, pin mux
+* and the connected phy
+*/
+   mtk_hw_deinit(eth);
+
+   if (eth->dev->pins)
+   devm_kfree(eth->dev, eth->dev->pins);
+   pinctrl_bind_pins(eth->dev);
+
+   mtk_hw_init(eth);
+
+   for (i = 0; i < MTK_MAC_COUNT; i++) {
+   if (!eth->mac[i] ||
+   of_phy_is_fixed_link(eth->mac[i]->of_node))
+   continue;
+   err = phy_init_hw(eth->mac[i]->phy_dev);
+   if (err)
+   dev_err(eth->dev, "%s: PHY init failed.\n",
+   eth->netdev[i]->name);
+   }
+

[PATCH net-next 4/7] net: ethernet: mediatek: add controlling power domain the ethernet belongs to

2016-09-13 Thread sean.wang
From: Sean Wang 

introduce power domain control which the digital circuit of
the ethernet belongs to inside the flow of hardware initialization
and deinitialization which helps the entire ethernet hardware block
could restart cleanly and completely as being back to the initial
state when the whole machine reboot.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 917a49c6..fd5d064 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1417,6 +1418,9 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
 {
int i;
 
+   pm_runtime_enable(eth->dev);
+   pm_runtime_get_sync(eth->dev);
+
clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
@@ -1484,6 +1488,9 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
clk_disable_unprepare(eth->clks[MTK_CLK_ESW]);
clk_disable_unprepare(eth->clks[MTK_CLK_ETHIF]);
 
+   pm_runtime_put_sync(eth->dev);
+   pm_runtime_disable(eth->dev);
+
return 0;
 }
 
-- 
1.9.1



[PATCH net-next 1/7] net: ethernet: mediatek: refactoring mtk_hw_init to be reused

2016-09-13 Thread sean.wang
From: Sean Wang 

the existing mtk_hw_init includes hardware and software
initialization inside so that it is slightly hard to reuse
them for the process of the reset recovery, so some splitting
is made here for keeping hardware initializing relevant thing
and the else such as IRQ registration and MDIO initialization
what are all about to the interface of core driver moved to the
other proper place because they have no needs to register IRQ and
re-initialize structure again during the reset process.

Signed-off-by: Sean Wang 
---
 drivers/net/ethernet/mediatek/mtk_eth_soc.c | 62 -
 1 file changed, 34 insertions(+), 28 deletions(-)

diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c 
b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 66fd45a..ca46e82 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1415,7 +1415,12 @@ static int mtk_stop(struct net_device *dev)
 
 static int __init mtk_hw_init(struct mtk_eth *eth)
 {
-   int err, i;
+   int i;
+
+   clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
+   clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
+   clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
+   clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
 
/* reset the frame engine */
reset_control_assert(eth->rstc);
@@ -1441,19 +1446,6 @@ static int __init mtk_hw_init(struct mtk_eth *eth)
/* Enable RX VLan Offloading */
mtk_w32(eth, 1, MTK_CDMP_EG_CTRL);
 
-   err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
-  dev_name(eth->dev), eth);
-   if (err)
-   return err;
-   err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
-  dev_name(eth->dev), eth);
-   if (err)
-   return err;
-
-   err = mtk_mdio_init(eth);
-   if (err)
-   return err;
-
/* disable delay and normal interrupt */
mtk_w32(eth, 0, MTK_QDMA_DELAY_INT);
mtk_w32(eth, 0, MTK_PDMA_DELAY_INT);
@@ -1783,16 +1775,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct 
device_node *np)
eth->netdev[id]->features |= MTK_HW_FEATURES;
eth->netdev[id]->ethtool_ops = _ethtool_ops;
 
-   err = register_netdev(eth->netdev[id]);
-   if (err) {
-   dev_err(eth->dev, "error bringing up device\n");
-   goto free_netdev;
-   }
eth->netdev[id]->irq = eth->irq[0];
-   netif_info(eth, probe, eth->netdev[id],
-  "mediatek frame engine at 0x%08lx, irq %d\n",
-  eth->netdev[id]->base_addr, eth->irq[0]);
-
return 0;
 
 free_netdev:
@@ -1862,11 +1845,6 @@ static int mtk_probe(struct platform_device *pdev)
}
}
 
-   clk_prepare_enable(eth->clks[MTK_CLK_ETHIF]);
-   clk_prepare_enable(eth->clks[MTK_CLK_ESW]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP1]);
-   clk_prepare_enable(eth->clks[MTK_CLK_GP2]);
-
eth->msg_enable = netif_msg_init(mtk_msg_level, MTK_DEFAULT_MSG_ENABLE);
INIT_WORK(>pending_work, mtk_pending_work);
 
@@ -1887,6 +1865,34 @@ static int mtk_probe(struct platform_device *pdev)
goto err_free_dev;
}
 
+   err = devm_request_irq(eth->dev, eth->irq[1], mtk_handle_irq_tx, 0,
+  dev_name(eth->dev), eth);
+   if (err)
+   goto err_free_dev;
+
+   err = devm_request_irq(eth->dev, eth->irq[2], mtk_handle_irq_rx, 0,
+  dev_name(eth->dev), eth);
+   if (err)
+   goto err_free_dev;
+
+   err = mtk_mdio_init(eth);
+   if (err)
+   goto err_free_dev;
+
+   for (i = 0; i < MTK_MAX_DEVS; i++) {
+   if (!eth->netdev[i])
+   continue;
+
+   err = register_netdev(eth->netdev[i]);
+   if (err) {
+   dev_err(eth->dev, "error bringing up device\n");
+   goto err_free_dev;
+   } else
+   netif_info(eth, probe, eth->netdev[i],
+  "mediatek frame engine at 0x%08lx, irq %d\n",
+  eth->netdev[i]->base_addr, eth->irq[0]);
+   }
+
/* we run 2 devices on the same DMA ring so we need a dummy device
 * for NAPI to work
 */
-- 
1.9.1



  1   2   >