diff options
Diffstat (limited to 'drivers/net/ethernet/amd')
-rw-r--r-- | drivers/net/ethernet/amd/pds_core/main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-common.h | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c | 30 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-i2c.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-pps.c | 74 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 26 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe.h | 17 |
10 files changed, 182 insertions, 10 deletions
diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c index 9b81e1c260c2..c7a2eff57632 100644 --- a/drivers/net/ethernet/amd/pds_core/main.c +++ b/drivers/net/ethernet/amd/pds_core/main.c @@ -280,7 +280,7 @@ static int pdsc_init_pf(struct pdsc *pdsc) goto err_out_del_dev; } - hr = devl_health_reporter_create(dl, &pdsc_fw_reporter_ops, 0, pdsc); + hr = devl_health_reporter_create(dl, &pdsc_fw_reporter_ops, pdsc); if (IS_ERR(hr)) { devl_unlock(dl); dev_warn(pdsc->dev, "Failed to create fw reporter: %pe\n", hr); diff --git a/drivers/net/ethernet/amd/xgbe/Makefile b/drivers/net/ethernet/amd/xgbe/Makefile index 5b0ab6240cf2..980e27652237 100644 --- a/drivers/net/ethernet/amd/xgbe/Makefile +++ b/drivers/net/ethernet/amd/xgbe/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \ xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \ - xgbe-hwtstamp.o xgbe-ptp.o \ + xgbe-hwtstamp.o xgbe-ptp.o xgbe-pps.o \ xgbe-i2c.o xgbe-phy-v1.o xgbe-phy-v2.o \ xgbe-platform.o diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index 009fbc9b11ce..62b01de93db4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -227,7 +227,11 @@ #define MAC_TICSNR 0x0d5C #define MAC_TECNR 0x0d60 #define MAC_TECSNR 0x0d64 - +#define MAC_PPSCR 0x0d70 +#define MAC_PPS0_TTSR 0x0d80 +#define MAC_PPS0_TTNSR 0x0d84 +#define MAC_PPS0_INTERVAL 0x0d88 +#define MAC_PPS0_WIDTH 0x0d8C #define MAC_QTFCR_INC 4 #define MAC_MACA_INC 4 #define MAC_HTR_INC 4 @@ -235,6 +239,18 @@ #define MAC_RQC2_INC 4 #define MAC_RQC2_Q_PER_REG 4 +/* PPS helpers */ +#define PPSEN0 BIT(4) +#define MAC_PPSx_TTSR(x) ((MAC_PPS0_TTSR) + ((x) * 0x10)) +#define MAC_PPSx_TTNSR(x) ((MAC_PPS0_TTNSR) + ((x) * 0x10)) +#define MAC_PPSx_INTERVAL(x) ((MAC_PPS0_INTERVAL) + ((x) * 0x10)) +#define MAC_PPSx_WIDTH(x) ((MAC_PPS0_WIDTH) + ((x) * 0x10)) +#define PPS_MAXIDX(x) ((((x) + 1) * 8) - 1) +#define PPS_MINIDX(x) ((x) * 8) +#define XGBE_PPSCMD_STOP 0x5 +#define XGBE_PPSCMD_START 0x2 +#define XGBE_PPSTARGET_PULSE 0x2 + /* MAC register entry bit positions and sizes */ #define MAC_HWF0R_ADDMACADRSEL_INDEX 18 #define MAC_HWF0R_ADDMACADRSEL_WIDTH 5 @@ -496,8 +512,10 @@ #define MAC_VR_SNPSVER_WIDTH 8 #define MAC_VR_USERVER_INDEX 16 #define MAC_VR_USERVER_WIDTH 8 +#define MAC_PPSx_TTNSR_TRGTBUSY0_INDEX 31 +#define MAC_PPSx_TTNSR_TRGTBUSY0_WIDTH 1 -/* MMC register offsets */ + /* MMC register offsets */ #define MMC_CR 0x0800 #define MMC_RISR 0x0804 #define MMC_TISR 0x0808 diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 2e9b95a94f89..f0989aa01855 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -691,6 +691,21 @@ void xgbe_get_all_hw_features(struct xgbe_prv_data *pdata) hw_feat->pps_out_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, PPSOUTNUM); hw_feat->aux_snap_num = XGMAC_GET_BITS(mac_hfr2, MAC_HWF2R, AUXSNAPNUM); + /* Sanity check and warn if hardware reports more than supported */ + if (hw_feat->pps_out_num > XGBE_MAX_PPS_OUT) { + dev_warn(pdata->dev, + "Hardware reports %u PPS outputs, limiting to %u\n", + hw_feat->pps_out_num, XGBE_MAX_PPS_OUT); + hw_feat->pps_out_num = XGBE_MAX_PPS_OUT; + } + + if (hw_feat->aux_snap_num > XGBE_MAX_AUX_SNAP) { + dev_warn(pdata->dev, + "Hardware reports %u aux snapshot inputs, limiting to %u\n", + hw_feat->aux_snap_num, XGBE_MAX_AUX_SNAP); + hw_feat->aux_snap_num = XGBE_MAX_AUX_SNAP; + } + /* Translate the Hash Table size into actual number */ switch (hw_feat->hash_table_size) { case 0: diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c index be0d2c7d08dc..b6e1b67a2d0e 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c @@ -329,6 +329,7 @@ static int xgbe_get_coalesce(struct net_device *netdev, ec->rx_coalesce_usecs = pdata->rx_usecs; ec->rx_max_coalesced_frames = pdata->rx_frames; + ec->tx_coalesce_usecs = pdata->tx_usecs; ec->tx_max_coalesced_frames = pdata->tx_frames; return 0; @@ -342,7 +343,8 @@ static int xgbe_set_coalesce(struct net_device *netdev, struct xgbe_prv_data *pdata = netdev_priv(netdev); struct xgbe_hw_if *hw_if = &pdata->hw_if; unsigned int rx_frames, rx_riwt, rx_usecs; - unsigned int tx_frames; + unsigned int tx_frames, tx_usecs; + unsigned int jiffy_us = jiffies_to_usecs(1); rx_riwt = hw_if->usec_to_riwt(pdata, ec->rx_coalesce_usecs); rx_usecs = ec->rx_coalesce_usecs; @@ -364,20 +366,42 @@ static int xgbe_set_coalesce(struct net_device *netdev, return -EINVAL; } + tx_usecs = ec->tx_coalesce_usecs; tx_frames = ec->tx_max_coalesced_frames; /* Check the bounds of values for Tx */ + if (!tx_usecs) { + NL_SET_ERR_MSG_FMT_MOD(extack, + "tx-usecs must not be 0"); + return -EINVAL; + } + if (tx_usecs > XGMAC_MAX_COAL_TX_TICK) { + NL_SET_ERR_MSG_FMT_MOD(extack, "tx-usecs is limited to %d usec", + XGMAC_MAX_COAL_TX_TICK); + return -EINVAL; + } if (tx_frames > pdata->tx_desc_count) { netdev_err(netdev, "tx-frames is limited to %d frames\n", pdata->tx_desc_count); return -EINVAL; } + /* Round tx-usecs to nearest multiple of jiffy granularity */ + if (tx_usecs % jiffy_us) { + tx_usecs = rounddown(tx_usecs, jiffy_us); + if (!tx_usecs) + tx_usecs = jiffy_us; + NL_SET_ERR_MSG_FMT_MOD(extack, + "tx-usecs rounded to %u usec due to jiffy granularity (%u usec)", + tx_usecs, jiffy_us); + } + pdata->rx_riwt = rx_riwt; pdata->rx_usecs = rx_usecs; pdata->rx_frames = rx_frames; hw_if->config_rx_coalesce(pdata); + pdata->tx_usecs = tx_usecs; pdata->tx_frames = tx_frames; hw_if->config_tx_coalesce(pdata); @@ -440,7 +464,7 @@ static int xgbe_set_rxfh(struct net_device *netdev, { struct xgbe_prv_data *pdata = netdev_priv(netdev); struct xgbe_hw_if *hw_if = &pdata->hw_if; - unsigned int ret; + int ret; if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && rxfh->hfunc != ETH_RSS_HASH_TOP) { @@ -709,7 +733,7 @@ out: } static const struct ethtool_ops xgbe_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS | + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | ETHTOOL_COALESCE_MAX_FRAMES, .get_drvinfo = xgbe_get_drvinfo, .get_msglevel = xgbe_get_msglevel, diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c index d40011e8ddf2..65eb7b577b65 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c @@ -70,7 +70,7 @@ static int xgbe_i2c_set_enable(struct xgbe_prv_data *pdata, bool enable) static int xgbe_i2c_disable(struct xgbe_prv_data *pdata) { - unsigned int ret; + int ret; ret = xgbe_i2c_set_enable(pdata, false); if (ret) { diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 23c39e92e783..a56efc1bee33 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2902,7 +2902,7 @@ static void xgbe_phy_sfp_setup(struct xgbe_prv_data *pdata) static int xgbe_phy_int_mdio_reset(struct xgbe_prv_data *pdata) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int ret; + int ret; ret = pdata->hw_if.set_gpio(pdata, phy_data->mdio_reset_gpio); if (ret) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pps.c b/drivers/net/ethernet/amd/xgbe/xgbe-pps.c new file mode 100644 index 000000000000..6d03ae7ab36f --- /dev/null +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pps.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (c) 2014-2025, Advanced Micro Devices, Inc. + * Copyright (c) 2014, Synopsys, Inc. + * All rights reserved + * + * Author: Raju Rangoju <Raju.Rangoju@amd.com> + */ + +#include "xgbe.h" +#include "xgbe-common.h" + +static u32 get_pps_mask(unsigned int x) +{ + return GENMASK(PPS_MAXIDX(x), PPS_MINIDX(x)); +} + +static u32 get_pps_cmd(unsigned int x, u32 val) +{ + return (val & GENMASK(3, 0)) << PPS_MINIDX(x); +} + +static u32 get_target_mode_sel(unsigned int x, u32 val) +{ + return (val & GENMASK(1, 0)) << (PPS_MAXIDX(x) - 2); +} + +int xgbe_pps_config(struct xgbe_prv_data *pdata, + struct xgbe_pps_config *cfg, int index, bool on) +{ + unsigned int ppscr = 0; + unsigned int tnsec; + u64 period; + + /* Check if target time register is busy */ + tnsec = XGMAC_IOREAD(pdata, MAC_PPSx_TTNSR(index)); + if (XGMAC_GET_BITS(tnsec, MAC_PPSx_TTNSR, TRGTBUSY0)) + return -EBUSY; + + ppscr = XGMAC_IOREAD(pdata, MAC_PPSCR); + ppscr &= ~get_pps_mask(index); + + if (!on) { + /* Disable PPS output */ + ppscr |= get_pps_cmd(index, XGBE_PPSCMD_STOP); + ppscr |= PPSEN0; + XGMAC_IOWRITE(pdata, MAC_PPSCR, ppscr); + + return 0; + } + + /* Configure start time */ + XGMAC_IOWRITE(pdata, MAC_PPSx_TTSR(index), cfg->start.tv_sec); + XGMAC_IOWRITE(pdata, MAC_PPSx_TTNSR(index), cfg->start.tv_nsec); + + period = cfg->period.tv_sec * NSEC_PER_SEC + cfg->period.tv_nsec; + period = div_u64(period, XGBE_V2_TSTAMP_SSINC); + + if (period < 4) + return -EINVAL; + + /* Configure interval and pulse width (50% duty cycle) */ + XGMAC_IOWRITE(pdata, MAC_PPSx_INTERVAL(index), period - 1); + XGMAC_IOWRITE(pdata, MAC_PPSx_WIDTH(index), (period >> 1) - 1); + + /* Enable PPS with pulse train mode */ + ppscr |= get_pps_cmd(index, XGBE_PPSCMD_START); + ppscr |= get_target_mode_sel(index, XGBE_PPSTARGET_PULSE); + ppscr |= PPSEN0; + + XGMAC_IOWRITE(pdata, MAC_PPSCR, ppscr); + + return 0; +} diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c index 3658afc7801d..0e0b8ec3b504 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c @@ -106,7 +106,29 @@ static int xgbe_settime(struct ptp_clock_info *info, static int xgbe_enable(struct ptp_clock_info *info, struct ptp_clock_request *request, int on) { - return -EOPNOTSUPP; + struct xgbe_prv_data *pdata = container_of(info, struct xgbe_prv_data, + ptp_clock_info); + struct xgbe_pps_config *pps_cfg; + unsigned long flags; + int ret; + + dev_dbg(pdata->dev, "rq->type %d on %d\n", request->type, on); + + if (request->type != PTP_CLK_REQ_PEROUT) + return -EOPNOTSUPP; + + pps_cfg = &pdata->pps[request->perout.index]; + + pps_cfg->start.tv_sec = request->perout.start.sec; + pps_cfg->start.tv_nsec = request->perout.start.nsec; + pps_cfg->period.tv_sec = request->perout.period.sec; + pps_cfg->period.tv_nsec = request->perout.period.nsec; + + spin_lock_irqsave(&pdata->tstamp_lock, flags); + ret = xgbe_pps_config(pdata, pps_cfg, request->perout.index, on); + spin_unlock_irqrestore(&pdata->tstamp_lock, flags); + + return ret; } void xgbe_ptp_register(struct xgbe_prv_data *pdata) @@ -122,6 +144,8 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) info->adjtime = xgbe_adjtime; info->gettimex64 = xgbe_gettimex; info->settime64 = xgbe_settime; + info->n_per_out = pdata->hw_feat.pps_out_num; + info->n_ext_ts = pdata->hw_feat.aux_snap_num; info->enable = xgbe_enable; clock = ptp_clock_register(info, pdata->dev); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index d7e03e292ec4..e8bbb6805901 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -142,6 +142,10 @@ #define XGBE_V2_TSTAMP_SNSINC 0 #define XGBE_V2_PTP_ACT_CLK_FREQ 1000000000 +/* Define maximum supported values */ +#define XGBE_MAX_PPS_OUT 4 +#define XGBE_MAX_AUX_SNAP 4 + /* Driver PMT macros */ #define XGMAC_DRIVER_CONTEXT 1 #define XGMAC_IOCTL_CONTEXT 2 @@ -168,6 +172,7 @@ /* Default coalescing parameters */ #define XGMAC_INIT_DMA_TX_USECS 1000 #define XGMAC_INIT_DMA_TX_FRAMES 25 +#define XGMAC_MAX_COAL_TX_TICK 100000 #define XGMAC_MAX_DMA_RIWT 0xff #define XGMAC_INIT_DMA_RX_USECS 30 @@ -672,6 +677,11 @@ struct xgbe_ext_stats { u64 rx_vxlan_csum_errors; }; +struct xgbe_pps_config { + struct timespec64 start; + struct timespec64 period; +}; + struct xgbe_hw_if { int (*tx_complete)(struct xgbe_ring_desc *); @@ -1142,6 +1152,9 @@ struct xgbe_prv_data { struct sk_buff *tx_tstamp_skb; u64 tx_tstamp; + /* Pulse Per Second output */ + struct xgbe_pps_config pps[XGBE_MAX_PPS_OUT]; + /* DCB support */ struct ieee_ets *ets; struct ieee_pfc *pfc; @@ -1304,6 +1317,10 @@ void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata, int xgbe_init_ptp(struct xgbe_prv_data *pdata); void xgbe_update_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, unsigned int nsec); + +int xgbe_pps_config(struct xgbe_prv_data *pdata, struct xgbe_pps_config *cfg, + int index, bool on); + #ifdef CONFIG_DEBUG_FS void xgbe_debugfs_init(struct xgbe_prv_data *); void xgbe_debugfs_exit(struct xgbe_prv_data *); |