diff options
author | Paolo Abeni <pabeni@redhat.com> | 2023-01-10 13:38:40 +0100 |
---|---|---|
committer | Paolo Abeni <pabeni@redhat.com> | 2023-01-10 13:38:40 +0100 |
commit | 96b7a9d11a92cc0b09fd645657462a9d9558ef5f (patch) | |
tree | a1f58aba00107836b94e29698c65988f2fa5af95 | |
parent | a3ae16030a0320229df10cedfeff1f80df26ee76 (diff) | |
parent | 97a89ed101bbb790e80b562f9cb95f0cfd05f430 (diff) |
Merge branch 'net-phy-mxl-gpy-broken-interrupt-fixes'
Michael Walle says:
====================
net: phy: mxl-gpy: broken interrupt fixes
The GPY215 has a broken interrupt pin. This patch series tries to
workaround that and because in general that is not possible, disables the
interrupts by default and falls back to polling mode. There is an opt-in
via the devicetree.
====================
Link: https://lore.kernel.org/r/20230109123013.3094144-1-michael@walle.cc
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
-rw-r--r-- | Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml | 47 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 | ||||
-rw-r--r-- | drivers/net/phy/mxl-gpy.c | 5 | ||||
-rw-r--r-- | drivers/net/phy/phy_device.c | 7 | ||||
-rw-r--r-- | include/linux/phy.h | 3 |
5 files changed, 64 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml b/Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml new file mode 100644 index 000000000000..d71fa9de2b64 --- /dev/null +++ b/Documentation/devicetree/bindings/net/maxlinear,gpy2xx.yaml @@ -0,0 +1,47 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/maxlinear,gpy2xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MaxLinear GPY2xx PHY + +maintainers: + - Andrew Lunn <andrew@lunn.ch> + - Michael Walle <michael@walle.cc> + +allOf: + - $ref: ethernet-phy.yaml# + +properties: + maxlinear,use-broken-interrupts: + description: | + Interrupts are broken on some GPY2xx PHYs in that they keep the + interrupt line asserted even after the interrupt status register is + cleared. Thus it is blocking the interrupt line which is usually bad + for shared lines. By default interrupts are disabled for this PHY and + polling mode is used. If one can live with the consequences, this + property can be used to enable interrupt handling. + + Affected PHYs (as far as known) are GPY215B and GPY215C. + type: boolean + +dependencies: + maxlinear,use-broken-interrupts: [ interrupts ] + +unevaluatedProperties: false + +examples: + - | + ethernet { + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@0 { + reg = <0>; + interrupts-extended = <&intc 0>; + maxlinear,use-broken-interrupts; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 70ffb3780621..161766b1de50 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -775,6 +775,8 @@ patternProperties: description: MaxBotix Inc. "^maxim,.*": description: Maxim Integrated Products + "^maxlinear,.*": + description: MaxLinear Inc. "^mbvl,.*": description: Mobiveil Inc. "^mcube,.*": diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c index 147d7a5a9b35..e5972b4ef6e8 100644 --- a/drivers/net/phy/mxl-gpy.c +++ b/drivers/net/phy/mxl-gpy.c @@ -12,6 +12,7 @@ #include <linux/mutex.h> #include <linux/phy.h> #include <linux/polynomial.h> +#include <linux/property.h> #include <linux/netdevice.h> /* PHY ID */ @@ -292,6 +293,10 @@ static int gpy_probe(struct phy_device *phydev) phydev->priv = priv; mutex_init(&priv->mbox_lock); + if (gpy_has_broken_mdint(phydev) && + !device_property_present(dev, "maxlinear,use-broken-interrupts")) + phydev->dev_flags |= PHY_F_NO_IRQ; + fw_version = phy_read(phydev, PHY_FWV); if (fw_version < 0) return fw_version; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 716870a4499c..e4562859ac00 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1487,6 +1487,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, phydev->interrupts = PHY_INTERRUPT_DISABLED; + /* PHYs can request to use poll mode even though they have an + * associated interrupt line. This could be the case if they + * detect a broken interrupt handling. + */ + if (phydev->dev_flags & PHY_F_NO_IRQ) + phydev->irq = PHY_POLL; + /* Port is set to PORT_TP by default and the actual PHY driver will set * it to different value depending on the PHY configuration. If we have * the generic PHY driver we can't figure it out, thus set the old diff --git a/include/linux/phy.h b/include/linux/phy.h index 6378c997ded5..742754d72fc0 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -739,6 +739,9 @@ struct phy_device { #endif }; +/* Generic phy_device::dev_flags */ +#define PHY_F_NO_IRQ 0x80000000 + static inline struct phy_device *to_phy_device(const struct device *dev) { return container_of(to_mdio_device(dev), struct phy_device, mdio); |