mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	Update RPI patches
This commit is contained in:
		
							parent
							
								
									cc24592e6c
								
							
						
					
					
						commit
						50323f4caa
					
				
					 14 changed files with 1499 additions and 43 deletions
				
			
		| 
						 | 
				
			
			@ -1,43 +0,0 @@
 | 
			
		|||
From 7c34b5c7793c40265af49880caea0a4a0caf202b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
Date: Tue, 17 Oct 2017 15:04:29 +0100
 | 
			
		||||
Subject: [PATCH 151/277] lan78xx: Enable LEDs and auto-negotiation
 | 
			
		||||
 | 
			
		||||
For applications of the LAN78xx that don't have valid programmed
 | 
			
		||||
EEPROMs or OTPs, enabling both LEDs and auto-negotiation by default
 | 
			
		||||
seems reasonable.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/usb/lan78xx.c | 11 +++++++++++
 | 
			
		||||
 1 file changed, 11 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
 | 
			
		||||
index ee95fc957e1f..76674d8881b5 100644
 | 
			
		||||
--- a/drivers/net/usb/lan78xx.c
 | 
			
		||||
+++ b/drivers/net/usb/lan78xx.c
 | 
			
		||||
@@ -2362,6 +2362,11 @@ static int lan78xx_reset(struct lan78xx_net *dev)
 | 
			
		||||
 	u32 buf;
 | 
			
		||||
 	int ret = 0;
 | 
			
		||||
 	unsigned long timeout;
 | 
			
		||||
+	bool has_eeprom;
 | 
			
		||||
+	bool has_otp;
 | 
			
		||||
+
 | 
			
		||||
+	has_eeprom = !lan78xx_read_eeprom(dev, 0, 0, NULL);
 | 
			
		||||
+	has_otp = !lan78xx_read_otp(dev, 0, 0, NULL);
 | 
			
		||||
 
 | 
			
		||||
 	ret = lan78xx_read_reg(dev, HW_CFG, &buf);
 | 
			
		||||
 	buf |= HW_CFG_LRST_;
 | 
			
		||||
@@ -2415,6 +2420,9 @@ 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 (!has_eeprom && !has_otp)
 | 
			
		||||
+	    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);
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,148 @@
 | 
			
		|||
From ab087adc9f5ea07a37d0993a7528f9af4bf903de Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 2 Jan 2018 10:58:27 +0000
 | 
			
		||||
Subject: [PATCH 322/340] net: mdiobus: add unlocked accessors
 | 
			
		||||
 | 
			
		||||
commit 34dc08e4be208539b7c4aa8154a610e1736705e8 upstream.
 | 
			
		||||
 | 
			
		||||
Add unlocked versions of the bus accessors, which allows access to the
 | 
			
		||||
bus with all the tracing. These accessors validate that the bus mutex
 | 
			
		||||
is held, which is a basic requirement for all mii bus accesses.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
 | 
			
		||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/mdio_bus.c | 65 +++++++++++++++++++++++++++++++++++++---------
 | 
			
		||||
 include/linux/mdio.h       |  3 +++
 | 
			
		||||
 2 files changed, 56 insertions(+), 12 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
 | 
			
		||||
index 2df7b62c1a36..7da805475517 100644
 | 
			
		||||
--- a/drivers/net/phy/mdio_bus.c
 | 
			
		||||
+++ b/drivers/net/phy/mdio_bus.c
 | 
			
		||||
@@ -492,6 +492,55 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mdiobus_scan);
 | 
			
		||||
 
 | 
			
		||||
+/**
 | 
			
		||||
+ * __mdiobus_read - Unlocked version of the mdiobus_read function
 | 
			
		||||
+ * @bus: the mii_bus struct
 | 
			
		||||
+ * @addr: the phy address
 | 
			
		||||
+ * @regnum: register number to read
 | 
			
		||||
+ *
 | 
			
		||||
+ * Read a MDIO bus register. Caller must hold the mdio bus lock.
 | 
			
		||||
+ *
 | 
			
		||||
+ * NOTE: MUST NOT be called from interrupt context.
 | 
			
		||||
+ */
 | 
			
		||||
+int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
 | 
			
		||||
+{
 | 
			
		||||
+	int retval;
 | 
			
		||||
+
 | 
			
		||||
+	WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock));
 | 
			
		||||
+
 | 
			
		||||
+	retval = bus->read(bus, addr, regnum);
 | 
			
		||||
+
 | 
			
		||||
+	trace_mdio_access(bus, 1, addr, regnum, retval, retval);
 | 
			
		||||
+
 | 
			
		||||
+	return retval;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(__mdiobus_read);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * __mdiobus_write - Unlocked version of the mdiobus_write function
 | 
			
		||||
+ * @bus: the mii_bus struct
 | 
			
		||||
+ * @addr: the phy address
 | 
			
		||||
+ * @regnum: register number to write
 | 
			
		||||
+ * @val: value to write to @regnum
 | 
			
		||||
+ *
 | 
			
		||||
+ * Write a MDIO bus register. Caller must hold the mdio bus lock.
 | 
			
		||||
+ *
 | 
			
		||||
+ * NOTE: MUST NOT be called from interrupt context.
 | 
			
		||||
+ */
 | 
			
		||||
+int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock));
 | 
			
		||||
+
 | 
			
		||||
+	err = bus->write(bus, addr, regnum, val);
 | 
			
		||||
+
 | 
			
		||||
+	trace_mdio_access(bus, 0, addr, regnum, val, err);
 | 
			
		||||
+
 | 
			
		||||
+	return err;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(__mdiobus_write);
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * mdiobus_read_nested - Nested version of the mdiobus_read function
 | 
			
		||||
  * @bus: the mii_bus struct
 | 
			
		||||
@@ -512,11 +561,9 @@ int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum)
 | 
			
		||||
 	BUG_ON(in_interrupt());
 | 
			
		||||
 
 | 
			
		||||
 	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
 | 
			
		||||
-	retval = bus->read(bus, addr, regnum);
 | 
			
		||||
+	retval = __mdiobus_read(bus, addr, regnum);
 | 
			
		||||
 	mutex_unlock(&bus->mdio_lock);
 | 
			
		||||
 
 | 
			
		||||
-	trace_mdio_access(bus, 1, addr, regnum, retval, retval);
 | 
			
		||||
-
 | 
			
		||||
 	return retval;
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mdiobus_read_nested);
 | 
			
		||||
@@ -538,11 +585,9 @@ int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
 | 
			
		||||
 	BUG_ON(in_interrupt());
 | 
			
		||||
 
 | 
			
		||||
 	mutex_lock(&bus->mdio_lock);
 | 
			
		||||
-	retval = bus->read(bus, addr, regnum);
 | 
			
		||||
+	retval = __mdiobus_read(bus, addr, regnum);
 | 
			
		||||
 	mutex_unlock(&bus->mdio_lock);
 | 
			
		||||
 
 | 
			
		||||
-	trace_mdio_access(bus, 1, addr, regnum, retval, retval);
 | 
			
		||||
-
 | 
			
		||||
 	return retval;
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mdiobus_read);
 | 
			
		||||
@@ -568,11 +613,9 @@ int mdiobus_write_nested(struct mii_bus *bus, int addr, u32 regnum, u16 val)
 | 
			
		||||
 	BUG_ON(in_interrupt());
 | 
			
		||||
 
 | 
			
		||||
 	mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
 | 
			
		||||
-	err = bus->write(bus, addr, regnum, val);
 | 
			
		||||
+	err = __mdiobus_write(bus, addr, regnum, val);
 | 
			
		||||
 	mutex_unlock(&bus->mdio_lock);
 | 
			
		||||
 
 | 
			
		||||
-	trace_mdio_access(bus, 0, addr, regnum, val, err);
 | 
			
		||||
-
 | 
			
		||||
 	return err;
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mdiobus_write_nested);
 | 
			
		||||
@@ -595,11 +638,9 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
 | 
			
		||||
 	BUG_ON(in_interrupt());
 | 
			
		||||
 
 | 
			
		||||
 	mutex_lock(&bus->mdio_lock);
 | 
			
		||||
-	err = bus->write(bus, addr, regnum, val);
 | 
			
		||||
+	err = __mdiobus_write(bus, addr, regnum, val);
 | 
			
		||||
 	mutex_unlock(&bus->mdio_lock);
 | 
			
		||||
 
 | 
			
		||||
-	trace_mdio_access(bus, 0, addr, regnum, val, err);
 | 
			
		||||
-
 | 
			
		||||
 	return err;
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(mdiobus_write);
 | 
			
		||||
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
 | 
			
		||||
index ca08ab16ecdc..34796e29c90c 100644
 | 
			
		||||
--- a/include/linux/mdio.h
 | 
			
		||||
+++ b/include/linux/mdio.h
 | 
			
		||||
@@ -257,6 +257,9 @@ static inline u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv)
 | 
			
		||||
 	return reg;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
 | 
			
		||||
+int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
 | 
			
		||||
+
 | 
			
		||||
 int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
 | 
			
		||||
 int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum);
 | 
			
		||||
 int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,61 @@
 | 
			
		|||
From 71e69462132675b878ac9fc59f1207f5062c3905 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 2 Jan 2018 10:58:32 +0000
 | 
			
		||||
Subject: [PATCH 323/340] net: phy: use unlocked accessors for indirect MMD
 | 
			
		||||
 accesses
 | 
			
		||||
 | 
			
		||||
commit 1b2dea2e6a6e3399e88784d57aea80f4fd5e8956 upstream.
 | 
			
		||||
 | 
			
		||||
Use unlocked accessors for indirect MMD accesses to clause 22 PHYs.
 | 
			
		||||
This permits tracing of these accesses.
 | 
			
		||||
 | 
			
		||||
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
 | 
			
		||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phy-core.c | 11 ++++++-----
 | 
			
		||||
 1 file changed, 6 insertions(+), 5 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
 | 
			
		||||
index 21f75ae244b3..83d32644cb4d 100644
 | 
			
		||||
--- a/drivers/net/phy/phy-core.c
 | 
			
		||||
+++ b/drivers/net/phy/phy-core.c
 | 
			
		||||
