2023-06-23 08:09:13

by Radu Pirea (NXP OSS)

[permalink] [raw]
Subject: [PATCH v2 00/13] Add TJA1120 support

Hello everyone,

This patch series got bigger than I expected. It cleans up the
next-c45-tja11xx driver and adds support for the TJA1120(1000BaseT1
automotive phy).

Master/slave custom implementation was replaced with the generic
implementation (genphy_c45_config_aneg/genphy_c45_read_status).

The TJA1120 and TJA1103 are a bit different when it comes to the PTP
interface. The timestamp read procedure was changed, some addresses were
changed and some bits were moved from one register to another. Adding
TJA1120 support was tricky, and I tried not to duplicate the code. If
something looks too hacky to you, I am open to suggestions.

Cheers,
Radu P

Changes in v2:
- dropped "net: phy: nxp-c45-tja11xx: fix the PTP interrupt
enablig/disabling"
- added error msgs to nxp_c45_set_reg_field and nxp_c45_clear_reg_field
- used phy_err instead of phy_warn in nxp_c45_write_reg_field and
nxp_c45_read_reg_field
- removed null checks for .driver_data and its fields
- added 100BT1 and 1000BT1 features bit
- replaced .features with .get_features
- dropped changed on TJA1103 EXT TS behaviour
- improved timestamp reading workarounds
- merged patch "net: phy: nxp-c45-tja11xx: timestamp reading workaround for
TJA1120" to 9 and 12
- implemented PCS reset workaround in link_change_notify callback

Radu Pirea (NXP OSS) (13):
net: phy: nxp-c45-tja11xx: use phylib master/slave implementation
net: phy: nxp-c45-tja11xx: remove RX BIST frame counters
net: phy: nxp-c45-tja11xx: add *_reg_field functions
net: phy: nxp-c45-tja11xx: prepare the ground for TJA1120
net: phy: c45: detect 100BaseT1 and 1000BaseT1 PMA abilites
net: phy: nxp-c45-tja11xx: use get_features
net: phy: nxp-c45-tja11xx: add TJA1120 support
net: phy: nxp-c45-tja11xx: enable LTC sampling on both ext_ts edges
net: phy: nxp-c45-tja11xx: read egress ts on TJA1120
net: phy: nxp-c45-tja11xx: handle FUSA irq
net: phy: nxp-c45-tja11xx: run cable test with the PHY in test mode
net: phy: nxp-c45-tja11xx: read ext trig ts on TJA1120
net: phy: nxp-c45-tja11xx: reset PCS if the link goes down

drivers/net/phy/Kconfig | 2 +-
drivers/net/phy/nxp-c45-tja11xx.c | 1134 ++++++++++++++++++++++-------
drivers/net/phy/phy-c45.c | 8 +
include/uapi/linux/mdio.h | 2 +
4 files changed, 873 insertions(+), 273 deletions(-)

--
2.34.1



2023-06-23 08:12:09

by Radu Pirea (NXP OSS)

[permalink] [raw]
Subject: [PATCH v2 06/13] net: phy: nxp-c45-tja11xx: use get_features

PHY_BASIC_T1_FEATURES are not the right features supported by TJA1103
anymore.
For example ethtool reports:
[root@alarm ~]# ethtool end0
Settings for end0:
Supported ports: [ TP ]
Supported link modes: 100baseT1/Full
10baseT1L/Full

10baseT1L/Full is not supported by TJA1103 and supported ports list is
not completed. The PHY also have a MII port.

genphy_c45_pma_read_abilities implementation can detect the PHY features
and they look like this.
[root@alarm ~]# ethtool end0
Settings for end0:
Supported ports: [ TP MII ]
Supported link modes: 100baseT1/Full
Supported pause frame use: Symmetric
Supports auto-negotiation: No
Supported FEC modes: Not reported
Advertised link modes: 100baseT1/Full
Advertised pause frame use: Symmetric
Advertised auto-negotiation: No
Advertised FEC modes: Not reported
Speed: 100Mb/s
Duplex: Full
Auto-negotiation: off
master-slave cfg: forced master
master-slave status: master
Port: Twisted Pair
PHYAD: 1
Transceiver: external
MDI-X: Unknown
Supports Wake-on: g
Wake-on: d
Link detected: yes
SQI: 7/7

Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>
---
drivers/net/phy/nxp-c45-tja11xx.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index 162886cce08b..11fb5a4f47fb 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -1353,6 +1353,14 @@ static int nxp_c45_config_init(struct phy_device *phydev)
return nxp_c45_start_op(phydev);
}

