summaryrefslogtreecommitdiff
path: root/drivers/net/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy')
-rw-r--r--drivers/net/phy/nxp-c45-tja11xx.c79
1 files changed, 77 insertions, 2 deletions
diff --git a/drivers/net/phy/nxp-c45-tja11xx.c b/drivers/net/phy/nxp-c45-tja11xx.c
index e596ffcf8683..a52067da9dbf 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,