@@ -193,13 +193,14 @@ static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
 | 
			
		||||
 			     u16 regnum)
 | 
			
		||||
 {
 | 
			
		||||
 	/* Write the desired MMD Devad */
 | 
			
		||||
-	bus->write(bus, phy_addr, MII_MMD_CTRL, devad);
 | 
			
		||||
+	__mdiobus_write(bus, phy_addr, MII_MMD_CTRL, devad);
 | 
			
		||||
 
 | 
			
		||||
 	/* Write the desired MMD register address */
 | 
			
		||||
-	bus->write(bus, phy_addr, MII_MMD_DATA, regnum);
 | 
			
		||||
+	__mdiobus_write(bus, phy_addr, MII_MMD_DATA, regnum);
 | 
			
		||||
 
 | 
			
		||||
 	/* Select the Function : DATA with no post increment */
 | 
			
		||||
-	bus->write(bus, phy_addr, MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR);
 | 
			
		||||
+	__mdiobus_write(bus, phy_addr, MII_MMD_CTRL,
 | 
			
		||||
+			devad | MII_MMD_CTRL_NOINCR);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 /**
 | 
			
		||||
@@ -232,7 +233,7 @@ int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)
 | 
			
		||||
 		mmd_phy_indirect(bus, phy_addr, devad, regnum);
 | 
			
		||||
 
 | 
			
		||||
 		/* Read the content of the MMD's selected register */
 | 
			
		||||
-		val = bus->read(bus, phy_addr, MII_MMD_DATA);
 | 
			
		||||
+		val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
 | 
			
		||||
 		mutex_unlock(&bus->mdio_lock);
 | 
			
		||||
 	}
 | 
			
		||||
 	return val;
 | 
			
		||||
@@ -271,7 +272,7 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
 | 
			
		||||
 		mmd_phy_indirect(bus, phy_addr, devad, regnum);
 | 
			
		||||
 
 | 
			
		||||
 		/* Write the data into MMD's selected register */
 | 
			
		||||
-		bus->write(bus, phy_addr, MII_MMD_DATA, val);
 | 
			
		||||
+		__mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
 | 
			
		||||
 		mutex_unlock(&bus->mdio_lock);
 | 
			
		||||
 
 | 
			
		||||
 		ret = 0;
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,104 @@
 | 
			
		|||
From f816dc53e35dd06cb0c3b36d6883d7fe7f8dbae6 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 2 Jan 2018 10:58:37 +0000
 | 
			
		||||
Subject: [PATCH 324/340] net: phy: add unlocked accessors
 | 
			
		||||
 | 
			
		||||
commit 788f9933db6172801336d0ae2dec5bdc7525389f upstream.
 | 
			
		||||
 | 
			
		||||
Add unlocked versions of the bus accessors, which allows access to the
 | 
			
		||||
bus with all the tracing. These accessors validate that the bus mutex
 | 
			
		||||
is held, which is a basic requirement for all mii bus accesses.
 | 
			
		||||
 | 
			
		||||
Also added is a read-modify-write unlocked accessor with the same
 | 
			
		||||
locking requirements.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phy-core.c | 25 +++++++++++++++++++++++++
 | 
			
		||||
 include/linux/phy.h        | 28 ++++++++++++++++++++++++++++
 | 
			
		||||
 2 files changed, 53 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
 | 
			
		||||
index 83d32644cb4d..37c039da0c16 100644
 | 
			
		||||
--- a/drivers/net/phy/phy-core.c
 | 
			
		||||
+++ b/drivers/net/phy/phy-core.c
 | 
			
		||||
@@ -280,3 +280,28 @@ int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL(phy_write_mmd);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * __phy_modify() - Convenience function for modifying a PHY register
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @regnum: register number
 | 
			
		||||
+ * @mask: bit mask of bits to clear
 | 
			
		||||
+ * @set: bit mask of bits to set
 | 
			
		||||
+ *
 | 
			
		||||
+ * Unlocked helper function which allows a PHY register to be modified as
 | 
			
		||||
+ * new register value = (old register value & mask) | set
 | 
			
		||||
+ */
 | 
			
		||||
+int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret, res;
 | 
			
		||||
+
 | 
			
		||||
+	ret = __phy_read(phydev, regnum);
 | 
			
		||||
+	if (ret >= 0) {
 | 
			
		||||
+		res = __phy_write(phydev, regnum, (ret & ~mask) | set);
 | 
			
		||||
+		if (res < 0)
 | 
			
		||||
+			ret = res;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return ret;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL_GPL(__phy_modify);
 | 
			
		||||
diff --git a/include/linux/phy.h b/include/linux/phy.h
 | 
			
		||||
index dca9e926b88f..a8118cc313ea 100644
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -713,6 +713,18 @@ static inline int phy_read(struct phy_device *phydev, u32 regnum)
 | 
			
		||||
 	return mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/**
 | 
			
		||||
+ * __phy_read - convenience function for reading a given PHY register
 | 
			
		||||
+ * @phydev: the phy_device struct
 | 
			
		||||
+ * @regnum: register number to read
 | 
			
		||||
+ *
 | 
			
		||||
+ * The caller must have taken the MDIO bus lock.
 | 
			
		||||
+ */
 | 
			
		||||
+static inline int __phy_read(struct phy_device *phydev, u32 regnum)
 | 
			
		||||
+{
 | 
			
		||||
+	return __mdiobus_read(phydev->mdio.bus, phydev->mdio.addr, regnum);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * phy_write - Convenience function for writing a given PHY register
 | 
			
		||||
  * @phydev: the phy_device struct
 | 
			
		||||
@@ -728,6 +740,22 @@ static inline int phy_write(struct phy_device *phydev, u32 regnum, u16 val)
 | 
			
		||||
 	return mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, regnum, val);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+/**
 | 
			
		||||
+ * __phy_write - Convenience function for writing a given PHY register
 | 
			
		||||
+ * @phydev: the phy_device struct
 | 
			
		||||
+ * @regnum: register number to write
 | 
			
		||||
+ * @val: value to write to @regnum
 | 
			
		||||
+ *
 | 
			
		||||
+ * The caller must have taken the MDIO bus lock.
 | 
			
		||||
+ */
 | 
			
		||||
+static inline int __phy_write(struct phy_device *phydev, u32 regnum, u16 val)
 | 
			
		||||
+{
 | 
			
		||||
+	return __mdiobus_write(phydev->mdio.bus, phydev->mdio.addr, regnum,
 | 
			
		||||
+			       val);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set);
 | 
			
		||||
+
 | 
			
		||||
 /**
 | 
			
		||||
  * phy_interrupt_is_valid - Convenience function for testing a given PHY irq
 | 
			
		||||
  * @phydev: the phy_device struct
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,215 @@
 | 
			
		|||
From 85606b71f999eee8609016e3de41a55e41019a4b Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Date: Tue, 2 Jan 2018 10:58:43 +0000
 | 
			
		||||
Subject: [PATCH 325/340] net: phy: add paged phy register accessors
 | 
			
		||||
 | 
			
		||||
commit 78ffc4acceff48522b92d8fbf8f4a0ffe78838b2 upstream.
 | 
			
		||||
 | 
			
		||||
Add a set of paged phy register accessors which are inherently safe in
 | 
			
		||||
their design against other accesses interfering with the paged access.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
 | 
			
		||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
 | 
			
		||||
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/phy-core.c | 157 +++++++++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
 include/linux/phy.h        |  11 ++++
 | 
			
		||||
 2 files changed, 168 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
 | 
			
		||||
index 37c039da0c16..412ed8ff50e2 100644
 | 
			
		||||
--- a/drivers/net/phy/phy-core.c
 | 
			
		||||
+++ b/drivers/net/phy/phy-core.c
 | 
			
		||||
@@ -305,3 +305,160 @@ int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 EXPORT_SYMBOL_GPL(__phy_modify);
 | 
			
		||||
+
 | 
			
		||||
+static int __phy_read_page(struct phy_device *phydev)
 | 
			
		||||
+{
 | 
			
		||||
+	return phydev->drv->read_page(phydev);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int __phy_write_page(struct phy_device *phydev, int page)
 | 
			
		||||
+{
 | 
			
		||||
+	return phydev->drv->write_page(phydev, page);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * phy_save_page() - take the bus lock and save the current page
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ *
 | 
			
		||||
+ * Take the MDIO bus lock, and return the current page number. On error,
 | 
			
		||||
+ * returns a negative errno. phy_restore_page() must always be called
 | 
			
		||||
+ * after this, irrespective of success or failure of this call.
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_save_page(struct phy_device *phydev)
 | 
			
		||||
+{
 | 
			
		||||
+	mutex_lock(&phydev->mdio.bus->mdio_lock);
 | 
			
		||||
+	return __phy_read_page(phydev);
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL_GPL(phy_save_page);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * phy_select_page() - take the bus lock, save the current page, and set a page
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @page: desired page
 | 
			
		||||
+ *
 | 
			
		||||
+ * Take the MDIO bus lock to protect against concurrent access, save the
 | 
			
		||||
+ * current PHY page, and set the current page.  On error, returns a
 | 
			
		||||
+ * negative errno, otherwise returns the previous page number.
 | 
			
		||||
+ * phy_restore_page() must always be called after this, irrespective
 | 
			
		||||
+ * of success or failure of this call.
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_select_page(struct phy_device *phydev, int page)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret, oldpage;
 | 
			
		||||
+
 | 
			
		||||
+	oldpage = ret = phy_save_page(phydev);
 | 
			
		||||
+	if (ret < 0)
 | 
			
		||||
+		return ret;
 | 
			
		||||
+
 | 
			
		||||
+	if (oldpage != page) {
 | 
			
		||||
+		ret = __phy_write_page(phydev, page);
 | 
			
		||||
+		if (ret < 0)
 | 
			
		||||
+			return ret;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	return oldpage;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL_GPL(phy_select_page);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * phy_restore_page() - restore the page register and release the bus lock
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @oldpage: the old page, return value from phy_save_page() or phy_select_page()
 | 
			
		||||
+ * @ret: operation's return code
 | 
			
		||||
+ *
 | 
			
		||||
+ * Release the MDIO bus lock, restoring @oldpage if it is a valid page.
 | 
			
		||||
+ * This function propagates the earliest error code from the group of
 | 
			
		||||
+ * operations.
 | 
			
		||||
+ *
 | 
			
		||||
+ * Returns:
 | 
			
		||||
+ *   @oldpage if it was a negative value, otherwise
 | 
			
		||||
+ *   @ret if it was a negative errno value, otherwise
 | 
			
		||||
+ *   phy_write_page()'s negative value if it were in error, otherwise
 | 
			
		||||
+ *   @ret.
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)
 | 
			
		||||
+{
 | 
			
		||||
+	int r;
 | 
			
		||||
+
 | 
			
		||||
+	if (oldpage >= 0) {
 | 
			
		||||
+		r = __phy_write_page(phydev, oldpage);
 | 
			
		||||
+
 | 
			
		||||
+		/* Propagate the operation return code if the page write
 | 
			
		||||
+		 * was successful.
 | 
			
		||||
+		 */
 | 
			
		||||
+		if (ret >= 0 && r < 0)
 | 
			
		||||
+			ret = r;
 | 
			
		||||
+	} else {
 | 
			
		||||
+		/* Propagate the phy page selection error code */
 | 
			
		||||
+		ret = oldpage;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	mutex_unlock(&phydev->mdio.bus->mdio_lock);
 | 
			
		||||
+
 | 
			
		||||
+	return ret;
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL_GPL(phy_restore_page);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * phy_read_paged() - Convenience function for reading a paged register
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @page: the page for the phy
 | 
			
		||||
+ * @regnum: register number
 | 
			
		||||
+ *
 | 
			
		||||
+ * Same rules as for phy_read().
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_read_paged(struct phy_device *phydev, int page, u32 regnum)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret = 0, oldpage;
 | 
			
		||||
+
 | 
			
		||||
+	oldpage = phy_select_page(phydev, page);
 | 
			
		||||
+	if (oldpage >= 0)
 | 
			
		||||
+		ret = __phy_read(phydev, regnum);
 | 
			
		||||
+
 | 
			
		||||
+	return phy_restore_page(phydev, oldpage, ret);
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(phy_read_paged);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * phy_write_paged() - Convenience function for writing a paged register
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @page: the page for the phy
 | 
			
		||||
+ * @regnum: register number
 | 
			
		||||
+ * @val: value to write
 | 
			
		||||
+ *
 | 
			
		||||
+ * Same rules as for phy_write().
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret = 0, oldpage;
 | 
			
		||||
+
 | 
			
		||||
+	oldpage = phy_select_page(phydev, page);
 | 
			
		||||
+	if (oldpage >= 0)
 | 
			
		||||
+		ret = __phy_write(phydev, regnum, val);
 | 
			
		||||
+
 | 
			
		||||
+	return phy_restore_page(phydev, oldpage, ret);
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(phy_write_paged);
 | 
			
		||||
+
 | 
			
		||||
+/**
 | 
			
		||||
+ * phy_modify_paged() - Convenience function for modifying a paged register
 | 
			
		||||
+ * @phydev: a pointer to a &struct phy_device
 | 
			
		||||
+ * @page: the page for the phy
 | 
			
		||||
+ * @regnum: register number
 | 
			
		||||
+ * @mask: bit mask of bits to clear
 | 
			
		||||
+ * @set: bit mask of bits to set
 | 
			
		||||
+ *
 | 
			
		||||
+ * Same rules as for phy_read() and phy_write().
 | 
			
		||||
+ */
 | 
			
		||||
+int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
 | 
			
		||||
+		     u16 mask, u16 set)
 | 
			
		||||
