From: Jeremy Linton <hidden> Date: 2020-02-24 22:54:12
This patch series allows the BCM GENET, as used on the RPi4,
to attach when booted in an ACPI environment. The DSDT entry to
trigger this is seen below. Of note, the first patch adds a
small extension to the mdio layer which allows drivers to find
the mii_bus without firmware assistance. The fifth patch in
the set retrieves the MAC address from the umac registers
rather than carrying it directly in the DSDT. This of course
requires the firmware to pre-program it, so we continue to fall
back on a random one if it appears to be garbage.
v1 -> v2:
fail on missing phy-mode property
replace phy-mode internal property read string with
device_get_phy_mode() equivalent
rework mac address detection logic so that it merges
the acpi/DT case into device_get_mac_address()
allowing _DSD mac address properties.
some commit messages justifying why phy_find_first()
isn't the worst choice for this driver.
+ Device (ETH0)
+ {
+ Name (_HID, "BCM6E4E")
+ Name (_UID, 0)
+ Name (_CCA, 0x0)
+ Method (_STA)
+ {
+ Return (0xf)
+ }
+ Method (_CRS, 0x0, Serialized)
+ {
+ Name (RBUF, ResourceTemplate ()
+ {
+ Memory32Fixed (ReadWrite, 0xFd580000, 0x10000, )
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 0xBD }
+ Interrupt (ResourceConsumer, Level, ActiveHigh, Exclusive) { 0xBE }
+ })
+ Return (RBUF)
+ }
+ Name (_DSD, Package () {
+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+ Package () {
+ Package () { "phy-mode", "rgmii-rxid" },
+ }
+ })
+ }
Jeremy Linton (6):
mdio_bus: Add generic mdio_find_bus()
net: bcmgenet: refactor phy mode configuration
net: bcmgenet: enable automatic phy discovery
net: bcmgenet: Initial bcmgenet ACPI support
net: bcmgenet: Fetch MAC address from the adapter
net: bcmgenet: reduce severity of missing clock warnings
.../net/ethernet/broadcom/genet/bcmgenet.c | 62 +++++++++-----
drivers/net/ethernet/broadcom/genet/bcmmii.c | 82 ++++++++++++++-----
drivers/net/phy/mdio_bus.c | 17 ++++
include/linux/phy.h | 1 +
4 files changed, 120 insertions(+), 42 deletions(-)
--
2.24.1
From: Jeremy Linton <hidden> Date: 2020-02-24 22:54:14
It appears most ethernet drivers follow one of two main strategies
for mdio bus/phy management. A monolithic model where the net driver
itself creates, probes and uses the phy, and one where an external
mdio/phy driver instantiates the mdio bus/phy and the net driver
only attaches to a known phy. Usually in this latter model the phys
are discovered via DT relationships or simply phy name/address
hardcoding.
This is a shame because modern well behaved mdio buses are self
describing and can be probed. The mdio layer itself is fully capable
of this, yet there isn't a clean way for a standalone net driver
to attach and enumerate the discovered devices. This is because
outside of of_mdio_find_bus() there isn't a straightforward way
to acquire the mii_bus pointer.
So, lets add a mdio_find_bus which can return the mii_bus based
only on its name.
Signed-off-by: Jeremy Linton <redacted>
---
drivers/net/phy/mdio_bus.c | 17 +++++++++++++++++
include/linux/phy.h | 1 +
2 files changed, 18 insertions(+)
From: Jeremy Linton <hidden> Date: 2020-02-24 22:54:19
If one types "failed to get enet clock" or similar into google
there are ~370k hits. The vast majority are people debugging
problems unrelated to this adapter, or bragging about their
rpi's. Further, the DT clock bindings here are optional.
Given that its not a fatal situation with common DT based
systems, lets reduce the severity so people aren't seeing failure
messages in everyday operation.
Signed-off-by: Jeremy Linton <redacted>
Reviewed-by: Nicolas Saenz Julienne <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/genet/bcmgenet.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -3562,7 +3562,7 @@ static int bcmgenet_probe(struct platform_device *pdev)priv->clk=devm_clk_get(&priv->pdev->dev,"enet");if(IS_ERR(priv->clk)){-dev_warn(&priv->pdev->dev,"failed to get enet clock\n");+dev_dbg(&priv->pdev->dev,"failed to get enet clock\n");priv->clk=NULL;}
@@ -3586,13 +3586,13 @@ static int bcmgenet_probe(struct platform_device *pdev)priv->clk_wol=devm_clk_get(&priv->pdev->dev,"enet-wol");if(IS_ERR(priv->clk_wol)){-dev_warn(&priv->pdev->dev,"failed to get enet-wol clock\n");+dev_dbg(&priv->pdev->dev,"failed to get enet-wol clock\n");priv->clk_wol=NULL;}priv->clk_eee=devm_clk_get(&priv->pdev->dev,"enet-eee");if(IS_ERR(priv->clk_eee)){-dev_warn(&priv->pdev->dev,"failed to get enet-eee clock\n");+dev_dbg(&priv->pdev->dev,"failed to get enet-eee clock\n");priv->clk_eee=NULL;}
From: Jeremy Linton <hidden> Date: 2020-02-24 22:54:23
ARM/ACPI machines should utilize self describing hardware
when possible. The MAC address on the BCMGENET can be
read from the adapter if a full featured firmware has already
programmed it. Lets try using the address already programmed,
if it appears to be valid.
It should be noted that while we move the macaddr logic below
the clock and power logic in the driver, none of that code will
ever be active in an ACPI environment as the device will be
attached to the acpi power domain, and brought to full power
with all clocks enabled immediately before the device probe
routine is called.
One side effect of the above tweak is that while its now
possible to read the MAC address via _DSD properties, it should
be avoided.
Signed-off-by: Jeremy Linton <redacted>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
---
.../net/ethernet/broadcom/genet/bcmgenet.c | 39 +++++++++++++------
1 file changed, 27 insertions(+), 12 deletions(-)
From: Jeremy Linton <hidden> Date: 2020-02-24 22:54:27
The unimac mdio driver falls back to scanning the
entire bus if its given an appropriate mask. In ACPI
mode we expect that the system is well behaved and
conforms to recent versions of the specification.
We then utilize phy_find_first(), and
phy_connect_direct() to find and attach to the
discovered phy during net_device open. While its
apparently possible to build a genet based device
with multiple phys on a single mdio bus, this works
for current machines. Further, this driver makes
a number of assumptions about the platform device,
mac, mdio and phy all being 1:1. Lastly, It also
avoids having to create references across the ACPI
namespace hierarchy.
Signed-off-by: Jeremy Linton <redacted>
---
drivers/net/ethernet/broadcom/genet/bcmmii.c | 39 +++++++++++++++++---
1 file changed, 33 insertions(+), 6 deletions(-)
@@ -311,7 +311,8 @@ int bcmgenet_mii_config(struct net_device *dev, bool init)intbcmgenet_mii_probe(structnet_device*dev){structbcmgenet_priv*priv=netdev_priv(dev);-structdevice_node*dn=priv->pdev->dev.of_node;+structdevice*kdev=&priv->pdev->dev;+structdevice_node*dn=kdev->of_node;structphy_device*phydev;u32phy_flags=0;intret;
@@ -334,7 +335,27 @@ int bcmgenet_mii_probe(struct net_device *dev)return-ENODEV;}}else{-phydev=dev->phydev;+if(has_acpi_companion(kdev)){+charmdio_bus_id[MII_BUS_ID_SIZE];+structmii_bus*unimacbus;++snprintf(mdio_bus_id,MII_BUS_ID_SIZE,"%s-%d",+UNIMAC_MDIO_DRV_NAME,priv->pdev->id);++unimacbus=mdio_find_bus(mdio_bus_id);+if(!unimacbus){+pr_err("Unable to find mii\n");+return-ENODEV;+}+phydev=phy_find_first(unimacbus);+put_device(&unimacbus->dev);+if(!phydev){+pr_err("Unable to find PHY\n");+return-ENODEV;+}+}else{+phydev=dev->phydev;+}phydev->dev_flags=phy_flags;ret=phy_connect_direct(dev,phydev,bcmgenet_mii_setup,
@@ -455,9 +476,12 @@ static int bcmgenet_mii_register(struct bcmgenet_priv *priv)/* Retain this platform_device pointer for later cleanup */priv->mii_pdev=ppdev;ppdev->dev.parent=&pdev->dev;-ppdev->dev.of_node=bcmgenet_mii_of_find_mdio(priv);-if(pdata)+if(dn)+ppdev->dev.of_node=bcmgenet_mii_of_find_mdio(priv);+elseif(pdata)bcmgenet_mii_pdata_init(priv,&ppd);+else+ppd.phy_mask=~0;ret=platform_device_add_resources(ppdev,&res,1);if(ret)
@@ -591,10 +615,13 @@ static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)staticintbcmgenet_mii_bus_init(structbcmgenet_priv*priv){-structdevice_node*dn=priv->pdev->dev.of_node;+structdevice*kdev=&priv->pdev->dev;+structdevice_node*dn=kdev->of_node;if(dn)returnbcmgenet_mii_of_init(priv);+elseif(has_acpi_companion(kdev))+returnbcmgenet_phy_interface_init(priv);elsereturnbcmgenet_mii_pd_init(priv);}
From: Jeremy Linton <hidden> Date: 2020-02-24 22:54:33
The rpi4 is capable of booting in ACPI mode with the latest
edk2-platform commits. As such it would be helpful if the genet
platform device were usable.
To achieve this we add a new MODULE_DEVICE_TABLE, and convert
a few dt specific methods to their generic device_ calls. Until
the next patch, ACPI based machines will fallback on random
mac addresses.
Signed-off-by: Jeremy Linton <redacted>
---
.../net/ethernet/broadcom/genet/bcmgenet.c | 21 ++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
@@ -3466,10 +3467,9 @@ static int bcmgenet_probe(struct platform_device *pdev)conststructbcmgenet_plat_data*pdata;structbcmgenet_priv*priv;structnet_device*dev;-constvoid*macaddr;+constvoid*macaddr=NULL;unsignedinti;interr=-EIO;-constchar*phy_mode_str;/* Up to GENET_MAX_MQ_CNT + 1 TX queues and RX queues */dev=alloc_etherdev_mqs(sizeof(*priv),GENET_MAX_MQ_CNT+1,
@@ -3500,7 +3500,7 @@ static int bcmgenet_probe(struct platform_device *pdev)if(dn)macaddr=of_get_mac_address(dn);-else+elseif(pd)macaddr=pd->mac_address;priv->base=devm_platform_ioremap_resource(pdev,0);
@@ -3547,8 +3547,9 @@ static int bcmgenet_probe(struct platform_device *pdev)priv->dev=dev;priv->pdev=pdev;-if(of_id){-pdata=of_id->data;++pdata=device_get_match_data(&pdev->dev);+if(pdata){priv->version=pdata->version;priv->dma_max_burst_length=pdata->dma_max_burst_length;}else{
@@ -3595,8 +3596,7 @@ static int bcmgenet_probe(struct platform_device *pdev)/* If this is an internal GPHY, power it on now, before UniMAC is*broughtoutofresetasabsolutelynoUniMACactivityisallowed*/-if(dn&&!of_property_read_string(dn,"phy-mode",&phy_mode_str)&&-!strcasecmp(phy_mode_str,"internal"))+if(device_get_phy_mode(&pdev->dev)==PHY_INTERFACE_MODE_INTERNAL)bcmgenet_power_up(priv,GENET_POWER_PASSIVE);reset_umac(priv);
@@ -3771,6 +3771,12 @@ static int bcmgenet_suspend(struct device *d)staticSIMPLE_DEV_PM_OPS(bcmgenet_pm_ops,bcmgenet_suspend,bcmgenet_resume);+staticconststructacpi_device_idgenet_acpi_match[]={+{"BCM6E4E",(kernel_ulong_t)&bcm2711_plat_data},+{},+};+MODULE_DEVICE_TABLE(acpi,genet_acpi_match);+staticstructplatform_driverbcmgenet_driver={.probe=bcmgenet_probe,.remove=bcmgenet_remove,
From: Jeremy Linton <hidden> Date: 2020-02-24 22:54:39
The DT phy mode is similar to what we want for ACPI
lets factor it out of the of path, and change the
of_ call to device_.
Signed-off-by: Jeremy Linton <redacted>
---
drivers/net/ethernet/broadcom/genet/bcmmii.c | 42 ++++++++++++--------
1 file changed, 26 insertions(+), 16 deletions(-)
@@ -477,12 +477,33 @@ static int bcmgenet_mii_register(struct bcmgenet_priv *priv)returnret;}+staticintbcmgenet_phy_interface_init(structbcmgenet_priv*priv)+{+structdevice*kdev=&priv->pdev->dev;+intphy_mode=device_get_phy_mode(kdev);++if(phy_mode<0){+dev_err(kdev,"invalid PHY mode property\n");+returnphy_mode;+}++priv->phy_interface=phy_mode;++/* We need to specifically look up whether this PHY interface is+*internalornot*before*weeventrytoprobethePHYdriver+*overMDIOaswemayhaveshutdowntheinternalPHYforpower+*savingpurposes.+*/+if(priv->phy_interface==PHY_INTERFACE_MODE_INTERNAL)+priv->internal_phy=true;++return0;+}+staticintbcmgenet_mii_of_init(structbcmgenet_priv*priv){structdevice_node*dn=priv->pdev->dev.of_node;-structdevice*kdev=&priv->pdev->dev;structphy_device*phydev;-phy_interface_tphy_mode;intret;/* Fetch the PHY phandle */
@@ -500,23 +521,12 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)}/* Get the link mode */-ret=of_get_phy_mode(dn,&phy_mode);-if(ret){-dev_err(kdev,"invalid PHY mode property\n");+ret=bcmgenet_phy_interface_init(priv);+if(ret)returnret;-}--priv->phy_interface=phy_mode;--/* We need to specifically look up whether this PHY interface is internal-*ornot*before*weeventrytoprobethePHYdriveroverMDIOaswe-*mayhaveshutdowntheinternalPHYforpowersavingpurposes.-*/-if(priv->phy_interface==PHY_INTERFACE_MODE_INTERNAL)-priv->internal_phy=true;/* Make sure we initialize MoCA PHYs with a link down */-if(phy_mode==PHY_INTERFACE_MODE_MOCA){+if(priv->phy_interface==PHY_INTERFACE_MODE_MOCA){phydev=of_phy_find_device(dn);if(phydev){phydev->link=0;
The DT phy mode is similar to what we want for ACPI
lets factor it out of the of path, and change the
of_ call to device_.
Signed-off-by: Jeremy Linton <redacted>
The rpi4 is capable of booting in ACPI mode with the latest
edk2-platform commits. As such it would be helpful if the genet
platform device were usable.
To achieve this we add a new MODULE_DEVICE_TABLE, and convert
a few dt specific methods to their generic device_ calls. Until
the next patch, ACPI based machines will fallback on random
mac addresses.
Signed-off-by: Jeremy Linton <redacted>
It appears most ethernet drivers follow one of two main strategies
for mdio bus/phy management. A monolithic model where the net driver
itself creates, probes and uses the phy, and one where an external
mdio/phy driver instantiates the mdio bus/phy and the net driver
only attaches to a known phy. Usually in this latter model the phys
are discovered via DT relationships or simply phy name/address
hardcoding.
This is a shame because modern well behaved mdio buses are self
describing and can be probed. The mdio layer itself is fully capable
of this, yet there isn't a clean way for a standalone net driver
to attach and enumerate the discovered devices. This is because
outside of of_mdio_find_bus() there isn't a straightforward way
to acquire the mii_bus pointer.
So, lets add a mdio_find_bus which can return the mii_bus based
only on its name.
Signed-off-by: Jeremy Linton <redacted>
This patch series allows the BCM GENET, as used on the RPi4,
to attach when booted in an ACPI environment. The DSDT entry to
trigger this is seen below. Of note, the first patch adds a
small extension to the mdio layer which allows drivers to find
the mii_bus without firmware assistance. The fifth patch in
the set retrieves the MAC address from the umac registers
rather than carrying it directly in the DSDT. This of course
requires the firmware to pre-program it, so we continue to fall
back on a random one if it appears to be garbage.
Thanks for your persistence on this I was able to apply this to the
latest net-next tree and give this a spin on a STB chip (which uses DT)
and did not see any issues, so:
Tested-by: Florian Fainelli <f.fainelli@gmail.com>
Thanks!
--
Florian
This patch series allows the BCM GENET, as used on the RPi4,
to attach when booted in an ACPI environment. The DSDT entry to
trigger this is seen below. Of note, the first patch adds a
small extension to the mdio layer which allows drivers to find
the mii_bus without firmware assistance. The fifth patch in
the set retrieves the MAC address from the umac registers
rather than carrying it directly in the DSDT. This of course
requires the firmware to pre-program it, so we continue to fall
back on a random one if it appears to be garbage.
Thanks for your persistence on this I was able to apply this to the
latest net-next tree and give this a spin on a STB chip (which uses DT)
and did not see any issues, so:
Tested-by: Florian Fainelli <f.fainelli@gmail.com>