The ADIN1200/ADIN1300 provide a control bit that selects between normal
receive termination and the lowest common mode impedance for 100BASE-TX
operation. This behavior is controlled through the Low Power Termination
register (B_100_ZPTM_EN_DIMRX).
Bit 0 of this register enables normal termination when set (this is the
default), and selects the lowest common mode impedance when cleared.
Signed-off-by: Osose Itua <osose.itua@savoirfairelinux.com>
---
drivers/net/phy/adin.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
index 7fa713ca8d45..e8b778cb191d 100644
--- a/drivers/net/phy/adin.c
+++ b/drivers/net/phy/adin.c
@@ -4,6 +4,7 @@
*
* Copyright 2019 Analog Devices Inc.
*/
+#include <cerrno>
#include <linux/kernel.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
@@ -89,6 +90,9 @@
#define ADIN1300_CLOCK_STOP_REG 0x9400
#define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000
+#define ADIN1300_B_100_ZPTM_DIMRX 0xB685
+#define ADIN1300_B_100_ZPTM_EN_DIMRX BIT(0)
+
#define ADIN1300_CDIAG_RUN 0xba1b
#define ADIN1300_CDIAG_RUN_EN BIT(0)
@@ -522,6 +526,32 @@ static int adin_config_clk_out(struct phy_device *phydev)
ADIN1300_GE_CLK_CFG_MASK, sel);
}
+static int adin_config_zptm100(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ int reg;
+ int rc;
+
+ if (!(device_property_read_bool(dev, "adi,low-cmode-impedance")))
+ return 0;
+
+ /* set to 0 to configure for lowest common-mode impedance */
+ rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX, 0x0);
+ if (rc < 0)
+ return rc;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX);
+ if (reg < 0)
+ return reg;
+
+ if (!(reg & ADIN1300_B_100_ZPTM_EN_DIMRX)) {
+ phydev_err(phydev, "Failed to set lowest common-mode impedance.\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int adin_config_init(struct phy_device *phydev)
{
int rc;
@@ -548,6 +578,10 @@ static int adin_config_init(struct phy_device *phydev)
if (rc < 0)
return rc;
+ rc = adin_config_zptm100(phydev);
+ if (rc < 0)
+ return rc;
+
phydev_dbg(phydev, "PHY is using mode '%s'\n",
phy_modes(phydev->interface));
On 22/12/2025 22:21, Osose Itua wrote: > The ADIN1200/ADIN1300 provide a control bit that selects between normal > receive termination and the lowest common mode impedance for 100BASE-TX > operation. This behavior is controlled through the Low Power Termination > register (B_100_ZPTM_EN_DIMRX). > > Bit 0 of this register enables normal termination when set (this is the > default), and selects the lowest common mode impedance when cleared. > > Signed-off-by: Osose Itua <osose.itua@savoirfairelinux.com> > --- > drivers/net/phy/adin.c | 34 ++++++++++++++++++++++++++++++++++ > 1 file changed, 34 insertions(+) > > diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c > index 7fa713ca8d45..e8b778cb191d 100644 > --- a/drivers/net/phy/adin.c > +++ b/drivers/net/phy/adin.c > @@ -4,6 +4,7 @@ > * > * Copyright 2019 Analog Devices Inc. > */ > +#include <cerrno> This kind of include is not used in kernel. You don't need to include anything in this file to have EINVAL defined. > #include <linux/kernel.h> > #include <linux/bitfield.h> > #include <linux/delay.h> > @@ -89,6 +90,9 @@
Hi Osose,
kernel test robot noticed the following build errors:
[auto build test ERROR on net/main]
[also build test ERROR on net-next/main linus/master horms-ipvs/master v6.19-rc2 next-20251219]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Osose-Itua/net-phy-adin-enable-configuration-of-the-LP-Termination-Register/20251223-064926
base: net/main
patch link: https://lore.kernel.org/r/20251222222210.3651577-2-osose.itua%40savoirfairelinux.com
patch subject: [PATCH v2 1/2] net: phy: adin: enable configuration of the LP Termination Register
config: hexagon-randconfig-002-20251223 (https://download.01.org/0day-ci/archive/20251223/202512232136.7GHkdaw8-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 4ef602d446057dabf5f61fb221669ecbeda49279)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251223/202512232136.7GHkdaw8-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512232136.7GHkdaw8-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/net/phy/adin.c:7:10: fatal error: 'cerrno' file not found
7 | #include <cerrno>
| ^~~~~~~~
1 error generated.
vim +/cerrno +7 drivers/net/phy/adin.c
> 7 #include <cerrno>
8 #include <linux/kernel.h>
9 #include <linux/bitfield.h>
10 #include <linux/delay.h>
11 #include <linux/errno.h>
12 #include <linux/ethtool_netlink.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/mii.h>
16 #include <linux/phy.h>
17 #include <linux/property.h>
18
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Hi Osose,
kernel test robot noticed the following build errors:
[auto build test ERROR on net/main]
[also build test ERROR on net-next/main linus/master horms-ipvs/master v6.19-rc2 next-20251219]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Osose-Itua/net-phy-adin-enable-configuration-of-the-LP-Termination-Register/20251223-064926
base: net/main
patch link: https://lore.kernel.org/r/20251222222210.3651577-2-osose.itua%40savoirfairelinux.com
patch subject: [PATCH v2 1/2] net: phy: adin: enable configuration of the LP Termination Register
config: parisc-randconfig-001-20251223 (https://download.01.org/0day-ci/archive/20251223/202512232150.85cDPKrJ-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251223/202512232150.85cDPKrJ-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202512232150.85cDPKrJ-lkp@intel.com/
All errors (new ones prefixed by >>):
>> drivers/net/phy/adin.c:7:10: fatal error: cerrno: No such file or directory
#include <cerrno>
^~~~~~~~
compilation terminated.
vim +7 drivers/net/phy/adin.c
> 7 #include <cerrno>
8 #include <linux/kernel.h>
9 #include <linux/bitfield.h>
10 #include <linux/delay.h>
11 #include <linux/errno.h>
12 #include <linux/ethtool_netlink.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/mii.h>
16 #include <linux/phy.h>
17 #include <linux/property.h>
18
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
> +static int adin_config_zptm100(struct phy_device *phydev)
> +{
> + struct device *dev = &phydev->mdio.dev;
> + int reg;
> + int rc;
> +
> + if (!(device_property_read_bool(dev, "adi,low-cmode-impedance")))
> + return 0;
> +
> + /* set to 0 to configure for lowest common-mode impedance */
> + rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX, 0x0);
> + if (rc < 0)
> + return rc;
> +
> + reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX);
> + if (reg < 0)
> + return reg;
> +
> + if (!(reg & ADIN1300_B_100_ZPTM_EN_DIMRX)) {
> + phydev_err(phydev, "Failed to set lowest common-mode impedance.\n");
> + return -EINVAL;
> + }
Under what condition do you think this could happen? Do you think
there are variants of the hardware which do not have this register?
Andrew
On Tue, 2025-12-23 at 10:36 +0100, Andrew Lunn wrote:
> > +static int adin_config_zptm100(struct phy_device *phydev)
> > +{
> > + struct device *dev = &phydev->mdio.dev;
> > + int reg;
> > + int rc;
> > +
> > + if (!(device_property_read_bool(dev, "adi,low-cmode-impedance")))
> > + return 0;
> > +
> > + /* set to 0 to configure for lowest common-mode impedance */
> > + rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX, 0x0);
> > + if (rc < 0)
> > + return rc;
> > +
> > + reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX);
> > + if (reg < 0)
> > + return reg;
> > +
> > + if (!(reg & ADIN1300_B_100_ZPTM_EN_DIMRX)) {
> > + phydev_err(phydev, "Failed to set lowest common-mode impedance.\n");
> > + return -EINVAL;
> > + }
>
> Under what condition do you think this could happen? Do you think
> there are variants of the hardware which do not have this register?
>
> Andrew
I think he's just reading back the register to make sure the value was really updated...
If we were going to that for every write our lives would be miserable :).
I looked at both adin1200 and adin1300 and they support this in the same way so the above
should just be:
return phy_write_mmd()...
- Nuno Sá
Hi,
On 2025-12-23 at 03:51:04, Osose Itua (osose.itua@savoirfairelinux.com) wrote:
> The ADIN1200/ADIN1300 provide a control bit that selects between normal
> receive termination and the lowest common mode impedance for 100BASE-TX
> operation. This behavior is controlled through the Low Power Termination
> register (B_100_ZPTM_EN_DIMRX).
>
> Bit 0 of this register enables normal termination when set (this is the
> default), and selects the lowest common mode impedance when cleared.
>
> Signed-off-by: Osose Itua <osose.itua@savoirfairelinux.com>
> ---
> drivers/net/phy/adin.c | 34 ++++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c
> index 7fa713ca8d45..e8b778cb191d 100644
> --- a/drivers/net/phy/adin.c
> +++ b/drivers/net/phy/adin.c
> @@ -4,6 +4,7 @@
> *
> * Copyright 2019 Analog Devices Inc.
> */
> +#include <cerrno>
> #include <linux/kernel.h>
> #include <linux/bitfield.h>
> #include <linux/delay.h>
> @@ -89,6 +90,9 @@
> #define ADIN1300_CLOCK_STOP_REG 0x9400
> #define ADIN1300_LPI_WAKE_ERR_CNT_REG 0xa000
>
> +#define ADIN1300_B_100_ZPTM_DIMRX 0xB685
> +#define ADIN1300_B_100_ZPTM_EN_DIMRX BIT(0)
> +
> #define ADIN1300_CDIAG_RUN 0xba1b
> #define ADIN1300_CDIAG_RUN_EN BIT(0)
>
> @@ -522,6 +526,32 @@ static int adin_config_clk_out(struct phy_device *phydev)
> ADIN1300_GE_CLK_CFG_MASK, sel);
> }
>
> +static int adin_config_zptm100(struct phy_device *phydev)
> +{
> + struct device *dev = &phydev->mdio.dev;
> + int reg;
> + int rc;
> +
> + if (!(device_property_read_bool(dev, "adi,low-cmode-impedance")))
> + return 0;
> +
> + /* set to 0 to configure for lowest common-mode impedance */
> + rc = phy_write_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX, 0x0);
This clears full register instead of just bit 0. Is that intended?
> + if (rc < 0)
> + return rc;
> +
> + reg = phy_read_mmd(phydev, MDIO_MMD_VEND1, ADIN1300_B_100_ZPTM_DIMRX);
> + if (reg < 0)
> + return reg;
> +
> + if (!(reg & ADIN1300_B_100_ZPTM_EN_DIMRX)) {
From commit description, check should be if (reg & ADIN1300_B_100_ZPTM_EN_DIMRX)
AI review also caught this:
https://netdev-ai.bots.linux.dev/ai-review.html?id=05b38bb2-1244-46fc-a4d9-311ca8c825ee#patch-0
Fix the build errors reported at:
https://patchwork.kernel.org/project/netdevbpf/patch/20251222222210.3651577-2-osose.itua@savoirfairelinux.com/
Also net-next is closed till Jan 2. Please post v3 after that.
Thanks,
Sundeep
> + phydev_err(phydev, "Failed to set lowest common-mode impedance.\n");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> static int adin_config_init(struct phy_device *phydev)
> {
> int rc;
> @@ -548,6 +578,10 @@ static int adin_config_init(struct phy_device *phydev)
> if (rc < 0)
> return rc;
>
> + rc = adin_config_zptm100(phydev);
> + if (rc < 0)
> + return rc;
> +
> phydev_dbg(phydev, "PHY is using mode '%s'\n",
> phy_modes(phydev->interface));
>
© 2016 - 2026 Red Hat, Inc.