+{
 | 
			
		||||
+	int ret = 0, oldpage;
 | 
			
		||||
+
 | 
			
		||||
+	oldpage = phy_select_page(phydev, page);
 | 
			
		||||
+	if (oldpage >= 0)
 | 
			
		||||
+		ret = __phy_modify(phydev, regnum, mask, set);
 | 
			
		||||
+
 | 
			
		||||
+	return phy_restore_page(phydev, oldpage, ret);
 | 
			
		||||
+}
 | 
			
		||||
+EXPORT_SYMBOL(phy_modify_paged);
 | 
			
		||||
diff --git a/include/linux/phy.h b/include/linux/phy.h
 | 
			
		||||
index a8118cc313ea..2ac6fa7dd785 100644
 | 
			
		||||
--- a/include/linux/phy.h
 | 
			
		||||
+++ b/include/linux/phy.h
 | 
			
		||||
@@ -632,6 +632,9 @@ struct phy_driver {
 | 
			
		||||
 	int (*write_mmd)(struct phy_device *dev, int devnum, u16 regnum,
 | 
			
		||||
 			 u16 val);
 | 
			
		||||
 
 | 
			
		||||
+	int (*read_page)(struct phy_device *dev);
 | 
			
		||||
+	int (*write_page)(struct phy_device *dev, int page);
 | 
			
		||||
+
 | 
			
		||||
 	/* Get the size and type of the eeprom contained within a plug-in
 | 
			
		||||
 	 * module */
 | 
			
		||||
 	int (*module_info)(struct phy_device *dev,
 | 
			
		||||
@@ -820,6 +823,14 @@ static inline bool phy_is_pseudo_fixed_link(struct phy_device *phydev)
 | 
			
		||||
  */
 | 
			
		||||
 int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val);
 | 
			
		||||
 
 | 
			
		||||
+int phy_save_page(struct phy_device *phydev);
 | 
			
		||||
+int phy_select_page(struct phy_device *phydev, int page);
 | 
			
		||||
+int phy_restore_page(struct phy_device *phydev, int oldpage, int ret);
 | 
			
		||||
+int phy_read_paged(struct phy_device *phydev, int page, u32 regnum);
 | 
			
		||||
+int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val);
 | 
			
		||||
+int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
 | 
			
		||||
+		     u16 mask, u16 set);
 | 
			
		||||
+
 | 
			
		||||
 struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
 | 
			
		||||
 				     bool is_c45,
 | 
			
		||||
 				     struct phy_c45_device_ids *c45_ids);
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,263 @@
 | 
			
		|||
From 354898f0a0f4a62ab950e826c8c598fc78378b06 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Raghuram Chary J <raghuramchary.jallipalli@microchip.com>
 | 
			
		||||
Date: Wed, 11 Apr 2018 20:36:36 +0530
 | 
			
		||||
Subject: [PATCH 326/340] lan78xx: PHY DSP registers initialization to address
 | 
			
		||||
 EEE link drop issues with long cables
 | 
			
		||||
 | 
			
		||||
commit 1c2734b31d72316e3faaad88c0c9c46fa92a4b20 upstream.
 | 
			
		||||
 | 
			
		||||
The patch is to configure DSP registers of PHY device
 | 
			
		||||
to handle Gbe-EEE failures with >40m cable length.
 | 
			
		||||
 | 
			
		||||
Fixes: 55d7de9de6c3 ("Microchip's LAN7800 family USB 2/3 to 10/100/1000 Ethernet device driver")
 | 
			
		||||
Signed-off-by: Raghuram Chary J <raghuramchary.jallipalli@microchip.com>
 | 
			
		||||
Signed-off-by: David S. Miller <davem@davemloft.net>
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/phy/microchip.c  | 178 ++++++++++++++++++++++++++++++++++++++++++-
 | 
			
		||||
 include/linux/microchipphy.h |   8 ++
 | 
			
		||||
 2 files changed, 185 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c
 | 
			
		||||
index 37ee856c7680..5418c662b08c 100644
 | 
			
		||||
--- a/drivers/net/phy/microchip.c
 | 
			
		||||
+++ b/drivers/net/phy/microchip.c
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
 #include <linux/ethtool.h>
 | 
			
		||||
 #include <linux/phy.h>
 | 
			
		||||
 #include <linux/microchipphy.h>
 | 
			
		||||
+#include <linux/delay.h>
 | 
			
		||||
 
 | 
			
		||||
 #define DRIVER_AUTHOR	"WOOJUNG HUH <woojung.huh@microchip.com>"
 | 
			
		||||
 #define DRIVER_DESC	"Microchip LAN88XX PHY driver"
 | 
			
		||||
@@ -30,6 +31,16 @@ struct lan88xx_priv {
 | 
			
		||||
 	__u32	wolopts;
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+static int lan88xx_read_page(struct phy_device *phydev)
 | 
			
		||||
+{
 | 
			
		||||
+	return __phy_read(phydev, LAN88XX_EXT_PAGE_ACCESS);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static int lan88xx_write_page(struct phy_device *phydev, int page)
 | 
			
		||||
+{
 | 
			
		||||
+	return __phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, page);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int lan88xx_phy_config_intr(struct phy_device *phydev)
 | 
			
		||||
 {
 | 
			
		||||
 	int rc;
 | 
			
		||||
@@ -66,6 +77,150 @@ static int lan88xx_suspend(struct phy_device *phydev)
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int lan88xx_TR_reg_set(struct phy_device *phydev, u16 regaddr,
 | 
			
		||||
+			      u32 data)
 | 
			
		||||
+{
 | 
			
		||||
+	int val, save_page, ret = 0;
 | 
			
		||||
+	u16 buf;
 | 
			
		||||
+
 | 
			
		||||
+	/* Save current page */
 | 
			
		||||
+	save_page = phy_save_page(phydev);
 | 
			
		||||
+	if (save_page < 0) {
 | 
			
		||||
+		pr_warn("Failed to get current page\n");
 | 
			
		||||
+		goto err;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	/* Switch to TR page */
 | 
			
		||||
+	lan88xx_write_page(phydev, LAN88XX_EXT_PAGE_ACCESS_TR);
 | 
			
		||||
+
 | 
			
		||||
+	ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_LOW_DATA,
 | 
			
		||||
+			  (data & 0xFFFF));
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		pr_warn("Failed to write TR low data\n");
 | 
			
		||||
+		goto err;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_HIGH_DATA,
 | 
			
		||||
+			  (data & 0x00FF0000) >> 16);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		pr_warn("Failed to write TR high data\n");
 | 
			
		||||
+		goto err;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	/* Config control bits [15:13] of register */
 | 
			
		||||
+	buf = (regaddr & ~(0x3 << 13));/* Clr [14:13] to write data in reg */
 | 
			
		||||
+	buf |= 0x8000; /* Set [15] to Packet transmit */
 | 
			
		||||
+
 | 
			
		||||
+	ret = __phy_write(phydev, LAN88XX_EXT_PAGE_TR_CR, buf);
 | 
			
		||||
+	if (ret < 0) {
 | 
			
		||||
+		pr_warn("Failed to write data in reg\n");
 | 
			
		||||
+		goto err;
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
+	usleep_range(1000, 2000);/* Wait for Data to be written */
 | 
			
		||||
+	val = __phy_read(phydev, LAN88XX_EXT_PAGE_TR_CR);
 | 
			
		||||
+	if (!(val & 0x8000))
 | 
			
		||||
+		pr_warn("TR Register[0x%X] configuration failed\n", regaddr);
 | 
			
		||||
+err:
 | 
			
		||||
+	return phy_restore_page(phydev, save_page, ret);
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
+static void lan88xx_config_TR_regs(struct phy_device *phydev)
 | 
			
		||||
+{
 | 
			
		||||
+	int err;
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel 0x1, Node 0xF , Register 0x01.
 | 
			
		||||
+	 * Write 24-bit value 0x12B00A to register. Setting MrvlTrFix1000Kf,
 | 
			
		||||
+	 * MrvlTrFix1000Kp, MasterEnableTR bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x0F82, 0x12B00A);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x0F82]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'10, Node b'1101, Register 0x06.
 | 
			
		||||
+	 * Write 24-bit value 0xD2C46F to register. Setting SSTrKf1000Slv,
 | 
			
		||||
+	 * SSTrKp1000Mas bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x168C, 0xD2C46F);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x168C]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'10, Node b'1111, Register 0x11.
 | 
			
		||||
+	 * Write 24-bit value 0x620 to register. Setting rem_upd_done_thresh
 | 
			
		||||
+	 * bits
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x17A2, 0x620);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x17A2]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'10, Node b'1101, Register 0x10.
 | 
			
		||||