+static int nxp_c45_get_features(struct phy_device *phydev)
+{
+ linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, phydev->supported);
+ linkmode_set_bit(ETHTOOL_LINK_MODE_MII_BIT, phydev->supported);
+
+ return genphy_c45_pma_read_abilities(phydev);
+}
+
static int nxp_c45_probe(struct phy_device *phydev)
{
struct nxp_c45_phy *priv;
@@ -1507,7 +1515,7 @@ static struct phy_driver nxp_c45_driver[] = {
{
PHY_ID_MATCH_MODEL(PHY_ID_TJA_1103),
.name = "NXP C45 TJA1103",
- .features = PHY_BASIC_T1_FEATURES,
+ .get_features = nxp_c45_get_features,
.driver_data = &tja1103_phy_data,
.probe = nxp_c45_probe,
.soft_reset = nxp_c45_soft_reset,
--
2.34.1


2023-06-23 08:13:06

by Radu Pirea (NXP OSS)

[permalink] [raw]
Subject: [PATCH v2 01/13] net: phy: nxp-c45-tja11xx: use phylib master/slave implementation

Remove the custom implementation of master/save setup and read status
and use genphy_c45_config_aneg and genphy_c45_read_status since phylib
has support for master/slave setup and master/slave status.

Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>
Reviewed-by: Andrew Lunn <[email protected]>
---
drivers/net/phy/nxp-c45-tja11xx.c | 77 +------------------------------
1 file changed, 2 insertions(+), 75 deletions(-)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index 029875a59ff8..41b8af0547e4 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -19,13 +19,6 @@

#define PHY_ID_TJA_1103 0x001BB010

-#define PMAPMD_B100T1_PMAPMD_CTL 0x0834
-#define B100T1_PMAPMD_CONFIG_EN BIT(15)
-#define B100T1_PMAPMD_MASTER BIT(14)
-#define MASTER_MODE (B100T1_PMAPMD_CONFIG_EN | \
- B100T1_PMAPMD_MASTER)
-#define SLAVE_MODE (B100T1_PMAPMD_CONFIG_EN)
-
#define VEND1_DEVICE_CONTROL 0x0040
#define DEVICE_CONTROL_RESET BIT(15)
#define DEVICE_CONTROL_CONFIG_GLOBAL_EN BIT(14)
@@ -988,72 +981,6 @@ static int nxp_c45_cable_test_get_status(struct phy_device *phydev,
return nxp_c45_start_op(phydev);
}

-static int nxp_c45_setup_master_slave(struct phy_device *phydev)
-{
- switch (phydev->master_slave_set) {
- case MASTER_SLAVE_CFG_MASTER_FORCE:
- case MASTER_SLAVE_CFG_MASTER_PREFERRED:
- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL,
- MASTER_MODE);
- break;
- case MASTER_SLAVE_CFG_SLAVE_PREFERRED:
- case MASTER_SLAVE_CFG_SLAVE_FORCE:
- phy_write_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL,
- SLAVE_MODE);
- break;
- case MASTER_SLAVE_CFG_UNKNOWN:
- case MASTER_SLAVE_CFG_UNSUPPORTED:
- return 0;
- default:
- phydev_warn(phydev, "Unsupported Master/Slave mode\n");
- return -EOPNOTSUPP;
- }
-
- return 0;
-}
-
-static int nxp_c45_read_master_slave(struct phy_device *phydev)
-{
- int reg;
-
- phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN;
- phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
-
- reg = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_B100T1_PMAPMD_CTL);
- if (reg < 0)
- return reg;
-
- if (reg & B100T1_PMAPMD_MASTER) {
- phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE;
- phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
- } else {
- phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE;
- phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
- }
-
- return 0;
-}
-
-static int nxp_c45_config_aneg(struct phy_device *phydev)
-{
- return nxp_c45_setup_master_slave(phydev);
-}
-
-static int nxp_c45_read_status(struct phy_device *phydev)
-{
- int ret;
-
- ret = genphy_c45_read_status(phydev);
- if (ret)
- return ret;
-
- ret = nxp_c45_read_master_slave(phydev);
- if (ret)
- return ret;
-
- return 0;
-}
-
static int nxp_c45_get_sqi(struct phy_device *phydev)
{
int reg;
@@ -1355,11 +1282,11 @@ static struct phy_driver nxp_c45_driver[] = {
.features = PHY_BASIC_T1_FEATURES,
.probe = nxp_c45_probe,
.soft_reset = nxp_c45_soft_reset,
- .config_aneg = nxp_c45_config_aneg,
+ .config_aneg = genphy_c45_config_aneg,
.config_init = nxp_c45_config_init,
.config_intr = nxp_c45_config_intr,
.handle_interrupt = nxp_c45_handle_interrupt,
- .read_status = nxp_c45_read_status,
+ .read_status = genphy_c45_read_status,
.suspend = genphy_c45_pma_suspend,
.resume = genphy_c45_pma_resume,
.get_sset_count = nxp_c45_get_sset_count,
--
2.34.1


2023-06-23 08:13:11

by Radu Pirea (NXP OSS)

[permalink] [raw]
Subject: [PATCH v2 10/13] net: phy: nxp-c45-tja11xx: handle FUSA irq

TJA1120 and TJA1103 have a set of functional safety hardware tests
executed after every reset, and when the tests are done, the IRQ line is
asserted. For the moment, the purpose of these handlers is to acknowledge
the IRQ and not to check the FUSA tests status.

Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>
---
drivers/net/phy/nxp-c45-tja11xx.c | 79 ++++++++++++++++++++++++++++++-
1 file changed, 77 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index 0567a366af37..a826c845ee7d 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -29,6 +29,11 @@

#define TJA1120_VEND1_EXT_TS_MODE 0x1012

+#define TJA1120_GLOBAL_INFRA_IRQ_ACK 0x2C08
+#define TJA1120_GLOBAL_INFRA_IRQ_EN 0x2C0A
+#define TJA1120_GLOBAL_INFRA_IRQ_STATUS 0x2C0C
+#define TJA1120_DEV_BOOT_DONE BIT(1)
+
#define TJA1120_EGRESS_TS_DATA_S 0x9060
#define TJA1120_EGRESS_TS_END 0x9067
#define TJA1120_TS_VALID BIT(0)
@@ -39,6 +44,9 @@
#define VEND1_PHY_IRQ_STATUS 0x80A2
#define PHY_IRQ_LINK_EVENT BIT(1)

+#define VEND1_ALWAYS_ACCESSIBLE 0x801F
+#define FUSA_PASS BIT(4)
+
#define VEND1_PHY_CONTROL 0x8100
#define PHY_CONFIG_EN BIT(14)
#define PHY_START_OP BIT(0)
@@ -262,6 +270,8 @@ struct nxp_c45_phy_data {
struct nxp_c45_hwts *hwts);
void (*ptp_init)(struct phy_device *phydev);
void (*ptp_enable)(struct phy_device *phydev, bool enable);
+ void (*nmi_handler)(struct phy_device *phydev,
+ irqreturn_t *irq_status);
};

struct nxp_c45_phy {
@@ -1162,6 +1172,37 @@ static int nxp_c45_config_intr(struct phy_device *phydev)
VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
}

+static int tja1103_config_intr(struct phy_device *phydev)
+{
+ int ret;
+
+ /* We can't disable the FUSA IRQ for TJA1103, but we can clean it up. */
+ ret = phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_ALWAYS_ACCESSIBLE,
+ FUSA_PASS);
+ if (ret)
+ return ret;
+
+ return nxp_c45_config_intr(phydev);
+}
+
+static int tja1120_config_intr(struct phy_device *phydev)
+{
+ int ret;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_GLOBAL_INFRA_IRQ_EN,
+ TJA1120_DEV_BOOT_DONE);
+ else
+ ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_GLOBAL_INFRA_IRQ_EN,
+ TJA1120_DEV_BOOT_DONE);
+ if (ret)
+ return ret;
+
+ return nxp_c45_config_intr(phydev);
+}
+
static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev)
{
const struct nxp_c45_phy_data *data = nxp_c45_get_data(phydev);
@@ -1193,6 +1234,8 @@ static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev)
ret = IRQ_HANDLED;
}

