[][[Panther][AX8400][MT7986A][MT7976][ePA][WiFi]The 2.5G wan interface didn't show any link up/down log when cable plug/unplug]
[Description]
Add a external interrupt handler for GPY211 single phy chip.
This interrupt handler will display link up/down message and notify kernel when receiving link status change interrupt.
Note1: This patch will disable UART2 on the 2500WAN RFB, since single phy external interrupt occupied UART2_RXD and UART2_TXD.
Note2: The interrupt handler will not notify kernel on the 2500WAN GSW RFB.
[Release-log]
NA
Change-Id: Ibbecb437049f02a4ce479fee2cb035b7c17dac66
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6194248
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts
index d190872..a050c88 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-emmc-rfb.dts
@@ -68,7 +68,7 @@
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
- status = "okay";
+ status = "disabled";
};
&i2c0 {
@@ -102,6 +102,9 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 47 0>;
+ phy-handle = <&phy5>;
+ label = "lan5";
};
};
@@ -114,6 +117,8 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 46 0>;
+ phy-handle = <&phy6>;
};
};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts
index 457c351..4c4f987 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-gsw-spim-nand-rfb.dts
@@ -57,7 +57,7 @@
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
- status = "okay";
+ status = "disabled";
};
&i2c0 {
@@ -91,6 +91,8 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 47 0>;
+ phy-handle = <&phy5>;
};
};
@@ -103,6 +105,8 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 46 0>;
+ phy-handle = <&phy6>;
};
};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts
index 5163536..6af58aa 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-sd-rfb.dts
@@ -59,7 +59,7 @@
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
- status = "okay";
+ status = "disabled";
};
&i2c0 {
@@ -93,6 +93,9 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 47 0>;
+ phy-handle = <&phy5>;
+ label = "lan5";
};
};
@@ -105,6 +108,8 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 46 0>;
+ phy-handle = <&phy6>;
};
};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts
index 53356cb..e5024b5 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nand-rfb.dts
@@ -50,7 +50,7 @@
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
- status = "okay";
+ status = "disabled";
};
&i2c0 {
@@ -84,6 +84,9 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 47 0>;
+ phy-handle = <&phy5>;
+ label = "lan5";
};
};
@@ -96,6 +99,8 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 46 0>;
+ phy-handle = <&phy6>;
};
};
diff --git a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts
index f7de3dd..15e9773 100644
--- a/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts
+++ b/target/linux/mediatek/files-5.4/arch/arm64/boot/dts/mediatek/mt7986a-2500wan-spim-nor-rfb.dts
@@ -50,7 +50,7 @@
&uart2 {
pinctrl-names = "default";
pinctrl-0 = <&uart2_pins>;
- status = "okay";
+ status = "disabled";
};
&i2c0 {
@@ -84,6 +84,9 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 47 0>;
+ phy-handle = <&phy5>;
+ label = "lan5";
};
};
@@ -96,6 +99,8 @@
speed = <2500>;
full-duplex;
pause;
+ link-gpio = <&pio 46 0>;
+ phy-handle = <&phy6>;
};
};
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index df737e3..e6f6cce 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/pinctrl/devinfo.h>
#include <linux/phylink.h>
+#include <linux/gpio/consumer.h>
#include <net/dsa.h>
#include "mtk_eth_soc.h"
@@ -2547,6 +2548,36 @@
return IRQ_HANDLED;
}
+static irqreturn_t mtk_handle_irq_fixed_link(int irq, void *_mac)
+{
+ struct mtk_mac *mac = _mac;
+ struct mtk_eth *eth = mac->hw;
+ struct mtk_phylink_priv *phylink_priv = &mac->phylink_priv;
+ struct net_device *dev = phylink_priv->dev;
+ int link_old, link_new;
+
+ // clear interrupt status for gpy211
+ _mtk_mdio_read(eth, phylink_priv->phyaddr, 0x1A);
+
+ link_old = phylink_priv->link;
+ link_new = _mtk_mdio_read(eth, phylink_priv->phyaddr, MII_BMSR) & BMSR_LSTATUS;
+
+ if (link_old != link_new) {
+ phylink_priv->link = link_new;
+ if (link_new) {
+ printk("phylink.%d %s: Link is Up\n", phylink_priv->id, dev->name);
+ if (dev)
+ netif_carrier_on(dev);
+ } else {
+ printk("phylink.%d %s: Link is Down\n", phylink_priv->id, dev->name);
+ if (dev)
+ netif_carrier_off(dev);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
#ifdef CONFIG_NET_POLL_CONTROLLER
static void mtk_poll_controller(struct net_device *dev)
{
@@ -2640,6 +2671,7 @@
{
struct mtk_mac *mac = netdev_priv(dev);
struct mtk_eth *eth = mac->hw;
+ struct mtk_phylink_priv *phylink_priv = &mac->phylink_priv;
int err, i;
struct device_node *phy_node;
@@ -2685,6 +2717,34 @@
else
refcount_inc(ð->dma_refcnt);
+ if (phylink_priv->desc) {
+ /*Notice: This programming sequence is only for GPY211 single PHY chip.
+ If single PHY chip is not GPY211, the following step you should do:
+ 1. Contact your Single PHY chip vendor and get the details of
+ - how to enables link status change interrupt
+ - how to clears interrupt source
+ */
+
+ // clear interrupt source for gpy211
+ _mtk_mdio_read(eth, phylink_priv->phyaddr, 0x1A);
+
+ // enable link status change interrupt for gpy211
+ _mtk_mdio_write(eth, phylink_priv->phyaddr, 0x19, 0x0001);
+
+ phylink_priv->dev = dev;
+
+ // override dev pointer for single PHY chip 0
+ if (phylink_priv->id == 0) {
+ struct net_device *tmp;
+
+ tmp = __dev_get_by_name(&init_net, phylink_priv->label);
+ if (tmp)
+ phylink_priv->dev = tmp;
+ else
+ phylink_priv->dev = NULL;
+ }
+ }
+
phylink_start(mac->phylink);
netif_start_queue(dev);
phy_node = of_parse_phandle(mac->of_node, "phy-handle", 0);
@@ -3400,6 +3460,9 @@
struct phylink *phylink;
int phy_mode, id, err;
struct mtk_mac *mac;
+ struct mtk_phylink_priv *phylink_priv;
+ struct fwnode_handle *fixed_node;
+ struct gpio_desc *desc;
if (!_id) {
dev_err(eth->dev, "missing mac id\n");
@@ -3469,6 +3532,41 @@
mac->phylink = phylink;
+ fixed_node = fwnode_get_named_child_node(of_fwnode_handle(mac->of_node),
+ "fixed-link");
+ if (fixed_node) {
+ desc = fwnode_get_named_gpiod(fixed_node, "link-gpio",
+ 0, GPIOD_IN, "?");
+ if (!IS_ERR(desc)) {
+ struct device_node *phy_np;
+ const char *label;
+ int irq, phyaddr;
+
+ phylink_priv = &mac->phylink_priv;
+
+ phylink_priv->desc = desc;
+ phylink_priv->id = id;
+ phylink_priv->link = -1;
+
+ irq = gpiod_to_irq(desc);
+ if (irq > 0) {
+ devm_request_irq(eth->dev, irq, mtk_handle_irq_fixed_link,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "ethernet:fixed link", mac);
+ }
+
+ if (!of_property_read_string(to_of_node(fixed_node), "label", &label))
+ strcpy(phylink_priv->label, label);
+
+ phy_np = of_parse_phandle(to_of_node(fixed_node), "phy-handle", 0);
+ if (phy_np) {
+ if (!of_property_read_u32(phy_np, "reg", &phyaddr))
+ phylink_priv->phyaddr = phyaddr;
+ }
+ }
+ fwnode_handle_put(fixed_node);
+ }
+
SET_NETDEV_DEV(eth->netdev[id], eth->dev);
eth->netdev[id]->watchdog_timeo = 5 * HZ;
eth->netdev[id]->netdev_ops = &mtk_netdev_ops;
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index d74107b..88f9280 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -1196,6 +1196,21 @@
u32 count[32];
};
+/* struct mtk_phylink_priv - This is the structure holding private data for phylink
+ * @desc: Pointer to the memory holding info about the phylink gpio
+ * @id: The element is used to record the phy index of phylink
+ * @phyaddr: The element is used to record the phy address of phylink
+ * @link: The element is used to record the phy link status of phylink
+ */
+struct mtk_phylink_priv {
+ struct net_device *dev;
+ struct gpio_desc *desc;
+ char label[16];
+ int id;
+ int phyaddr;
+ int link;
+};
+
/* struct mtk_eth - This is the main datasructure for holding the state
* of the driver
* @dev: The device pointer
@@ -1290,6 +1305,7 @@
struct device_node *of_node;
struct phylink *phylink;
struct phylink_config phylink_config;
+ struct mtk_phylink_priv phylink_priv;
struct mtk_eth *hw;
struct mtk_hw_stats *hw_stats;
__be32 hwlro_ip[MTK_MAX_LRO_IP_CNT];