+	 * Write 24-bit value 0xEEFFDD to register. Setting
 | 
			
		||||
+	 * eee_TrKp1Long_1000, eee_TrKp2Long_1000, eee_TrKp3Long_1000,
 | 
			
		||||
+	 * eee_TrKp1Short_1000,eee_TrKp2Short_1000, eee_TrKp3Short_1000 bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x16A0, 0xEEFFDD);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x16A0]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'10, Node b'1101, Register 0x13.
 | 
			
		||||
+	 * Write 24-bit value 0x071448 to register. Setting
 | 
			
		||||
+	 * slv_lpi_tr_tmr_val1, slv_lpi_tr_tmr_val2 bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x16A6, 0x071448);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x16A6]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'10, Node b'1101, Register 0x12.
 | 
			
		||||
+	 * Write 24-bit value 0x13132F to register. Setting
 | 
			
		||||
+	 * slv_sigdet_timer_val1, slv_sigdet_timer_val2 bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x16A4, 0x13132F);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x16A4]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'10, Node b'1101, Register 0x14.
 | 
			
		||||
+	 * Write 24-bit value 0x0 to register. Setting eee_3level_delay,
 | 
			
		||||
+	 * eee_TrKf_freeze_delay bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x16A8, 0x0);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x16A8]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'01, Node b'1111, Register 0x34.
 | 
			
		||||
+	 * Write 24-bit value 0x91B06C to register. Setting
 | 
			
		||||
+	 * FastMseSearchThreshLong1000, FastMseSearchThreshShort1000,
 | 
			
		||||
+	 * FastMseSearchUpdGain1000 bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x0FE8, 0x91B06C);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x0FE8]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'01, Node b'1111, Register 0x3E.
 | 
			
		||||
+	 * Write 24-bit value 0xC0A028 to register. Setting
 | 
			
		||||
+	 * FastMseKp2ThreshLong1000, FastMseKp2ThreshShort1000,
 | 
			
		||||
+	 * FastMseKp2UpdGain1000, FastMseKp2ExitEn1000 bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x0FFC, 0xC0A028);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x0FFC]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'01, Node b'1111, Register 0x35.
 | 
			
		||||
+	 * Write 24-bit value 0x041600 to register. Setting
 | 
			
		||||
+	 * FastMseSearchPhShNum1000, FastMseSearchClksPerPh1000,
 | 
			
		||||
+	 * FastMsePhChangeDelay1000 bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x0FEA, 0x041600);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x0FEA]\n");
 | 
			
		||||
+
 | 
			
		||||
+	/* Get access to Channel b'10, Node b'1101, Register 0x03.
 | 
			
		||||
+	 * Write 24-bit value 0x000004 to register. Setting TrFreeze bits.
 | 
			
		||||
+	 */
 | 
			
		||||
+	err = lan88xx_TR_reg_set(phydev, 0x1686, 0x000004);
 | 
			
		||||
+	if (err < 0)
 | 
			
		||||