+ data->nmi_handler(phydev, &ret);
+
return ret;
}

@@ -1599,6 +1642,21 @@ static void tja1103_ptp_enable(struct phy_device *phydev, bool enable)
PORT_PTP_CONTROL_BYPASS);
}

+static void tja1103_nmi_handler(struct phy_device *phydev,
+ irqreturn_t *irq_status)
+{
+ int ret;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_ALWAYS_ACCESSIBLE);
+ if (ret & FUSA_PASS) {
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_ALWAYS_ACCESSIBLE,
+ FUSA_PASS);
+ *irq_status = IRQ_HANDLED;
+ }
+}
+
static const struct nxp_c45_regmap tja1103_regmap = {
.vend1_ptp_clk_period = 0x1104,
.vend1_event_msg_filt = 0x1148,
@@ -1663,6 +1721,7 @@ static const struct nxp_c45_phy_data tja1103_phy_data = {
.get_egressts = nxp_c45_get_hwtxts,
.ptp_init = tja1103_ptp_init,
.ptp_enable = tja1103_ptp_enable,
+ .nmi_handler = tja1103_nmi_handler,
};

static void tja1120_counters_enable(struct phy_device *phydev)
@@ -1697,6 +1756,21 @@ static void tja1120_ptp_enable(struct phy_device *phydev, bool enable)
PTP_ENABLE);
}

