This patch adds support for the onsemi NCN26000 10BASE-T1S industrial
Ethernet PHY. The driver supports Point-to-Multipoint operation without
auto-negotiation and with link control handling. The PHY also features
PLCA for improving performance in P2MP mode.
Signed-off-by: Piergiorgio Beruto <piergiorgio.beruto@gmail.com>
---
MAINTAINERS | 7 ++
drivers/net/phy/Kconfig | 7 ++
drivers/net/phy/Makefile | 1 +
drivers/net/phy/ncn26000.c | 173 +++++++++++++++++++++++++++++++++++++
4 files changed, 188 insertions(+)
create mode 100644 drivers/net/phy/ncn26000.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 4356382ad57c..c1dadb34009d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15581,6 +15581,13 @@ L: linux-mips@vger.kernel.org
S: Maintained
F: arch/mips/boot/dts/ralink/omega2p.dts
+ONSEMI ETHERNET PHY DRIVERS
+M: Piergiorgio Beruto <piergiorgio.beruto@gmail.com>
+L: netdev@vger.kernel.org
+S: Supported
+W: http://www.onsemi.com
+F: drivers/net/phy/ncn*
+
OP-TEE DRIVER
M: Jens Wiklander <jens.wiklander@linaro.org>
L: op-tee@lists.trustedfirmware.org
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 1327290decab..08706efa4b43 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -264,6 +264,13 @@ config NATIONAL_PHY
help
Currently supports the DP83865 PHY.
+config NCN26000_PHY
+ tristate "onsemi 10BASE-T1S Ethernet PHY"
+ help
+ Adds support for the onsemi 10BASE-T1S Ethernet PHY.
+ Currently supports the NCN26000 10BASE-T1S Industrial PHY
+ with MII interface.
+
config NXP_C45_TJA11XX_PHY
tristate "NXP C45 TJA11XX PHYs"
depends on PTP_1588_CLOCK_OPTIONAL
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index f7138d3c896b..b5138066ba04 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -77,6 +77,7 @@ obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o
obj-$(CONFIG_MICROSEMI_PHY) += mscc/
obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o
obj-$(CONFIG_NATIONAL_PHY) += national.o
+obj-$(CONFIG_NCN26000_PHY) += ncn26000.o
obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o
obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o
diff --git a/drivers/net/phy/ncn26000.c b/drivers/net/phy/ncn26000.c
new file mode 100644
index 000000000000..2b2ce49c32fc
--- /dev/null
+++ b/drivers/net/phy/ncn26000.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Driver for the onsemi 10BASE-T1S NCN26000 PHYs family.
+ *
+ * Copyright 2022 onsemi
+ */
+#include <linux/kernel.h>
+#include <linux/bitfield.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#include "mdio-open-alliance.h"
+
+#define PHY_ID_NCN26000 0x180FF5A1
+
+#define NCN26000_REG_IRQ_CTL 16
+#define NCN26000_REG_IRQ_STATUS 17
+
+// the NCN26000 maps link_ctrl to BMCR_ANENABLE
+#define NCN26000_BCMR_LINK_CTRL_BIT BMCR_ANENABLE
+
+// the NCN26000 maps link_status to BMSR_ANEGCOMPLETE
+#define NCN26000_BMSR_LINK_STATUS_BIT BMSR_ANEGCOMPLETE
+
+#define NCN26000_IRQ_LINKST_BIT BIT(0)
+#define NCN26000_IRQ_PLCAST_BIT BIT(1)
+#define NCN26000_IRQ_LJABBER_BIT BIT(2)
+#define NCN26000_IRQ_RJABBER_BIT BIT(3)
+#define NCN26000_IRQ_PLCAREC_BIT BIT(4)
+#define NCN26000_IRQ_PHYSCOL_BIT BIT(5)
+#define NCN26000_IRQ_RESET_BIT BIT(15)
+
+#define TO_TMR_DEFAULT 32
+
+// driver callbacks --------------------------------------------------------- //
+
+static int ncn26000_config_init(struct phy_device *phydev)
+{
+ /* HW bug workaround: the default value of the PLCA TO_TIMER should be
+ * 32, where the current version of NCN26000 reports 24. This will be
+ * fixed in future PHY versions. For the time being, we force the
+ * correct default here.
+ */
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, MDIO_OATC14_PLCA_TOTMR,
+ TO_TMR_DEFAULT);
+}
+
+static int ncn26000_config_aneg(struct phy_device *phydev)
+{
+ /* Note: the NCN26000 supports only P2MP link mode. Therefore, AN is not
+ * supported. However, this function is invoked by phylib to enable the
+ * PHY, regardless of the AN support.
+ */
+ phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
+ phydev->mdix = ETH_TP_MDI;
+
+ // bring up the link
+ return phy_write(phydev, MII_BMCR, NCN26000_BCMR_LINK_CTRL_BIT);
+}
+
+static int ncn26000_read_status(struct phy_device *phydev)
+{
+ /* The NCN26000 reports NCN26000_LINK_STATUS_BIT if the link status of
+ * the PHY is up. It further reports the logical AND of the link status
+ * and the PLCA status in the BMSR_LSTATUS bit.
+ */
+ int ret;
+
+ /* The link state is latched low so that momentary link
+ * drops can be detected. Do not double-read the status
+ * in polling mode to detect such short link drops except
+ * the link was already down.
+ */
+ if (!phy_polling_mode(phydev) || !phydev->link) {
+ ret = phy_read(phydev, MII_BMSR);
+ if (ret < 0)
+ return ret;
+ else if (ret & NCN26000_BMSR_LINK_STATUS_BIT)
+ goto upd_link;
+ }
+
+ ret = phy_read(phydev, MII_BMSR);
+ if (unlikely(ret < 0))
+ return ret;
+
+upd_link:
+ // update link status
+ if (ret & NCN26000_BMSR_LINK_STATUS_BIT) {
+ phydev->link = 1;
+ phydev->pause = 0;
+ phydev->duplex = DUPLEX_HALF;
+ phydev->speed = SPEED_10;
+ } else {
+ phydev->link = 0;
+ phydev->duplex = DUPLEX_UNKNOWN;
+ phydev->speed = SPEED_UNKNOWN;
+ }
+
+ return 0;
+}
+
+static irqreturn_t ncn26000_handle_interrupt(struct phy_device *phydev)
+{
+ int ret;
+
+ // read and aknowledge the IRQ status register
+ ret = phy_read(phydev, NCN26000_REG_IRQ_STATUS);
+
+ // check only link status changes
+ if (unlikely(ret < 0) || (ret & NCN26000_REG_IRQ_STATUS) == 0)
+ return IRQ_NONE;
+
+ phy_trigger_machine(phydev);
+ return IRQ_HANDLED;
+}
+
+static int ncn26000_config_intr(struct phy_device *phydev)
+{
+ int ret;
+ u16 irqe;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+ // acknowledge IRQs
+ ret = phy_read(phydev, NCN26000_REG_IRQ_STATUS);
+ if (ret < 0)
+ return ret;
+
+ // get link status notifications
+ irqe = NCN26000_IRQ_LINKST_BIT;
+ } else {
+ // disable all IRQs
+ irqe = 0;
+ }
+
+ ret = phy_write(phydev, NCN26000_REG_IRQ_CTL, irqe);
+ if (ret != 0)
+ return ret;
+
+ return 0;
+}
+
+static struct phy_driver ncn26000_driver[] = {
+ {
+ PHY_ID_MATCH_MODEL(PHY_ID_NCN26000),
+ .name = "NCN26000",
+ .features = PHY_BASIC_T1S_P2MP_FEATURES,
+ .config_init = ncn26000_config_init,
+ .config_intr = ncn26000_config_intr,
+ .config_aneg = ncn26000_config_aneg,
+ .read_status = ncn26000_read_status,
+ .handle_interrupt = ncn26000_handle_interrupt,
+ .get_plca_cfg = genphy_c45_plca_get_cfg,
+ .set_plca_cfg = genphy_c45_plca_set_cfg,
+ .get_plca_status = genphy_c45_plca_get_status,
+ .soft_reset = genphy_soft_reset,
+ },
+};
+
+module_phy_driver(ncn26000_driver);
+
+static struct mdio_device_id __maybe_unused ncn26000_tbl[] = {
+ { PHY_ID_MATCH_MODEL(PHY_ID_NCN26000) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(mdio, ncn26000_tbl);
+
+MODULE_AUTHOR("Piergiorgio Beruto");
+MODULE_DESCRIPTION("onsemi 10BASE-T1S PHY driver");
+MODULE_LICENSE("Dual BSD/GPL");
--
2.37.4
> +++ b/drivers/net/phy/Kconfig > @@ -264,6 +264,13 @@ config NATIONAL_PHY > help > Currently supports the DP83865 PHY. > > +config NCN26000_PHY > + tristate "onsemi 10BASE-T1S Ethernet PHY" > + help > + Adds support for the onsemi 10BASE-T1S Ethernet PHY. > + Currently supports the NCN26000 10BASE-T1S Industrial PHY > + with MII interface. > + > config NXP_C45_TJA11XX_PHY > tristate "NXP C45 TJA11XX PHYs" These are actually sorted by the tristate string, which is what you see when you use make menuconfig So 'onsemi' should be after 'NXP TJA11xx PHYs support'. Also, all the other entries capitalise the first word. > depends on PTP_1588_CLOCK_OPTIONAL > diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile > index f7138d3c896b..b5138066ba04 100644 > --- a/drivers/net/phy/Makefile > +++ b/drivers/net/phy/Makefile > @@ -77,6 +77,7 @@ obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o > obj-$(CONFIG_MICROSEMI_PHY) += mscc/ > obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o > obj-$(CONFIG_NATIONAL_PHY) += national.o > +obj-$(CONFIG_NCN26000_PHY) += ncn26000.o > obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o > obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o > obj-$(CONFIG_QSEMI_PHY) += qsemi.o This is sorted by CONFIG_ symbol, so is correct. > + > +// driver callbacks --------------------------------------------------------- // Comments like this don't really add any value. > +static irqreturn_t ncn26000_handle_interrupt(struct phy_device *phydev) > +{ > + int ret; > + > + // read and aknowledge the IRQ status register > + ret = phy_read(phydev, NCN26000_REG_IRQ_STATUS); > + > + // check only link status changes > + if (unlikely(ret < 0) || (ret & NCN26000_REG_IRQ_STATUS) == 0) > + return IRQ_NONE; More usage of unlikely(). If this was on the hot path, handling 10M frames a second, then maybe unlikley() could be justified. But how often do you get PHY interrupts? Once a day? Andrew
On Sat, Jan 07, 2023 at 07:23:59PM +0100, Andrew Lunn wrote: > > +++ b/drivers/net/phy/Kconfig > > @@ -264,6 +264,13 @@ config NATIONAL_PHY > > help > > Currently supports the DP83865 PHY. > > > > +config NCN26000_PHY > > + tristate "onsemi 10BASE-T1S Ethernet PHY" > > + help > > + Adds support for the onsemi 10BASE-T1S Ethernet PHY. > > + Currently supports the NCN26000 10BASE-T1S Industrial PHY > > + with MII interface. > > + > > config NXP_C45_TJA11XX_PHY > > tristate "NXP C45 TJA11XX PHYs" > > These are actually sorted by the tristate string, which is what you > see when you use > > make menuconfig > > So 'onsemi' should be after 'NXP TJA11xx PHYs support'. Also, all the > other entries capitalise the first word. As for the order I fixed it. Thanks for noticing. Regarding the capitalization, I have a little problem here. 'onsemi' is a brand and according to company rules it MUST be written all in lowercase. I know we're not obliged to follow any company directive here, but as wierd as it might sound, I'd rather keep it lowercase just not to get comments later on trying to fix this, if you agree... > > > depends on PTP_1588_CLOCK_OPTIONAL > > diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile > > index f7138d3c896b..b5138066ba04 100644 > > --- a/drivers/net/phy/Makefile > > +++ b/drivers/net/phy/Makefile > > @@ -77,6 +77,7 @@ obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o > > obj-$(CONFIG_MICROSEMI_PHY) += mscc/ > > obj-$(CONFIG_MOTORCOMM_PHY) += motorcomm.o > > obj-$(CONFIG_NATIONAL_PHY) += national.o > > +obj-$(CONFIG_NCN26000_PHY) += ncn26000.o > > obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja11xx.o > > obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o > > obj-$(CONFIG_QSEMI_PHY) += qsemi.o > > This is sorted by CONFIG_ symbol, so is correct. > > > + > > +// driver callbacks --------------------------------------------------------- // > > Comments like this don't really add any value. Sure, I can remove it. > > > +static irqreturn_t ncn26000_handle_interrupt(struct phy_device *phydev) > > +{ > > + int ret; > > + > > + // read and aknowledge the IRQ status register > > + ret = phy_read(phydev, NCN26000_REG_IRQ_STATUS); > > + > > + // check only link status changes > > + if (unlikely(ret < 0) || (ret & NCN26000_REG_IRQ_STATUS) == 0) > > + return IRQ_NONE; > > More usage of unlikely(). If this was on the hot path, handling 10M > frames a second, then maybe unlikley() could be justified. But how > often do you get PHY interrupts? Once a day? Right, it is my instinct to use unlikely on any sanity check which is effectively unlikely to happen. But I understand it is not needed here. > > Andrew
On Mon, Jan 09, 2023 at 12:57:03AM +0100, Piergiorgio Beruto wrote: > On Sat, Jan 07, 2023 at 07:23:59PM +0100, Andrew Lunn wrote: > > > +++ b/drivers/net/phy/Kconfig > > > @@ -264,6 +264,13 @@ config NATIONAL_PHY > > > help > > > Currently supports the DP83865 PHY. > > > > > > +config NCN26000_PHY > > > + tristate "onsemi 10BASE-T1S Ethernet PHY" > > > + help > > > + Adds support for the onsemi 10BASE-T1S Ethernet PHY. > > > + Currently supports the NCN26000 10BASE-T1S Industrial PHY > > > + with MII interface. > > > + > > > config NXP_C45_TJA11XX_PHY > > > tristate "NXP C45 TJA11XX PHYs" > > > > These are actually sorted by the tristate string, which is what you > > see when you use > > > > make menuconfig > > > > So 'onsemi' should be after 'NXP TJA11xx PHYs support'. Also, all the > > other entries capitalise the first word. > As for the order I fixed it. Thanks for noticing. > > Regarding the capitalization, I have a little problem here. 'onsemi' is a > brand and according to company rules it MUST be written all in > lowercase. I know we're not obliged to follow any company directive here, but > as wierd as it might sound, I'd rather keep it lowercase just not to get > comments later on trying to fix this, if you agree... Linux tends to ignore Marketing, because Marketing tends to change its mind every 6 months. Also, Linux ignores companies being bought and sold, changing their name. So this PHY will forever be called whatever name you give it here. The vitesse PHY driver is an example of this. They got bought by Microsemi, and then Microchip bought Microsemi. The PHY driver is still called vitesse.c. How about using the legal name, 'ON Semiconductor Corporation' Andrew
On Mon, Jan 09, 2023 at 02:31:39PM +0100, Andrew Lunn wrote: > Linux tends to ignore Marketing, because Marketing tends to change its > mind every 6 months. Also, Linux ignores companies being bought and > sold, changing their name. So this PHY will forever be called whatever > name you give it here. The vitesse PHY driver is an example of > this. They got bought by Microsemi, and then Microchip bought > Microsemi. The PHY driver is still called vitesse.c. > > How about using the legal name, 'ON Semiconductor > Corporation' That's perfectly clear Andrew, I can certainly see why Linux should ignore marketing. Sill, 'ON Semiconductor' is the old company name, the product datasheet can be found at www.onsemi.com. I would honestly feel more comfortable using the current company name. If you really want the first 'o' to be capitalized, then so be it. Hopefully people will not notice :-) Thanks, Piergiorgio
On Mon, Jan 09, 2023 at 03:21:18PM +0100, Piergiorgio Beruto wrote: > On Mon, Jan 09, 2023 at 02:31:39PM +0100, Andrew Lunn wrote: > > Linux tends to ignore Marketing, because Marketing tends to change its > > mind every 6 months. Also, Linux ignores companies being bought and > > sold, changing their name. So this PHY will forever be called whatever > > name you give it here. The vitesse PHY driver is an example of > > this. They got bought by Microsemi, and then Microchip bought > > Microsemi. The PHY driver is still called vitesse.c. > > > > How about using the legal name, 'ON Semiconductor > > Corporation' > That's perfectly clear Andrew, I can certainly see why Linux should > ignore marketing. > > Sill, 'ON Semiconductor' is the old company name, the product datasheet can be > found at www.onsemi.com. I would honestly feel more comfortable using > the current company name. If you really want the first 'o' to be > capitalized, then so be it. Hopefully people will not notice :-) I would prefer it was capitalised, to make it uniform with all the other entries. Andrew
On Mon, Jan 09, 2023 at 03:24:26PM +0100, Andrew Lunn wrote: > On Mon, Jan 09, 2023 at 03:21:18PM +0100, Piergiorgio Beruto wrote: > > On Mon, Jan 09, 2023 at 02:31:39PM +0100, Andrew Lunn wrote: > > > Linux tends to ignore Marketing, because Marketing tends to change its > > > mind every 6 months. Also, Linux ignores companies being bought and > > > sold, changing their name. So this PHY will forever be called whatever > > > name you give it here. The vitesse PHY driver is an example of > > > this. They got bought by Microsemi, and then Microchip bought > > > Microsemi. The PHY driver is still called vitesse.c. > > > > > > How about using the legal name, 'ON Semiconductor > > > Corporation' > > That's perfectly clear Andrew, I can certainly see why Linux should > > ignore marketing. > > > > Sill, 'ON Semiconductor' is the old company name, the product datasheet can be > > found at www.onsemi.com. I would honestly feel more comfortable using > > the current company name. If you really want the first 'o' to be > > capitalized, then so be it. Hopefully people will not notice :-) > > I would prefer it was capitalised, to make it uniform with all the > other entries. I've just re-submitted the patches, fixing also a warning on a multi-line comment w/o newline. Thanks! Piergiorgio
© 2016 - 2025 Red Hat, Inc.