Commit 96b7a9d1 authored by Paolo Abeni's avatar Paolo Abeni

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.ccSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents a3ae1603 97a89ed1
# 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;
};
};
...
...@@ -775,6 +775,8 @@ patternProperties: ...@@ -775,6 +775,8 @@ patternProperties:
description: MaxBotix Inc. description: MaxBotix Inc.
"^maxim,.*": "^maxim,.*":
description: Maxim Integrated Products description: Maxim Integrated Products
"^maxlinear,.*":
description: MaxLinear Inc.
"^mbvl,.*": "^mbvl,.*":
description: Mobiveil Inc. description: Mobiveil Inc.
"^mcube,.*": "^mcube,.*":
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/phy.h> #include <linux/phy.h>
#include <linux/polynomial.h> #include <linux/polynomial.h>
#include <linux/property.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
/* PHY ID */ /* PHY ID */
...@@ -292,6 +293,10 @@ static int gpy_probe(struct phy_device *phydev) ...@@ -292,6 +293,10 @@ static int gpy_probe(struct phy_device *phydev)
phydev->priv = priv; phydev->priv = priv;
mutex_init(&priv->mbox_lock); 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); fw_version = phy_read(phydev, PHY_FWV);
if (fw_version < 0) if (fw_version < 0)
return fw_version; return fw_version;
......
...@@ -1487,6 +1487,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, ...@@ -1487,6 +1487,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
phydev->interrupts = PHY_INTERRUPT_DISABLED; 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 /* 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 * 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 * the generic PHY driver we can't figure it out, thus set the old
......
...@@ -739,6 +739,9 @@ struct phy_device { ...@@ -739,6 +739,9 @@ struct phy_device {
#endif #endif
}; };
/* Generic phy_device::dev_flags */
#define PHY_F_NO_IRQ 0x80000000
static inline struct phy_device *to_phy_device(const struct device *dev) static inline struct phy_device *to_phy_device(const struct device *dev)
{ {
return container_of(to_mdio_device(dev), struct phy_device, mdio); return container_of(to_mdio_device(dev), struct phy_device, mdio);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment