From e37e08fffc373206ad4e905c05729ea6bbdcb22c Mon Sep 17 00:00:00 2001 From: Harman Kalra Date: Tue, 28 Sep 2021 17:00:58 +0530 Subject: [PATCH 1/4] octeontx2-af: Reset PTP config in FLR handler Upon receiving ptp config request from netdev interface , Octeontx2 MAC block CGX is configured to append timestamp to every incoming packet and NPC config is updated with DMAC offset change. Currently this configuration is not reset in FLR handler. This patch resets the same. Signed-off-by: Harman Kalra Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 1 + .../net/ethernet/marvell/octeontx2/af/rvu_cgx.c | 3 +++ .../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 14 ++++++++++++++ 3 files changed, 18 insertions(+) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index 0128211806f94..95e807626a3e3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -220,6 +220,7 @@ struct rvu_pfvf { u16 maxlen; u16 minlen; + bool hw_rx_tstamp_en; /* Is rx_tstamp enabled */ u8 mac_addr[ETH_ALEN]; /* MAC address of this PF/VF */ u8 default_mac[ETH_ALEN]; /* MAC address from FWdata */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index 21e5906bcc372..a5c717ad12c15 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -694,6 +694,7 @@ int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req, static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) { + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); int pf = rvu_get_pf(pcifunc); u8 cgx_id, lmac_id; void *cgxd; @@ -718,6 +719,8 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) */ if (npc_config_ts_kpuaction(rvu, pf, pcifunc, enable)) return -EINVAL; + /* This flag is required to clean up CGX conf if app gets killed */ + pfvf->hw_rx_tstamp_en = enable; return 0; } diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index e299ec13c7f1f..601935a05921b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -4516,6 +4516,9 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) { struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); struct hwctx_disable_req ctx_req; + int pf = rvu_get_pf(pcifunc); + u8 cgx_id, lmac_id; + void *cgxd; int err; ctx_req.hdr.pcifunc = pcifunc; @@ -4556,6 +4559,17 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) rvu_npc_set_parse_mode(rvu, pcifunc, OTX2_PRIV_FLAGS_DEFAULT, (PKIND_TX | PKIND_RX), 0, 0, 0, 0); + /* Disabling CGX and NPC config done for PTP */ + if (pfvf->hw_rx_tstamp_en) { + rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); + cgxd = rvu_cgx_pdata(cgx_id, rvu); + cgx_lmac_ptp_config(cgxd, lmac_id, false); + /* Undo NPC config done for PTP */ + if (npc_config_ts_kpuaction(rvu, pf, pcifunc, false)) + dev_err(rvu->dev, "NPC config for PTP failed\n"); + pfvf->hw_rx_tstamp_en = false; + } + nix_ctx_free(rvu, pfvf); nix_free_all_bandprof(rvu, pcifunc); From d1489208681dfe432609fdaa49b160219c6e221c Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Tue, 28 Sep 2021 17:00:59 +0530 Subject: [PATCH 2/4] octeontx2-af: cn10k: RPM hardware timestamp configuration MAC on CN10K support hardware timestamping such that 8 bytes addition header is prepended to incoming packets. This patch does necessary configuration to enable Hardware time stamping upon receiving request from PF netdev interfaces. Timestamp configuration is different on MAC (CGX) Octeontx2 silicon and MAC (RPM) OcteonTX3 CN10k. Based on silicon variant appropriate fn() pointer is called. Refactor MAC specific mbox messages to remove unnecessary gaps in mboxids. Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- .../net/ethernet/marvell/octeontx2/af/cgx.c | 10 ++--- .../marvell/octeontx2/af/lmac_common.h | 5 +++ .../net/ethernet/marvell/octeontx2/af/mbox.h | 41 ++++++++++--------- .../net/ethernet/marvell/octeontx2/af/rpm.c | 17 ++++++++ .../net/ethernet/marvell/octeontx2/af/rpm.h | 3 ++ .../ethernet/marvell/octeontx2/af/rvu_cgx.c | 4 +- .../ethernet/marvell/octeontx2/af/rvu_nix.c | 4 +- 7 files changed, 58 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c index 34a089b71e554..d379a35c4618f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c @@ -838,9 +838,6 @@ void cgx_lmac_ptp_config(void *cgxd, int lmac_id, bool enable) if (!cgx) return; - if (is_dev_rpm(cgx)) - return; - if (enable) { /* Enable inbound PTP timestamping */ cfg = cgx_read(cgx, lmac_id, CGXX_GMP_GMI_RXX_FRM_CTL); @@ -1545,9 +1542,11 @@ static int cgx_lmac_exit(struct cgx *cgx) static void cgx_populate_features(struct cgx *cgx) { if (is_dev_rpm(cgx)) - cgx->hw_features = (RVU_MAC_RPM | RVU_LMAC_FEAT_FC); + cgx->hw_features = (RVU_LMAC_FEAT_DMACF | RVU_MAC_RPM | + RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP); else - cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_PTP); + cgx->hw_features = (RVU_LMAC_FEAT_FC | RVU_LMAC_FEAT_HIGIG2 | + RVU_LMAC_FEAT_PTP | RVU_LMAC_FEAT_DMACF); } static struct mac_ops cgx_mac_ops = { @@ -1571,6 +1570,7 @@ static struct mac_ops cgx_mac_ops = { .mac_get_pause_frm_status = cgx_lmac_get_pause_frm_status, .mac_enadis_pause_frm = cgx_lmac_enadis_pause_frm, .mac_pause_frm_config = cgx_lmac_pause_frm_config, + .mac_enadis_ptp_config = cgx_lmac_ptp_config, }; static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h index c38306b3384a7..fc6e7423cbd81 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/lmac_common.h @@ -102,6 +102,11 @@ struct mac_ops { void (*mac_pause_frm_config)(void *cgxd, int lmac_id, bool enable); + + /* Enable/Disable Inbound PTP */ + void (*mac_enadis_ptp_config)(void *cgxd, + int lmac_id, + bool enable); }; struct cgx { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index cb48ddf548971..b5ee324d17c9a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -154,23 +154,23 @@ M(CGX_PTP_RX_ENABLE, 0x20C, cgx_ptp_rx_enable, msg_req, msg_rsp) \ M(CGX_PTP_RX_DISABLE, 0x20D, cgx_ptp_rx_disable, msg_req, msg_rsp) \ M(CGX_CFG_PAUSE_FRM, 0x20E, cgx_cfg_pause_frm, cgx_pause_frm_cfg, \ cgx_pause_frm_cfg) \ -M(CGX_FEC_SET, 0x210, cgx_set_fec_param, fec_mode, fec_mode) \ -M(CGX_FEC_STATS, 0x211, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \ -M(CGX_GET_PHY_FEC_STATS, 0x212, cgx_get_phy_fec_stats, msg_req, msg_rsp) \ -M(CGX_FW_DATA_GET, 0x213, cgx_get_aux_link_info, msg_req, cgx_fw_data) \ -M(CGX_SET_LINK_MODE, 0x214, cgx_set_link_mode, cgx_set_link_mode_req,\ - cgx_set_link_mode_rsp) \ -M(CGX_FEATURES_GET, 0x215, cgx_features_get, msg_req, \ - cgx_features_info_msg) \ -M(RPM_STATS, 0x216, rpm_stats, msg_req, rpm_stats_rsp) \ -M(CGX_MAC_ADDR_ADD, 0x217, cgx_mac_addr_add, cgx_mac_addr_add_req, \ - cgx_mac_addr_add_rsp) \ -M(CGX_MAC_ADDR_DEL, 0x218, cgx_mac_addr_del, cgx_mac_addr_del_req, \ +M(CGX_FW_DATA_GET, 0x20F, cgx_get_aux_link_info, msg_req, cgx_fw_data) \ +M(CGX_FEC_SET, 0x210, cgx_set_fec_param, fec_mode, fec_mode) \ +M(CGX_MAC_ADDR_ADD, 0x211, cgx_mac_addr_add, cgx_mac_addr_add_req, \ + cgx_mac_addr_add_rsp) \ +M(CGX_MAC_ADDR_DEL, 0x212, cgx_mac_addr_del, cgx_mac_addr_del_req, \ msg_rsp) \ -M(CGX_MAC_MAX_ENTRIES_GET, 0x219, cgx_mac_max_entries_get, msg_req, \ +M(CGX_MAC_MAX_ENTRIES_GET, 0x213, cgx_mac_max_entries_get, msg_req, \ cgx_max_dmac_entries_get_rsp) \ -M(CGX_MAC_ADDR_RESET, 0x21A, cgx_mac_addr_reset, msg_req, msg_rsp) \ -M(CGX_MAC_ADDR_UPDATE, 0x21B, cgx_mac_addr_update, cgx_mac_addr_update_req, \ +M(CGX_FEC_STATS, 0x217, cgx_fec_stats, msg_req, cgx_fec_stats_rsp) \ +M(CGX_SET_LINK_MODE, 0x218, cgx_set_link_mode, cgx_set_link_mode_req,\ + cgx_set_link_mode_rsp) \ +M(CGX_GET_PHY_FEC_STATS, 0x219, cgx_get_phy_fec_stats, msg_req, msg_rsp) \ +M(CGX_FEATURES_GET, 0x21B, cgx_features_get, msg_req, \ + cgx_features_info_msg) \ +M(RPM_STATS, 0x21C, rpm_stats, msg_req, rpm_stats_rsp) \ +M(CGX_MAC_ADDR_RESET, 0x21D, cgx_mac_addr_reset, msg_req, msg_rsp) \ +M(CGX_MAC_ADDR_UPDATE, 0x21E, cgx_mac_addr_update, cgx_mac_addr_update_req, \ msg_rsp) \ /* NPA mbox IDs (range 0x400 - 0x5FF) */ \ M(NPA_LF_ALLOC, 0x400, npa_lf_alloc, \ @@ -583,10 +583,13 @@ struct cgx_mac_addr_update_req { }; #define RVU_LMAC_FEAT_FC BIT_ULL(0) /* pause frames */ -#define RVU_LMAC_FEAT_PTP BIT_ULL(1) /* precision time protocol */ -#define RVU_MAC_VERSION BIT_ULL(2) -#define RVU_MAC_CGX BIT_ULL(3) -#define RVU_MAC_RPM BIT_ULL(4) +#define RVU_LMAC_FEAT_HIGIG2 BIT_ULL(1) + /* flow control from physical link higig2 messages */ +#define RVU_LMAC_FEAT_PTP BIT_ULL(2) /* precison time protocol */ +#define RVU_LMAC_FEAT_DMACF BIT_ULL(3) /* DMAC FILTER */ +#define RVU_MAC_VERSION BIT_ULL(4) +#define RVU_MAC_CGX BIT_ULL(5) +#define RVU_MAC_RPM BIT_ULL(6) struct cgx_features_info_msg { struct mbox_msghdr hdr; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c index 07b0eafccad87..e695fa0e82a94 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.c @@ -29,6 +29,7 @@ static struct mac_ops rpm_mac_ops = { .mac_get_pause_frm_status = rpm_lmac_get_pause_frm_status, .mac_enadis_pause_frm = rpm_lmac_enadis_pause_frm, .mac_pause_frm_config = rpm_lmac_pause_frm_config, + .mac_enadis_ptp_config = rpm_lmac_ptp_config, }; struct mac_ops *rpm_get_mac_ops(void) @@ -270,3 +271,19 @@ int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable) return 0; } + +void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable) +{ + rpm_t *rpm = rpmd; + u64 cfg; + + if (!is_lmac_valid(rpm, lmac_id)) + return; + + cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_CFG); + if (enable) + cfg |= RPMX_RX_TS_PREPEND; + else + cfg &= ~RPMX_RX_TS_PREPEND; + rpm_write(rpm, lmac_id, RPMX_CMRX_CFG, cfg); +} diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h index f0b069442dccb..57c8a687b488a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rpm.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rpm.h @@ -14,6 +14,8 @@ #define PCI_DEVID_CN10K_RPM 0xA060 /* Registers */ +#define RPMX_CMRX_CFG 0x00 +#define RPMX_RX_TS_PREPEND BIT_ULL(22) #define RPMX_CMRX_SW_INT 0x180 #define RPMX_CMRX_SW_INT_W1S 0x188 #define RPMX_CMRX_SW_INT_ENA_W1S 0x198 @@ -54,4 +56,5 @@ int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause); int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat); int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat); +void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable); #endif /* RPM_H */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c index a5c717ad12c15..5bdbc77aa721d 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c @@ -696,6 +696,7 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) { struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); int pf = rvu_get_pf(pcifunc); + struct mac_ops *mac_ops; u8 cgx_id, lmac_id; void *cgxd; @@ -712,7 +713,8 @@ static int rvu_cgx_ptp_rx_cfg(struct rvu *rvu, u16 pcifunc, bool enable) rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); cgxd = rvu_cgx_pdata(cgx_id, rvu); - cgx_lmac_ptp_config(cgxd, lmac_id, enable); + mac_ops = get_mac_ops(cgxd); + mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, true); /* If PTP is enabled then inform NPC that packets to be * parsed by this PF will have their data shifted by 8 bytes * and if PTP is disabled then no shift is required diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index 601935a05921b..67feb26792e4b 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -4517,6 +4517,7 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); struct hwctx_disable_req ctx_req; int pf = rvu_get_pf(pcifunc); + struct mac_ops *mac_ops; u8 cgx_id, lmac_id; void *cgxd; int err; @@ -4563,7 +4564,8 @@ void rvu_nix_lf_teardown(struct rvu *rvu, u16 pcifunc, int blkaddr, int nixlf) if (pfvf->hw_rx_tstamp_en) { rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id); cgxd = rvu_cgx_pdata(cgx_id, rvu); - cgx_lmac_ptp_config(cgxd, lmac_id, false); + mac_ops = get_mac_ops(cgxd); + mac_ops->mac_enadis_ptp_config(cgxd, lmac_id, false); /* Undo NPC config done for PTP */ if (npc_config_ts_kpuaction(rvu, pf, pcifunc, false)) dev_err(rvu->dev, "NPC config for PTP failed\n"); From e266f66393963964c867aabee67820222109771c Mon Sep 17 00:00:00 2001 From: Subbaraya Sundeep Date: Tue, 28 Sep 2021 17:01:00 +0530 Subject: [PATCH 3/4] octeontx2-af: Use ptp input clock info from firmware data The input clock frequency of PTP block is figured out from hardware reset block currently. The firmware data already has this info in sclk. Hence simplify ptp driver to use sclk from firmware data. Signed-off-by: Subbaraya Sundeep Signed-off-by: Hariprasad Kelam Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- .../net/ethernet/marvell/octeontx2/af/ptp.c | 80 +++++++------------ .../net/ethernet/marvell/octeontx2/af/ptp.h | 1 + .../net/ethernet/marvell/octeontx2/af/rvu.c | 3 + 3 files changed, 33 insertions(+), 51 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c index 9b8e59f4c206d..477491c001b63 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c @@ -27,7 +27,6 @@ #define PCI_DEVID_CN10K_PTP 0xA09E #define PCI_PTP_BAR_NO 0 -#define PCI_RST_BAR_NO 0 #define PTP_CLOCK_CFG 0xF00ULL #define PTP_CLOCK_CFG_PTP_EN BIT_ULL(0) @@ -35,46 +34,9 @@ #define PTP_CLOCK_HI 0xF10ULL #define PTP_CLOCK_COMP 0xF18ULL -#define RST_BOOT 0x1600ULL -#define RST_MUL_BITS GENMASK_ULL(38, 33) -#define CLOCK_BASE_RATE 50000000ULL - static struct ptp *first_ptp_block; static const struct pci_device_id ptp_id_table[]; -static u64 get_clock_rate(void) -{ - u64 cfg, ret = CLOCK_BASE_RATE * 16; - struct pci_dev *pdev; - void __iomem *base; - - /* To get the input clock frequency with which PTP co-processor - * block is running the base frequency(50 MHz) needs to be multiplied - * with multiplier bits present in RST_BOOT register of RESET block. - * Hence below code gets the multiplier bits from the RESET PCI - * device present in the system. - */ - pdev = pci_get_device(PCI_VENDOR_ID_CAVIUM, - PCI_DEVID_OCTEONTX2_RST, NULL); - if (!pdev) - goto error; - - base = pci_ioremap_bar(pdev, PCI_RST_BAR_NO); - if (!base) - goto error_put_pdev; - - cfg = readq(base + RST_BOOT); - ret = CLOCK_BASE_RATE * FIELD_GET(RST_MUL_BITS, cfg); - - iounmap(base); - -error_put_pdev: - pci_dev_put(pdev); - -error: - return ret; -} - struct ptp *ptp_get(void) { struct ptp *ptp = first_ptp_block; @@ -145,13 +107,40 @@ static int ptp_get_clock(struct ptp *ptp, u64 *clk) return 0; } +void ptp_start(struct ptp *ptp, u64 sclk) +{ + struct pci_dev *pdev; + u64 clock_comp; + u64 clock_cfg; + + if (!ptp) + return; + + pdev = ptp->pdev; + + if (!sclk) { + dev_err(&pdev->dev, "PTP input clock cannot be zero\n"); + return; + } + + /* sclk is in MHz */ + ptp->clock_rate = sclk * 1000000; + + /* Enable PTP clock */ + clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); + clock_cfg |= PTP_CLOCK_CFG_PTP_EN; + writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); + + clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate; + /* Initial compensation value to start the nanosecs counter */ + writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP); +} + static int ptp_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct device *dev = &pdev->dev; struct ptp *ptp; - u64 clock_comp; - u64 clock_cfg; int err; ptp = devm_kzalloc(dev, sizeof(*ptp), GFP_KERNEL); @@ -172,17 +161,6 @@ static int ptp_probe(struct pci_dev *pdev, ptp->reg_base = pcim_iomap_table(pdev)[PCI_PTP_BAR_NO]; - ptp->clock_rate = get_clock_rate(); - - /* Enable PTP clock */ - clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); - clock_cfg |= PTP_CLOCK_CFG_PTP_EN; - writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); - - clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate; - /* Initial compensation value to start the nanosecs counter */ - writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP); - pci_set_drvdata(pdev, ptp); if (!first_ptp_block) first_ptp_block = ptp; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h index 76d404b24552e..1ed350ad6f1f2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h @@ -20,6 +20,7 @@ struct ptp { struct ptp *ptp_get(void); void ptp_put(struct ptp *ptp); +void ptp_start(struct ptp *ptp, u64 sclk); extern struct pci_driver ptp_driver; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 5909173ff788b..87a32a17d49ef 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -3240,6 +3240,9 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id) mutex_init(&rvu->rswitch.switch_lock); + if (rvu->fwdata) + ptp_start(rvu->ptp, rvu->fwdata->sclk); + return 0; err_dl: rvu_unregister_dl(rvu); From 99bbc4ae69b9798b8cd6cbf3ec62a60a17044b1f Mon Sep 17 00:00:00 2001 From: Yi Guo Date: Tue, 28 Sep 2021 17:01:01 +0530 Subject: [PATCH 4/4] octeontx2-af: Add external ptp input clock PTP hardware block can be configured to utilize the external clock. Also the current ptp timestamp can be captured when external trigger is applied on a gpio pin. These features are required in scenarios like connecting a external timing device to the chip for time synchronization. The timing device provides the clock and trigger(PPS signal) to the PTP block. This patch does the following: 1. configures PTP block to use external clock frequency and timestamp capture on external event. 2. sends PTP_REQ_EXTTS events to kernel ptp phc susbsytem with captured timestamps 3. aligns PPS edge to adjusted ptp clock in the ptp device by setting the PPS_THRESH to the reminder of the last timestamp value captured by external PPS Signed-off-by: Yi Guo Signed-off-by: Hariprasad Kelam Signed-off-by: Subbaraya Sundeep Signed-off-by: Sunil Goutham Signed-off-by: David S. Miller --- .../net/ethernet/marvell/octeontx2/af/mbox.h | 3 + .../net/ethernet/marvell/octeontx2/af/ptp.c | 55 +++++++- .../net/ethernet/marvell/octeontx2/af/ptp.h | 2 +- .../net/ethernet/marvell/octeontx2/af/rvu.c | 3 +- .../net/ethernet/marvell/octeontx2/af/rvu.h | 4 +- .../marvell/octeontx2/nic/otx2_common.h | 6 + .../ethernet/marvell/octeontx2/nic/otx2_ptp.c | 120 +++++++++++++++++- 7 files changed, 187 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index b5ee324d17c9a..dfe487235007e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1420,12 +1420,15 @@ struct npc_mcam_get_stats_rsp { enum ptp_op { PTP_OP_ADJFINE = 0, PTP_OP_GET_CLOCK = 1, + PTP_OP_GET_TSTMP = 2, + PTP_OP_SET_THRESH = 3, }; struct ptp_req { struct mbox_msghdr hdr; u8 op; s64 scaled_ppm; + u64 thresh; }; struct ptp_rsp { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c index 477491c001b63..d6321de3cc171 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.c @@ -30,9 +30,22 @@ #define PTP_CLOCK_CFG 0xF00ULL #define PTP_CLOCK_CFG_PTP_EN BIT_ULL(0) +#define PTP_CLOCK_CFG_EXT_CLK_EN BIT_ULL(1) +#define PTP_CLOCK_CFG_EXT_CLK_IN_MASK GENMASK_ULL(7, 2) +#define PTP_CLOCK_CFG_TSTMP_EDGE BIT_ULL(9) +#define PTP_CLOCK_CFG_TSTMP_EN BIT_ULL(8) +#define PTP_CLOCK_CFG_TSTMP_IN_MASK GENMASK_ULL(15, 10) +#define PTP_CLOCK_CFG_PPS_EN BIT_ULL(30) +#define PTP_CLOCK_CFG_PPS_INV BIT_ULL(31) + +#define PTP_PPS_HI_INCR 0xF60ULL +#define PTP_PPS_LO_INCR 0xF68ULL +#define PTP_PPS_THRESH_HI 0xF58ULL + #define PTP_CLOCK_LO 0xF08ULL #define PTP_CLOCK_HI 0xF10ULL #define PTP_CLOCK_COMP 0xF18ULL +#define PTP_TIMESTAMP 0xF20ULL static struct ptp *first_ptp_block; static const struct pci_device_id ptp_id_table[]; @@ -107,7 +120,7 @@ static int ptp_get_clock(struct ptp *ptp, u64 *clk) return 0; } -void ptp_start(struct ptp *ptp, u64 sclk) +void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts) { struct pci_dev *pdev; u64 clock_comp; @@ -128,14 +141,48 @@ void ptp_start(struct ptp *ptp, u64 sclk) /* Enable PTP clock */ clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG); + + if (ext_clk_freq) { + ptp->clock_rate = ext_clk_freq; + /* Set GPIO as PTP clock source */ + clock_cfg &= ~PTP_CLOCK_CFG_EXT_CLK_IN_MASK; + clock_cfg |= PTP_CLOCK_CFG_EXT_CLK_EN; + } + + if (extts) { + clock_cfg |= PTP_CLOCK_CFG_TSTMP_EDGE; + /* Set GPIO as timestamping source */ + clock_cfg &= ~PTP_CLOCK_CFG_TSTMP_IN_MASK; + clock_cfg |= PTP_CLOCK_CFG_TSTMP_EN; + } + clock_cfg |= PTP_CLOCK_CFG_PTP_EN; + clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV; writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG); + /* Set 50% duty cycle for 1Hz output */ + writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_HI_INCR); + writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_LO_INCR); + clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate; /* Initial compensation value to start the nanosecs counter */ writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP); } +static int ptp_get_tstmp(struct ptp *ptp, u64 *clk) +{ + *clk = readq(ptp->reg_base + PTP_TIMESTAMP); + + return 0; +} + +static int ptp_set_thresh(struct ptp *ptp, u64 thresh) +{ + writeq(thresh, ptp->reg_base + PTP_PPS_THRESH_HI); + + return 0; +} + static int ptp_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -250,6 +297,12 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req, case PTP_OP_GET_CLOCK: err = ptp_get_clock(rvu->ptp, &rsp->clk); break; + case PTP_OP_GET_TSTMP: + err = ptp_get_tstmp(rvu->ptp, &rsp->clk); + break; + case PTP_OP_SET_THRESH: + err = ptp_set_thresh(rvu->ptp, req->thresh); + break; default: err = -EINVAL; break; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h index 1ed350ad6f1f2..1b81a0493cd32 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/ptp.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/ptp.h @@ -20,7 +20,7 @@ struct ptp { struct ptp *ptp_get(void); void ptp_put(struct ptp *ptp); -void ptp_start(struct ptp *ptp, u64 sclk); +void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts); extern struct pci_driver ptp_driver; diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c index 87a32a17d49ef..4cb24e91e648a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c @@ -3241,7 +3241,8 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id) mutex_init(&rvu->rswitch.switch_lock); if (rvu->fwdata) - ptp_start(rvu->ptp, rvu->fwdata->sclk); + ptp_start(rvu->ptp, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate, + rvu->fwdata->ptp_ext_tstamp); return 0; err_dl: diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index 95e807626a3e3..58b166698fa5d 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -396,7 +396,9 @@ struct rvu_fwdata { u64 mcam_addr; u64 mcam_sz; u64 msixtr_base; -#define FWDATA_RESERVED_MEM 1023 + u32 ptp_ext_clk_rate; + u32 ptp_ext_tstamp; +#define FWDATA_RESERVED_MEM 1022 u64 reserved[FWDATA_RESERVED_MEM]; #define CGX_MAX 5 #define CGX_LMACS_MAX 4 diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index 8e51a1db7e295..0a792fce55f18 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -264,6 +264,12 @@ struct otx2_ptp { struct cyclecounter cycle_counter; struct timecounter time_counter; + + struct delayed_work extts_work; + u64 last_extts; + u64 thresh; + + struct ptp_pin_desc extts_config; }; #define OTX2_HW_TIMESTAMP_LEN 8 diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c index ec9e49985c2ce..5e3056a89ee07 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ptp.c @@ -27,6 +27,23 @@ static int otx2_ptp_adjfine(struct ptp_clock_info *ptp_info, long scaled_ppm) return otx2_sync_mbox_msg(&ptp->nic->mbox); } +static int ptp_set_thresh(struct otx2_ptp *ptp, u64 thresh) +{ + struct ptp_req *req; + + if (!ptp->nic) + return -ENODEV; + + req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox); + if (!req) + return -ENOMEM; + + req->op = PTP_OP_SET_THRESH; + req->thresh = thresh; + + return otx2_sync_mbox_msg(&ptp->nic->mbox); +} + static u64 ptp_cc_read(const struct cyclecounter *cc) { struct otx2_ptp *ptp = container_of(cc, struct otx2_ptp, cycle_counter); @@ -55,6 +72,33 @@ static u64 ptp_cc_read(const struct cyclecounter *cc) return rsp->clk; } +static u64 ptp_tstmp_read(struct otx2_ptp *ptp) +{ + struct ptp_req *req; + struct ptp_rsp *rsp; + int err; + + if (!ptp->nic) + return 0; + + req = otx2_mbox_alloc_msg_ptp_op(&ptp->nic->mbox); + if (!req) + return 0; + + req->op = PTP_OP_GET_TSTMP; + + err = otx2_sync_mbox_msg(&ptp->nic->mbox); + if (err) + return 0; + + rsp = (struct ptp_rsp *)otx2_mbox_get_rsp(&ptp->nic->mbox.mbox, 0, + &req->hdr); + if (IS_ERR(rsp)) + return 0; + + return rsp->clk; +} + static int otx2_ptp_adjtime(struct ptp_clock_info *ptp_info, s64 delta) { struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, @@ -102,9 +146,73 @@ static int otx2_ptp_settime(struct ptp_clock_info *ptp_info, return 0; } +static int otx2_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin, + enum ptp_pin_function func, unsigned int chan) +{ + switch (func) { + case PTP_PF_NONE: + case PTP_PF_EXTTS: + break; + case PTP_PF_PEROUT: + case PTP_PF_PHYSYNC: + return -1; + } + return 0; +} + +static void otx2_ptp_extts_check(struct work_struct *work) +{ + struct otx2_ptp *ptp = container_of(work, struct otx2_ptp, + extts_work.work); + struct ptp_clock_event event; + u64 tstmp, new_thresh; + + mutex_lock(&ptp->nic->mbox.lock); + tstmp = ptp_tstmp_read(ptp); + mutex_unlock(&ptp->nic->mbox.lock); + + if (tstmp != ptp->last_extts) { + event.type = PTP_CLOCK_EXTTS; + event.index = 0; + event.timestamp = timecounter_cyc2time(&ptp->time_counter, tstmp); + ptp_clock_event(ptp->ptp_clock, &event); + ptp->last_extts = tstmp; + + new_thresh = tstmp % 500000000; + if (ptp->thresh != new_thresh) { + mutex_lock(&ptp->nic->mbox.lock); + ptp_set_thresh(ptp, new_thresh); + mutex_unlock(&ptp->nic->mbox.lock); + ptp->thresh = new_thresh; + } + } + schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200)); +} + static int otx2_ptp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq, int on) { + struct otx2_ptp *ptp = container_of(ptp_info, struct otx2_ptp, + ptp_info); + int pin = -1; + + if (!ptp->nic) + return -ENODEV; + + switch (rq->type) { + case PTP_CLK_REQ_EXTTS: + pin = ptp_find_pin(ptp->ptp_clock, PTP_PF_EXTTS, + rq->extts.index); + if (pin < 0) + return -EBUSY; + if (on) + schedule_delayed_work(&ptp->extts_work, msecs_to_jiffies(200)); + else + cancel_delayed_work_sync(&ptp->extts_work); + return 0; + default: + break; + } return -EOPNOTSUPP; } @@ -149,20 +257,28 @@ int otx2_ptp_init(struct otx2_nic *pfvf) timecounter_init(&ptp_ptr->time_counter, &ptp_ptr->cycle_counter, ktime_to_ns(ktime_get_real())); + snprintf(ptp_ptr->extts_config.name, sizeof(ptp_ptr->extts_config.name), "TSTAMP"); + ptp_ptr->extts_config.index = 0; + ptp_ptr->extts_config.func = PTP_PF_NONE; + ptp_ptr->ptp_info = (struct ptp_clock_info) { .owner = THIS_MODULE, .name = "OcteonTX2 PTP", .max_adj = 1000000000ull, - .n_ext_ts = 0, - .n_pins = 0, + .n_ext_ts = 1, + .n_pins = 1, .pps = 0, + .pin_config = &ptp_ptr->extts_config, .adjfine = otx2_ptp_adjfine, .adjtime = otx2_ptp_adjtime, .gettime64 = otx2_ptp_gettime, .settime64 = otx2_ptp_settime, .enable = otx2_ptp_enable, + .verify = otx2_ptp_verify_pin, }; + INIT_DELAYED_WORK(&ptp_ptr->extts_work, otx2_ptp_extts_check); + ptp_ptr->ptp_clock = ptp_clock_register(&ptp_ptr->ptp_info, pfvf->dev); if (IS_ERR_OR_NULL(ptp_ptr->ptp_clock)) { err = ptp_ptr->ptp_clock ?