summaryrefslogtreecommitdiffstats
path: root/bcm2837-lan78xx-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'bcm2837-lan78xx-fixes.patch')
-rw-r--r--bcm2837-lan78xx-fixes.patch757
1 files changed, 373 insertions, 384 deletions
diff --git a/bcm2837-lan78xx-fixes.patch b/bcm2837-lan78xx-fixes.patch
index 1cb1dea08..e8ac07b92 100644
--- a/bcm2837-lan78xx-fixes.patch
+++ b/bcm2837-lan78xx-fixes.patch
@@ -1,174 +1,7 @@
-From 6ed88d188a8240ba44da6578eab7d17e036d0e61 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 17 Oct 2017 15:04:29 +0100
-Subject: [PATCH] lan78xx: Enable LEDs if no valid EEPROM or OTP
-
-For applications of the LAN78xx that don't have valid programmed
-EEPROMs or OTPs, enabling both LEDs by default seems reasonable.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/usb/lan78xx.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index a21039852f8d..cd20ce4ed87d 100644
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -2414,6 +2414,12 @@ static int lan78xx_reset(struct lan78xx_net *dev)
-
- ret = lan78xx_read_reg(dev, HW_CFG, &buf);
- buf |= HW_CFG_MEF_;
-+
-+ /* If no valid EEPROM and no valid OTP, enable the LEDs by default */
-+ if (lan78xx_read_eeprom(dev, 0, 0, NULL) &&
-+ lan78xx_read_otp(dev, 0, 0, NULL))
-+ buf |= HW_CFG_LED0_EN_ | HW_CFG_LED1_EN_;
-+
- ret = lan78xx_write_reg(dev, HW_CFG, buf);
-
- ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
-From f8a798bb45ae15cbec980c8e921eb377fd1a3df6 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Tue, 28 Nov 2017 12:02:37 +0000
-Subject: [PATCH] lan78xx: Correctly indicate invalid OTP
-
-lan78xx_read_otp tries to return -EINVAL in the event of invalid OTP
-content, but the value gets overwritten before it is returned and the
-read goes ahead anyway. Make the read conditional as it should be
-and preserve the error code.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/usb/lan78xx.c | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index cd20ce4ed87d..b270935f3f8d 100644
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -929,7 +929,8 @@ static int lan78xx_read_otp(struct lan78xx_net *dev, u32 offset,
- offset += 0x100;
- else
- ret = -EINVAL;
-- ret = lan78xx_read_raw_otp(dev, offset, length, data);
-+ if (!ret)
-+ ret = lan78xx_read_raw_otp(dev, offset, length, data);
- }
-
- return ret;
-From 4a4710f3847cd087e150f83382dffd92e09d9914 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Sat, 17 Mar 2018 00:10:02 +0100
-Subject: [PATCH] lan78xx: Read MAC address from DT if present
-
-There is a standard mechanism for locating and using a MAC address from
-the Device Tree. Use this facility in the lan78xx driver to support
-applications without programmed EEPROM or OTP.
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/usb/lan78xx.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
-diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index 60a604cc7647..a21039852f8d 100644
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -36,6 +36,7 @@
- #include <linux/irq.h>
- #include <linux/irqchip/chained_irq.h>
- #include <linux/microchipphy.h>
-+#include <linux/of_net.h>
- #include <linux/phy.h>
- #include "lan78xx.h"
-
-@@ -1639,6 +1640,14 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
- u32 addr_lo, addr_hi;
- int ret;
- u8 addr[6];
-+ const u8 *mac_addr;
-+
-+ /* maybe the boot loader passed the MAC address in devicetree */
-+ mac_addr = of_get_mac_address(dev->udev->dev.of_node);
-+ if (mac_addr) {
-+ ether_addr_copy(addr, mac_addr);
-+ goto set_mac_addr;
-+ }
-
- ret = lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
- ret = lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
-@@ -1667,6 +1676,7 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
- "MAC address set to random addr");
- }
-
-+set_mac_addr:
- addr_lo = addr[0] | (addr[1] << 8) |
- (addr[2] << 16) | (addr[3] << 24);
- addr_hi = addr[4] | (addr[5] << 8);
-From b5284e5d2d3562dac311443969a538b7fecb9848 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 28 Mar 2018 12:18:13 +0100
-Subject: [PATCH 1/5] lan78xx: Ignore DT MAC address if already valid
-
-The patch to set the lan78xx MAC address from DT does so regardless of
-whether or not the interface already has a valid address. As the
-initialisation function is called from the reset handler when the
-interface is brought up, it is impossible to change the MAC address
-in a way that persists across the interface being brought up.
-
-Fix the problem by moving the DT reading code after the check for a
-valid address.
-
-See: https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=209309
-
-Signed-off-by: Phil Elwell <phil@raspberrypi.org>
----
- drivers/net/usb/lan78xx.c | 17 +++++++++--------
- 1 file changed, 9 insertions(+), 8 deletions(-)
-
-diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index b43b16b6e7ee..97ee7d3f749d 100644
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -1641,14 +1641,6 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
- u32 addr_lo, addr_hi;
- int ret;
- u8 addr[6];
-- const u8 *mac_addr;
--
-- /* maybe the boot loader passed the MAC address in devicetree */
-- mac_addr = of_get_mac_address(dev->udev->dev.of_node);
-- if (mac_addr) {
-- ether_addr_copy(addr, mac_addr);
-- goto set_mac_addr;
-- }
-
- ret = lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
- ret = lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
-@@ -1661,6 +1653,15 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
- addr[5] = (addr_hi >> 8) & 0xFF;
-
- if (!is_valid_ether_addr(addr)) {
-+ const u8 *mac_addr;
-+
-+ /* maybe the boot loader passed the MAC address in devicetree */
-+ mac_addr = of_get_mac_address(dev->udev->dev.of_node);
-+ if (mac_addr) {
-+ ether_addr_copy(addr, mac_addr);
-+ goto set_mac_addr;
-+ }
-+
- /* reading mac address from EEPROM or OTP */
- if ((lan78xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
- addr) == 0) ||
---
-2.17.0
-
-From 2c5d6ac9133cbfed05b97b34246121bddaf2aea4 Mon Sep 17 00:00:00 2001
+From bce4fe9fa48df0cbbe842e80d9a520f7265b4cd4 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 4 Apr 2018 16:34:24 +0100
-Subject: [PATCH 2/5] net: lan78xx: Allow for VLAN headers in timeout.
+Subject: [PATCH 5/9] net: lan78xx: Allow for VLAN headers in timeout.
The frame abort timeout being set by lan78xx_set_rx_max_frame_length
didn't account for any VLAN headers, resulting in very low
@@ -183,10 +16,10 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index 97ee7d3f749d..5fd7b8569cba 100644
+index 0867f7275852..5b46998a6dce 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
-@@ -2193,7 +2193,7 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
+@@ -2178,7 +2178,7 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
if ((ll_mtu % dev->maxpacket) == 0)
return -EDOM;
@@ -195,7 +28,7 @@ index 97ee7d3f749d..5fd7b8569cba 100644
netdev->mtu = new_mtu;
-@@ -2488,7 +2488,8 @@ static int lan78xx_reset(struct lan78xx_net *dev)
+@@ -2467,7 +2467,8 @@ static int lan78xx_reset(struct lan78xx_net *dev)
buf |= FCT_TX_CTL_EN_;
ret = lan78xx_write_reg(dev, FCT_TX_CTL, buf);
@@ -208,218 +41,10 @@ index 97ee7d3f749d..5fd7b8569cba 100644
--
2.17.0
-From 833315351413d94d7db407847448dfeddfafe127 Mon Sep 17 00:00:00 2001
-From: Peter Robinson <pbrobinson@gmail.com>
-Date: Mon, 9 Apr 2018 17:51:35 +0100
-Subject: [PATCH 3/5] lan78xx: Connect phy early
-
-When using wicked with a lan78xx device attached to the system, we
-end up with ethtool commands issued on the device before an ifup
-got issued. That lead to the following crash:
-
- Unable to handle kernel NULL pointer dereference at virtual address 0000039c
- pgd = ffff800035b30000
- [0000039c] *pgd=0000000000000000
- Internal error: Oops: 96000004 [#1] SMP
- Modules linked in: [...]
- Supported: Yes
- CPU: 3 PID: 638 Comm: wickedd Tainted: G E 4.12.14-0-default #1
- Hardware name: raspberrypi rpi/rpi, BIOS 2018.03-rc2 02/21/2018
- task: ffff800035e74180 task.stack: ffff800036718000
- PC is at phy_ethtool_ksettings_get+0x20/0x98
- LR is at lan78xx_get_link_ksettings+0x44/0x60 [lan78xx]
- pc : [<ffff0000086f7f30>] lr : [<ffff000000dcca84>] pstate: 20000005
- sp : ffff80003671bb20
- x29: ffff80003671bb20 x28: ffff800035e74180
- x27: ffff000008912000 x26: 000000000000001d
- x25: 0000000000000124 x24: ffff000008f74d00
- x23: 0000004000114809 x22: 0000000000000000
- x21: ffff80003671bbd0 x20: 0000000000000000
- x19: ffff80003671bbd0 x18: 000000000000040d
- x17: 0000000000000001 x16: 0000000000000000
- x15: 0000000000000000 x14: ffffffffffffffff
- x13: 0000000000000000 x12: 0000000000000020
- x11: 0101010101010101 x10: fefefefefefefeff
- x9 : 7f7f7f7f7f7f7f7f x8 : fefefeff31677364
- x7 : 0000000080808080 x6 : ffff80003671bc9c
- x5 : ffff80003671b9f8 x4 : ffff80002c296190
- x3 : 0000000000000000 x2 : 0000000000000000
- x1 : ffff80003671bbd0 x0 : ffff80003671bc00
- Process wickedd (pid: 638, stack limit = 0xffff800036718000)
- Call trace:
- Exception stack(0xffff80003671b9e0 to 0xffff80003671bb20)
- b9e0: ffff80003671bc00 ffff80003671bbd0 0000000000000000 0000000000000000
- ba00: ffff80002c296190 ffff80003671b9f8 ffff80003671bc9c 0000000080808080
- ba20: fefefeff31677364 7f7f7f7f7f7f7f7f fefefefefefefeff 0101010101010101
- ba40: 0000000000000020 0000000000000000 ffffffffffffffff 0000000000000000
- ba60: 0000000000000000 0000000000000001 000000000000040d ffff80003671bbd0
- ba80: 0000000000000000 ffff80003671bbd0 0000000000000000 0000004000114809
- baa0: ffff000008f74d00 0000000000000124 000000000000001d ffff000008912000
- bac0: ffff800035e74180 ffff80003671bb20 ffff000000dcca84 ffff80003671bb20
- bae0: ffff0000086f7f30 0000000020000005 ffff80002c296000 ffff800035223900
- bb00: 0000ffffffffffff 0000000000000000 ffff80003671bb20 ffff0000086f7f30
- [<ffff0000086f7f30>] phy_ethtool_ksettings_get+0x20/0x98
- [<ffff000000dcca84>] lan78xx_get_link_ksettings+0x44/0x60 [lan78xx]
- [<ffff0000087cbc40>] ethtool_get_settings+0x68/0x210
- [<ffff0000087cc0d4>] dev_ethtool+0x214/0x2180
- [<ffff0000087e5008>] dev_ioctl+0x400/0x630
- [<ffff00000879dd00>] sock_do_ioctl+0x70/0x88
- [<ffff00000879f5f8>] sock_ioctl+0x208/0x368
- [<ffff0000082cde10>] do_vfs_ioctl+0xb0/0x848
- [<ffff0000082ce634>] SyS_ioctl+0x8c/0xa8
- Exception stack(0xffff80003671bec0 to 0xffff80003671c000)
- bec0: 0000000000000009 0000000000008946 0000fffff4e841d0 0000aa0032687465
- bee0: 0000aaaafa2319d4 0000fffff4e841d4 0000000032687465 0000000032687465
- bf00: 000000000000001d 7f7fff7f7f7f7f7f 72606b622e71ff4c 7f7f7f7f7f7f7f7f
- bf20: 0101010101010101 0000000000000020 ffffffffffffffff 0000ffff7f510c68
- bf40: 0000ffff7f6a9d18 0000ffff7f44ce30 000000000000040d 0000ffff7f6f98f0
- bf60: 0000fffff4e842c0 0000000000000001 0000aaaafa2c2e00 0000ffff7f6ab000
- bf80: 0000fffff4e842c0 0000ffff7f62a000 0000aaaafa2b9f20 0000aaaafa2c2e00
- bfa0: 0000fffff4e84818 0000fffff4e841a0 0000ffff7f5ad0cc 0000fffff4e841a0
- bfc0: 0000ffff7f44ce3c 0000000080000000 0000000000000009 000000000000001d
- bfe0: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
-
-The culprit is quite simple: The driver tries to access the phy left and right,
-but only actually has a working reference to it when the device is up.
-
-The fix thus is quite simple too: Get a reference to the phy on probe already
-and keep it even when the device is going down.
-
-With this patch applied, I can successfully run wicked on my system and bring
-the interface up and down as many times as I want, without getting NULL pointer
-dereferences in between.
-
-Signed-off-by: Alexander Graf <agraf@suse.de>
----
- drivers/net/usb/lan78xx.c | 34 ++++++++++++++++++----------------
- 1 file changed, 18 insertions(+), 16 deletions(-)
-
-diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index 5fd7b8569cba..60fa1257721c 100644
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -2094,10 +2094,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
-
- dev->fc_autoneg = phydev->autoneg;
-
-- phy_start(phydev);
--
-- netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
--
- return 0;
-
- error:
-@@ -2541,9 +2537,9 @@ static int lan78xx_open(struct net_device *net)
- if (ret < 0)
- goto done;
-
-- ret = lan78xx_phy_init(dev);
-- if (ret < 0)
-- goto done;
-+ phy_start(net->phydev);
-+
-+ netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
-
- /* for Link Check */
- if (dev->urb_intr) {
-@@ -2604,13 +2600,8 @@ static int lan78xx_stop(struct net_device *net)
- if (timer_pending(&dev->stat_monitor))
- del_timer_sync(&dev->stat_monitor);
-
-- phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0);
-- phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0);
--
-- phy_stop(net->phydev);
-- phy_disconnect(net->phydev);
--
-- net->phydev = NULL;
-+ if (net->phydev)
-+ phy_stop(net->phydev);
-
- clear_bit(EVENT_DEV_OPEN, &dev->flags);
- netif_stop_queue(net);
-@@ -3525,8 +3516,13 @@ static void lan78xx_disconnect(struct usb_interface *intf)
- return;
-
- udev = interface_to_usbdev(intf);
--
- net = dev->net;
-+
-+ phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0);
-+ phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0);
-+
-+ phy_disconnect(net->phydev);
-+
- unregister_netdev(net);
-
- cancel_delayed_work_sync(&dev->wq);
-@@ -3682,8 +3678,14 @@ static int lan78xx_probe(struct usb_interface *intf,
- pm_runtime_set_autosuspend_delay(&udev->dev,
- DEFAULT_AUTOSUSPEND_DELAY);
-
-+ ret = lan78xx_phy_init(dev);
-+ if (ret < 0)
-+ goto out4;
-+
- return 0;
-
-+out4:
-+ unregister_netdev(netdev);
- out3:
- lan78xx_unbind(dev, intf);
- out2:
-@@ -4031,7 +4033,7 @@ static int lan78xx_reset_resume(struct usb_interface *intf)
-
- lan78xx_reset(dev);
-
-- lan78xx_phy_init(dev);
-+ phy_start(dev->net->phydev);
-
- return lan78xx_resume(intf);
- }
---
-2.17.0
-
-From 7b4cc4a0af02c0d798007a143efa7509711d52d7 Mon Sep 17 00:00:00 2001
-From: Phil Elwell <phil@raspberrypi.org>
-Date: Wed, 4 Apr 2018 16:39:44 +0100
-Subject: [PATCH 4/5] lan78xx: Don't reset the interface on open
-
-With Alexander Graf's patch ("lan78xx: Connect phy early") applied,
-the call to lan78xx_reset within lan78xx_open prevents the phy
-interrupt from being generated (even though the link is up).
-
-Avoid this issue by removing the lan78xx_reset call.
-
-See: https://github.com/raspberrypi/linux/issues/2437
- https://github.com/raspberrypi/linux/issues/2442
- https://github.com/raspberrypi/linux/issues/2457
----
- drivers/net/usb/lan78xx.c | 4 ----
- 1 file changed, 4 deletions(-)
-
-diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index 60fa1257721c..293ed1847932 100644
---- a/drivers/net/usb/lan78xx.c
-+++ b/drivers/net/usb/lan78xx.c
-@@ -2533,10 +2533,6 @@ static int lan78xx_open(struct net_device *net)
- if (ret < 0)
- goto out;
-
-- ret = lan78xx_reset(dev);
-- if (ret < 0)
-- goto done;
--
- phy_start(net->phydev);
-
- netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
---
-2.17.0
-
-From ddbd11509f01c388b968872aeabf630654275b0a Mon Sep 17 00:00:00 2001
+From 6fecd97fd35e9c624d101495ca34c83b1cb23e3d Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Mon, 9 Apr 2018 14:31:54 +0100
-Subject: [PATCH 5/5] net: lan78xx: Request s/w csum check on VLAN tagged
+Subject: [PATCH 6/9] net: lan78xx: Request s/w csum check on VLAN tagged
packets.
There appears to be some issue in the LAN78xx where the checksum
@@ -441,10 +66,10 @@ Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
-index 293ed1847932..44cabda17bb6 100644
+index 5b46998a6dce..6b61bb21f2ae 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
-@@ -2937,8 +2937,12 @@ static void lan78xx_rx_csum_offload(struct lan78xx_net *dev,
+@@ -2920,8 +2920,12 @@ static void lan78xx_rx_csum_offload(struct lan78xx_net *dev,
struct sk_buff *skb,
u32 rx_cmd_a, u32 rx_cmd_b)
{
@@ -461,3 +86,367 @@ index 293ed1847932..44cabda17bb6 100644
--
2.17.0
+From 7528d39c5d01383fadb17a84b9840f9f685d1e0b Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 19 Apr 2018 17:59:38 +0100
+Subject: [PATCH 7/9] lan78xx: Read MAC address from DT if present
+
+There is a standard mechanism for locating and using a MAC address from
+the Device Tree. Use this facility in the lan78xx driver to support
+applications without programmed EEPROM or OTP. At the same time,
+regularise the handling of the different address sources.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+---
+ drivers/net/usb/lan78xx.c | 42 +++++++++++++++++++--------------------
+ 1 file changed, 20 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 6b61bb21f2ae..6c38a74bb32d 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -37,6 +37,7 @@
+ #include <linux/irqchip/chained_irq.h>
+ #include <linux/microchipphy.h>
+ #include <linux/phy.h>
++#include <linux/of_net.h>
+ #include "lan78xx.h"
+
+ #define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>"
+@@ -1652,34 +1653,31 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
+ addr[5] = (addr_hi >> 8) & 0xFF;
+
+ if (!is_valid_ether_addr(addr)) {
+- /* reading mac address from EEPROM or OTP */
+- if ((lan78xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
+- addr) == 0) ||
+- (lan78xx_read_otp(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
+- addr) == 0)) {
+- if (is_valid_ether_addr(addr)) {
+- /* eeprom values are valid so use them */
+- netif_dbg(dev, ifup, dev->net,
+- "MAC address read from EEPROM");
+- } else {
+- /* generate random MAC */
+- random_ether_addr(addr);
+- netif_dbg(dev, ifup, dev->net,
+- "MAC address set to random addr");
+- }
+-
+- addr_lo = addr[0] | (addr[1] << 8) |
+- (addr[2] << 16) | (addr[3] << 24);
+- addr_hi = addr[4] | (addr[5] << 8);
+-
+- ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
+- ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
++ if (!eth_platform_get_mac_address(&dev->udev->dev, addr)) {
++ /* valid address present in Device Tree */
++ netif_dbg(dev, ifup, dev->net,
++ "MAC address read from Device Tree");
++ } else if (((lan78xx_read_eeprom(dev, EEPROM_MAC_OFFSET,
++ ETH_ALEN, addr) == 0) ||
++ (lan78xx_read_otp(dev, EEPROM_MAC_OFFSET,
++ ETH_ALEN, addr) == 0)) &&
++ is_valid_ether_addr(addr)) {
++ /* eeprom values are valid so use them */
++ netif_dbg(dev, ifup, dev->net,
++ "MAC address read from EEPROM");
+ } else {
+ /* generate random MAC */
+ random_ether_addr(addr);
+ netif_dbg(dev, ifup, dev->net,
+ "MAC address set to random addr");
+ }
++
++ addr_lo = addr[0] | (addr[1] << 8) |
++ (addr[2] << 16) | (addr[3] << 24);
++ addr_hi = addr[4] | (addr[5] << 8);
++
++ ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
++ ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+ }
+
+ ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
+--
+2.17.0
+
+From f8f9ad43b37f5db5895619e4304aa9ba286cbbb0 Mon Sep 17 00:00:00 2001
+From: Phil Elwell <phil@raspberrypi.org>
+Date: Thu, 19 Apr 2018 17:59:40 +0100
+Subject: [PATCH 8/9] dt-bindings: Document the DT bindings for lan78xx
+
+The Microchip LAN78XX family of devices are Ethernet controllers with
+a USB interface. Despite being discoverable devices it can be useful to
+be able to configure them from Device Tree, particularly in low-cost
+applications without an EEPROM or programmed OTP.
+
+Document the supported properties in a bindings file.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+---
+ .../bindings/net/microchip,lan78xx.txt | 54 +++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+ create mode 100644 Documentation/devicetree/bindings/net/microchip,lan78xx.txt
+
+diff --git a/Documentation/devicetree/bindings/net/microchip,lan78xx.txt b/Documentation/devicetree/bindings/net/microchip,lan78xx.txt
+new file mode 100644
+index 000000000000..76786a0f6d3d
+--- /dev/null
++++ b/Documentation/devicetree/bindings/net/microchip,lan78xx.txt
+@@ -0,0 +1,54 @@
++Microchip LAN78xx Gigabit Ethernet controller
++
++The LAN78XX devices are usually configured by programming their OTP or with
++an external EEPROM, but some platforms (e.g. Raspberry Pi 3 B+) have neither.
++The Device Tree properties, if present, override the OTP and EEPROM.
++
++Required properties:
++- compatible: Should be one of "usb424,7800", "usb424,7801" or "usb424,7850".
++
++Optional properties:
++- local-mac-address: see ethernet.txt
++- mac-address: see ethernet.txt
++
++Optional properties of the embedded PHY:
++- microchip,led-modes: a 0..4 element vector, with each element configuring
++ the operating mode of an LED. Omitted LEDs are turned off. Allowed values
++ are defined in "include/dt-bindings/net/microchip-lan78xx.h".
++
++Example:
++
++/* Based on the configuration for a Raspberry Pi 3 B+ */
++&usb {
++ usb-port@1 {
++ compatible = "usb424,2514";
++ reg = <1>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ usb-port@1 {
++ compatible = "usb424,2514";
++ reg = <1>;
++ #address-cells = <1>;
++ #size-cells = <0>;
++
++ ethernet: ethernet@1 {
++ compatible = "usb424,7800";
++ reg = <1>;
++ local-mac-address = [ 00 11 22 33 44 55 ];
++
++ mdio {
++ #address-cells = <0x1>;
++ #size-cells = <0x0>;
++ eth_phy: ethernet-phy@1 {
++ reg = <1>;
++ microchip,led-modes = <
++ LAN78XX_LINK_1000_ACTIVITY
++ LAN78XX_LINK_10_100_ACTIVITY
++ >;
++ };
++ };
++ };
++ };
++ };
++};
+--
+2.17.0
+
+From be24db04ec2949e9b03763366f100ae40836c61e Mon Sep 17 00:00:00 2001
+From: Peter Robinson <pbrobinson@gmail.com>
+Date: Mon, 23 Apr 2018 14:31:26 +0100
+Subject: [PATCH 9/9] lan78xx: Read LED states from Device Tree
+
+Add support for DT property "microchip,led-modes", a vector of zero
+to four cells (u32s) in the range 0-15, each of which sets the mode
+for one of the LEDs. Some possible values are:
+
+ 0=link/activity 1=link1000/activity
+ 2=link100/activity 3=link10/activity
+ 4=link100/1000/activity 5=link10/1000/activity
+ 6=link10/100/activity 14=off 15=on
+
+These values are given symbolic constants in a dt-bindings header.
+
+Also use the presence of the DT property to indicate that the
+LEDs should be enabled - necessary in the event that no valid OTP
+or EEPROM is available.
+
+Signed-off-by: Phil Elwell <phil@raspberrypi.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+---
+ MAINTAINERS | 1 +
+ drivers/net/phy/microchip.c | 25 ++++++++++++++++
+ drivers/net/usb/lan78xx.c | 32 ++++++++++++++++++++-
+ include/dt-bindings/net/microchip-lan78xx.h | 21 ++++++++++++++
+ include/linux/microchipphy.h | 3 ++
+ 5 files changed, 81 insertions(+), 1 deletion(-)
+ create mode 100644 include/dt-bindings/net/microchip-lan78xx.h
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 6e950b8b4a41..c7d5f8c60a2c 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -14437,6 +14437,7 @@ M: Microchip Linux Driver Support <UNGLinuxDriver@microchip.com>
+ L: netdev@vger.kernel.org
+ S: Maintained
+ F: drivers/net/usb/lan78xx.*
++F: include/dt-bindings/net/microchip-lan78xx.h
+
+ USB MASS STORAGE DRIVER
+ M: Alan Stern <stern@rowland.harvard.edu>
+diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c
+index a97ac8c12c4c..2d67937866a3 100644
+--- a/drivers/net/phy/microchip.c
++++ b/drivers/net/phy/microchip.c
+@@ -21,6 +21,8 @@
+ #include <linux/phy.h>
+ #include <linux/microchipphy.h>
+ #include <linux/delay.h>
++#include <linux/of.h>
++#include <dt-bindings/net/microchip-lan78xx.h>
+
+ #define DRIVER_AUTHOR "WOOJUNG HUH <woojung.huh@microchip.com>"
+ #define DRIVER_DESC "Microchip LAN88XX PHY driver"
+@@ -225,6 +227,8 @@ static int lan88xx_probe(struct phy_device *phydev)
+ {
+ struct device *dev = &phydev->mdio.dev;
+ struct lan88xx_priv *priv;
++ u32 led_modes[4];
++ int len;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+@@ -232,6 +236,27 @@ static int lan88xx_probe(struct phy_device *phydev)
+
+ priv->wolopts = 0;
+
++ len = of_property_read_variable_u32_array(dev->of_node,
++ "microchip,led-modes",
++ led_modes,
++ 0,
++ ARRAY_SIZE(led_modes));
++ if (len >= 0) {
++ u32 reg = 0;
++ int i;
++
++ for (i = 0; i < len; i++) {
++ if (led_modes[i] > 15)
++ return -EINVAL;
++ reg |= led_modes[i] << (i * 4);
++ }
++ for (; i < ARRAY_SIZE(led_modes); i++)
++ reg |= LAN78XX_FORCE_LED_OFF << (i * 4);
++ (void)phy_write(phydev, LAN78XX_PHY_LED_MODE_SELECT, reg);
++ } else if (len == -EOVERFLOW) {
++ return -EINVAL;
++ }
++
+ /* these values can be used to identify internal PHY */
+ priv->chip_id = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_ID);
+ priv->chip_rev = phy_read_mmd(phydev, 3, LAN88XX_MMD3_CHIP_REV);
+diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
+index 6c38a74bb32d..01b876daa600 100644
+--- a/drivers/net/usb/lan78xx.c
++++ b/drivers/net/usb/lan78xx.c
+@@ -37,6 +37,7 @@
+ #include <linux/irqchip/chained_irq.h>
+ #include <linux/microchipphy.h>
+ #include <linux/phy.h>
++#include <linux/of_mdio.h>
+ #include <linux/of_net.h>
+ #include "lan78xx.h"
+
+@@ -1760,6 +1761,7 @@ static int lan78xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx,
+
+ static int lan78xx_mdio_init(struct lan78xx_net *dev)
+ {
++ struct device_node *node;
+ int ret;
+
+ dev->mdiobus = mdiobus_alloc();
+@@ -1788,7 +1790,13 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev)
+ break;
+ }
+
+- ret = mdiobus_register(dev->mdiobus);
++ node = of_get_child_by_name(dev->udev->dev.of_node, "mdio");
++ if (node) {
++ ret = of_mdiobus_register(dev->mdiobus, node);
++ of_node_put(node);
++ } else {
++ ret = mdiobus_register(dev->mdiobus);
++ }
+ if (ret) {
+ netdev_err(dev->net, "can't register MDIO bus\n");
+ goto exit1;
+@@ -2077,6 +2085,28 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
+ mii_adv = (u32)mii_advertise_flowctrl(dev->fc_request_control);
+ phydev->advertising |= mii_adv_to_ethtool_adv_t(mii_adv);
+
++ if (phydev->mdio.dev.of_node) {
++ u32 reg;
++ int len;
++
++ len = of_property_count_elems_of_size(phydev->mdio.dev.of_node,
++ "microchip,led-modes",
++ sizeof(u32));
++ if (len >= 0) {
++ /* Ensure the appropriate LEDs are enabled */
++ lan78xx_read_reg(dev, HW_CFG, &reg);
++ reg &= ~(HW_CFG_LED0_EN_ |
++ HW_CFG_LED1_EN_ |
++ HW_CFG_LED2_EN_ |
++ HW_CFG_LED3_EN_);
++ reg |= (len > 0) * HW_CFG_LED0_EN_ |
++ (len > 1) * HW_CFG_LED1_EN_ |
++ (len > 2) * HW_CFG_LED2_EN_ |
++ (len > 3) * HW_CFG_LED3_EN_;
++ lan78xx_write_reg(dev, HW_CFG, reg);
++ }
++ }
++
+ genphy_config_aneg(phydev);
+
+ dev->fc_autoneg = phydev->autoneg;
+diff --git a/include/dt-bindings/net/microchip-lan78xx.h b/include/dt-bindings/net/microchip-lan78xx.h
+new file mode 100644
+index 000000000000..0742ff075307
+--- /dev/null
++++ b/include/dt-bindings/net/microchip-lan78xx.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef _DT_BINDINGS_MICROCHIP_LAN78XX_H
++#define _DT_BINDINGS_MICROCHIP_LAN78XX_H
++
++/* LED modes for LAN7800/LAN7850 embedded PHY */
++
++#define LAN78XX_LINK_ACTIVITY 0
++#define LAN78XX_LINK_1000_ACTIVITY 1
++#define LAN78XX_LINK_100_ACTIVITY 2
++#define LAN78XX_LINK_10_ACTIVITY 3
++#define LAN78XX_LINK_100_1000_ACTIVITY 4
++#define LAN78XX_LINK_10_1000_ACTIVITY 5
++#define LAN78XX_LINK_10_100_ACTIVITY 6
++#define LAN78XX_DUPLEX_COLLISION 8
++#define LAN78XX_COLLISION 9
++#define LAN78XX_ACTIVITY 10
++#define LAN78XX_AUTONEG_FAULT 12
++#define LAN78XX_FORCE_LED_OFF 14
++#define LAN78XX_FORCE_LED_ON 15
++
++#endif
+diff --git a/include/linux/microchipphy.h b/include/linux/microchipphy.h
+index 8f9c90379732..fd1fc8c248ef 100644
+--- a/include/linux/microchipphy.h
++++ b/include/linux/microchipphy.h
+@@ -78,4 +78,7 @@
+ #define LAN88XX_EXT_PAGE_TR_LOW_DATA 17
+ #define LAN88XX_EXT_PAGE_TR_HIGH_DATA 18
+
++/* Registers specific to the LAN7800/LAN7850 embedded phy */
++#define LAN78XX_PHY_LED_MODE_SELECT (0x1D)
++
+ #endif /* _MICROCHIPPHY_H */
+--
+2.17.0