+static void tja1120_nmi_handler(struct phy_device *phydev,
+ irqreturn_t *irq_status)
+{
+ int ret;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_GLOBAL_INFRA_IRQ_STATUS);
+ if (ret & TJA1120_DEV_BOOT_DONE) {
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_GLOBAL_INFRA_IRQ_ACK,
+ TJA1120_DEV_BOOT_DONE);
+ *irq_status = IRQ_HANDLED;
+ }
+}
+
static const struct nxp_c45_regmap tja1120_regmap = {
.vend1_ptp_clk_period = 0x1020,
.vend1_event_msg_filt = 0x9010,
@@ -1761,6 +1835,7 @@ static const struct nxp_c45_phy_data tja1120_phy_data = {
.get_egressts = tja1120_get_hwtxts,
.ptp_init = tja1120_ptp_init,
.ptp_enable = tja1120_ptp_enable,
+ .nmi_handler = tja1120_nmi_handler,
};

static struct phy_driver nxp_c45_driver[] = {
@@ -1773,7 +1848,7 @@ static struct phy_driver nxp_c45_driver[] = {
.soft_reset = nxp_c45_soft_reset,
.config_aneg = genphy_c45_config_aneg,
.config_init = nxp_c45_config_init,
- .config_intr = nxp_c45_config_intr,
+ .config_intr = tja1103_config_intr,
.handle_interrupt = nxp_c45_handle_interrupt,
.read_status = genphy_c45_read_status,
.suspend = genphy_c45_pma_suspend,
@@ -1797,7 +1872,7 @@ static struct phy_driver nxp_c45_driver[] = {
.soft_reset = nxp_c45_soft_reset,
.config_aneg = genphy_c45_config_aneg,
.config_init = nxp_c45_config_init,
- .config_intr = nxp_c45_config_intr,
+ .config_intr = tja1120_config_intr,
.handle_interrupt = nxp_c45_handle_interrupt,
.read_status = genphy_c45_read_status,
.suspend = genphy_c45_pma_suspend,
--
2.34.1


2023-06-23 08:13:17

by Radu Pirea (NXP OSS)

[permalink] [raw]
Subject: [PATCH v2 11/13] net: phy: nxp-c45-tja11xx: run cable test with the PHY in test mode

For TJA1120, the enable bit for cable test is not writable if the PHY is
not in test mode.

Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>
---
drivers/net/phy/nxp-c45-tja11xx.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index a826c845ee7d..8097ac8d6962 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -145,6 +145,7 @@

#define VEND1_PORT_FUNC_ENABLES 0x8048
#define PTP_ENABLE BIT(3)
+#define PHY_TEST_ENABLE BIT(0)

#define VEND1_PORT_PTP_CONTROL 0x9000
#define PORT_PTP_CONTROL_BYPASS BIT(11)
@@ -1258,6 +1259,8 @@ static int nxp_c45_cable_test_start(struct phy_device *phydev)
{
const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(phydev);

+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE);
return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test,
CABLE_TEST_ENABLE | CABLE_TEST_START);
}
@@ -1299,6 +1302,8 @@ static int nxp_c45_cable_test_get_status(struct phy_device *phydev,

phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, regmap->cable_test,
CABLE_TEST_ENABLE);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ VEND1_PORT_FUNC_ENABLES, PHY_TEST_ENABLE);

return nxp_c45_start_op(phydev);
}
--
2.34.1