+		pr_warn("Failed to Set Register[0x1686]\n");
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int lan88xx_probe(struct phy_device *phydev)
 | 
			
		||||
 {
 | 
			
		||||
 	struct device *dev = &phydev->mdio.dev;
 | 
			
		||||
@@ -132,6 +287,25 @@ static void lan88xx_set_mdix(struct phy_device *phydev)
 | 
			
		||||
 	phy_write(phydev, LAN88XX_EXT_PAGE_ACCESS, LAN88XX_EXT_PAGE_SPACE_0);
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int lan88xx_config_init(struct phy_device *phydev)
 | 
			
		||||
+{
 | 
			
		||||
+	int val;
 | 
			
		||||
+
 | 
			
		||||
+	genphy_config_init(phydev);
 | 
			
		||||
+	/*Zerodetect delay enable */
 | 
			
		||||
+	val = phy_read_mmd(phydev, MDIO_MMD_PCS,
 | 
			
		||||
+			   PHY_ARDENNES_MMD_DEV_3_PHY_CFG);
 | 
			
		||||
+	val |= PHY_ARDENNES_MMD_DEV_3_PHY_CFG_ZD_DLY_EN_;
 | 
			
		||||
+
 | 
			
		||||
+	phy_write_mmd(phydev, MDIO_MMD_PCS, PHY_ARDENNES_MMD_DEV_3_PHY_CFG,
 | 
			
		||||
+		      val);
 | 
			
		||||
+
 | 
			
		||||
+	/* Config DSP registers */
 | 
			
		||||
+	lan88xx_config_TR_regs(phydev);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static int lan88xx_config_aneg(struct phy_device *phydev)
 | 
			
		||||
 {
 | 
			
		||||
 	lan88xx_set_mdix(phydev);
 | 
			
		||||
@@ -151,7 +325,7 @@ static struct phy_driver microchip_phy_driver[] = {
 | 
			
		||||
 	.probe		= lan88xx_probe,
 | 
			
		||||
 	.remove		= lan88xx_remove,
 | 
			
		||||
 
 | 
			
		||||
-	.config_init	= genphy_config_init,
 | 
			
		||||
+	.config_init	= lan88xx_config_init,
 | 
			
		||||
 	.config_aneg	= lan88xx_config_aneg,
 | 
			
		||||
 	.read_status	= genphy_read_status,
 | 
			
		||||
 
 | 
			
		||||
@@ -161,6 +335,8 @@ static struct phy_driver microchip_phy_driver[] = {
 | 
			
		||||
 	.suspend	= lan88xx_suspend,
 | 
			
		||||
 	.resume		= genphy_resume,
 | 
			
		||||
 	.set_wol	= lan88xx_set_wol,
 | 
			
		||||
+	.read_page	= lan88xx_read_page,
 | 
			
		||||
+	.write_page	= lan88xx_write_page,
 | 
			
		||||
 } };
 | 
			
		||||
 
 | 
			
		||||
 module_phy_driver(microchip_phy_driver);
 | 
			
		||||
diff --git a/include/linux/microchipphy.h b/include/linux/microchipphy.h
 | 
			
		||||
index eb492d47f717..8f9c90379732 100644
 | 
			
		||||
--- a/include/linux/microchipphy.h
 | 
			
		||||
+++ b/include/linux/microchipphy.h
 | 
			
		||||
@@ -70,4 +70,12 @@
 | 
			
		||||
 #define	LAN88XX_MMD3_CHIP_ID			(32877)
 | 
			
		||||
 #define	LAN88XX_MMD3_CHIP_REV			(32878)
 | 
			
		||||
 
 | 
			
		||||
+/* DSP registers */
 | 
			
		||||
+#define PHY_ARDENNES_MMD_DEV_3_PHY_CFG		(0x806A)
 | 
			
		||||
+#define PHY_ARDENNES_MMD_DEV_3_PHY_CFG_ZD_DLY_EN_	(0x2000)
 | 
			
		||||
+#define LAN88XX_EXT_PAGE_ACCESS_TR		(0x52B5)
 | 
			
		||||
+#define LAN88XX_EXT_PAGE_TR_CR			16
 | 
			
		||||
+#define LAN88XX_EXT_PAGE_TR_LOW_DATA		17
 | 
			
		||||
+#define LAN88XX_EXT_PAGE_TR_HIGH_DATA		18
 | 
			
		||||
+
 | 
			
		||||
 #endif /* _MICROCHIPPHY_H */
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,57 @@
 | 
			
		|||
From d8b4a08cafd4d235a49e96244427232e147de9ac Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: James Hughes <james.hughes@raspberrypi.org>
 | 
			
		||||
Date: Tue, 8 May 2018 15:03:36 +0100
 | 
			
		||||
Subject: [PATCH 327/340] Revert "Sets the BCDC priority to constant 0"
 | 
			
		||||
 | 
			
		||||
This reverts commit 8e4cdcb1c2ff7e991044e2ee01dba7f572ab29a2.
 | 
			
		||||
 | 
			
		||||
Testing the latest wireless firmware and unable to replicate the
 | 
			
		||||
bug once this change is reverted.
 | 
			
		||||
 | 
			
		||||
Test used is :
 | 
			
		||||
 | 
			
		||||
Connect a Pi wirelessly to an AP (PiA), with another device
 | 
			
		||||
connected either wirelessly or via ethernet to the same
 | 
			
		||||
network (PiB).
 | 
			
		||||
 | 
			
		||||
On PiB run
 | 
			
		||||
 | 
			
		||||
sudo tcpdump -n 'udp port 7' -v -i wlan0
 | 
			
		||||
 | 
			
		||||
On PiA,
 | 
			
		||||
 | 
			
		||||
nc -T 0x10 -u <PiB ipaddress> 7
 | 
			
		||||
 | 
			
		||||
This sends a UDP packet to port 7, with the TOS flag set to 0x10.
 | 
			
		||||
 | 
			
		||||
Previously this would NOT arrive (or sometime be very badly delayed
 | 
			
		||||
 - 10's of seconds)
 | 
			
		||||
 | 
			
		||||
Sending TOS as 0
 | 
			
		||||
 | 
			
		||||
nc -T 0x0 -u <PiB ipaddress> 7
 | 
			
		||||
 | 
			
		||||
would arrive.
 | 
			
		||||
 | 
			
		||||
Now with the change reverted but the latest wireless firmware present
 | 
			
		||||
the tests works in all cases.
 | 
			
		||||
---
 | 
			
		||||
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c | 2 +-
 | 
			
		||||
 1 file changed, 1 insertion(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
 | 
			
		||||
index b009f3083490..9f2d0b0cf6e5 100644
 | 
			
		||||
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
 | 
			
		||||
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
 | 
			
		||||
@@ -274,7 +274,7 @@ brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
 | 
			
		||||
 	if (pktbuf->ip_summed == CHECKSUM_PARTIAL)
 | 
			
		||||
 		h->flags |= BCDC_FLAG_SUM_NEEDED;
 | 
			
		||||
 
 | 
			
		||||
-	h->priority = 0;
 | 
			
		||||
+	h->priority = (pktbuf->priority & BCDC_PRIORITY_MASK);
 | 
			
		||||
 	h->flags2 = 0;
 | 
			
		||||
 	h->data_offset = offset;
 | 
			
		||||
 	BCDC_SET_IF_IDX(h, ifidx);
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,359 @@
 | 
			
		|||
From 70608893d8081e2ec4fee1b6112f7d839ae308f3 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: James Hughes <james.hughes@raspberrypi.org>
 | 
			
		||||
Date: Thu, 10 May 2018 11:34:38 +0100
 | 
			
		||||
Subject: [PATCH 328/340] Cleanup of bcm2708_fb file to kernel coding standards
 | 
			
		||||
 | 
			
		||||
Some minor change to function - remove a use of
 | 
			
		||||
in_atomic, plus replacing various debug messages
 | 
			
		||||
that manually specify the function name with
 | 
			
		||||
("%s",.__func__)
 | 
			
		||||
 | 
			
		||||
Signed-off-by: James Hughes <james.hughes@raspberrypi.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/video/fbdev/bcm2708_fb.c | 136 +++++++++++++++++++++++----------------
 | 
			
		||||
 1 file changed, 81 insertions(+), 55 deletions(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/video/fbdev/bcm2708_fb.c b/drivers/video/fbdev/bcm2708_fb.c
 | 
			
		||||
index a048c964b115..6c9ee9ca8ee2 100644
 | 
			
		||||
--- a/drivers/video/fbdev/bcm2708_fb.c
 | 
			
		||||
+++ b/drivers/video/fbdev/bcm2708_fb.c
 | 
			
		||||
@@ -41,9 +41,10 @@
 | 
			
		||||
 #define MODULE_NAME "bcm2708_fb"
 | 
			
		||||
 
 | 
			
		||||
 #ifdef BCM2708_FB_DEBUG
 | 
			
		||||
-#define print_debug(fmt,...) pr_debug("%s:%s:%d: "fmt, MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
 | 
			
		||||
+#define print_debug(fmt, ...) pr_debug("%s:%s:%d: "fmt, \
 | 
			
		||||
+			MODULE_NAME, __func__, __LINE__, ##__VA_ARGS__)
 | 
			
		||||
 #else
 | 
			
		||||
-#define print_debug(fmt,...)
 | 
			
		||||
+#define print_debug(fmt, ...)
 | 
			
		||||
 #endif
 | 
			
		||||
 
 | 
			
		||||
 /* This is limited to 16 characters when displayed by X startup */
 | 
			
		||||
@@ -51,10 +52,10 @@ static const char *bcm2708_name = "BCM2708 FB";
 | 
			
		||||
 
 | 
			
		||||
 #define DRIVER_NAME "bcm2708_fb"
 | 
			
		||||
 
 | 
			
		||||
-static int fbwidth = 800;  /* module parameter */
 | 
			
		||||
-static int fbheight = 480; /* module parameter */
 | 
			
		||||
-static int fbdepth = 32;   /* module parameter */
 | 
			
		||||
-static int fbswap = 0;     /* module parameter */
 | 
			
		||||
+static int fbwidth = 800;	/* module parameter */
 | 
			
		||||
+static int fbheight = 480;	/* module parameter */
 | 
			
		||||
+static int fbdepth = 32;	/* module parameter */
 | 
			
		||||
+static int fbswap;		/* module parameter */
 | 
			
		||||
 
 | 
			
		||||
 static u32 dma_busy_wait_threshold = 1<<15;
 | 
			
		||||
 module_param(dma_busy_wait_threshold, int, 0644);
 | 
			
		||||
@@ -221,11 +222,13 @@ static int bcm2708_fb_check_var(struct fb_var_screeninfo *var,
 | 
			
		||||
 				struct fb_info *info)
 | 
			
		||||
 {
 | 
			
		||||
 	/* info input, var output */
 | 
			
		||||
-	print_debug("bcm2708_fb_check_var info(%p) %dx%d (%dx%d), %d, %d\n", info,
 | 
			
		||||
+	print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n",
 | 
			
		||||
+		__func__,
 | 
			
		||||
+		info,
 | 
			
		||||
 		info->var.xres, info->var.yres, info->var.xres_virtual,
 | 
			
		||||
 		info->var.yres_virtual, (int)info->screen_size,
 | 
			
		||||
 		info->var.bits_per_pixel);
 | 
			
		||||
-	print_debug("bcm2708_fb_check_var var(%p) %dx%d (%dx%d), %d\n", var,
 | 
			
		||||
+	print_debug("%s(%p) %dx%d (%dx%d), %d\n", __func__, var,
 | 
			
		||||
 		var->xres, var->yres, var->xres_virtual, var->yres_virtual,
 | 
			
		||||
 		var->bits_per_pixel);
 | 
			
		||||
 
 | 
			
		||||
@@ -233,7 +236,7 @@ static int bcm2708_fb_check_var(struct fb_var_screeninfo *var,
 | 
			
		||||
 		var->bits_per_pixel = 16;
 | 
			
		||||
 
 | 
			
		||||
 	if (bcm2708_fb_set_bitfields(var) != 0) {
 | 
			
		||||
-		pr_err("bcm2708_fb_check_var: invalid bits_per_pixel %d\n",
 | 
			
		||||
+		pr_err("%s: invalid bits_per_pixel %d\n", __func__,
 | 
			
		||||
 		     var->bits_per_pixel);
 | 
			
		||||
 		return -EINVAL;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -245,9 +248,8 @@ static int bcm2708_fb_check_var(struct fb_var_screeninfo *var,
 | 
			
		||||
 	if (var->yres_virtual == -1) {
 | 
			
		||||
 		var->yres_virtual = 480;
 | 
			
		||||
 
 | 
			
		||||
-		pr_err
 | 
			
		||||
-		    ("bcm2708_fb_check_var: virtual resolution set to maximum of %dx%d\n",
 | 
			
		||||
-		     var->xres_virtual, var->yres_virtual);
 | 
			
		||||
+		pr_err("%s: virtual resolution set to maximum of %dx%d\n",
 | 
			
		||||
+		     __func__, var->xres_virtual, var->yres_virtual);
 | 
			
		||||
 	}
 | 
			
		||||
 	if (var->yres_virtual < var->yres)
 | 
			
		||||
 		var->yres_virtual = var->yres;
 | 
			
		||||
@@ -291,7 +293,7 @@ static int bcm2708_fb_set_par(struct fb_info *info)
 | 
			
		||||
 	};
 | 
			
		||||
 	int ret;
 | 
			
		||||
 
 | 
			
		||||
-	print_debug("bcm2708_fb_set_par info(%p) %dx%d (%dx%d), %d, %d\n", info,
 | 
			
		||||
+	print_debug("%s(%p) %dx%d (%dx%d), %d, %d\n", __func__, info,
 | 
			
		||||
 		info->var.xres, info->var.yres, info->var.xres_virtual,
 | 
			
		||||
 		info->var.yres_virtual, (int)info->screen_size,
 | 
			
		||||
 		info->var.bits_per_pixel);
 | 
			
		||||
@@ -326,11 +328,12 @@ static int bcm2708_fb_set_par(struct fb_info *info)
 | 
			
		||||
 		return -ENOMEM;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	print_debug
 | 
			
		||||
-	    ("BCM2708FB: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
 | 
			
		||||
-	     (void *)fb->fb.screen_base, (void *)fb->fb_bus_address,
 | 
			
		||||
-	     fbinfo.xres, fbinfo.yres, fbinfo.bpp,
 | 
			
		||||
-	     fbinfo.pitch, (int)fb->fb.screen_size);
 | 
			
		||||
+	print_debug(
 | 
			
		||||
+	  "%s: start = %p,%p width=%d, height=%d, bpp=%d, pitch=%d size=%d\n",
 | 
			
		||||
+	  __func__,
 | 
			
		||||
+	  (void *)fb->fb.screen_base, (void *)fb->fb_bus_address,
 | 
			
		||||
+	  fbinfo.xres, fbinfo.yres, fbinfo.bpp,
 | 
			
		||||
+	  fbinfo.pitch, (int)fb->fb.screen_size);
 | 
			
		||||
 
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -349,7 +352,6 @@ static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
 | 
			
		||||
 {
 | 
			
		||||
 	struct bcm2708_fb *fb = to_bcm2708(info);
 | 
			
		||||
 
 | 
			
		||||
-	/*print_debug("BCM2708FB: setcolreg %d:(%02x,%02x,%02x,%02x) %x\n", regno, red, green, blue, transp, fb->fb.fix.visual);*/
 | 
			
		||||
 	if (fb->fb.var.bits_per_pixel <= 8) {
 | 
			
		||||
 		if (regno < 256) {
 | 
			
		||||
 			/* blue [23:16], green [15:8], red [7:0] */
 | 
			
		||||
@@ -357,8 +359,12 @@ static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
 | 
			
		||||
 					      ((green >> 8) & 0xff) << 8 |
 | 
			
		||||
 					      ((blue  >> 8) & 0xff) << 16;
 | 
			
		||||
 		}
 | 
			
		||||
-		/* Hack: we need to tell GPU the palette has changed, but currently bcm2708_fb_set_par takes noticable time when called for every (256) colour */
 | 
			
		||||
-		/* So just call it for what looks like the last colour in a list for now. */
 | 
			
		||||
+		/* Hack: we need to tell GPU the palette has changed, but
 | 
			
		||||
+		 * currently bcm2708_fb_set_par takes noticeable time when
 | 
			
		||||
+		 * called for every (256) colour
 | 
			
		||||
+		 * So just call it for what looks like the last colour in a
 | 
			
		||||
+		 * list for now.
 | 
			
		||||
+		 */
 | 
			
		||||
 		if (regno == 15 || regno == 255) {
 | 
			
		||||
 			struct packet {
 | 
			
		||||
 				u32 offset;
 | 
			
		||||
@@ -372,19 +378,23 @@ static int bcm2708_fb_setcolreg(unsigned int regno, unsigned int red,
 | 
			
		||||
 				return -ENOMEM;
 | 
			
		||||
 			packet->offset = 0;
 | 
			
		||||
 			packet->length = regno + 1;
 | 
			
		||||
-			memcpy(packet->cmap, fb->gpu_cmap, sizeof(packet->cmap));
 | 
			
		||||
-			ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
 | 
			
		||||
-						    packet, (2 + packet->length) * sizeof(u32));
 | 
			
		||||
+			memcpy(packet->cmap, fb->gpu_cmap,
 | 
			
		||||
+				sizeof(packet->cmap));
 | 
			
		||||
+			ret = rpi_firmware_property(fb->fw,
 | 
			
		||||
+					RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE,
 | 
			
		||||
+					packet,
 | 
			
		||||
+					(2 + packet->length) * sizeof(u32));
 | 
			
		||||
 			if (ret || packet->offset)
 | 
			
		||||
-				dev_err(info->device, "Failed to set palette (%d,%u)\n",
 | 
			
		||||
+				dev_err(info->device,
 | 
			
		||||
+					"Failed to set palette (%d,%u)\n",
 | 
			
		||||
 					ret, packet->offset);
 | 
			
		||||
 			kfree(packet);
 | 
			
		||||
 		}
 | 
			
		||||
-        } else if (regno < 16) {
 | 
			
		||||
+	} else if (regno < 16) {
 | 
			
		||||
 		fb->cmap[regno] = convert_bitfield(transp, &fb->fb.var.transp) |
 | 
			
		||||
-		    convert_bitfield(blue, &fb->fb.var.blue) |
 | 
			
		||||
-		    convert_bitfield(green, &fb->fb.var.green) |
 | 
			
		||||
-		    convert_bitfield(red, &fb->fb.var.red);
 | 
			
		||||
+		convert_bitfield(blue, &fb->fb.var.blue) |
 | 
			
		||||
+		convert_bitfield(green, &fb->fb.var.green) |
 | 
			
		||||
+		convert_bitfield(red, &fb->fb.var.red);
 | 
			
		||||
 	}
 | 
			
		||||
 	return regno > 255;
 | 
			
		||||
 }
 | 
			
		||||
@@ -412,24 +422,28 @@ static int bcm2708_fb_blank(int blank_mode, struct fb_info *info)
 | 
			
		||||
 	ret = rpi_firmware_property(fb->fw, RPI_FIRMWARE_FRAMEBUFFER_BLANK,
 | 
			
		||||
 				    &value, sizeof(value));
 | 
			
		||||
 	if (ret)
 | 
			
		||||
-		dev_err(info->device, "bcm2708_fb_blank(%d) failed: %d\n",
 | 
			
		||||
+		dev_err(info->device, "%s(%d) failed: %d\n", __func__,
 | 
			
		||||
 			blank_mode, ret);
 | 
			
		||||
 
 | 
			
		||||
 	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
 | 
			
		||||
+static int bcm2708_fb_pan_display(struct fb_var_screeninfo *var,
 | 
			
		||||
+				  struct fb_info *info)
 | 
			
		||||
 {
 | 
			
		||||
 	s32 result;
 | 
			
		||||
+
 | 
			
		||||
 	info->var.xoffset = var->xoffset;
 | 
			
		||||
 	info->var.yoffset = var->yoffset;
 | 
			
		||||
 	result = bcm2708_fb_set_par(info);
 | 
			
		||||
 	if (result != 0)
 | 
			
		||||
-		pr_err("bcm2708_fb_pan_display(%d,%d) returns=%d\n", var->xoffset, var->yoffset, result);
 | 
			
		||||
+		pr_err("%s(%d,%d) returns=%d\n", __func__,
 | 
			
		||||
+			var->xoffset, var->yoffset, result);
 | 
			
		||||
 	return result;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, int size)
 | 
			
		||||
+static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src,
 | 
			
		||||
+		       int size)
 | 
			
		||||
 {
 | 
			
		||||
 	int burst_size = (fb->dma_chan == 0) ? 8 : 2;
 | 
			
		||||
 	struct bcm2708_dma_cb *cb = fb->cb_base;
 | 
			
		||||
@@ -450,6 +464,7 @@ static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, in
 | 
			
		||||
 		bcm_dma_wait_idle(fb->dma_chan_base);
 | 
			
		||||
 	} else {
 | 
			
		||||
 		void __iomem *dma_chan = fb->dma_chan_base;
 | 
			
		||||
+
 | 
			
		||||
 		cb->info |= BCM2708_DMA_INT_EN;
 | 
			
		||||
 		bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
 | 
			
		||||
 		while (bcm_dma_is_busy(dma_chan)) {
 | 
			
		||||
@@ -462,8 +477,10 @@ static void dma_memcpy(struct bcm2708_fb *fb, dma_addr_t dst, dma_addr_t src, in
 | 
			
		||||
 	fb->stats.dma_copies++;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-#define INTALIAS_NORMAL(x) ((x)&~0xc0000000) // address with no aliases
 | 
			
		||||
-#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000) // cache coherent but non-allocating in L1 and L2
 | 
			
		||||
+/* address with no aliases */
 | 
			
		||||
+#define INTALIAS_NORMAL(x) ((x)&~0xc0000000)
 | 
			
		||||
+/* cache coherent but non-allocating in L1 and L2 */
 | 
			
		||||
+#define INTALIAS_L1L2_NONALLOCATING(x) (((x)&~0xc0000000)|0x80000000)
 | 
			
		||||
 
 | 
			
		||||
 static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
 | 
			
		||||
 {
 | 
			
		||||
@@ -475,8 +492,7 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
 | 
			
		||||
 	size_t offset;
 | 
			
		||||
 
 | 
			
		||||
 	/* restrict this to root user */
 | 
			
		||||
-	if (!uid_eq(current_euid(), GLOBAL_ROOT_UID))
 | 
			
		||||
-	{
 | 
			
		||||
+	if (!uid_eq(current_euid(), GLOBAL_ROOT_UID)) {
 | 
			
		||||
 		rc = -EFAULT;
 | 
			
		||||
 		goto out;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -492,12 +508,16 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
 	if (fb->gpu.base == 0 || fb->gpu.length == 0) {
 | 
			
		||||
-		pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n", __func__, fb->gpu.base, fb->gpu.length);
 | 
			
		||||
+		pr_err("[%s]: Unable to determine gpu memory (%x,%x)\n",
 | 
			
		||||
+			__func__, fb->gpu.base, fb->gpu.length);
 | 
			
		||||
 		return -EFAULT;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
-	if (INTALIAS_NORMAL(ioparam.src) < fb->gpu.base || INTALIAS_NORMAL(ioparam.src) >= fb->gpu.base + fb->gpu.length) {
 | 
			
		||||
-		pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__, INTALIAS_NORMAL(ioparam.src), fb->gpu.base, fb->gpu.base + fb->gpu.length);
 | 
			
		||||
+	if (INTALIAS_NORMAL(ioparam.src) < fb->gpu.base ||
 | 
			
		||||
+		INTALIAS_NORMAL(ioparam.src) >= fb->gpu.base + fb->gpu.length) {
 | 
			
		||||
+		pr_err("[%s]: Invalid memory access %x (%x-%x)", __func__,
 | 
			
		||||
+			INTALIAS_NORMAL(ioparam.src), fb->gpu.base,
 | 
			
		||||
+			fb->gpu.base + fb->gpu.length);
 | 
			
		||||
 		return -EFAULT;
 | 
			
		||||
 	}
 | 
			
		||||
 
 | 
			
		||||
@@ -515,7 +535,9 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
 | 
			
		||||
 		size_t s = min(size, remaining);
 | 
			
		||||
 		unsigned char *p = (unsigned char *)ioparam.src + offset;
 | 
			
		||||
 		unsigned char *q = (unsigned char *)ioparam.dst + offset;
 | 
			
		||||
-		dma_memcpy(fb, bus_addr, INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
 | 
			
		||||
+
 | 
			
		||||
+		dma_memcpy(fb, bus_addr,
 | 
			
		||||
+			   INTALIAS_L1L2_NONALLOCATING((dma_addr_t)p), size);
 | 
			
		||||
 		if (copy_to_user(q, buf, s) != 0) {
 | 
			
		||||
 			pr_err("[%s]: failed to copy-to-user\n",
 | 
			
		||||
 					__func__);
 | 
			
		||||
@@ -525,11 +547,13 @@ static long vc_mem_copy(struct bcm2708_fb *fb, unsigned long arg)
 | 
			
		||||
 	}
 | 
			
		||||
 out:
 | 
			
		||||
 	if (buf)
 | 
			
		||||
-		dma_free_coherent(fb->fb.device, PAGE_ALIGN(size), buf, bus_addr);
 | 
			
		||||
+		dma_free_coherent(fb->fb.device, PAGE_ALIGN(size), buf,
 | 
			
		||||
+				  bus_addr);
 | 
			
		||||
 	return rc;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 | 
			
		||||
+static int bcm2708_ioctl(struct fb_info *info, unsigned int cmd,
 | 
			
		||||
+			 unsigned long arg)
 | 
			
		||||
 {
 | 
			
		||||
 	struct bcm2708_fb *fb = to_bcm2708(info);
 | 
			
		||||
 	u32 dummy = 0;
 | 
			
		||||
@@ -593,13 +617,13 @@ static void bcm2708_fb_copyarea(struct fb_info *info,
 | 
			
		||||
 	struct bcm2708_fb *fb = to_bcm2708(info);
 | 
			
		||||
 	struct bcm2708_dma_cb *cb = fb->cb_base;
 | 
			
		||||
 	int bytes_per_pixel = (info->var.bits_per_pixel + 7) >> 3;
 | 
			
		||||
+
 | 
			
		||||
 	/* Channel 0 supports larger bursts and is a bit faster */
 | 
			
		||||
 	int burst_size = (fb->dma_chan == 0) ? 8 : 2;
 | 
			
		||||
 	int pixels = region->width * region->height;
 | 
			
		||||
 
 | 
			
		||||
 	/* Fallback to cfb_copyarea() if we don't like something */
 | 
			
		||||
-	if (in_atomic() ||
 | 
			
		||||
-	    bytes_per_pixel > 4 ||
 | 
			
		||||
+	if (bytes_per_pixel > 4 ||
 | 
			
		||||
 	    info->var.xres * info->var.yres > 1920 * 1200 ||
 | 
			
		||||
 	    region->width <= 0 || region->width > info->var.xres ||
 | 
			
		||||
 	    region->height <= 0 || region->height > info->var.yres ||
 | 
			
		||||
@@ -663,6 +687,7 @@ static void bcm2708_fb_copyarea(struct fb_info *info,
 | 
			
		||||
 	} else {
 | 
			
		||||
 		/* A single dma control block is enough. */
 | 
			
		||||
 		int sy, dy, stride;
 | 
			
		||||
+
 | 
			
		||||
 		if (region->dy <= region->sy) {
 | 
			
		||||
 			/* processing from top to bottom */
 | 
			
		||||
 			dy = region->dy;
 | 
			
		||||
@@ -694,6 +719,7 @@ static void bcm2708_fb_copyarea(struct fb_info *info,
 | 
			
		||||
 		bcm_dma_wait_idle(fb->dma_chan_base);
 | 
			
		||||
 	} else {
 | 
			
		||||
 		void __iomem *dma_chan = fb->dma_chan_base;
 | 
			
		||||
+
 | 
			
		||||
 		cb->info |= BCM2708_DMA_INT_EN;
 | 
			
		||||
 		bcm_dma_start(fb->dma_chan_base, fb->cb_handle);
 | 
			
		||||
 		while (bcm_dma_is_busy(dma_chan)) {
 | 
			
		||||
@@ -791,8 +817,8 @@ static int bcm2708_fb_register(struct bcm2708_fb *fb)
 | 
			
		||||
 	if (ret)
 | 
			
		||||
 		return ret;
 | 
			
		||||
 
 | 
			
		||||
-	print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n", fbwidth,
 | 
			
		||||
-		fbheight, fbdepth, fbswap);
 | 
			
		||||
+	print_debug("BCM2708FB: registering framebuffer (%dx%d@%d) (%d)\n",
 | 
			
		||||
+		fbwidth, fbheight, fbdepth, fbswap);
 | 
			
		||||
 
 | 
			
		||||
 	ret = register_framebuffer(&fb->fb);
 | 
			
		||||
 	print_debug("BCM2708FB: register framebuffer (%d)\n", ret);
 | 
			
		||||
@@ -813,19 +839,17 @@ static int bcm2708_fb_probe(struct platform_device *dev)
 | 
			
		||||
 
 | 
			
		||||
 	fw_np = of_parse_phandle(dev->dev.of_node, "firmware", 0);
 | 
			
		||||
 /* Remove comment when booting without Device Tree is no longer supported
 | 
			
		||||
-	if (!fw_np) {
 | 
			
		||||
-		dev_err(&dev->dev, "Missing firmware node\n");
 | 
			
		||||
-		return -ENOENT;
 | 
			
		||||
-	}
 | 
			
		||||
-*/
 | 
			
		||||
+ *	if (!fw_np) {
 | 
			
		||||
+ *		dev_err(&dev->dev, "Missing firmware node\n");
 | 
			
		||||
+ *		return -ENOENT;
 | 
			
		||||
+ *	}
 | 
			
		||||
+ */
 | 
			
		||||
 	fw = rpi_firmware_get(fw_np);
 | 
			
		||||
 	if (!fw)
 | 
			
		||||
 		return -EPROBE_DEFER;
 | 
			
		||||
 
 | 
			
		||||
 	fb = kzalloc(sizeof(struct bcm2708_fb), GFP_KERNEL);
 | 
			
		||||
 	if (!fb) {
 | 
			
		||||
-		dev_err(&dev->dev,
 | 
			
		||||
-			"could not allocate new bcm2708_fb struct\n");
 | 
			
		||||
 		ret = -ENOMEM;
 | 
			
		||||
 		goto free_region;
 | 
			
		||||
 	}
 | 
			
		||||
@@ -866,7 +890,9 @@ static int bcm2708_fb_probe(struct platform_device *dev)
 | 
			
		||||
 	fb->dev = dev;
 | 
			
		||||
 	fb->fb.device = &dev->dev;
 | 
			
		||||
 
 | 
			
		||||
-	// failure here isn't fatal, but we'll fail in vc_mem_copy if fb->gpu is not valid
 | 
			
		||||
+	/* failure here isn't fatal, but we'll fail in vc_mem_copy if
 | 
			
		||||
+	 * fb->gpu is not valid
 | 
			
		||||
+	 */
 | 
			
		||||
 	rpi_firmware_property(fb->fw,
 | 
			
		||||
 				    RPI_FIRMWARE_GET_VC_MEMORY,
 | 
			
		||||
 				    &fb->gpu, sizeof(fb->gpu));
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
From 90b8b1ffe2134a015a4427f3eccfd4ccb3a067a4 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Nick Bulleid <nedbulleid@fastmail.com>
 | 
			
		||||
Date: Thu, 10 May 2018 21:57:02 +0100
 | 
			
		||||
Subject: [PATCH 329/340] Add ability to export gpio used by gpio-poweroff
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Nick Bulleid <nedbulleid@fastmail.com>
 | 
			
		||||
---
 | 
			
		||||
 drivers/power/reset/gpio-poweroff.c | 9 +++++++++
 | 
			
		||||
 1 file changed, 9 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
 | 
			
		||||
index a030ae9fb1fc..7ed2d824e482 100644
 | 
			
		||||
--- a/drivers/power/reset/gpio-poweroff.c
 | 
			
		||||
+++ b/drivers/power/reset/gpio-poweroff.c
 | 
			
		||||
@@ -50,6 +50,7 @@ static int gpio_poweroff_probe(struct platform_device *pdev)
 | 
			
		||||
 	bool input = false;
 | 
			
		||||
 	enum gpiod_flags flags;
 | 
			
		||||
 	bool force = false;
 | 
			
		||||
+	bool export = false;
 | 
			
		||||
 
 | 
			
		||||
 	/* If a pm_power_off function has already been added, leave it alone */
 | 
			
		||||
 	force = of_property_read_bool(pdev->dev.of_node, "force");
 | 
			
		||||
@@ -70,6 +71,12 @@ static int gpio_poweroff_probe(struct platform_device *pdev)
 | 
			
		||||
 	if (IS_ERR(reset_gpio))
 | 
			
		||||
 		return PTR_ERR(reset_gpio);
 | 
			
		||||
 
 | 
			
		||||
+	export = of_property_read_bool(pdev->dev.of_node, "export");
 | 
			
		||||
+	if (export) {
 | 
			
		||||
+		gpiod_export(reset_gpio, false);
 | 
			
		||||
+		gpiod_export_link(&pdev->dev, "poweroff-gpio", reset_gpio);
 | 
			
		||||
+	}
 | 
			
		||||
+
 | 
			
		||||
 	pm_power_off = &gpio_poweroff_do_poweroff;
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
@@ -79,6 +86,8 @@ static int gpio_poweroff_remove(struct platform_device *pdev)
 | 
			
		||||
 	if (pm_power_off == &gpio_poweroff_do_poweroff)
 | 
			
		||||
 		pm_power_off = NULL;
 | 
			
		||||
 
 | 
			
		||||
+	gpiod_unexport(reset_gpio);
 | 
			
		||||
+
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
From 8c806666f061f04894fdf887a0ecd983765c6c84 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Nick Bulleid <nedbulleid@fastmail.com>
 | 
			
		||||
Date: Sat, 12 May 2018 20:44:34 +0100
 | 
			
		||||
Subject: [PATCH 330/340] Added export feature to gpio-poweroff documentation
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Nick Bulleid <nedbulleid@fastmail.com>
 | 
			
		||||
---
 | 
			
		||||
 Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt | 1 +
 | 
			
		||||
 1 file changed, 1 insertion(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt
 | 
			
		||||
index e62d53d844cc..c9328a9223fa 100644
 | 
			
		||||
--- a/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt
 | 
			
		||||
+++ b/Documentation/devicetree/bindings/power/reset/gpio-poweroff.txt
 | 
			
		||||
@@ -27,6 +27,7 @@ Optional properties:
 | 
			
		||||
   it to an output when the power-off handler is called. If this optional
 | 
			
		||||
   property is not specified, the GPIO is initialized as an output in its
 | 
			
		||||
   inactive state.
 | 
			
		||||
+- export : Export the GPIO line to the sysfs system
 | 
			
		||||
 
 | 
			
		||||
 Examples:
 | 
			
		||||
 
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
From 30eb4e1033a35103f27d60ba609eb466513b5465 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Nick Bulleid <nedbulleid@fastmail.com>
 | 
			
		||||
Date: Sat, 12 May 2018 23:22:37 +0100
 | 
			
		||||
Subject: [PATCH 331/340] Updated the gpio-poweroff overlay and README entry
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Nick Bulleid <nedbulleid@fastmail.com>
 | 
			
		||||
---
 | 
			
		||||
 arch/arm/boot/dts/overlays/README                    | 3 +++
 | 
			
		||||
 arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts | 2 ++
 | 
			
		||||
 2 files changed, 5 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README
 | 
			
		||||
index bea703661027..f3ec2b6d2a4f 100644
 | 
			
		||||
--- a/arch/arm/boot/dts/overlays/README
 | 
			
		||||
+++ b/arch/arm/boot/dts/overlays/README
 | 
			
		||||
@@ -595,6 +595,9 @@ Params: gpiopin                 GPIO for signalling (default 26)
 | 
			
		||||
                                 custom dt-blob.bin to prevent a power-down
 | 
			
		||||
                                 during the boot process, and that a reboot
 | 
			
		||||
                                 will also cause the pin to go low.
 | 
			
		||||
+        input                   Set if the gpio pin should be configured as
 | 
			
		||||
+                                an input.
 | 
			
		||||
+        export                  Set to export the configured pin to sysfs
 | 
			
		||||
 
 | 
			
		||||
 
 | 
			
		||||
 Name:   gpio-shutdown
 | 
			
		||||
diff --git a/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
 | 
			
		||||
index ff8cb36d94d4..b9c834960556 100644
 | 
			
		||||
--- a/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
 | 
			
		||||
+++ b/arch/arm/boot/dts/overlays/gpio-poweroff-overlay.dts
 | 
			
		||||
@@ -30,5 +30,7 @@
 | 
			
		||||
 		gpiopin =       <&power_ctrl>,"gpios:4",
 | 
			
		||||
 				<&power_ctrl_pins>,"brcm,pins:0";
 | 
			
		||||
 		active_low =    <&power_ctrl>,"gpios:8";
 | 
			
		||||
+		input =         <&power_ctrl>,"input?";
 | 
			
		||||
+		export =        <&power_ctrl>,"export?";
 | 
			
		||||
 	};
 | 
			
		||||
 };
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
From 36c9bc61e0f5b410b2939a8624d7a8312a0251ef Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
Date: Sat, 12 May 2018 21:23:00 +0100
 | 
			
		||||
Subject: [PATCH 333/340] firmware/raspberrypi: Add two new messages
 | 
			
		||||
 | 
			
		||||
RPI_FIRMWARE_GET_CLOCK_MEASURED is similar to RPI_FIRMWARE_GET_CLOCK,
 | 
			
		||||
except that it uses a hardware feature to count the clock pulses to
 | 
			
		||||
measure the real clock speed.
 | 
			
		||||
 | 
			
		||||
RPI_FIRMWARE_NOTIFY_REBOOT informs the firmware that the OS is about to
 | 
			
		||||
reboot, allowing it to make any necessary adjustments.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
---
 | 
			
		||||
 include/soc/bcm2835/raspberrypi-firmware.h | 2 ++
 | 
			
		||||
 1 file changed, 2 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/include/soc/bcm2835/raspberrypi-firmware.h b/include/soc/bcm2835/raspberrypi-firmware.h
 | 
			
		||||
index 95cb67be1d58..3c57f456a0e4 100644
 | 
			
		||||
--- a/include/soc/bcm2835/raspberrypi-firmware.h
 | 
			
		||||
+++ b/include/soc/bcm2835/raspberrypi-firmware.h
 | 
			
		||||
@@ -78,6 +78,8 @@ enum rpi_firmware_property_tag {
 | 
			
		||||
 	RPI_FIRMWARE_GET_CUSTOMER_OTP =                       0x00030021,
 | 
			
		||||
 	RPI_FIRMWARE_GET_DOMAIN_STATE =                       0x00030030,
 | 
			
		||||
 	RPI_FIRMWARE_GET_THROTTLED =                          0x00030046,
 | 
			
		||||
+	RPI_FIRMWARE_GET_CLOCK_MEASURED =                     0x00030047,
 | 
			
		||||
+	RPI_FIRMWARE_NOTIFY_REBOOT =                          0x00030048,
 | 
			
		||||
 	RPI_FIRMWARE_SET_CLOCK_STATE =                        0x00038001,
 | 
			
		||||
 	RPI_FIRMWARE_SET_CLOCK_RATE =                         0x00038002,
 | 
			
		||||
 	RPI_FIRMWARE_SET_VOLTAGE =                            0x00038003,
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,89 @@
 | 
			
		|||
From 39f45c408ab8f9cc9b9980f165e62eb92293b927 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
Date: Sat, 12 May 2018 21:35:43 +0100
 | 
			
		||||
Subject: [PATCH 334/340] firmware/raspberrypi: Notify firmware of a reboot
 | 
			
		||||
 | 
			
		||||
Register for reboot notifications, sending RPI_FIRMWARE_NOTIFY_REBOOT
 | 
			
		||||
over the mailbox interface on reception.
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
---
 | 
			
		||||
 drivers/firmware/raspberrypi.c | 40 +++++++++++++++++++++++++++++++++++++++-
 | 
			
		||||
 1 file changed, 39 insertions(+), 1 deletion(-)
 | 
			
		||||
 | 
			
		||||
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
 | 
			
		||||
index d1943a7e68cf..a82819a78f53 100644
 | 
			
		||||
--- a/drivers/firmware/raspberrypi.c
 | 
			
		||||
+++ b/drivers/firmware/raspberrypi.c
 | 
			
		||||
@@ -14,6 +14,7 @@
 | 
			
		||||
 #include <linux/module.h>
 | 
			
		||||
 #include <linux/of_platform.h>
 | 
			
		||||
 #include <linux/platform_device.h>
 | 
			
		||||
+#include <linux/reboot.h>
 | 
			
		||||
 #include <linux/workqueue.h>
 | 
			
		||||
 #include <soc/bcm2835/raspberrypi-firmware.h>
 | 
			
		||||
 
 | 
			
		||||
@@ -275,6 +276,26 @@ static int rpi_firmware_get_throttled(struct rpi_firmware *fw, u32 *value)
 | 
			
		||||
 	return 0;
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
+static int rpi_firmware_notify_reboot(struct notifier_block *nb,
 | 
			
		||||
+				      unsigned long action,
 | 
			
		||||
+				      void *data)
 | 
			
		||||
+{
 | 
			
		||||
+	struct rpi_firmware *fw;
 | 
			
		||||
+	struct platform_device *pdev = g_pdev;
 | 
			
		||||
+
 | 
			
		||||
+	if (!pdev)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	fw = platform_get_drvdata(pdev);
 | 
			
		||||
+	if (!fw)
 | 
			
		||||
+		return 0;
 | 
			
		||||
+
 | 
			
		||||
+	(void)rpi_firmware_property(fw, RPI_FIRMWARE_NOTIFY_REBOOT,
 | 
			
		||||
+				    0, 0);
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+}
 | 
			
		||||
+
 | 
			
		||||
 static void get_throttled_poll(struct work_struct *work)
 | 
			
		||||
 {
 | 
			
		||||
 	struct rpi_firmware *fw = container_of(work, struct rpi_firmware,
 | 
			
		||||
@@ -416,15 +437,32 @@ static struct platform_driver rpi_firmware_driver = {
 | 
			
		||||
 	.remove		= rpi_firmware_remove,
 | 
			
		||||
 };
 | 
			
		||||
 
 | 
			
		||||
+static struct notifier_block rpi_firmware_reboot_notifier = {
 | 
			
		||||
+	.notifier_call = rpi_firmware_notify_reboot,
 | 
			
		||||
+};
 | 
			
		||||
+
 | 
			
		||||
 static int __init rpi_firmware_init(void)
 | 
			
		||||
 {
 | 
			
		||||
-	return platform_driver_register(&rpi_firmware_driver);
 | 
			
		||||
+	int ret = register_reboot_notifier(&rpi_firmware_reboot_notifier);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		goto out1;
 | 
			
		||||
+	ret = platform_driver_register(&rpi_firmware_driver);
 | 
			
		||||
+	if (ret)
 | 
			
		||||
+		goto out2;
 | 
			
		||||
+
 | 
			
		||||
+	return 0;
 | 
			
		||||
+
 | 
			
		||||
+out2:
 | 
			
		||||
+	unregister_reboot_notifier(&rpi_firmware_reboot_notifier);
 | 
			
		||||
+out1:
 | 
			
		||||
+	return ret;
 | 
			
		||||
 }
 | 
			
		||||
 subsys_initcall(rpi_firmware_init);
 | 
			
		||||
 
 | 
			
		||||
 static void __init rpi_firmware_exit(void)
 | 
			
		||||
 {
 | 
			
		||||
 	platform_driver_unregister(&rpi_firmware_driver);
 | 
			
		||||
+	unregister_reboot_notifier(&rpi_firmware_reboot_notifier);
 | 
			
		||||
 }
 | 
			
		||||
 module_exit(rpi_firmware_exit);
 | 
			
		||||
 
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,58 @@
 | 
			
		|||
From a2a82c7437c1de1e04810d2803ef39d8fed500b4 Mon Sep 17 00:00:00 2001
 | 
			
		||||
From: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
Date: Tue, 29 May 2018 10:52:11 +0100
 | 
			
		||||
Subject: [PATCH 339/340] overlays: Add sdtweak features for network booting
 | 
			
		||||
 | 
			
		||||
It has been observed that a Pi with no SD card will poll the interface
 | 
			
		||||
continuously, using up to 10% CPU. Add some new parameters to the
 | 
			
		||||
sdtweak overlay to control this behaviour:
 | 
			
		||||
 | 
			
		||||
poll_once   Only look for a card once, at boot time. If none is found
 | 
			
		||||
            then the interface is effectively disabled.
 | 
			
		||||
 | 
			
		||||
enable      Set to "off" or "no" to completely disable the interface.
 | 
			
		||||
 | 
			
		||||
See: https://github.com/raspberrypi/linux/issues/2567
 | 
			
		||||
 | 
			
		||||
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
 | 
			
		||||
---
 | 
			
		||||
 arch/arm/boot/dts/overlays/README              | 10 ++++++++++
 | 
			
		||||
 arch/arm/boot/dts/overlays/sdtweak-overlay.dts |  2 ++
 | 
			
		||||
 2 files changed, 12 insertions(+)
 | 
			
		||||
 | 
			
		||||
diff --git a/arch/arm/boot/dts/overlays/README b/arch/arm/boot/dts/overlays/README
 | 
			
		||||
index f3ec2b6d2a4f..a9e56efd6532 100644
 | 
			
		||||
--- a/arch/arm/boot/dts/overlays/README
 | 
			
		||||
+++ b/arch/arm/boot/dts/overlays/README
 | 
			
		||||
@@ -1618,6 +1618,16 @@ Params: overclock_50            Clock (in MHz) to use when the MMC framework
 | 
			
		||||
 
 | 
			
		||||
         debug                   Enable debug output (default off)
 | 
			
		||||
 
 | 
			
		||||
+        poll_once               Looks for a card once after booting. Useful
 | 
			
		||||
+                                for network booting scenarios to avoid the
 | 
			
		||||
+                                overhead of continuous polling. N.B. Using
 | 
			
		||||
+                                this option restricts the system to using a
 | 
			
		||||
+                                single card per boot (or none at all).
 | 
			
		||||
+                                (default off)
 | 
			
		||||
+
 | 
			
		||||
+        enable                  Set to off to completely disable the interface
 | 
			
		||||
+                                (default on)
 | 
			
		||||
+
 | 
			
		||||
 
 | 
			
		||||
 Name:   smi
 | 
			
		||||
 Info:   Enables the Secondary Memory Interface peripheral. Uses GPIOs 2-25!
 | 
			
		||||
diff --git a/arch/arm/boot/dts/overlays/sdtweak-overlay.dts b/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
 | 
			
		||||
index e4a4677f6b20..5880e7cd5d1c 100644
 | 
			
		||||
--- a/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
 | 
			
		||||
+++ b/arch/arm/boot/dts/overlays/sdtweak-overlay.dts
 | 
			
		||||
@@ -19,5 +19,7 @@
 | 
			
		||||
 		force_pio        = <&frag0>,"brcm,force-pio?";
 | 
			
		||||
 		pio_limit        = <&frag0>,"brcm,pio-limit:0";
 | 
			
		||||
 		debug            = <&frag0>,"brcm,debug?";
 | 
			
		||||
+		enable           = <&frag0>,"status";
 | 
			
		||||
+		poll_once        = <&frag0>,"non-removable?";
 | 
			
		||||
 	};
 | 
			
		||||
 };
 | 
			
		||||
-- 
 | 
			
		||||
2.16.1
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue