net: phy: nxp-c45-tja11xx: add MACsec support

Add MACsec support.
The MACsec block has four TX SCs and four RX SCs. The driver supports up
to four SecY. Each SecY with one TX SC and one RX SC.
The RX SCs can have two keys, key A and key B, written in hardware and
enabled at the same time.
The TX SCs can have two keys written in hardware, but only one can be
active at a given time.
On TX, the SC is selected using the MAC source address. Due of this
selection mechanism, each offloaded netdev must have a unique MAC
address.
On RX, the SC is selected by SCI(found in SecTAG or calculated using MAC
SA), or using RX SC 0 as implicit.

Signed-off-by: Radu Pirea (NXP OSS) <radu-nicolae.pirea@oss.nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Radu Pirea (NXP OSS) 2023-12-19 16:53:31 +02:00 committed by David S. Miller
parent a73d8779d6
commit a868b486cb
6 changed files with 1460 additions and 33 deletions

View File

@ -15444,7 +15444,7 @@ NXP C45 TJA11XX PHY DRIVER
M: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/phy/nxp-c45-tja11xx.c
F: drivers/net/phy/nxp-c45-tja11xx*
NXP FSPI DRIVER
M: Han Xu <han.xu@nxp.com>

View File

@ -317,9 +317,10 @@ config NXP_CBTX_PHY
config NXP_C45_TJA11XX_PHY
tristate "NXP C45 TJA11XX PHYs"
depends on PTP_1588_CLOCK_OPTIONAL
depends on MACSEC || !MACSEC
help
Enable support for NXP C45 TJA11XX PHYs.
Currently supports the TJA1103 and TJA1120 PHYs.
Currently supports the TJA1103, TJA1104 and TJA1120 PHYs.
config NXP_TJA11XX_PHY
tristate "NXP TJA11xx PHYs support"

View File