2023-06-23 08:21:51

by Radu Pirea (NXP OSS)

[permalink] [raw]
Subject: [PATCH v2 13/13] net: phy: nxp-c45-tja11xx: reset PCS if the link goes down

During PTP testing on early TJA1120 engineering samples I observed that
if the link is lost and recovered, the tx timestamps will be randomly
lost. To avoid this HW issue, the PCS should be reseted.

Resetting the PCS will break the link and we should reset the PCS on
LINK UP -> LINK DOWN transition, otherwise we will trigger and infinite
loop of LINK UP -> LINK DOWN events.

Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>
---
drivers/net/phy/nxp-c45-tja11xx.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index c21c6aefc705..af3951e76a47 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -56,6 +56,9 @@
#define VEND1_PHY_CONFIG 0x8108
#define PHY_CONFIG_AUTO BIT(0)

+#define TJA1120_EPHY_RESETS 0x810A
+#define EPHY_PCS_RESET BIT(3)
+
#define VEND1_SIGNAL_QUALITY 0x8320
#define SQI_VALID BIT(14)
#define SQI_MASK GENMASK(2, 0)
@@ -1371,6 +1374,19 @@ static int nxp_c45_get_sqi(struct phy_device *phydev)
return reg;
}

+static void tja1120_link_change_notify(struct phy_device *phydev)
+{
+ /* Bug workaround for TJA1120 enegineering samples: fix egress
+ * timestamps lost after link recovery.
+ */
+ if (phydev->state == PHY_NOLINK) {
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_EPHY_RESETS, EPHY_PCS_RESET);
+ phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_EPHY_RESETS, EPHY_PCS_RESET);
+ }
+}
+
static int nxp_c45_get_sqi_max(struct phy_device *phydev)
{
return MAX_SQI;
@@ -1932,6 +1948,7 @@ static struct phy_driver nxp_c45_driver[] = {
.config_intr = tja1120_config_intr,
.handle_interrupt = nxp_c45_handle_interrupt,
.read_status = genphy_c45_read_status,
+ .link_change_notify = tja1120_link_change_notify,
.suspend = genphy_c45_pma_suspend,
.resume = genphy_c45_pma_resume,
.get_sset_count = nxp_c45_get_sset_count,
--
2.34.1


2023-06-23 08:22:51

by Radu Pirea (NXP OSS)

[permalink] [raw]
Subject: [PATCH v2 12/13] net: phy: nxp-c45-tja11xx: read ext trig ts on TJA1120

On TJA1120, the external trigger timestamp now has a VALID bit. This
changes the logic and we can't use the TJA1103 procedure.

For TJA1103, we can always read a valid timestamp from the registers,
compare the new timestamp with the old timestamp and, if they are not the
same, an event occurred. This logic cannot be applied for TJA1120 because
the timestamp is 0 if the VALID bit is not set.

Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>
---
drivers/net/phy/nxp-c45-tja11xx.c | 64 ++++++++++++++++++++++++++++---
1 file changed, 58 insertions(+), 6 deletions(-)

diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index 8097ac8d6962..c21c6aefc705 100644
--- a/drivers/net/phy/nxp-c45-tja11xx.c
+++ b/drivers/net/phy/nxp-c45-tja11xx.c
@@ -34,6 +34,8 @@
#define TJA1120_GLOBAL_INFRA_IRQ_STATUS 0x2C0C
#define TJA1120_DEV_BOOT_DONE BIT(1)

+#define TJA1120_VEND1_PTP_TRIG_DATA_S 0x1070
+
#define TJA1120_EGRESS_TS_DATA_S 0x9060
#define TJA1120_EGRESS_TS_END 0x9067
#define TJA1120_TS_VALID BIT(0)
@@ -269,6 +271,7 @@ struct nxp_c45_phy_data {
void (*counters_enable)(struct phy_device *phydev);
bool (*get_egressts)(struct nxp_c45_phy *priv,
struct nxp_c45_hwts *hwts);
+ bool (*get_extts)(struct nxp_c45_phy *priv, struct timespec64 *extts);
void (*ptp_init)(struct phy_device *phydev);
void (*ptp_enable)(struct phy_device *phydev, bool enable);
void (*nmi_handler)(struct phy_device *phydev,
@@ -509,7 +512,7 @@ static bool nxp_c45_match_ts(struct ptp_header *header,
header->domain_number == hwts->domain_number;
}

-static void nxp_c45_get_extts(struct nxp_c45_phy *priv,
+static bool nxp_c45_get_extts(struct nxp_c45_phy *priv,
struct timespec64 *extts)
{
const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
@@ -524,6 +527,53 @@ static void nxp_c45_get_extts(struct nxp_c45_phy *priv,
regmap->vend1_ext_trg_data_3) << 16;
phy_write_mmd(priv->phydev, MDIO_MMD_VEND1,
regmap->vend1_ext_trg_ctrl, RING_DONE);
+
+ return true;
+}
+
+static bool tja1120_extts_is_valid(struct phy_device *phydev)
+{
+ bool valid;
+ int reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ TJA1120_VEND1_PTP_TRIG_DATA_S);
+ valid = !!(reg & TJA1120_TS_VALID);
+
+ return valid;
+}
+
+static bool tja1120_get_extts(struct nxp_c45_phy *priv,
+ struct timespec64 *extts)
+{
+ const struct nxp_c45_regmap *regmap = nxp_c45_get_regmap(priv->phydev);
+ struct phy_device *phydev = priv->phydev;
+ bool more_ts;
+ bool valid;
+ u16 reg;
+
+ reg = phy_read_mmd(phydev, MDIO_MMD_VEND1,
+ regmap->vend1_ext_trg_ctrl);
+ more_ts = !!(reg & TJA1120_MORE_TS);
+
+ valid = tja1120_extts_is_valid(phydev);
+ if (!valid) {
+ if (!more_ts)
+ goto tja1120_get_extts_out;
+
+ /* Bug workaround for TJA1120 engineering samples: move the new
+ * timestamp from the FIFO to the buffer.
+ */
+ phy_write_mmd(phydev, MDIO_MMD_VEND1,
+ regmap->vend1_ext_trg_ctrl, RING_DONE);
+ valid = tja1120_extts_is_valid(phydev);
+ if (!valid)
+ goto tja1120_get_extts_out;
+ }
+
+ nxp_c45_get_extts(priv, extts);
+tja1120_get_extts_out:
+ return valid;
}

static void nxp_c45_read_egress_ts(struct nxp_c45_phy *priv,
@@ -656,12 +706,12 @@ static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp)
bool reschedule = false;
struct timespec64 ts;
struct sk_buff *skb;
- bool txts_valid;
+ bool ts_valid;
u32 ts_raw;

while (!skb_queue_empty_lockless(&priv->tx_queue) && poll_txts) {
- txts_valid = data->get_egressts(priv, &hwts);
- if (unlikely(!txts_valid)) {
+ ts_valid = data->get_egressts(priv, &hwts);
+ if (unlikely(!ts_valid)) {
/* Still more skbs in the queue */
reschedule = true;
break;
@@ -683,8 +733,8 @@ static long nxp_c45_do_aux_work(struct ptp_clock_info *ptp)
}

if (priv->extts) {
- nxp_c45_get_extts(priv, &ts);
- if (timespec64_compare(&ts, &priv->extts_ts) != 0) {
+ ts_valid = data->get_extts(priv, &ts);
+ if (ts_valid && timespec64_compare(&ts, &priv->extts_ts) != 0) {
priv->extts_ts = ts;
event.index = priv->extts_index;
event.type = PTP_CLOCK_EXTTS;
@@ -1724,6 +1774,7 @@ static const struct nxp_c45_phy_data tja1103_phy_data = {
.ack_ptp_irq = false,
.counters_enable = tja1103_counters_enable,
.get_egressts = nxp_c45_get_hwtxts,
+ .get_extts = nxp_c45_get_extts,
.ptp_init = tja1103_ptp_init,
.ptp_enable = tja1103_ptp_enable,
.nmi_handler = tja1103_nmi_handler,
@@ -1838,6 +1889,7 @@ static const struct nxp_c45_phy_data tja1120_phy_data = {
.ack_ptp_irq = true,
.counters_enable = tja1120_counters_enable,
.get_egressts = tja1120_get_hwtxts,
+ .get_extts = tja1120_get_extts,
.ptp_init = tja1120_ptp_init,
.ptp_enable = tja1120_ptp_enable,
.nmi_handler = tja1120_nmi_handler,
--
2.34.1


2023-06-24 19:52:31

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH v2 06/13] net: phy: nxp-c45-tja11xx: use get_features

On Fri, Jun 23, 2023 at 10:41:16AM +0300, Radu Pirea (NXP OSS) wrote:
> PHY_BASIC_T1_FEATURES are not the right features supported by TJA1103
> anymore.
> For example ethtool reports:
> [root@alarm ~]# ethtool end0
> Settings for end0:
> Supported ports: [ TP ]
> Supported link modes: 100baseT1/Full
> 10baseT1L/Full
>
> 10baseT1L/Full is not supported by TJA1103 and supported ports list is
> not completed. The PHY also have a MII port.
>
> genphy_c45_pma_read_abilities implementation can detect the PHY features
> and they look like this.
> [root@alarm ~]# ethtool end0
> Settings for end0:
> Supported ports: [ TP MII ]
> Supported link modes: 100baseT1/Full
> Supported pause frame use: Symmetric
> Supports auto-negotiation: No
> Supported FEC modes: Not reported
> Advertised link modes: 100baseT1/Full
> Advertised pause frame use: Symmetric
> Advertised auto-negotiation: No
> Advertised FEC modes: Not reported
> Speed: 100Mb/s
> Duplex: Full
> Auto-negotiation: off
> master-slave cfg: forced master
> master-slave status: master
> Port: Twisted Pair
> PHYAD: 1
> Transceiver: external
> MDI-X: Unknown
> Supports Wake-on: g
> Wake-on: d
> Link detected: yes
> SQI: 7/7
>
> Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-06-24 19:52:48

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH v2 13/13] net: phy: nxp-c45-tja11xx: reset PCS if the link goes down

On Fri, Jun 23, 2023 at 10:41:23AM +0300, Radu Pirea (NXP OSS) wrote:
> During PTP testing on early TJA1120 engineering samples I observed that
> if the link is lost and recovered, the tx timestamps will be randomly
> lost. To avoid this HW issue, the PCS should be reseted.
>
> Resetting the PCS will break the link and we should reset the PCS on
> LINK UP -> LINK DOWN transition, otherwise we will trigger and infinite
> loop of LINK UP -> LINK DOWN events.
>
> Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-06-24 19:52:48

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH v2 10/13] net: phy: nxp-c45-tja11xx: handle FUSA irq

On Fri, Jun 23, 2023 at 10:41:20AM +0300, Radu Pirea (NXP OSS) wrote:
> TJA1120 and TJA1103 have a set of functional safety hardware tests
> executed after every reset, and when the tests are done, the IRQ line is
> asserted. For the moment, the purpose of these handlers is to acknowledge
> the IRQ and not to check the FUSA tests status.
>
> Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-06-24 19:52:48

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH v2 11/13] net: phy: nxp-c45-tja11xx: run cable test with the PHY in test mode

On Fri, Jun 23, 2023 at 10:41:21AM +0300, Radu Pirea (NXP OSS) wrote:
> For TJA1120, the enable bit for cable test is not writable if the PHY is
> not in test mode.
>
> Signed-off-by: Radu Pirea (NXP OSS) <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew