1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-14 20:31:54 +00:00

Update RPI patches

This commit is contained in:
Ycarus 2018-06-07 10:49:48 +02:00
parent cc24592e6c
commit 50323f4caa
14 changed files with 1499 additions and 43 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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