@ -84,7 +84,11 @@ 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
nxp-c45-tja-objs += nxp-c45-tja11xx.o
ifdef CONFIG_MACSEC
nxp-c45-tja-objs += nxp-c45-tja11xx-macsec.o
endif
obj-$(CONFIG_NXP_C45_TJA11XX_PHY) += nxp-c45-tja.o
obj-$(CONFIG_NXP_CBTX_PHY) += nxp-cbtx.o
obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
obj-$(CONFIG_QSEMI_PHY) += qsemi.o

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/* NXP C45 PHY driver
* Copyright (C) 2021 NXP
* Copyright 2021-2023 NXP
* Author: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
*/
@ -14,9 +14,10 @@
#include <linux/processor.h>
#include <linux/property.h>
#include <linux/ptp_classify.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/net_tstamp.h>
#include "nxp-c45-tja11xx.h"
#define PHY_ID_TJA_1103 0x001BB010
#define PHY_ID_TJA_1120 0x001BB031
@ -75,9 +76,11 @@
#define PORT_CONTROL_EN BIT(14)
#define VEND1_PORT_ABILITIES 0x8046
#define MACSEC_ABILITY BIT(5)
#define PTP_ABILITY BIT(3)
#define VEND1_PORT_FUNC_IRQ_EN 0x807A
#define MACSEC_IRQS BIT(5)
#define PTP_IRQS BIT(3)
#define VEND1_PTP_IRQ_ACK 0x9008
@ -148,7 +151,6 @@
#define TS_SEC_MASK GENMASK(1, 0)
#define VEND1_PORT_FUNC_ENABLES 0x8048
#define PTP_ENABLE BIT(3)
#define PHY_TEST_ENABLE BIT(0)
@ -281,25 +283,6 @@ struct nxp_c45_phy_data {
irqreturn_t *irq_status);
};
struct nxp_c45_phy {
const struct nxp_c45_phy_data *phy_data;
struct phy_device *phydev;
struct mii_timestamper mii_ts;
struct ptp_clock *ptp_clock;
struct ptp_clock_info caps;
struct sk_buff_head tx_queue;
struct sk_buff_head rx_queue;
/* used to access the PTP registers atomic */
struct mutex ptp_lock;
int hwts_tx;
int hwts_rx;
u32 tx_delay;
u32 rx_delay;
struct timespec64 extts_ts;
int extts_index;
bool extts;
};
static const
struct nxp_c45_phy_data *nxp_c45_get_data(struct phy_device *phydev)
{
@ -1215,12 +1198,25 @@ static int nxp_c45_start_op(struct phy_device *phydev)
static int nxp_c45_config_intr(struct phy_device *phydev)
{
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
int ret;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PORT_FUNC_IRQ_EN, MACSEC_IRQS);
if (ret)
return ret;
return phy_set_bits_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
else
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
}
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PORT_FUNC_IRQ_EN, MACSEC_IRQS);
if (ret)
return ret;
return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PHY_IRQ_EN, PHY_IRQ_LINK_EVENT);
}
static int tja1103_config_intr(struct phy_device *phydev)
@ -1286,6 +1282,7 @@ static irqreturn_t nxp_c45_handle_interrupt(struct phy_device *phydev)
}
data->nmi_handler(phydev, &ret);
nxp_c45_handle_macsec_interrupt(phydev, &ret);
return ret;
}
@ -1611,6 +1608,9 @@ static int nxp_c45_config_init(struct phy_device *phydev)
nxp_c45_counters_enable(phydev);
nxp_c45_ptp_init(phydev);
ret = nxp_c45_macsec_config_init(phydev);
if (ret)
return ret;
return nxp_c45_start_op(phydev);
}
@ -1626,7 +1626,9 @@ static int nxp_c45_get_features(struct phy_device *phydev)
static int nxp_c45_probe(struct phy_device *phydev)
{
struct nxp_c45_phy *priv;
int ptp_ability;
bool macsec_ability;
int phy_abilities;
bool ptp_ability;
int ret = 0;
priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
@ -1642,9 +1644,9 @@ static int nxp_c45_probe(struct phy_device *phydev)
mutex_init(&priv->ptp_lock);
ptp_ability = phy_read_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PORT_ABILITIES);
ptp_ability = !!(ptp_ability & PTP_ABILITY);
phy_abilities = phy_read_mmd(phydev, MDIO_MMD_VEND1,
VEND1_PORT_ABILITIES);
ptp_ability = !!(phy_abilities & PTP_ABILITY);
if (!ptp_ability) {
phydev_dbg(phydev, "the phy does not support PTP");
goto no_ptp_support;
@ -1663,6 +1665,20 @@ static int nxp_c45_probe(struct phy_device *phydev)
}
no_ptp_support:
macsec_ability = !!(phy_abilities & MACSEC_ABILITY);
if (!macsec_ability) {
phydev_info(phydev, "the phy does not support MACsec\n");
goto no_macsec_support;
}
if (IS_ENABLED(CONFIG_MACSEC)) {
ret = nxp_c45_macsec_probe(phydev);
phydev_dbg(phydev, "MACsec support enabled.");
} else {
phydev_dbg(phydev, "MACsec support not enabled even if the phy supports it");
}
no_macsec_support:
return ret;
}
@ -1676,6 +1692,7 @@ static void nxp_c45_remove(struct phy_device *phydev)
skb_queue_purge(&priv->tx_queue);
skb_queue_purge(&priv->rx_queue);
nxp_c45_macsec_remove(phydev);
}
static void tja1103_counters_enable(struct phy_device *phydev)

View File

@ -0,0 +1,62 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* NXP C45 PHY driver header file
* Copyright 2023 NXP
* Author: Radu Pirea <radu-nicolae.pirea@oss.nxp.com>
*/
#include <linux/ptp_clock_kernel.h>
#define VEND1_PORT_FUNC_ENABLES 0x8048
struct nxp_c45_macsec;
struct nxp_c45_phy {
const struct nxp_c45_phy_data *phy_data;
struct phy_device *phydev;
struct mii_timestamper mii_ts;
struct ptp_clock *ptp_clock;
struct ptp_clock_info caps;
struct sk_buff_head tx_queue;
struct sk_buff_head rx_queue;
/* used to access the PTP registers atomic */
struct mutex ptp_lock;
int hwts_tx;
int hwts_rx;
u32 tx_delay;
u32 rx_delay;
struct timespec64 extts_ts;
int extts_index;
bool extts;
struct nxp_c45_macsec *macsec;
};
#if IS_ENABLED(CONFIG_MACSEC)
int nxp_c45_macsec_config_init(struct phy_device *phydev);
int nxp_c45_macsec_probe(struct phy_device *phydev);
void nxp_c45_macsec_remove(struct phy_device *phydev);
void nxp_c45_handle_macsec_interrupt(struct phy_device *phydev,
irqreturn_t *ret);
#else
static inline
int nxp_c45_macsec_config_init(struct phy_device *phydev)
{
return 0;
}
static inline
int nxp_c45_macsec_probe(struct phy_device *phydev)
{
return 0;
}
static inline
void nxp_c45_macsec_remove(struct phy_device *phydev)
{
}
static inline
void nxp_c45_handle_macsec_interrupt(struct phy_device *phydev,
irqreturn_t *ret)
{
}
#endif