* [PATCH 00/18] Wangxun Fixes
@ 2026-04-23 3:40 Zaiyu Wang
2026-04-23 3:40 ` [PATCH 01/18] net/txgbe: remove duplicate xstats counters Zaiyu Wang
` (20 more replies)
0 siblings, 21 replies; 92+ messages in thread
From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang
This series fixes several issues found on Wangxun Emerald, Sapphire and
Amber-lite NICs, with a focus on link-related problems.
Zaiyu Wang (18):
net/txgbe: remove duplicate xstats counters
net/ngbe: remove duplicate xstats counters
net/ngbe: add missing CDR config for YT PHY
net/ngbe: fix VF promiscuous and allmulticast
net/txgbe: fix inaccuracy in TX rate limiting
net/txgbe: fix link status check condition
net/txgbe: fix Tx desc free logic
net/txgbe: fix link flow control registers for Amber-Lite
net/txgbe: fix link flow control config for Sapphire
net/txgbe: fix a mass of unknown interrupts
net/txgbe: fix traffic class priority configuration
net/txgbe: fix link stability for 25G NIC
net/txgbe: fix link stability for 40G NIC
net/txgbe: fix link stability for Amber-Lite backplane mode
net/txgbe: fix FEC mode configuration on 25G NIC
net/txgbe: fix SFP module identification
net/txgbe: fix get module info operation
net/txgbe: fix get eeprom operation
drivers/net/ngbe/base/ngbe_phy_yt.c | 3 +
drivers/net/ngbe/ngbe_ethdev.c | 5 -
drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +-
drivers/net/txgbe/base/meson.build | 2 +
drivers/net/txgbe/base/txgbe.h | 2 +
drivers/net/txgbe/base/txgbe_aml.c | 187 +-
drivers/net/txgbe/base/txgbe_aml.h | 6 +-
drivers/net/txgbe/base/txgbe_aml40.c | 113 +-
drivers/net/txgbe/base/txgbe_aml40.h | 6 +-
drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +-
drivers/net/txgbe/base/txgbe_e56.c | 3705 +++++++++++++++++++++
drivers/net/txgbe/base/txgbe_e56.h | 1751 ++++++++++
drivers/net/txgbe/base/txgbe_e56_bp.c | 2595 +++++++++++++++
drivers/net/txgbe/base/txgbe_e56_bp.h | 279 ++
drivers/net/txgbe/base/txgbe_hw.c | 52 +-
drivers/net/txgbe/base/txgbe_hw.h | 4 +-
drivers/net/txgbe/base/txgbe_osdep.h | 12 +-
drivers/net/txgbe/base/txgbe_phy.c | 360 +-
drivers/net/txgbe/base/txgbe_phy.h | 42 +-
drivers/net/txgbe/base/txgbe_regs.h | 10 +-
drivers/net/txgbe/base/txgbe_type.h | 39 +-
drivers/net/txgbe/txgbe_ethdev.c | 390 ++-
drivers/net/txgbe/txgbe_ethdev.h | 6 +-
drivers/net/txgbe/txgbe_logs.h | 7 +
drivers/net/txgbe/txgbe_rxtx.c | 39 +-
drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 +-
26 files changed, 9233 insertions(+), 402 deletions(-)
create mode 100644 drivers/net/txgbe/base/txgbe_e56.c
create mode 100644 drivers/net/txgbe/base/txgbe_e56.h
create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c
create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h
--
2.21.0.windows.1
^ permalink raw reply [flat|nested] 92+ messages in thread* [PATCH 01/18] net/txgbe: remove duplicate xstats counters 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 02/18] net/ngbe: " Zaiyu Wang ` (19 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 5d360f8305..779874aac9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -261,11 +261,6 @@ static const struct rte_txgbe_xstats_name_off rte_txgbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 02/18] net/ngbe: remove duplicate xstats counters 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang 2026-04-23 3:40 ` [PATCH 01/18] net/txgbe: remove duplicate xstats counters Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 03/18] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang ` (18 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 8b9d6371fb..6df53f3266 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -227,11 +227,6 @@ static const struct rte_ngbe_xstats_name_off rte_ngbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 03/18] net/ngbe: add missing CDR config for YT PHY 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang 2026-04-23 3:40 ` [PATCH 01/18] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-04-23 3:40 ` [PATCH 02/18] net/ngbe: " Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 04/18] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang ` (17 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu According to the PHY vendor, when YT8531S operates in UTP-to-Fiber or RGMII-to-Fiber mode with auto-negotiation disabled (Force mode), additional CDR (Clock Data Recovery) configuration is required to improve link connectivity. Without this config, link may be unstable or fail to establish. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/base/ngbe_phy_yt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c index d110fbc8b2..ab0778d246 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.c +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -264,6 +264,9 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed, value = YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN | YT_BCR_DUPLEX | YT_BCR_SPEED_SELECT1; } else { + /* force mode need to config cdr */ + ngbe_write_phy_reg_sds_ext_yt(hw, 0x3, 0, 0x1434); + ngbe_write_phy_reg_sds_ext_yt(hw, 0xe, 0, 0x163); value = YT_BCR_RESET | YT_BCR_DUPLEX; if (speed & NGBE_LINK_SPEED_1GB_FULL) value |= YT_BCR_SPEED_SELECT1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 04/18] net/ngbe: fix VF promiscuous and allmulticast 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (2 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 03/18] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 05/18] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang ` (16 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The configuration of allmulti and promiscuous modes conflicts together. For instance, if we enable promiscuous mode, then enable and disable allmulti, then the promiscuous mode is wrongly disabled. Fix this behavior by: - doing nothing when we set/unset allmulti if promiscuous mode is on - restorting the proper mode (none or allmulti) when we disable promiscuous mode Fixes: 7744e90805b5 ("net/ngbe: add promiscuous and allmulticast ops for VF device") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev_vf.c b/drivers/net/ngbe/ngbe_ethdev_vf.c index 6406df40d0..81511fed8a 100644 --- a/drivers/net/ngbe/ngbe_ethdev_vf.c +++ b/drivers/net/ngbe/ngbe_ethdev_vf.c @@ -1196,9 +1196,13 @@ static int ngbevf_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct ngbe_hw *hw = ngbe_dev_hw(dev); + int mode = NGBEVF_XCAST_MODE_NONE; int ret; - switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_NONE)) { + if (dev->data->all_multicast) + mode = NGBEVF_XCAST_MODE_ALLMULTI; + + switch (hw->mac.update_xcast_mode(hw, mode)) { case 0: ret = 0; break; @@ -1219,7 +1223,7 @@ ngbevf_dev_allmulticast_enable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; - if (dev->data->promiscuous == 1) + if (dev->data->promiscuous) return 0; switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_ALLMULTI)) { @@ -1243,6 +1247,9 @@ ngbevf_dev_allmulticast_disable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; + if (dev->data->promiscuous) + return 0; + switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_MULTI)) { case 0: ret = 0; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 05/18] net/txgbe: fix inaccuracy in TX rate limiting 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (3 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 04/18] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 06/18] net/txgbe: fix link status check condition Zaiyu Wang ` (15 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Amber-lite NIC's TX rate limiting has large deviations for small packets. To fix this issue, there are some changes: 1. Set TDM_RL_ADJ (0x1820c) to 21B (includes 7B Ethernet preamble, 1B SFD, 1B EFD, and 12B IPG). 2) Remove the rate offset in the driver (e.g., 105 / 100, a rough compensation value from Linux kernel driver tests). After these changes, accuracy deviation for 64B packets is within ~5%, while large packets show lower deviation. Fixes: a309ab43acf3 ("net/txgbe: support Tx queue rate limiting for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_regs.h | 1 + drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 95c585a025..060757323a 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1670,6 +1670,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_TDM_FACTOR_INT_SHIFT 16 #define TXGBE_TDM_FACTOR_FRA_SHIFT 2 +#define TXGBE_TDM_RL_ADJ 0x1820C #define TXGBE_TDM_RL_VM_IDX 0x018218 #define TXGBE_TDM_RL_VM_CFG 0x01821C #define TXGBE_TDM_RL_CFG 0x018400 diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 779874aac9..414107d7a7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -4314,7 +4314,6 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, u16 frac; link_speed = dev->data->dev_link.link_speed; - tx_rate = tx_rate * 105 / 100; /* Calculate the rate factor values to set */ factor_int = link_speed / tx_rate; frac = (link_speed % tx_rate) * 10000 / tx_rate; @@ -4324,6 +4323,7 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, factor_fra = 0; } + wr32(hw, TXGBE_TDM_RL_ADJ, 21); wr32(hw, TXGBE_TDM_RL_QUEUE_IDX, queue_idx); wr32m(hw, TXGBE_TDM_RL_QUEUE_CFG, TXGBE_TDM_FACTOR_INT_MASK, factor_int << TXGBE_TDM_FACTOR_INT_SHIFT); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 06/18] net/txgbe: fix link status check condition 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (4 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 05/18] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 07/18] net/txgbe: fix Tx desc free logic Zaiyu Wang ` (14 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original code incorrectly used 'if (link_up)' instead of 'if (*link_up)', causing the condition to always evaluate to true because the pointer itself is non-NULL. This led to incorrect speed assignment. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 2 +- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index b376eca5b5..de9a1b1c93 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -67,7 +67,7 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { switch (links_reg & TXGBE_CFG_PORT_ST_AML_LINK_MASK) { case TXGBE_CFG_PORT_ST_AML_LINK_25G: *speed = TXGBE_LINK_SPEED_25GB_FULL; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 733bbac13a..eefd7119fd 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -68,7 +68,7 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 07/18] net/txgbe: fix Tx desc free logic 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (5 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 06/18] net/txgbe: fix link status check condition Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 08/18] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang ` (13 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On some server environments, this driver caused TDM non-fatal errors or PCIe request errors during Tx operation In Amber-Lite NIC's Tx head write-back mode, the hardware periodically writes back a head index pointing to the next descriptor it is adout to process in Tx ring. All descriptors before the head are considered processed by hardware and can be safely freed by the driver. The root cause is that the driver can safely free a batch of descriptors only when the hardware's write-back head pointer has advanced beyond all descriptors in that batch, meaning they have all been processed by the hardware. If the driver frees a descriptor before the hardware has finished processing it, invalid memory access may occur, leading to the observed bug. To fix the issue, correct the boundary check in all three Tx cleanup functions, each of which was missing the proper condition to prevent freeing unprocessed descriptors. Fixes: 8ada71d0bb7f ("net/txgbe: add Tx head write-back mode for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 9 ++++++++- drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index e2cd9b8841..72a4965693 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -100,7 +100,9 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) @@ -652,6 +654,11 @@ txgbe_xmit_cleanup(struct txgbe_tx_queue *txq) /* we have caught up to head, no work left to do */ if (desc_to_clean_to == head) return -(1); + else if (desc_to_clean_to > head && head > last_desc_cleaned) + return -(1); + else if (last_desc_cleaned > desc_to_clean_to && + (head > last_desc_cleaned || head < desc_to_clean_to)) + return -(1); } else { if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) { PMD_TX_FREE_LOG(DEBUG, diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h index 00847d087b..edf3586b77 100644 --- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h +++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h @@ -94,8 +94,11 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) txq->tx_next_dd - txq->tx_free_thresh; if (tx_last_dd >= txq->nb_tx_desc) tx_last_dd -= txq->nb_tx_desc; - volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + + volatile uint16_t head = (uint16_t)*txq->headwb_mem; + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 08/18] net/txgbe: fix link flow control registers for Amber-Lite 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (6 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 07/18] net/txgbe: fix Tx desc free logic Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 7:54 ` Jiawen Wu 2026-04-23 3:40 ` [PATCH 09/18] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang ` (12 subsequent siblings) 20 siblings, 1 reply; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The flow control counter registers on AML NICs differ from those on SP NICs. Update the register offsets accordingly to ensure the counters work correctly. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 5 +++++ drivers/net/txgbe/base/txgbe_regs.h | 2 ++ drivers/net/txgbe/txgbe_ethdev.c | 10 ++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0f3db3a1ad..52fead6171 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -394,6 +394,11 @@ s32 txgbe_clear_hw_cntrs(struct txgbe_hw *hw) rd32(hw, TXGBE_PBTXLNKXON); rd32(hw, TXGBE_PBTXLNKXOFF); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + wr32(hw, TXGBE_PBRXLNKXON_AML, 0); + wr32(hw, TXGBE_PBRXLNKXOFF_AML, 0); + } + /* DMA Stats */ rd32(hw, TXGBE_DMARXPKT); rd32(hw, TXGBE_DMATXPKT); diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 060757323a..de382601c9 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1085,6 +1085,8 @@ enum txgbe_5tuple_protocol { #define TXGBE_PBRXDROP 0x019068 #define TXGBE_PBRXLNKXOFF 0x011988 #define TXGBE_PBRXLNKXON 0x011E0C +#define TXGBE_PBRXLNKXOFF_AML 0x011F80 +#define TXGBE_PBRXLNKXON_AML 0x011F84 #define TXGBE_PBRXUPXON(up) (0x011E30 + (up) * 4) #define TXGBE_PBRXUPXOFF(up) (0x011E10 + (up) * 4) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 414107d7a7..e3492c9cd7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2331,8 +2331,14 @@ txgbe_read_stats_registers(struct txgbe_hw *hw, hw_stats->up[i].rx_up_dropped += rd32(hw, TXGBE_PBRXMISS(i)); } - hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); - hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + hw_stats->rx_xon_packets = rd32(hw, TXGBE_PBRXLNKXON_AML); + hw_stats->rx_xoff_packets = rd32(hw, TXGBE_PBRXLNKXOFF_AML); + } else { + hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); + hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + } hw_stats->tx_xon_packets += rd32(hw, TXGBE_PBTXLNKXON); hw_stats->tx_xoff_packets += rd32(hw, TXGBE_PBTXLNKXOFF); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* RE: [PATCH 08/18] net/txgbe: fix link flow control registers for Amber-Lite 2026-04-23 3:40 ` [PATCH 08/18] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang @ 2026-04-23 7:54 ` Jiawen Wu 0 siblings, 0 replies; 92+ messages in thread From: Jiawen Wu @ 2026-04-23 7:54 UTC (permalink / raw) To: 'Zaiyu Wang', dev; +Cc: stable > -----Original Message----- > From: Zaiyu Wang <zaiyuwang@trustnetic.com> > Sent: Thursday, April 23, 2026 11:40 AM > To: dev@dpdk.org > Cc: Zaiyu Wang <zaiyuwang@trustnetic.com>; stable@dpdk.org; Jiawen Wu <jiawenwu@trustnetic.com> > Subject: [PATCH 08/18] net/txgbe: fix link flow control registers for Amber-Lite > > The flow control counter registers on AML NICs differ from those on SP > NICs. Update the register offsets accordingly to ensure the counters > work correctly. > > Cc: stable@dpdk.org > > Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> > --- > drivers/net/txgbe/base/txgbe_hw.c | 5 +++++ > drivers/net/txgbe/base/txgbe_regs.h | 2 ++ > drivers/net/txgbe/txgbe_ethdev.c | 10 ++++++++-- > 3 files changed, 15 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c > index 0f3db3a1ad..52fead6171 100644 > --- a/drivers/net/txgbe/base/txgbe_hw.c > +++ b/drivers/net/txgbe/base/txgbe_hw.c > @@ -394,6 +394,11 @@ s32 txgbe_clear_hw_cntrs(struct txgbe_hw *hw) > rd32(hw, TXGBE_PBTXLNKXON); > rd32(hw, TXGBE_PBTXLNKXOFF); > > + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { > + wr32(hw, TXGBE_PBRXLNKXON_AML, 0); > + wr32(hw, TXGBE_PBRXLNKXOFF_AML, 0); > + } > + > /* DMA Stats */ > rd32(hw, TXGBE_DMARXPKT); > rd32(hw, TXGBE_DMATXPKT); > diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h > index 060757323a..de382601c9 100644 > --- a/drivers/net/txgbe/base/txgbe_regs.h > +++ b/drivers/net/txgbe/base/txgbe_regs.h > @@ -1085,6 +1085,8 @@ enum txgbe_5tuple_protocol { > #define TXGBE_PBRXDROP 0x019068 > #define TXGBE_PBRXLNKXOFF 0x011988 > #define TXGBE_PBRXLNKXON 0x011E0C > +#define TXGBE_PBRXLNKXOFF_AML 0x011F80 > +#define TXGBE_PBRXLNKXON_AML 0x011F84 > #define TXGBE_PBRXUPXON(up) (0x011E30 + (up) * 4) > #define TXGBE_PBRXUPXOFF(up) (0x011E10 + (up) * 4) > > diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c > index 414107d7a7..e3492c9cd7 100644 > --- a/drivers/net/txgbe/txgbe_ethdev.c > +++ b/drivers/net/txgbe/txgbe_ethdev.c > @@ -2331,8 +2331,14 @@ txgbe_read_stats_registers(struct txgbe_hw *hw, > hw_stats->up[i].rx_up_dropped += > rd32(hw, TXGBE_PBRXMISS(i)); > } > - hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); > - hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); > + > + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { > + hw_stats->rx_xon_packets = rd32(hw, TXGBE_PBRXLNKXON_AML); > + hw_stats->rx_xoff_packets = rd32(hw, TXGBE_PBRXLNKXOFF_AML); What happens to these counters after .stats_reset()? > + } else { > + hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); > + hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); > + } > hw_stats->tx_xon_packets += rd32(hw, TXGBE_PBTXLNKXON); > hw_stats->tx_xoff_packets += rd32(hw, TXGBE_PBTXLNKXOFF); > > -- > 2.21.0.windows.1 > ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH 09/18] net/txgbe: fix link flow control config for Sapphire 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (7 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 08/18] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 10/18] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang ` (11 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu SP chips have a hardware bug preventing XON flow control support, so the driver disables it. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 52fead6171..0719b56e3c 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -1035,8 +1035,10 @@ s32 txgbe_fc_enable(struct txgbe_hw *hw) for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { if ((hw->fc.current_mode & txgbe_fc_tx_pause) && hw->fc.high_water[i]) { - fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]) | - TXGBE_FCWTRLO_XON; + fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]); + /* SP doesn't support xon */ + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + fcrtl |= TXGBE_FCWTRLO_XON; fcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[i]) | TXGBE_FCWTRHI_XOFF; } else { -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 10/18] net/txgbe: fix a mass of unknown interrupts 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (8 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 09/18] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 11/18] net/txgbe: fix traffic class priority configuration Zaiyu Wang ` (10 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu When RSC is enabled, Rx ring IVAR is set to configure ITR. It causes Rx ring interrupts report on the default msix_vector. Thus a mass of unknown interrupts occupy CPU. Fix the issue by setting ring IVAR only when the rxq interrupt is enabled. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 72a4965693..be279dc4ec 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -4354,6 +4354,8 @@ static int txgbe_set_rsc(struct rte_eth_dev *dev) { struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = pci_dev->intr_handle; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct rte_eth_dev_info dev_info = { 0 }; bool rsc_capable = false; @@ -4404,8 +4406,6 @@ txgbe_set_rsc(struct rte_eth_dev *dev) rd32(hw, TXGBE_RXCFG(rxq->reg_idx)); uint32_t psrtype = rd32(hw, TXGBE_POOLRSS(rxq->reg_idx)); - uint32_t eitr = - rd32(hw, TXGBE_ITR(rxq->reg_idx)); /* * txgbe PMD doesn't support header-split at the moment. @@ -4424,6 +4424,9 @@ txgbe_set_rsc(struct rte_eth_dev *dev) srrctl |= txgbe_get_rscctl_maxdesc(rxq->mb_pool); psrtype |= TXGBE_POOLRSS_L4HDR; + wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); + wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); + /* * RSC: Set ITR interval corresponding to 2K ints/s. * @@ -4437,19 +4440,20 @@ txgbe_set_rsc(struct rte_eth_dev *dev) * For a sparse streaming case this setting will yield * at most 500us latency for a single RSC aggregation. */ - eitr &= ~TXGBE_ITR_IVAL_MASK; - eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); - eitr |= TXGBE_ITR_WRDSA; + if (rte_intr_dp_is_en(intr_handle)) { + uint32_t eitr = rd32(hw, TXGBE_ITR(rxq->reg_idx)); - wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); - wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); - wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); + eitr &= ~TXGBE_ITR_IVAL_MASK; + eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); + eitr |= TXGBE_ITR_WRDSA; + wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); - /* - * RSC requires the mapping of the queue to the - * interrupt vector. - */ - txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + /* + * RSC requires the mapping of the queue to the + * interrupt vector. + */ + txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + } } dev->data->lro = 1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 11/18] net/txgbe: fix traffic class priority configuration 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (9 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 10/18] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 12/18] net/txgbe: fix link stability for 25G NIC Zaiyu Wang ` (9 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu After applying the following testpmd command, 802.1Q packets with specific priorities were not properly directed to the corresponding traffic classes: port config 0 dcb vt off 4 pfc off The old driver had two issues: 1. The hardware uses a 4-bit mapping register per traffic class for priority-to-TC mapping, but the driver incorrectly configured it as 3 bits. 2. The DCB TX configuration mistakenly wrote to the RX register. Fix both issues, ensuring that tc-prio mapping works as expected. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- drivers/net/txgbe/base/txgbe_regs.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_dcb_hw.c b/drivers/net/txgbe/base/txgbe_dcb_hw.c index 75c91a6b6a..79e1da447b 100644 --- a/drivers/net/txgbe/base/txgbe_dcb_hw.c +++ b/drivers/net/txgbe/base/txgbe_dcb_hw.c @@ -154,7 +154,7 @@ s32 txgbe_dcb_config_tx_data_arbiter_raptor(struct txgbe_hw *hw, u16 *refill, for (i = 0; i < TXGBE_DCB_UP_MAX; i++) reg |= TXGBE_DCBUP2TC_MAP(i, map[i]); - wr32(hw, TXGBE_PBRXUP2TC, reg); + wr32(hw, TXGBE_PBTXUP2TC, reg); /* Configure traffic class credits and priority */ for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index de382601c9..bc73f28ca2 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -503,9 +503,8 @@ #define TXGBE_PBRXCTL 0x019000 #define TXGBE_PBRXCTL_ST MS(0, 0x1) #define TXGBE_PBRXCTL_ENA MS(31, 0x1) -#define TXGBE_PBRXUP2TC 0x019008 #define TXGBE_PBTXUP2TC 0x01C800 -#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 3 * (tc), 0x7) +#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 4 * (tc), 0x7) #define TXGBE_DCBUP2TC_DEC(tc, r) RS(r, 3 * (tc), 0x7) #define TXGBE_PBRXSIZE(tc) (0x019020 + (tc) * 4) #define TXGBE_PBRXSIZE_KB(v) LS(v, 10, 0x3FF) @@ -1703,7 +1702,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_RDM_PF_HIDE(_i) (0x12090 + ((_i) * 4)) #define TXGBE_RPUP2TC 0x019008 -#define TXGBE_RPUP2TC_UP_SHIFT 3 +#define TXGBE_RPUP2TC_UP_SHIFT 4 #define TXGBE_RPUP2TC_UP_MASK 0x7 #define TXGBE_RDM_DCACHE_CTL 0x0120A8 -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 12/18] net/txgbe: fix link stability for 25G NIC 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (10 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 11/18] net/txgbe: fix traffic class priority configuration Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 8:22 ` Jiawen Wu 2026-04-23 3:40 ` [PATCH 13/18] net/txgbe: fix link stability for 40G NIC Zaiyu Wang ` (8 subsequent siblings) 20 siblings, 1 reply; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe_aml.c | 107 +- drivers/net/txgbe/base/txgbe_aml.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 2466 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56.h | 1749 ++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 279 +++ drivers/net/txgbe/base/txgbe_hw.c | 35 +- drivers/net/txgbe/base/txgbe_osdep.h | 8 - drivers/net/txgbe/base/txgbe_phy.h | 1 - drivers/net/txgbe/base/txgbe_regs.h | 2 + drivers/net/txgbe/base/txgbe_type.h | 12 + drivers/net/txgbe/txgbe_ethdev.c | 83 +- drivers/net/txgbe/txgbe_ethdev.h | 4 + drivers/net/txgbe/txgbe_logs.h | 7 + 14 files changed, 4694 insertions(+), 66 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56.c create mode 100644 drivers/net/txgbe/base/txgbe_e56.h create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index ac4a05005e..305c0291e3 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -12,4 +12,5 @@ base_sources = files( 'txgbe_mng.c', 'txgbe_phy.c', 'txgbe_vf.c', + 'txgbe_e56.c', ) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index de9a1b1c93..208f999d78 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -12,6 +12,7 @@ #include "txgbe_mng.h" #include "txgbe_hw.h" #include "txgbe_aml.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -23,6 +24,7 @@ void txgbe_init_ops_aml(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml; + phy->setup_link_core = txgbe_setup_phy_link_aml; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml; @@ -175,16 +177,21 @@ void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed) } } -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; - u32 value = 0; + u32 value; + + *need_reset = false; if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { DEBUGOUT("SFP not detected, skip setup mac link"); @@ -197,33 +204,80 @@ s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, if (status) return status; + /* setup the highest link when no autoneg */ + if (!autoneg) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + speed = TXGBE_LINK_SPEED_25GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + } + speed &= link_capabilities; if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - value = rd32(hw, TXGBE_GPIOEXT); - if (value & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | + TXGBE_SFP1_RX_LOS_LS)) { + DEBUGOUT("RX LOS"); return status; + } - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) { + DEBUGOUT("check phy link_up"); + break; + } + msleep(250); + } - if (link_up && speed == TXGBE_LINK_SPEED_25GB_FULL) + if (speed == TXGBE_LINK_SPEED_25GB_FULL) hw->cur_fec_link = txgbe_phy_fec_get(hw); if (link_speed == speed && link_up && - !(speed == TXGBE_LINK_SPEED_25GB_FULL && - !(hw->fec_mode & hw->cur_fec_link))) - return status; + !(speed == TXGBE_LINK_SPEED_25GB_FULL && + !(hw->fec_mode & hw->cur_fec_link))) + goto out; - if (speed & TXGBE_LINK_SPEED_25GB_FULL) - speed = 0x10; - else if (speed & TXGBE_LINK_SPEED_10GB_FULL) - speed = 0x08; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) { + hw->link_valid = false; + *need_reset = true; + goto out; + } else { + hw->link_valid = true; + } + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + } else { + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + PMD_DRV_LOG(DEBUG, "MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + PMD_DRV_LOG(DEBUG, "MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + PMD_DRV_LOG(DEBUG, "Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -269,9 +323,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (10G -> 25G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, + bool need_reset; + + status = hw->phy.setup_link_core(hw, TXGBE_LINK_SPEED_25GB_FULL, - autoneg_wait_to_complete); + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -297,8 +354,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (25G->10G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, TXGBE_LINK_SPEED_10GB_FULL, - autoneg_wait_to_complete); + bool need_reset; + + status = hw->phy.setup_link_core(hw, + TXGBE_LINK_SPEED_10GB_FULL, + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -348,10 +409,8 @@ void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw) if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->setup_link = txgbe_setup_mac_link_multispeed_fiber_aml; - mac->setup_mac_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } else { - mac->setup_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } } diff --git a/drivers/net/txgbe/base/txgbe_aml.h b/drivers/net/txgbe/base/txgbe_aml.h index e98c952787..bfb01b4968 100644 --- a/drivers/net/txgbe/base/txgbe_aml.h +++ b/drivers/net/txgbe/base/txgbe_aml.h @@ -16,7 +16,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml(struct txgbe_hw *hw); void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed); -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw); #endif /* _TXGBE_AML_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c new file mode 100644 index 0000000000..352eb2e110 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -0,0 +1,2466 @@ +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" +#include "../txgbe_logs.h" + +void +set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value) +{ + unsigned int i; + + /* Single bit field handling */ + if (bit_high == bit_low) { + if (set_value == 0) { + /* clear single bit */ + *src_data &= ~(1 << bit_low); + } else { + /* set single bit */ + *src_data |= (1 << bit_low); + } + } else { + /* first, clear the bit fields */ + for (i = bit_low; i <= bit_high; i++) { + /* clear single bit */ + *src_data &= ~(1 << i); + } + + /* second, or the bit fields with set value */ + *src_data |= (set_value << bit_low); + } +} + +/* + * compare function for qsort() + */ +static inline +int compare(const void *a, const void *b) +{ + const int *num1 = (const int *)a; + const int *num2 = (const int *)b; + + if (*num1 < *num2) + return -1; + + else if (*num1 > *num2) + return 1; + + else + return 0; +} + +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up) +{ + u32 rdata = 0; + u32 links_reg = 0; + + /* must read it twice because the state may + * not be correct the first time you read it + */ + rdata = rd32_epcs(hw, 0x30001); + rdata = rd32_epcs(hw, 0x30001); + + if (rdata & TXGBE_E56_PHY_LINK_UP) + *link_up = true; + else + *link_up = false; + + if (!hw->link_valid) + *link_up = false; + + links_reg = rd32(hw, TXGBE_PORTSTAT); + if (*link_up) { + if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == + TXGBE_CFG_PORT_ST_AML_LINK_40G) + *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == + TXGBE_CFG_PORT_ST_AML_LINK_25G) + *speed = TXGBE_LINK_SPEED_25GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; + } else { + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + + return 0; +} + +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) +{ + u32 ffe_main = 0, pre1 = 0, pre2 = 0, post = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_MAIN; + pre1 = S25G_TX_FFE_CFG_PRE1; + pre2 = S25G_TX_FFE_CFG_PRE2; + post = S25G_TX_FFE_CFG_POST; + } + } + + if (hw->phy.ffe_set) { + ffe_main = hw->phy.ffe_main; + pre1 = hw->phy.ffe_pre; + pre2 = hw->phy.ffe_pre2; + post = hw->phy.ffe_post; + } + + PMD_DRV_LOG(DEBUG, "main = 0x%x, pre1 = 0x%x, pre2 = 0x%x, post = 0x%x", + ffe_main, pre1, pre2, post); + + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_1_ADDR, ffe_main); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_2_ADDR, pre1); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_3_ADDR, pre2); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_4_ADDR, post); + + return 0; +} + +int +txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) +{ + int data_code, temp_data, temp_fraction; + u32 rdata; + u32 timer = 0; + + while (1) { + rdata = rd32(hw, 0x1033c); + if (((rdata >> 12) & 0x1) != 0) + break; + if (timer++ > PHYINIT_TIMEOUT) + return -1; + } + + data_code = rdata & 0xFFF; + temp_data = 419400 + 2205 * (data_code * 1000 / 4094 - 500); + + /* Change double Temperature to int */ + *temp = temp_data / 10000; + temp_fraction = temp_data - (*temp * 10000); + if (temp_fraction >= 5000) + *temp += 1; + + return 0; +} + +u32 +txgbe_e56_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + /* change 0x90 to 0x0 to fix 25G link up keep when cable unplugged */ + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S25G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S25G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S25G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +u32 +txgbe_e56_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static inline int +txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int addr, rdata, timer; + int T = 40; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int OFFSET_CENTRE_RANGE_H, OFFSET_CENTRE_RANGE_L, RANGE_FINAL; + int i = 0; + int lane_num = 1; + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* 2. Define software variable RX_COARSE_MID_TD (RX Coarse Code mid value dependent upon temperature) */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { //10G mode + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { //25G mode + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + } + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + lane_num = 4; + + /* 3. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_H */ + for (i = 0; i < lane_num; i++) { + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 4. Do SEQ::RX_ENABLE to enable RXS, and let it stop after oscillator calibration. + * This needs to be done by blocking the RX power-up fsm at the state following the oscillator calibration state. + * Follow below steps to do the same before SEQ::RX_ENABLE. + * a. ALIAS::PDIG::CTRL_FSM_RX_ST can be stopped at RX_SAMP_CAL_ST which is the state + * after RX_OSC_CAL_ST by configuring ALIAS::RXS::SAMP_CAL_DONE=0b0 + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Do SEQ::RX_ENABLE to enable RXS */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* b. Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm its value is RX_SAMP_CAL_ST */ + rdata = 0; + timer = 0; + while ((rdata >> (i * 8) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (rdata & (0x100 << i)) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* 5/6.Define software variable as OFFSET_CENTRE_RANGE_H = ALIAS::RXS::COARSE */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H = (rdata >> 4) & 0xf; + if(OFFSET_CENTRE_RANGE_H > RX_COARSE_MID_TD) { + OFFSET_CENTRE_RANGE_H = OFFSET_CENTRE_RANGE_H - RX_COARSE_MID_TD; + } else { + OFFSET_CENTRE_RANGE_H = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_H; + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) { break; } + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 8. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, it is possible the timeout interrupt is set. + * Clear the same by clearing ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. + * Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + usec_delay(500); + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 9. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_L */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 10. Do SEQ::RX_ENABLE to enable RXS, and let it stop after oscillator calibration. */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* poll CTRL_FSM_RX_ST */ + timer = 0; + while (((rdata >> (i * 8)) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x100) == 0x100) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 11/12.Define software variable as OFFSET_CENTRE_RANGE_L = ALIAS::RXS::COARSE - + * RX_COARSE_MID_TD. Clear the INTR. + */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L = (rdata >> 4) & 0xf; + if(OFFSET_CENTRE_RANGE_L > RX_COARSE_MID_TD) { + OFFSET_CENTRE_RANGE_L = OFFSET_CENTRE_RANGE_L - RX_COARSE_MID_TD; + } else { + OFFSET_CENTRE_RANGE_L = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_L; + } + + /* 13. Perform below calculation in software. Goal is to pick range value which is closer to RX_COARSE_MID_TD */ + if (OFFSET_CENTRE_RANGE_L < OFFSET_CENTRE_RANGE_H) { + RANGE_FINAL = CMVAR_RANGE_L; + } + else { + RANGE_FINAL = CMVAR_RANGE_H; + } + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) { break; } + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 15. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, + * it is possible the timeout interrupt is set. Clear the same by clearing + * ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR + * which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(500); + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 16. Program ALIAS::RXS::RANGE_SEL = RANGE_FINAL */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, RANGE_FINAL); + wr32_ephy(hw, addr, rdata); + + /* + * 17. Program following before enabling RXS. Purpose is to disable power-up FSM control on ADC offset adaptation + * Note: this step will be done in 2.3.3 RXS calibration and adaptation sequence + * 18. After this SEQ::RX_ENABLE can be done at any time. Note to ensure that ALIAS::RXS::RANGE_SEL = RANGE_FINAL configuration is retained. + * Rmove the OVRDEN on rxs0_rx0_samp_cal_done_o + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + } + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0xf); + else + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x1); + wr32_ephy(hw, addr, rdata); + + return status; +} + +static inline +int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + + unsigned int CMVAR_UFINE_MAX = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + else if (speed == TXGBE_LINK_SPEED_25GB_FULL) + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + + /* a. Assign software defined variables as below */ + /* ii. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE); + /* Set ovrd_en=1 to overide ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i, + 1); + /* Wait until 1milliseconds or greater */ + msleep(10); + } + + return status; +} + +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) +{ + int status = 0, i, N, median; + unsigned int rdata; + int arraySize, RXS_BBCDR_SECOND_ORDER_ST[5]; + + + /* Set ovrd_en=0 to read ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + + /* + * As status update from RXS hardware is asynchronous to read status + * of SECOND_ORDER, follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + /* set RXS_BBCDR_SECOND_ORDER_ST[i] = RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + arraySize = sizeof(RXS_BBCDR_SECOND_ORDER_ST) / sizeof( + RXS_BBCDR_SECOND_ORDER_ST[0]); + qsort(RXS_BBCDR_SECOND_ORDER_ST, arraySize, sizeof(int), compare); + + median = ((N + 1) / 2) -1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ + +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH ; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX ; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX ; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH ; + int CMVAR_UFINE_MIN ; + int CMVAR_FINE_MIN ; + int CMVAR_UFINE_UMIN_WRAP ; + int CMVAR_COARSE_MIN ; + int CMVAR_UFINE_FMIN_WRAP ; + int CMVAR_FINE_FMIN_WRAP ; + int temperature; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP ; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + DEBUGOUT("Error Speed\n"); + return 0; + } + + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; + + hw->temperature = temperature; + + /* + * Assign software defined variables as below + * a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER + */ + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + /* Set ovrd_en=1 to overide ASIC value */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All two of above code updates should be written in a single register write + * Set ovrd_en=1 to overide ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All three of above code updates should be written in a single register write + * Set ovrd_en=1 to overide ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature " + "tracking occurs Error condition"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " + "temperature tracking occurs Error condition"); + } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static inline int +txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypassCtle = 1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + bypassCtle = 0; + + if (hw->mac.type == txgbe_mac_aml) { + msleep(350); + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { + if (rdata & TXGBE_SFP1_MOD_ABS_LS) + PMD_DRV_LOG(DEBUG, + "E56phyRxsCalibAdaptSeq TXGBE_SFP1_MOD_ABS_LS"); + else if (rdata & TXGBE_SFP1_RX_LOS_LS) + PMD_DRV_LOG(DEBUG, + "E56phyRxsCalibAdaptSeq TXGBE_SFP1_RX_LOS_LS"); + return TXGBE_ERR_PHY_INIT_NOT_DONE; + } + } + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + if (bypassCtle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature + * tracking range here. RXS would be enabled at the end of this sequence. For the case + * when PAM4 KR training is not enabled (including PAM4 mode without KR training), + * wait until ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, + ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + EPHY_RREG(E56G__PMD_CTRL_FSM_RX_STAT_0); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + /* + * 4. Disable VGA and CTLE training so that they don't interfere with ADC calibration + * a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 5. Perform ADC interleaver calibration + * a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE + */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) & 1) + != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* + * 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (i = 0; i < 16; i++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_gain_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* + * 7. Perform ADC interleaver adaptation for 10ms or greater, and after that disable it + * a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_intl_adapt_en_i, 0); + + /* + * 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking changes in temperature or voltage + * <1> Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + * Set ALIAS::RXS::CTLE_TRAIN_EN = 0b1 + */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypassCtle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + /* + * <2> wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 + * wait for ALIAS::RXS::CTLE_TRAIN_DONE = 1 + */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_vga_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + if (bypassCtle == 0) { + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypassCtle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + return status; +} + +static inline u32 +txgbe_e56_cfg_temp(struct txgbe_hw *hw) +{ + u32 status; + u32 value; + int temp; + + status = txgbe_e56_get_temp(hw, &temp); + if (status) + temp = DEFAULT_TEMP; + + if (temp < DEFAULT_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else if (temp > HIGH_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else { + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 4, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL4); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL4, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL5); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 23, 23, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL9); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL9, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL10); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL10, value); + } + + return 0; +} + +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + + return 0; +} + +/* + * 2.2.10 SEQ::RX_DISABLE + * Use PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 to powerdown specific RXS lanes. + * Completion of RXS powerdown can be confirmed by observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST + */ +static int txgbe_e56_disable_rx(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i, 0); + + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o, 0); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_2); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_2); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_3); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_3); + + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_RREG(E56G__RXS0_DIG_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + EPHY_WREG(E56G__RXS0_DIG_OVRDEN_1); + + /* 2. Disable pattern checker */ + txgbe_e56_ephy_config(E56G__RXS0_DFT_1, ber_en, 0); + + /* 3. Disable internal serial loopback mode */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i, 0); + + //4. Enable bypass of clock gates in RXS */ + txgbe_e56_ephy_config(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en, 0x1FFF); + + //5. Disable KR training mode */ + //a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0, 0); + + //6. Disable RX to TX parallel loopback */ + //a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en, 0); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + while (1) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x3f) == 0x21) + break; + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) +{ + u32 addr; + u32 rdata; + int status = 0; + + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + + if (hw->mac.type == txgbe_mac_aml) { + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { + return TXGBE_ERR_TIMEOUT; + } + } + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, 0x0); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, 0x0); + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); + + addr = E56PHY_INTR_1_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_1_IDLE_EXIT1); + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + hw->mac.enable_sec_tx_path(hw); + + return status; +} + +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) +{ + u32 value = 0; + u32 ppl_lock = false; + int status = 0; + u32 reset = 0; + + PMD_DRV_LOG(DEBUG, "port[%d] force set speed: 0x%x", hw->bus.lan_id, speed); + + if ((rd32(hw, TXGBE_EPHY_STAT) & TXGBE_EPHY_STAT_PPL_LOCK) == + TXGBE_EPHY_STAT_PPL_LOCK) { + ppl_lock = true; + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.disable_tx_laser(hw); + + if (hw->bus.lan_id == 0) + reset = TXGBE_RST_EPHY_LAN_0; + + else + reset = TXGBE_RST_EPHY_LAN_1; + + wr32(hw, TXGBE_RST, + reset | rd32(hw, TXGBE_RST)); + txgbe_flush(hw); + usec_delay(10); + + /* XLGPCS REGS Start */ + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + value |= 0x8000; + wr32_epcs(hw, VR_PCS_DIG_CTRL1, value); + + usec_delay(1000); + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + if ((value & 0x8000)) { + status = TXGBE_ERR_PHY_INIT_NOT_DONE; + hw->mac.enable_tx_laser(hw); + goto out; + } + + value = rd32_epcs(hw, SR_AN_CTRL); + set_fields_e56(&value, 12, 12, 0); + wr32_epcs(hw, SR_AN_CTRL, value); + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 5); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 7); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0x39); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + /* Update to 0 from SNPS for PIN CLKP/N: Enable the termination of the input buffer */ + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 2, 0, 0x3); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x9); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_25g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0xb); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_10g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.enable_tx_laser(hw); + + status = txgbe_e56_config_rx(hw, speed); + + value = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, value); + + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + if (hw->fec_mode != TXGBE_PHY_FEC_AUTO) { + hw->cur_fec_link = hw->fec_mode; + txgbe_e56_fec_set(hw); + } + +out: + if (ppl_lock) { + hw->mac.enable_sec_tx_path(hw); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + TXGBE_MACRXCFG_ENA); + } + + return status; +} + +s32 txgbe_e56_fec_set(struct txgbe_hw *hw) +{ + u32 value; + + if (hw->cur_fec_link & TXGBE_PHY_FEC_RS) { + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + + /* enable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 1); + wr32_epcs(hw, 0x100c8, value); + } else if (hw->cur_fec_link & TXGBE_PHY_FEC_BASER) { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* enable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 1); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } else { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } + + return 0; +} + +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up) +{ + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + s32 i = 0, j = 0; + + do { + if (!(hw->fec_mode & BIT(j))) { + j += 1; + continue; + } + + hw->cur_fec_link = hw->fec_mode & BIT(j); + + /* + * If in fec auto mode, try another fec mode after no link in 1s + * for lr sfp, enable KR-FEC to link up with mellonax and intel + */ + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_fec_set(hw); + rte_spinlock_unlock(&hw->phy_lock); + + for (i = 0; i < 4; i++) { + msleep(250); + txgbe_e56_check_phy_link(hw, &link_speed, link_up); + if (*link_up) + return 0; + } + j += 1; + } while (j < 3); + + return 0; +} diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h new file mode 100644 index 0000000000..d9b3d70cf1 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -0,0 +1,1749 @@ +#ifndef _TXGBE_E56_H_ +#define _TXGBE_E56_H_ + +#include "txgbe_type.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" + +#define EPHY_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_ephy(hw, REG##_ADDR); \ + } while (0) + +#define EPHY_WREG(REG) \ + do { \ + wr32_ephy(hw, REG##_ADDR, rdata); \ + } while (0) + +#define EPCS_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_epcs(hw, REG##_ADDR); \ + } while (0) + +#define EPCS_WREG(REG) \ + do { \ + wr32_epcs(hw, REG##_ADDR, rdata); \ + } while (0) + +#define txgbe_e56_ephy_config(reg, field, val) \ + do { \ + EPHY_RREG(reg); \ + EPHY_XFLD(reg, field) = (val); \ + EPHY_WREG(reg); \ + } while (0) + +#define txgbe_e56_epcs_config(reg, field, val) \ + do { \ + EPCS_RREG(reg); \ + EPCS_XFLD(reg, field) = (val); \ + EPCS_WREG(reg); \ + } while (0) + +/* + * LAN GPIO define for SFP+ module + * -- Fields + */ +#define SFP1_RS0 5, 5 +#define SFP1_RS1 4, 4 +#define SFP1_RX_LOS 3, 3 +#define SFP1_MOD_ABS 2, 2 +#define SFP1_TX_DISABLE 1, 1 +#define SFP1_TX_FAULT 0, 0 + +#define EPHY_XFLD(REG, FLD) ((REG *)&rdata)->FLD +#define EPCS_XFLD(REG, FLD) ((REG *)&rdata)->FLD + +typedef union { + struct { + u32 ana_refclk_buf_daisy_en_i : 1; + u32 ana_refclk_buf_pad_en_i : 1; + u32 ana_vddinoff_dcore_dig_o : 1; + u32 ana_lcpll_en_clkout_hf_left_top_i : 1; + u32 ana_lcpll_en_clkout_hf_right_top_i : 1; + u32 ana_lcpll_en_clkout_hf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_hf_right_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_left_top_i : 1; + u32 ana_lcpll_en_clkout_lf_right_top_i : 1; + u32 ana_lcpll_en_clkout_lf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_right_bot_i : 1; + u32 ana_bg_en_i : 1; + u32 ana_en_rescal_i : 1; + u32 ana_rescal_comp_o : 1; + u32 ana_en_ldo_core_i : 1; + u32 ana_lcpll_hf_en_bias_i : 1; + u32 ana_lcpll_hf_en_loop_i : 1; + u32 ana_lcpll_hf_en_cp_i : 1; + u32 ana_lcpll_hf_set_lpf_i : 1; + u32 ana_lcpll_hf_en_vco_i : 1; + u32 ana_lcpll_hf_vco_amp_status_o : 1; + u32 ana_lcpll_hf_en_odiv_i : 1; + u32 ana_lcpll_lf_en_bias_i : 1; + u32 ana_lcpll_lf_en_loop_i : 1; + u32 ana_lcpll_lf_en_cp_i : 1; + u32 ana_lcpll_lf_set_lpf_i : 1; + u32 ana_lcpll_lf_en_vco_i : 1; + u32 ana_lcpll_lf_vco_amp_status_o : 1; + u32 ana_lcpll_lf_en_odiv_i : 1; + u32 ana_lcpll_hf_refclk_select_i : 1; + u32 ana_lcpll_lf_refclk_select_i : 1; + u32 rsvd0 : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_0; + +/* AMLITE ETH PHY Registers */ +#define VR_PCS_DIG_CTRL1 0x38000 +#define SR_PCS_CTRL1 0x30000 +#define SR_PCS_CTRL2 0x30007 +#define SR_PMA_CTRL2 0x10007 +#define VR_PCS_DIG_CTRL3 0x38003 +#define VR_PMA_CTRL3 0x180a8 +#define VR_PMA_CTRL4 0x180a9 +#define SR_PMA_RS_FEC_CTRL 0x100c8 +#define CMS_ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN1 0xca8 +#define ANA_OVRDVAL0 0xcb0 +#define ANA_OVRDVAL5 0xcc4 +#define OSC_CAL_N_CDR4 0x14 +#define PLL0_CFG0 0xc10 +#define PLL0_CFG2 0xc18 +#define PLL0_DIV_CFG0 0xc1c +#define PLL1_CFG0 0xc48 +#define PLL1_CFG2 0xc50 +#define CMS_PIN_OVRDEN0 0xc8c +#define CMS_PIN_OVRDVAL0 0xc94 +#define DATAPATH_CFG0 0x142c +#define DATAPATH_CFG1 0x1430 +#define AN_CFG1 0x1438 +#define SPARE52 0x16fc +#define RXS_CFG0 0x000 +#define PMD_CFG0 0x1400 +#define SR_PCS_STS1 0x30001 +#define PMD_CTRL_FSM_TX_STAT0 0x14dc +#define CMS_ANA_OVRDEN0 0xca4 +#define CMS_ANA_OVRDEN1 0xca8 +#define CMS_ANA_OVRDVAL2 0xcb8 +#define CMS_ANA_OVRDVAL4 0xcc0 +#define CMS_ANA_OVRDVAL5 0xcc4 +#define CMS_ANA_OVRDVAL7 0xccc +#define CMS_ANA_OVRDVAL9 0xcd4 +#define CMS_ANA_OVRDVAL10 0xcd8 + +#define TXS_TXS_CFG1 0x804 +#define TXS_WKUP_CNT 0x808 +#define TXS_PIN_OVRDEN0 0x80c +#define TXS_PIN_OVRDVAL6 0x82c +#define TXS_ANA_OVRDVAL1 0x854 + +#define E56PHY_CMS_BASE_ADDR 0x0C00 + +#define E56PHY_CMS_PIN_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x8C) +#define E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I 12, 12 + +#define E56PHY_CMS_PIN_OVRDVAL_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x94) +#define E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I 10, 10 + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) + +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I 29, 29 + +#define E56PHY_CMS_ANA_OVRDEN_1_ADDR (E56PHY_CMS_BASE_ADDR + 0xA8) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I 4, 4 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ADDR (E56PHY_CMS_BASE_ADDR + 0xB8) + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I 31, 28 + +#define E56PHY_CMS_ANA_OVRDVAL_4_ADDR (E56PHY_CMS_BASE_ADDR + 0xC0) + +#define E56PHY_TXS_BASE_ADDR 0x0800 +#define E56PHY_TXS1_BASE_ADDR 0x0900 +#define E56PHY_TXS2_BASE_ADDR 0x0A00 +#define E56PHY_TXS3_BASE_ADDR 0x0B00 +#define E56PHY_TXS_OFFSET 0x0100 + +#define E56PHY_PMD_RX_OFFSET 0x02C + +#define E56PHY_TXS_TXS_CFG_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x04) +#define E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256 7, 4 +#define E56PHY_TXS_WKUP_CNT_ADDR (E56PHY_TXS_BASE_ADDR + 0x08) +#define E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32 7, 0 +#define E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32 15, 8 + +#define E56PHY_TXS_PIN_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x0C) +#define E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I 28, 28 + +#define E56PHY_TXS_PIN_OVRDVAL_6_ADDR (E56PHY_TXS_BASE_ADDR + 0x2C) + +#define E56PHY_TXS_ANA_OVRDVAL_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x54) +#define E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I 23, 8 + +#define E56PHY_TXS_ANA_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x44) +#define E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I 13, 13 + +#define E56PHY_RXS_BASE_ADDR 0x0000 +#define E56PHY_RXS1_BASE_ADDR 0x0200 +#define E56PHY_RXS2_BASE_ADDR 0x0400 +#define E56PHY_RXS3_BASE_ADDR 0x0600 +#define E56PHY_RXS_OFFSET 0x0200 + +#define E56PHY_RXS_RXS_CFG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x000) +#define E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL 1, 1 +#define E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN 17, 4 + +#define E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x008) +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1 15, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1_LSB 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1 31, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1_LSB 16 + +#define E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x014) +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT 18, 8 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1 21, 21 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1 27, 26 + +#define E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x018) +#define E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK 15, 12 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK 19, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK 23, 20 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK 27, 24 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT 30, 28 + +#define E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x01C) +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK 3, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK 7, 4 + +#define E56PHY_RXS_INTL_CONFIG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x020) +#define E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1 31, 16 + +#define E56PHY_RXS_INTL_CONFIG_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x028) +#define E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1 1, 1 + +#define E56PHY_RXS_TXFFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x02C) +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH 18, 12 +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH 26, 20 + +#define E56PHY_RXS_TXFFE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x030) +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x034) +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x038) +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH 20, 12 +#define E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE 26, 21 + +#define E56PHY_RXS_VGA_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x04C) +#define E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET 18, 12 + +#define E56PHY_RXS_VGA_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x050) +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0 4, 0 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0 12, 8 +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123 20, 16 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123 28, 24 + +#define E56PHY_RXS_CTLE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x054) +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0 24, 20 +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123 31, 27 + +#define E56PHY_RXS_CTLE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x058) +#define E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT 24, 0 + +#define E56PHY_RXS_CTLE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x05C) +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1 5, 0 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2 13, 8 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3 21, 16 + +#define E56PHY_RXS_CTLE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x060) +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1 9, 8 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2 11, 10 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3 13, 12 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x064) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT 5, 4 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT 9, 8 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8 31, 28 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x068) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG 31, 28 + +#define E56PHY_RXS_FFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x070) +#define E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN 23, 8 + +#define E56PHY_RXS_IDLE_DETECT_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x088) +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX 22, 16 +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN 30, 24 + +#define E56PHY_RXS_ANA_OVRDEN_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x08C) +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_TRIM_RTERM_I 1, 1 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I 29, 29 + +#define E56PHY_RXS_ANA_OVRDEN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x090) +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I 9, 9 + +#define E56PHY_RXS_ANA_OVRDEN_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x098) +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I 15, 15 +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I 25, 25 + +#define E56PHY_RXS_ANA_OVRDEN_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x09C) +#define E56PHY_RXS_ANA_OVRDVAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x0A0) +#define E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I 0, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B8) +#define E56PHY_RXS_ANA_OVRDVAL_14_ADDR (E56PHY_RXS_BASE_ADDR + 0x0D8) +#define E56PHY_RXS_ANA_OVRDVAL_15_ADDR (E56PHY_RXS_BASE_ADDR + 0x0DC) +#define E56PHY_RXS_ANA_OVRDVAL_17_ADDR (E56PHY_RXS_BASE_ADDR + 0x0E4) +#define E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I 18, 16 + +#define E56PHY_RXS_EYE_SCAN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x1A4) +#define E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER 31, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B4) +#define E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I 1, 0 + +#define E56PHY_RXS_RINGO_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x1FC) + +#define E56PHY_PMD_BASE_ADDR 0x1400 +#define E56PHY_PMD_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x000) +#define E56PHY_PMD_CFG_0_RX_EN_CFG 19, 16 + +#define E56PHY_PMD_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x00C) +#define E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K 31, 24 +#define E56PHY_PMD_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x010) +#define E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K 7, 0 +#define E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K 15, 8 +#define E56PHY_PMD_CFG_5_ADDR (E56PHY_PMD_BASE_ADDR + 0x014) +#define E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET 12, 12 +#define E56PHY_CTRL_FSM_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x040) +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_OFST_CAL_ERR 4, 4 +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR 5, 5 +#define E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL 9, 8 +#define E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN 31, 24 + +#define E56PHY_CTRL_FSM_CFG_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x044) +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x048) +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x04C) +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096 7, 0 + +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x050) +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_7_ADDR (E56PHY_PMD_BASE_ADDR + 0x05C) +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_8_ADDR (E56PHY_PMD_BASE_ADDR + 0x060) +#define E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_12_ADDR (E56PHY_PMD_BASE_ADDR + 0x070) +#define E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_13_ADDR (E56PHY_PMD_BASE_ADDR + 0x074) +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_14_ADDR (E56PHY_PMD_BASE_ADDR + 0x078) +#define E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_15_ADDR (E56PHY_PMD_BASE_ADDR + 0x07C) +#define E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_17_ADDR (E56PHY_PMD_BASE_ADDR + 0x084) +#define E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_18_ADDR (E56PHY_PMD_BASE_ADDR + 0x088) +#define E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_29_ADDR (E56PHY_PMD_BASE_ADDR + 0x0B4) +#define E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_33_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C4) +#define E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_CFG_34_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C8) +#define E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_RX_STAT_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x0FC) +#define E56PHY_RXS0_OVRDEN_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x130) +#define E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O 27, 27 + +#define E56PHY_RXS0_OVRDEN_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x134) +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I 14, 14 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I 16, 16 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CDR_EN_I 18, 18 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I 23, 23 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O 24, 24 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 24 + +#define E56PHY_RXS0_OVRDEN_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x138) +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I 0, 0 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 3, 3 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I 6, 6 + +#define E56PHY_RXS0_OVRDVAL_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x140) +#define E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O 22, 22 + +#define E56PHY_RXS0_OVRDVAL_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x144) +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I 7, 7 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I 9, 9 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CDR_EN_I 11, 11 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I 16, 16 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O 17, 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I 25, 25 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 28, 28 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I 31, 31 + +#define E56PHY_INTR_0_IDLE_ENTRY1 0x10000000 +#define E56PHY_INTR_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x1EC) +#define E56PHY_INTR_0_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E0) + +#define E56PHY_INTR_1_IDLE_EXIT1 0x1 +#define E56PHY_INTR_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x1F0) +#define E56PHY_INTR_1_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E4) + +#define E56PHY_KRT_TFSM_CFG_ADDR (E56PHY_PMD_BASE_ADDR + 0x2B8) +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K 7, 0 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K 15, 8 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 + +#define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 + +#define PHYINIT_TIMEOUT 1000 //PHY initialization timeout value in 0.5ms unit + +#define E56G__BASEADDR 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_7; +#define E56G_CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDEN_1; + +#define E56G_CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_9; + +#define E56G_CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_vcofilt_byp_i : 1; + u32 ovrd_en_ana_bbcdr_coarse_i : 1; + u32 ovrd_en_ana_bbcdr_fine_i : 1; + u32 ovrd_en_ana_bbcdr_ultrafine_i : 1; + u32 ovrd_en_ana_en_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_divctrl_i : 1; + u32 ovrd_en_ana_bbcdr_int_cstm_i : 1; + u32 ovrd_en_ana_bbcdr_prop_step_i : 1; + u32 ovrd_en_ana_en_bbcdr_clk_i : 1; + u32 ovrd_en_ana_test_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_270_o : 1; + u32 ovrd_en_ana_en_bbcdr_samp_dac_i : 1; + u32 ovrd_en_ana_bbcdr_dac0_i : 1; + u32 ovrd_en_ana_bbcdr_dac90_i : 1; + u32 ovrd_en_ana_vga2_cload_in_cstm_i : 1; + u32 ovrd_en_ana_intlvr_cut_bw_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_1; + +#define E56G__RXS0_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0x90) + +typedef union { + struct { + u32 prediv0 : 16; + u32 target_cnt0 : 16; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_0; + +#define E56G_RXS0_OSC_CAL_N_CDR_0_ADDR (E56G__BASEADDR + 0x4) + +typedef union { + struct { + u32 osc_range_sel0 : 2; + u32 osc_range_sel1 : 2; + u32 osc_range_sel2 : 2; + u32 osc_range_sel3 : 2; + u32 vco_code_init : 11; + u32 calibrate_range_sel : 1; + u32 osc_current_boost_en0 : 1; + u32 osc_current_boost_en1 : 1; + u32 osc_current_boost_en2 : 1; + u32 osc_current_boost_en3 : 1; + u32 bbcdr_current_boost0 : 2; + u32 bbcdr_current_boost1 : 2; + u32 bbcdr_current_boost2 : 2; + u32 bbcdr_current_boost3 : 2; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_4; + +#define E56G_RXS0_OSC_CAL_N_CDR_4_ADDR (E56G__BASEADDR + 0x14) + +typedef union { + struct { + u32 adc_intl2slice_delay0 : 16; + u32 adc_intl2slice_delay1 : 16; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_0; + +#define E56G_RXS0_INTL_CONFIG_0_ADDR (E56G__BASEADDR + 0x20) + +typedef union { + struct { + u32 interleaver_hbw_disable0 : 1; + u32 interleaver_hbw_disable1 : 1; + u32 interleaver_hbw_disable2 : 1; + u32 interleaver_hbw_disable3 : 1; + u32 rsvd0 : 28; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_2; + +#define E56G_RXS0_INTL_CONFIG_2_ADDR (E56G__BASEADDR + 0x28) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_dac180_i : 1; + u32 ovrd_en_ana_bbcdr_dac270_i : 1; + u32 ovrd_en_ana_bbcdr_en_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_0_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_90_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_180_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_270_o : 1; + u32 ovrd_en_ana_en_adcbuf1_i : 1; + u32 ovrd_en_ana_test_adcbuf1_i : 1; + u32 ovrd_en_ana_en_adc_clk4ui_i : 1; + u32 ovrd_en_ana_adc_clk_skew0_i : 1; + u32 ovrd_en_ana_adc_clk_skew90_i : 1; + u32 ovrd_en_ana_adc_clk_skew180_i : 1; + u32 ovrd_en_ana_adc_clk_skew270_i : 1; + u32 ovrd_en_ana_adc_update_skew_i : 1; + u32 ovrd_en_ana_en_adc_pi_i : 1; + u32 ovrd_en_ana_adc_pictrl_quad_i : 1; + u32 ovrd_en_ana_adc_pctrl_code_i : 1; + u32 ovrd_en_ana_adc_clkdiv_i : 1; + u32 ovrd_en_ana_test_adc_clkgen_i : 1; + u32 ovrd_en_ana_en_adc_i : 1; + u32 ovrd_en_ana_en_adc_vref_i : 1; + u32 ovrd_en_ana_vref_cnfg_i : 1; + u32 ovrd_en_ana_adc_data_cstm_o : 1; + u32 ovrd_en_ana_en_adccal_lpbk_i : 1; + u32 ovrd_en_ana_sel_adcoffset_cal_i : 1; + u32 ovrd_en_ana_sel_adcgain_cal_i : 1; + u32 ovrd_en_ana_adcgain_cal_swing_ctrl_i : 1; + u32 ovrd_en_ana_adc_gain_i : 1; + u32 ovrd_en_ana_vga_cload_out_cstm_i : 1; + u32 ovrd_en_ana_vga2_cload_out_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_2; + +#define E56G__RXS0_ANA_OVRDEN_2_ADDR (E56G__BASEADDR + 0x94) + +typedef union { + struct { + u32 ovrd_en_ana_adc_offset_i : 1; + u32 ovrd_en_ana_adc_slice_addr_i : 1; + u32 ovrd_en_ana_slice_wr_i : 1; + u32 ovrd_en_ana_test_adc_i : 1; + u32 ovrd_en_ana_test_adc_o : 1; + u32 ovrd_en_ana_spare_o : 8; + u32 ovrd_en_ana_sel_lpbk_i : 1; + u32 ovrd_en_ana_ana_debug_sel_i : 1; + u32 ovrd_en_ana_anabs_config_i : 1; + u32 ovrd_en_ana_en_anabs_i : 1; + u32 ovrd_en_ana_anabs_rxn_o : 1; + u32 ovrd_en_ana_anabs_rxp_o : 1; + u32 ovrd_en_ana_dser_clk_en_i : 1; + u32 ovrd_en_ana_dser_clk_config_i : 1; + u32 ovrd_en_ana_en_mmcdr_clk_obs_i : 1; + u32 ovrd_en_ana_skew_coarse0_fine1_i : 1; + u32 ovrd_en_ana_vddinoff_acore_dig_o : 1; + u32 ovrd_en_ana_vddinoff_dcore_dig_o : 1; + u32 ovrd_en_ana_vga2_boost_cstm_i : 1; + u32 ovrd_en_ana_adc_sel_vbgr_bias_i : 1; + u32 ovrd_en_ana_adc_nbuf_cnfg_i : 1; + u32 ovrd_en_ana_adc_pbuf_cnfg_i : 1; + u32 rsvd0 : 3; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_3; + +#define E56G__RXS0_ANA_OVRDEN_3_NUM 1 +#define E56G__RXS0_ANA_OVRDEN_3_ADDR (E56G__BASEADDR + 0x98) + +typedef union { + struct { + u32 pam4_ab_swap_en : 1; + u32 dser_data_sel : 1; + u32 signal_type : 1; + u32 precode_en : 1; + u32 train_clk_gate_bypass_en : 14; + u32 rsvd0 : 14; + }; + u32 reg; +} E56G__RXS0_RXS_CFG_0; + +#define E56G__RXS0_RXS_CFG_0_NUM 1 +#define E56G__RXS0_RXS_CFG_0_ADDR (E56G__BASEADDR + 0x0) + +typedef union { + struct { + u32 restart_training_ln0 : 1; + u32 training_enable_ln0 : 1; + u32 restart_training_ln1 : 1; + u32 training_enable_ln1 : 1; + u32 restart_training_ln2 : 1; + u32 training_enable_ln2 : 1; + u32 restart_training_ln3 : 1; + u32 training_enable_ln3 : 1; + u32 rsvd0 : 24; + }; + u32 reg; +} E56G__PMD_BASER_PMD_CONTROL; + +#define E56G__PMD_BASER_PMD_CONTROL_NUM 1 +#define E56G__PMD_BASER_PMD_CONTROL_ADDR (E56G__BASEADDR + 0x1640) + +typedef union { + struct { + u32 rx_to_tx_lpbk_en : 4; + u32 sel_wp_pmt_out : 4; + u32 sel_wp_pmt_clkout : 4; + u32 use_recent_marker_offset : 1; + u32 interrupt_debug_mode : 1; + u32 rsvd0 : 2; + u32 tx_ffe_coeff_update : 4; + u32 rsvd1 : 12; + }; + u32 reg; +} E56G__PMD_PMD_CFG_5; + +#define E56G__PMD_PMD_CFG_5_NUM 1 +#define E56G__PMD_PMD_CFG_5_ADDR (E56G__BASEADDR + 0x1414) + +typedef union { + struct { + u32 soft_reset : 1; + u32 pmd_en : 1; + u32 rsvd0 : 2; + u32 pll_refclk_sel : 2; + u32 rsvd1 : 2; + u32 pmd_mode : 1; + u32 rsvd2 : 3; + u32 tx_en_cfg : 4; + u32 rx_en_cfg : 4; + u32 pll_en_cfg : 2; + u32 rsvd3 : 2; + u32 pam4_precode_no_krt_en : 4; + u32 rsvd4 : 4; + }; + u32 reg; +} E56G__PMD_PMD_CFG_0; + +#define E56G__PMD_PMD_CFG_0_NUM 1 +#define E56G__PMD_PMD_CFG_0_ADDR (E56G__BASEADDR + 0x1400) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_rstn_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_divctrl_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_rate_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_width_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_o : 1; + u32 ovrd_en_rxs0_rx0_precode_en_i : 1; + u32 ovrd_en_rxs0_rx0_signal_type_i : 1; + u32 ovrd_en_rxs0_rx0_sync_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_sync_o : 1; + u32 ovrd_en_rxs0_rx0_rate_select_i : 1; + u32 ovrd_en_rxs0_rx0_rterm_en_i : 1; + u32 ovrd_en_rxs0_rx0_bias_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_rdy_i : 1; + u32 ovrd_en_rxs0_rx0_blwc_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_sel_i : 1; + u32 ovrd_en_rxs0_rx0_osc_en_i : 1; + u32 ovrd_en_rxs0_rx0_clkgencdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctlecdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_osc_freq_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_err_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_error_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_0; + +#define E56G__PMD_RXS0_OVRDEN_0_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_0_ADDR (E56G__BASEADDR + 0x1530) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_sparein_i : 8; + u32 ovrd_en_rxs0_rx0_spareout_o : 8; + u32 rsvd0 : 16; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_3; + +#define E56G__PMD_RXS0_OVRDEN_3_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_3_ADDR (E56G__BASEADDR + 0x153c) + +typedef union { + struct { + u32 vco_code_cont_adj_done_ovrd_en : 1; + u32 dfe_coeffl_ovrd_en : 1; + u32 dfe_coeffh_ovrd_en : 1; + u32 rsvd0 : 1; + u32 top_comp_th_ovrd_en : 1; + u32 mid_comp_th_ovrd_en : 1; + u32 bot_comp_th_ovrd_en : 1; + u32 rsvd1 : 1; + u32 level_target_ovrd_en : 4; + u32 ffe_coeff_c0to3_ovrd_en : 4; + u32 ffe_coeff_c4to7_ovrd_en : 4; + u32 ffe_coeff_c8to11_ovrd_en : 4; + u32 ffe_coeff_c12to15_ovrd_en : 4; + u32 ffe_coeff_update_ovrd_en : 1; + u32 rsvd2 : 3; + }; + u32 reg; +} E56G__RXS0_DIG_OVRDEN_1; + +#define E56G__RXS0_DIG_OVRDEN_1_NUM 1 +#define E56G__RXS0_DIG_OVRDEN_1_ADDR (E56G__BASEADDR + 0x160) + +typedef union { + struct { + u32 ber_en : 1; + u32 rsvd0 : 3; + u32 read_mode_en : 1; + u32 rsvd1 : 3; + u32 err_cnt_mode_all0_one1 : 1; + u32 rsvd2 : 3; + u32 init_lfsr_mode_continue0_restart1 : 1; + u32 rsvd3 : 3; + u32 pattern_sel : 4; + u32 rsvd4 : 12; + }; + u32 reg; +} E56G__RXS0_DFT_1; + +#define E56G__RXS0_DFT_1_NUM 1 +#define E56G__RXS0_DFT_1_ADDR (E56G__BASEADDR + 0xec) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_efuse_bits_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_in_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_out_o : 1; + u32 rsvd0 : 15; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_2; + +#define E56G__PMD_RXS0_OVRDEN_2_ADDR (E56G__BASEADDR + 0x1538) + +typedef union { + struct { + u32 ana_bbcdr_osc_range_sel_i : 2; + u32 rsvd0 : 2; + u32 ana_bbcdr_coarse_i : 4; + u32 ana_bbcdr_fine_i : 3; + u32 rsvd1 : 1; + u32 ana_bbcdr_ultrafine_i : 3; + u32 rsvd2 : 1; + u32 ana_bbcdr_divctrl_i : 2; + u32 rsvd3 : 2; + u32 ana_bbcdr_int_cstm_i : 5; + u32 rsvd4 : 3; + u32 ana_bbcdr_prop_step_i : 4; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_5; + +#define E56G__RXS0_ANA_OVRDVAL_5_ADDR (E56G__BASEADDR + 0xb4) + +typedef union { + struct { + u32 ana_adc_pictrl_quad_i : 2; + u32 rsvd0 : 2; + u32 ana_adc_clkdiv_i : 2; + u32 rsvd1 : 2; + u32 ana_test_adc_clkgen_i : 4; + u32 ana_vref_cnfg_i : 4; + u32 ana_adcgain_cal_swing_ctrl_i : 4; + u32 ana_adc_gain_i : 4; + u32 ana_adc_offset_i : 4; + u32 ana_ana_debug_sel_i : 4; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_11; + +#define E56G__RXS3_ANA_OVRDVAL_11_ADDR (E56G__BASEADDR + 0x6cc) + +typedef union { + struct { + u32 rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 rxs0_rx0_fom_en_i : 1; + u32 rxs0_rx0_idle_detect_en_i : 1; + u32 rxs0_rx0_idle_o : 1; + u32 rxs0_rx0_txffe_train_en_i : 1; + u32 rxs0_rx0_txffe_train_enack_o : 1; + u32 rxs0_rx0_txffe_train_done_o : 1; + u32 rxs0_rx0_vga_train_en_i : 1; + u32 rxs0_rx0_vga_train_done_o : 1; + u32 rxs0_rx0_ctle_train_en_i : 1; + u32 rxs0_rx0_ctle_train_done_o : 1; + u32 rxs0_rx0_cdr_en_i : 1; + u32 rxs0_rx0_cdr_rdy_o : 1; + u32 rxs0_rx0_ffe_train_en_i : 1; + u32 rxs0_rx0_ffe_train_done_o : 1; + u32 rxs0_rx0_mmpd_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_done_o : 1; + u32 rxs0_rx0_adc_intl_cal_error_o : 1; + u32 rxs0_rx0_dfe_train_en_i : 1; + u32 rxs0_rx0_dfe_train_done_o : 1; + u32 rxs0_rx0_vga_adapt_en_i : 1; + u32 rxs0_rx0_vga_adapt_done_o : 1; + u32 rxs0_rx0_ctle_adapt_en_i : 1; + u32 rxs0_rx0_ctle_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 rxs0_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDVAL_1; +#define E56G__PMD_RXS0_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1544) + +typedef union { + struct { + u32 rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 rxs1_rx0_fom_en_i : 1; + u32 rxs1_rx0_idle_detect_en_i : 1; + u32 rxs1_rx0_idle_o : 1; + u32 rxs1_rx0_txffe_train_en_i : 1; + u32 rxs1_rx0_txffe_train_enack_o : 1; + u32 rxs1_rx0_txffe_train_done_o : 1; + u32 rxs1_rx0_vga_train_en_i : 1; + u32 rxs1_rx0_vga_train_done_o : 1; + u32 rxs1_rx0_ctle_train_en_i : 1; + u32 rxs1_rx0_ctle_train_done_o : 1; + u32 rxs1_rx0_cdr_en_i : 1; + u32 rxs1_rx0_cdr_rdy_o : 1; + u32 rxs1_rx0_ffe_train_en_i : 1; + u32 rxs1_rx0_ffe_train_done_o : 1; + u32 rxs1_rx0_mmpd_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_done_o : 1; + u32 rxs1_rx0_adc_intl_cal_error_o : 1; + u32 rxs1_rx0_dfe_train_en_i : 1; + u32 rxs1_rx0_dfe_train_done_o : 1; + u32 rxs1_rx0_vga_adapt_en_i : 1; + u32 rxs1_rx0_vga_adapt_done_o : 1; + u32 rxs1_rx0_ctle_adapt_en_i : 1; + u32 rxs1_rx0_ctle_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs1_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs1_rx0_adc_gain_adapt_en_i : 1; + u32 rxs1_rx0_adc_gain_adapt_done_o : 1; + u32 rxs1_rx0_adc_gain_adapt_error_o : 1; + u32 rxs1_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDVAL_1; + +#define E56G__PMD_RXS1_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1570) + +typedef union { + struct { + u32 rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 rxs2_rx0_fom_en_i : 1; + u32 rxs2_rx0_idle_detect_en_i : 1; + u32 rxs2_rx0_idle_o : 1; + u32 rxs2_rx0_txffe_train_en_i : 1; + u32 rxs2_rx0_txffe_train_enack_o : 1; + u32 rxs2_rx0_txffe_train_done_o : 1; + u32 rxs2_rx0_vga_train_en_i : 1; + u32 rxs2_rx0_vga_train_done_o : 1; + u32 rxs2_rx0_ctle_train_en_i : 1; + u32 rxs2_rx0_ctle_train_done_o : 1; + u32 rxs2_rx0_cdr_en_i : 1; + u32 rxs2_rx0_cdr_rdy_o : 1; + u32 rxs2_rx0_ffe_train_en_i : 1; + u32 rxs2_rx0_ffe_train_done_o : 1; + u32 rxs2_rx0_mmpd_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_done_o : 1; + u32 rxs2_rx0_adc_intl_cal_error_o : 1; + u32 rxs2_rx0_dfe_train_en_i : 1; + u32 rxs2_rx0_dfe_train_done_o : 1; + u32 rxs2_rx0_vga_adapt_en_i : 1; + u32 rxs2_rx0_vga_adapt_done_o : 1; + u32 rxs2_rx0_ctle_adapt_en_i : 1; + u32 rxs2_rx0_ctle_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs2_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs2_rx0_adc_gain_adapt_en_i : 1; + u32 rxs2_rx0_adc_gain_adapt_done_o : 1; + u32 rxs2_rx0_adc_gain_adapt_error_o : 1; + u32 rxs2_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDVAL_1; + +#define E56G__PMD_RXS2_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x159c) + +typedef union { + struct { + u32 rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 rxs3_rx0_fom_en_i : 1; + u32 rxs3_rx0_idle_detect_en_i : 1; + u32 rxs3_rx0_idle_o : 1; + u32 rxs3_rx0_txffe_train_en_i : 1; + u32 rxs3_rx0_txffe_train_enack_o : 1; + u32 rxs3_rx0_txffe_train_done_o : 1; + u32 rxs3_rx0_vga_train_en_i : 1; + u32 rxs3_rx0_vga_train_done_o : 1; + u32 rxs3_rx0_ctle_train_en_i : 1; + u32 rxs3_rx0_ctle_train_done_o : 1; + u32 rxs3_rx0_cdr_en_i : 1; + u32 rxs3_rx0_cdr_rdy_o : 1; + u32 rxs3_rx0_ffe_train_en_i : 1; + u32 rxs3_rx0_ffe_train_done_o : 1; + u32 rxs3_rx0_mmpd_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_done_o : 1; + u32 rxs3_rx0_adc_intl_cal_error_o : 1; + u32 rxs3_rx0_dfe_train_en_i : 1; + u32 rxs3_rx0_dfe_train_done_o : 1; + u32 rxs3_rx0_vga_adapt_en_i : 1; + u32 rxs3_rx0_vga_adapt_done_o : 1; + u32 rxs3_rx0_ctle_adapt_en_i : 1; + u32 rxs3_rx0_ctle_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs3_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs3_rx0_adc_gain_adapt_en_i : 1; + u32 rxs3_rx0_adc_gain_adapt_done_o : 1; + u32 rxs3_rx0_adc_gain_adapt_error_o : 1; + u32 rxs3_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDVAL_1; + +#define E56G__PMD_RXS3_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x15c8) + +typedef union { + struct { + u32 ctrl_fsm_rx0_st : 6; + u32 rsvd0 : 2; + u32 ctrl_fsm_rx1_st : 6; + u32 rsvd1 : 2; + u32 ctrl_fsm_rx2_st : 6; + u32 rsvd2 : 2; + u32 ctrl_fsm_rx3_st : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_CTRL_FSM_RX_STAT_0; + +#define E56G__PMD_CTRL_FSM_RX_STAT_0_ADDR (E56G__BASEADDR + 0x14fc) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_0; +#define E56G__RXS0_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0xa0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_0; + +#define E56G__RXS1_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x2a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_0; + +#define E56G__RXS2_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x4a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_0; + +#define E56G__RXS3_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x6a0) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_0; + +#define E56G__RXS0_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x8c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDEN_0; + +#define E56G__RXS1_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x28c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDEN_0; + +#define E56G__RXS2_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x48c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDEN_0; + +#define E56G__RXS3_ANA_OVRDEN_0_NUM 1 +#define E56G__RXS3_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x68c) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_3; + +#define E56G__RXS0_ANA_OVRDVAL_3_NUM 1 +#define E56G__RXS0_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0xac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_3; + +#define E56G__RXS1_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x2ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_3; + +#define E56G__RXS2_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x4ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_3; + +#define E56G__RXS3_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x6ac) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fom_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs0_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_1; + +#define E56G__PMD_RXS0_OVRDEN_1_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1534) + +typedef union { + struct { + u32 ovrd_en_rxs1_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fom_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs1_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs1_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDEN_1; + +#define E56G__PMD_RXS1_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1560) + +typedef union { + struct { + u32 ovrd_en_rxs2_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fom_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs2_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs2_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDEN_1; + +#define E56G__PMD_RXS2_OVRDEN_1_ADDR (E56G__BASEADDR + 0x158c) + +typedef union { + struct { + u32 ovrd_en_rxs3_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fom_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs3_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs3_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDEN_1; + +#define E56G__PMD_RXS3_OVRDEN_1_ADDR (E56G__BASEADDR + 0x15b8) + +#define E56G__RXS0_FOM_18__ADDR (E56G__BASEADDR + 0x1f8) +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB 11 +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB 0 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB 23 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB 12 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB 25 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB 25 + +#define DEFAULT_TEMP 40 +#define HIGH_TEMP 70 + +#define E56PHY_RX_RDY_ST 0x1B + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 + +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 +#define S25G_CMVAR_SEC_LOW_TH 0x1A +#define S25G_CMVAR_SEC_HIGH_TH 0x1D +#define S25G_CMVAR_UFINE_MAX 0x2 +#define S25G_CMVAR_FINE_MAX 0x7 +#define S25G_CMVAR_COARSE_MAX 0xF +#define S25G_CMVAR_UFINE_UMAX_WRAP 0x0 +#define S25G_CMVAR_UFINE_FMAX_WRAP 0x0 +#define S25G_CMVAR_FINE_FMAX_WRAP 0x2 +#define S25G_CMVAR_UFINE_MIN 0x0 +#define S25G_CMVAR_FINE_MIN 0x0 +#define S25G_CMVAR_COARSE_MIN 0x1 +#define S25G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S25G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S25G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S10G_CMVAR_SEC_LOW_TH 0x1A +#define S10G_CMVAR_SEC_HIGH_TH 0x1D +#define S10G_CMVAR_UFINE_MAX 0x7 +#define S10G_CMVAR_FINE_MAX 0x7 +#define S10G_CMVAR_COARSE_MAX 0xF +#define S10G_CMVAR_UFINE_UMAX_WRAP 0x6 +#define S10G_CMVAR_UFINE_FMAX_WRAP 0x7 +#define S10G_CMVAR_FINE_FMAX_WRAP 0x1 +#define S10G_CMVAR_UFINE_MIN 0x0 +#define S10G_CMVAR_FINE_MIN 0x0 +#define S10G_CMVAR_COARSE_MIN 0x1 +#define S10G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S10G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S10G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_TX_FFE_CFG_MAIN 0x2c2c2c2c +#define S10G_TX_FFE_CFG_PRE1 0x0 +#define S10G_TX_FFE_CFG_PRE2 0x0 +#define S10G_TX_FFE_CFG_POST 0x06060606 +#define S25G_TX_FFE_CFG_MAIN 0x31 +#define S25G_TX_FFE_CFG_PRE1 0x4 +#define S25G_TX_FFE_CFG_PRE2 0x1 +#define S25G_TX_FFE_CFG_POST 0x9 + +#define S25G_TX_FFE_CFG_DAC_MAIN 0x2a +#define S25G_TX_FFE_CFG_DAC_PRE1 0x03 +#define S25G_TX_FFE_CFG_DAC_PRE2 0x0 +#define S25G_TX_FFE_CFG_DAC_POST 0x11 + +#define S40G_TX_FFE_CFG_MAIN 0x2b2b2b2b +#define S40G_TX_FFE_CFG_PRE1 0x03030303 +#define S40G_TX_FFE_CFG_PRE2 0x0 +#define S40G_TX_FFE_CFG_POST 0x11111111 + +#define BYPASS_CTLE_TAG 0x0 + +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S10G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S25G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define TXGBE_E56_PHY_LINK_UP 0x4 + +void set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value); +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane); +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE); +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_10g(struct txgbe_hw *hw); +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed); +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_fec_set(struct txgbe_hw *hw); +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); + +#endif /* _TXGBE_E56_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h new file mode 100644 index 0000000000..99dcca2af5 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -0,0 +1,279 @@ +#ifndef _TXGBE_E56_BP_H_ +#define _TXGBE_E56_BP_H_ + +#define TXGBE_10G_FEC_REQ BIT(15) +#define TXGBE_10G_FEC_ABL BIT(14) +#define TXGBE_25G_BASE_FEC_REQ BIT(13) +#define TXGBE_25G_RS_FEC_REQ BIT(12) + +#ifndef __bf_shf +#define __bf_shf(x) (__builtin_ffsll(x) - 1) +#endif +/** + * FIELD_GET_M() - extract a bitfield element + * @_mask: shifted mask defining the field's length and position + * @_reg: value of entire bitfield + * + * FIELD_GET_M() extracts the field specified by @_mask from the + * bitfield passed in as @_reg by masking and shifting it down. + */ +#define FIELD_GET_M(_mask, _reg) \ + ({ \ + (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ + }) + +typedef union { + struct { + u32 tx0_cursor_factor : 7; + u32 rsvd0 : 1; + u32 tx1_cursor_factor : 7; + u32 rsvd1 : 1; + u32 tx2_cursor_factor : 7; + u32 rsvd2 : 1; + u32 tx3_cursor_factor : 7; + u32 rsvd3 : 1; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_1; + +#define E56G__PMD_TX_FFE_CFG_1_NUM 1 +#define E56G__PMD_TX_FFE_CFG_1_ADDR (E56G__BASEADDR + 0x141c) +#define E56G__PMD_TX_FFE_CFG_1_PTR ((E56G__PMD_TX_FFE_CFG_1 *)(E56G__PMD_TX_FFE_CFG_1_ADDR)) +#define E56G__PMD_TX_FFE_CFG_1_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_1_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_READ_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_RESET_VALUE 0x3f3f3f3f + +typedef union { + struct { + u32 tx0_precursor1_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor1_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor1_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor1_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_2; + +#define E56G__PMD_TX_FFE_CFG_2_NUM 1 +#define E56G__PMD_TX_FFE_CFG_2_ADDR (E56G__BASEADDR + 0x1420) +#define E56G__PMD_TX_FFE_CFG_2_PTR ((E56G__PMD_TX_FFE_CFG_2 *)(E56G__PMD_TX_FFE_CFG_2_ADDR)) +#define E56G__PMD_TX_FFE_CFG_2_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_2_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_precursor2_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor2_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor2_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor2_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_3; +#define E56G__PMD_TX_FFE_CFG_3_NUM 1 +#define E56G__PMD_TX_FFE_CFG_3_ADDR (E56G__BASEADDR + 0x1424) +#define E56G__PMD_TX_FFE_CFG_3_PTR ((E56G__PMD_TX_FFE_CFG_3 *)(E56G__PMD_TX_FFE_CFG_3_ADDR)) +#define E56G__PMD_TX_FFE_CFG_3_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_3_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_postcursor_factor : 6; + u32 rsvd0 : 2; + u32 tx1_postcursor_factor : 6; + u32 rsvd1 : 2; + u32 tx2_postcursor_factor : 6; + u32 rsvd2 : 2; + u32 tx3_postcursor_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_4; +#define E56G__PMD_TX_FFE_CFG_4_NUM 1 +#define E56G__PMD_TX_FFE_CFG_4_ADDR (E56G__BASEADDR + 0x1428) +#define E56G__PMD_TX_FFE_CFG_4_PTR ((E56G__PMD_TX_FFE_CFG_4 *)(E56G__PMD_TX_FFE_CFG_4_ADDR)) +#define E56G__PMD_TX_FFE_CFG_4_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_4_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_7; +#define E56G__CMS_ANA_OVRDVAL_7_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) +#define E56G__CMS_ANA_OVRDVAL_7_PTR ((E56G__CMS_ANA_OVRDVAL_7 *)(E56G__CMS_ANA_OVRDVAL_7_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_7_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_7_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_READ_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G__CMS_ANA_OVRDEN_1; +#define E56G__CMS_ANA_OVRDEN_1_NUM 1 +#define E56G__CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) +#define E56G__CMS_ANA_OVRDEN_1_PTR ((E56G__CMS_ANA_OVRDEN_1 *)(E56G__CMS_ANA_OVRDEN_1_ADDR)) +#define E56G__CMS_ANA_OVRDEN_1_STRIDE 4 +#define E56G__CMS_ANA_OVRDEN_1_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_READ_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_READ_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_9; +#define E56G__CMS_ANA_OVRDVAL_9_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) +#define E56G__CMS_ANA_OVRDVAL_9_PTR ((E56G__CMS_ANA_OVRDVAL_9 *)(E56G__CMS_ANA_OVRDVAL_9_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_9_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_9_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_READ_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_RESET_VALUE 0x0 + +#define SFP2_RS0 5 +#define SFP2_RS1 4 +#define SFP2_TX_DISABLE 1 +#define SFP2_TX_FAULT 0 +#define SFP2_RX_LOS_BIT 3 +#ifdef PHYINIT_TIMEOUT +#undef PHYINIT_TIMEOUT +#define PHYINIT_TIMEOUT 2000 +#endif + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_DAISY_EN_I 0, 0 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I 1, 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I_LSB 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_VDDINOFF_DCORE_DIG_O 2, 2 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I 11, 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I_LSB 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I 12, 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I_LSB 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I 13, 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I_LSB 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O 14, 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O_LSB 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I 15, 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I_LSB 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I 16, 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I_LSB 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I 17, 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I_LSB 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I 18, 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I_LSB 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I 19, 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I_LSB 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I 20, 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I_LSB 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I 21, 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I_LSB 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I 22, 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I_LSB 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I 23, 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I_LSB 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I 24, 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I_LSB 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 25, 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I_LSB 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_SET_LPF_I 26, 26 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 20, 16 +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 12, 12 +#define E56PHY_CMS_ANA_OVRDVAL_7_ADDR (E56PHY_CMS_BASE_ADDR + 0xCC) +#define E56PHY_CMS_ANA_OVRDVAL_5_ADDR (E56PHY_CMS_BASE_ADDR + 0xC4) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I 23, 23 +#define E56PHY_CMS_ANA_OVRDVAL_9_ADDR (E56PHY_CMS_BASE_ADDR + 0xD4) +#define E56PHY_CMS_ANA_OVRDVAL_10_ADDR (E56PHY_CMS_BASE_ADDR + 0xD8) +#define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + unsigned char byLinkMode, unsigned int bypassCtle); +void txgbe_e65_bp_down_event(struct txgbe_hw *hw); +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw); + +#endif diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0719b56e3c..3b683eaa04 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4069,37 +4069,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { - u32 rdata = 0; - u32 links_reg = 0; + u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); - /* must read it twice because the state may - * not be correct the first time you read it - */ - rdata = rd32_epcs(hw, 0x30001); - rdata = rd32_epcs(hw, 0x30001); - - if (rdata & TXGBE_AML_PHY_LINK_UP) - *link_up = true; - else - *link_up = false; - - links_reg = rd32(hw, TXGBE_PORTSTAT); - if (*link_up) { - if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == - TXGBE_CFG_PORT_ST_AML_LINK_40G) - *speed = TXGBE_LINK_SPEED_40GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == - TXGBE_CFG_PORT_ST_AML_LINK_25G) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == - TXGBE_CFG_PORT_ST_AML_LINK_10G) - *speed = TXGBE_LINK_SPEED_10GB_FULL; - } else { - *speed = TXGBE_LINK_SPEED_UNKNOWN; - } + if (gpio_ext & gpio_ext_mask) + return true; - return 0; + return false; } diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index f4282b3241..91ad36f4d4 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -28,14 +28,6 @@ #define TMZ_VADDR(mz) ((mz)->addr) #define TDEV_NAME(eth_dev) ((eth_dev)->device->name) -extern int txgbe_logtype_bp; -#define RTE_LOGTYPE_TXGBE_BP txgbe_logtype_bp -#define BP_LOG(fmt, ...) \ - RTE_LOG(DEBUG, TXGBE_BP, \ - "[%"PRIu64".%"PRIu64"]%s(%d): " fmt, \ - usec_stamp() / 1000000, usec_stamp() % 1000000, \ - __func__, __LINE__, ## __VA_ARGS__) - #define ASSERT(x) do { \ if (!(x)) \ PMD_DRV_LOG(ERR, "TXGBE: %d", x); \ diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index f1849c8400..c02be3cc34 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -40,7 +40,6 @@ #define SR_PMA_KR_LD_CESTS_RR MS16(15, 0x1) #define SR_PMA_KR_FEC_CTRL 0x0100AB #define SR_PMA_KR_FEC_CTRL_EN MS16(0, 0x1) -#define SR_PMA_RS_FEC_CTRL 0x0100C8 #define SR_MII_MMD_CTL 0x1F0000 #define SR_MII_MMD_CTL_AN_EN 0x1000 #define SR_MII_MMD_CTL_RESTART_AN 0x0200 diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bc73f28ca2..85d0aee8ff 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -158,6 +158,8 @@ #define TXGBE_RST_SW MS(0, 0x1) #define TXGBE_RST_LAN(i) MS(((i) + 1), 0x1) #define TXGBE_RST_FW MS(3, 0x1) +#define TXGBE_RST_EPHY_LAN_1 MS(16, 0x1) +#define TXGBE_RST_EPHY_LAN_0 MS(19, 0x1) #define TXGBE_RST_MAC_LAN_1 MS(17, 0x1) #define TXGBE_RST_MAC_LAN_0 MS(20, 0x1) #define TXGBE_RST_ETH(i) MS(((i) + 29), 0x1) diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index ede780321f..421abc1145 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -64,6 +64,9 @@ #define TXGBE_AML_ALARM_THRE_MASK 0x1FFE0000U #define TXGBE_AML_DALARM_THRE_MASK 0x0001FFE0U +#define CL74_KRTR_TRAINNING_TIMEOUT 6000 /* 3000ms c74 trainning timeout */ +#define AN_TRAINNING_MODE 0 /* 0: not dis an 1: dis an */ + struct txgbe_thermal_diode_data { s16 temp; s16 alarm_thresh; @@ -690,6 +693,8 @@ struct txgbe_phy_info { s32 (*setup_link_speed)(struct txgbe_hw *hw, u32 speed, bool autoneg_wait_to_complete); s32 (*check_link)(struct txgbe_hw *hw, u32 *speed, bool *link_up); + s32 (*setup_link_core)(struct txgbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete, bool *need_reset); s32 (*get_fw_version)(struct txgbe_hw *hw, u32 *fw_version); s32 (*read_i2c_byte)(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); @@ -732,7 +737,9 @@ struct txgbe_phy_info { u16 ffe_set; u16 ffe_main; u16 ffe_pre; + u16 ffe_pre2; u16 ffe_post; + u16 fec_mode; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -823,6 +830,7 @@ struct txgbe_devargs { struct txgbe_hw { void IOMEM *hw_addr; void *back; + void *dev_back; struct txgbe_mac_info mac; struct txgbe_addr_filter_info addr_ctrl; struct txgbe_fc_info fc; @@ -881,8 +889,12 @@ struct txgbe_hw { /*amlite: new SW-FW mbox */ u8 swfw_index; rte_atomic32_t swfw_busy; + bool link_valid; + bool reconfig_rx; u32 fec_mode; u32 cur_fec_link; + int temperature; + u32 bp_link_mode; }; struct txgbe_backplane_ability { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index e3492c9cd7..622049890f 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -592,6 +592,17 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) fdir_conf->drop_queue = drop_queue; } +static void +txgbe_override_mac_ops(struct txgbe_hw *hw) +{ + struct txgbe_mac_info *mac = &hw->mac; + + if (hw->phy.multispeed_fiber) + mac->setup_mac_link = txgbe_setup_mac_link_aml; + else + mac->setup_link = txgbe_setup_mac_link_aml; +} + static int eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { @@ -651,6 +662,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) /* Vendor and Device ID need to be set before init of shared code */ hw->back = pci_dev; + hw->dev_back = eth_dev; hw->port_id = eth_dev->data->port_id; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; @@ -686,6 +698,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + if (hw->mac.type == txgbe_mac_aml) + txgbe_override_mac_ops(hw); + /* Unlock any pending hardware semaphore */ txgbe_swfw_lock_reset(hw); @@ -2039,6 +2054,9 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + if (hw->mac.type == txgbe_mac_aml) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); @@ -3087,6 +3105,65 @@ txgbe_tx_ring_recovery(struct rte_eth_dev *dev) } } +void +txgbe_dev_setup_link_alarm_handler_aml(void *param) +{ + struct txgbe_hw *hw = (struct txgbe_hw *)param; + struct rte_eth_dev *dev = (struct rte_eth_dev *)hw->dev_back; + struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev); + u32 speed; + bool autoneg = false; + u32 gssr = hw->phy.phy_semaphore_mask; + + if (!hw) + return; + + speed = hw->phy.autoneg_advertised; + if (!speed) + hw->mac.get_link_capabilities(hw, &speed, &autoneg); + + /* firmware is configuring phy now, delay host driver config action */ + if (hw->mac.acquire_swfw_sync(hw, gssr) != 0) { + rte_eal_alarm_set(1000 * 1000 * 2, + txgbe_dev_setup_link_alarm_handler_aml, hw); + printf("delay config ephy\n"); + return; + } + + hw->mac.setup_link(hw, speed, true); + + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + bool link_up = false; + + hw->mac.check_link(hw, &link_speed, &link_up, false); + if (link_up) { + DEBUGOUT("LINK UP IN HANDLER"); + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; + txgbe_dev_link_update_share(dev, 0); + } + + hw->mac.release_swfw_sync(hw, gssr); + + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; +} + +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete) +{ + bool need_reset = false; + s32 status = 0; + + status = hw->phy.setup_link_core(hw, speed, autoneg_wait_to_complete, &need_reset); + if (status) + return status; + + if (!hw->adapter_stopped && need_reset) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_setup_link_alarm_handler_aml, hw); + + return status; +} + /* * If @timeout_ms was 0, it means that it will not return until link complete. * It returns 1 on complete, return 0 on timeout. @@ -3120,9 +3197,13 @@ txgbe_dev_setup_link_thread_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_adapter *ad = TXGBE_DEV_ADAPTER(dev); + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - txgbe_dev_setup_link_alarm_handler(dev); + if (hw->mac.type == txgbe_mac_aml) + txgbe_dev_setup_link_alarm_handler_aml(hw); + else + txgbe_dev_setup_link_alarm_handler(dev); rte_atomic_store_explicit(&ad->link_thread_running, 0, rte_memory_order_seq_cst); return 0; } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 189fbac541..1ec8e096cc 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -733,6 +733,10 @@ int txgbe_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); void txgbe_dev_setup_link_alarm_handler(void *param); +void txgbe_dev_setup_link_alarm_handler_aml(void *param); +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete); void txgbe_read_stats_registers(struct txgbe_hw *hw, struct txgbe_hw_stats *hw_stats); diff --git a/drivers/net/txgbe/txgbe_logs.h b/drivers/net/txgbe/txgbe_logs.h index 1ad9d25ca1..2fc63e5921 100644 --- a/drivers/net/txgbe/txgbe_logs.h +++ b/drivers/net/txgbe/txgbe_logs.h @@ -49,6 +49,13 @@ extern int txgbe_logtype_tx_free; #define PMD_TX_FREE_LOG(...) do { } while (0) #endif +extern int txgbe_logtype_bp; +#define BP_LOG(fmt, args...) \ + rte_log(RTE_LOG_DEBUG, txgbe_logtype_bp, \ + "[%" PRIu64 ".%" PRIu64 "]%s(%d): <port %d> " fmt, \ + usec_stamp() / 1000000, usec_stamp() % 1000000, \ + __func__, __LINE__, hw->port_id, ##args) + #define DEBUGOUT(fmt, ...) PMD_DRV_LOG(DEBUG, fmt, ##__VA_ARGS__) #define PMD_INIT_FUNC_TRACE() PMD_DRV_LOG(DEBUG, ">>") -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* RE: [PATCH 12/18] net/txgbe: fix link stability for 25G NIC 2026-04-23 3:40 ` [PATCH 12/18] net/txgbe: fix link stability for 25G NIC Zaiyu Wang @ 2026-04-23 8:22 ` Jiawen Wu 0 siblings, 0 replies; 92+ messages in thread From: Jiawen Wu @ 2026-04-23 8:22 UTC (permalink / raw) To: 'Zaiyu Wang', dev; +Cc: stable > @@ -197,33 +204,80 @@ s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, > if (status) > return status; > > + /* setup the highest link when no autoneg */ > + if (!autoneg) { > + if (speed & TXGBE_LINK_SPEED_25GB_FULL) > + speed = TXGBE_LINK_SPEED_25GB_FULL; > + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) > + speed = TXGBE_LINK_SPEED_10GB_FULL; > + } > + > speed &= link_capabilities; > if (speed == TXGBE_LINK_SPEED_UNKNOWN) > return TXGBE_ERR_LINK_SETUP; > > - value = rd32(hw, TXGBE_GPIOEXT); > - if (value & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) > + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | > + TXGBE_SFP1_RX_LOS_LS)) { > + DEBUGOUT("RX LOS"); > return status; > + } > > - status = hw->mac.check_link(hw, &link_speed, &link_up, > - autoneg_wait_to_complete); > + for (i = 0; i < 4; i++) { > + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); > + if (link_up) { > + DEBUGOUT("check phy link_up"); > + break; > + } > + msleep(250); > + } > > - if (link_up && speed == TXGBE_LINK_SPEED_25GB_FULL) > + if (speed == TXGBE_LINK_SPEED_25GB_FULL) > hw->cur_fec_link = txgbe_phy_fec_get(hw); > > if (link_speed == speed && link_up && > - !(speed == TXGBE_LINK_SPEED_25GB_FULL && > - !(hw->fec_mode & hw->cur_fec_link))) > - return status; > + !(speed == TXGBE_LINK_SPEED_25GB_FULL && > + !(hw->fec_mode & hw->cur_fec_link))) > + goto out; > > - if (speed & TXGBE_LINK_SPEED_25GB_FULL) > - speed = 0x10; > - else if (speed & TXGBE_LINK_SPEED_10GB_FULL) > - speed = 0x08; > + rte_spinlock_lock(&hw->phy_lock); > + ret_status = txgbe_set_link_to_amlite(hw, speed); > + rte_spinlock_unlock(&hw->phy_lock); > + > + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) > + goto out; > > - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); > + if (ret_status == TXGBE_ERR_TIMEOUT) { > + hw->link_valid = false; > + *need_reset = true; > + goto out; > + } else { > + hw->link_valid = true; > + } > + > + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { > + txgbe_e56_fec_polling(hw, &link_up); > + } else { > + for (i = 0; i < 4; i++) { > + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); > + if (link_up) > + goto out; > + msleep(250); > + } > + } > > - txgbe_wait_for_link_up_aml(hw, speed); > +out: > + if (link_up) { > + value = rd32(hw, TXGBE_PORTSTAT); > + if (!(value & TXGBE_PORTSTAT_UP)) { > + PMD_DRV_LOG(DEBUG, "MAC link 0x14404: 0x%x", value); > + *need_reset = true; > + value = rd32(hw, 0x110b0); > + PMD_DRV_LOG(DEBUG, "MAC intr status 0x110b0: 0x%x", value); > + } > + } else { > + *need_reset = true; > + PMD_DRV_LOG(DEBUG, "Link reconfiguration required. Reset scheduled in 2000ms."); > + } > DEBUGOUT() and PMD_DRV_LOG(DEBUG, ...) can be unified in this function. ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH 13/18] net/txgbe: fix link stability for 40G NIC 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (11 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 12/18] net/txgbe: fix link stability for 25G NIC Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 14/18] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang ` (7 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 70 +- drivers/net/txgbe/base/txgbe_aml40.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 1391 ++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.c | 4 +- 4 files changed, 1375 insertions(+), 96 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index eefd7119fd..a9f5715e16 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -24,6 +25,7 @@ void txgbe_init_ops_aml40(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml40; + phy->setup_link_core = txgbe_setup_phy_link_aml40; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml40; @@ -52,6 +54,13 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if (link_up_wait_to_complete) { for (i = 0; i < hw->mac.max_link_up_time; i++) { + if (!hw->link_valid) { + *link_up = false; + + msleep(100); + continue; + } + if (!(links_reg & TXGBE_PORTSTAT_UP)) { *link_up = false; } else { @@ -68,6 +77,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } + if (!hw->link_valid) + *link_up = false; + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) @@ -107,20 +119,24 @@ u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) return txgbe_media_type_fiber_qsfp; } -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; + u32 value; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { - DEBUGOUT("SFP not detected, skip setup mac link"); - return 0; - } + *need_reset = false; + + if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ status = hw->mac.get_link_capabilities(hw, @@ -132,18 +148,43 @@ s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + break; + msleep(250); + } if (link_speed == speed && link_up) - return status; + goto out; - if (speed & TXGBE_LINK_SPEED_40GB_FULL) - speed = 0x20; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) + hw->link_valid = false; + + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + PMD_DRV_LOG(DEBUG, "MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + PMD_DRV_LOG(DEBUG, "MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + PMD_DRV_LOG(DEBUG, "Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -159,6 +200,5 @@ void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw) mac->flap_tx_laser = txgbe_flap_tx_laser_multispeed_fiber; - mac->setup_link = txgbe_setup_mac_link_aml40; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } diff --git a/drivers/net/txgbe/base/txgbe_aml40.h b/drivers/net/txgbe/base/txgbe_aml40.h index f31360c899..d97654fbf8 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.h +++ b/drivers/net/txgbe/base/txgbe_aml40.h @@ -14,7 +14,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw); -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw); #endif /* _TXGBE_AML40_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 352eb2e110..3dd3757c83 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -98,11 +98,29 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + pre1 = S25G_TX_FFE_CFG_DAC_PRE1; + pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + post = S25G_TX_FFE_CFG_DAC_POST; + } else { ffe_main = S25G_TX_FFE_CFG_MAIN; pre1 = S25G_TX_FFE_CFG_PRE1; pre2 = S25G_TX_FFE_CFG_PRE2; post = S25G_TX_FFE_CFG_POST; } + } else if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + ffe_main = S40G_TX_FFE_CFG_MAIN; + pre1 = S40G_TX_FFE_CFG_PRE1; + pre2 = S40G_TX_FFE_CFG_PRE2; + post = S40G_TX_FFE_CFG_POST; + } } if (hw->phy.ffe_set) { @@ -150,6 +168,408 @@ txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) return 0; } +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + int i; + + /* CMS Config Master */ + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + /* TXS Config Master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_TXS_TXS_CFG_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_40GB_FULL); + + /* RXS Config master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_RXS_RXS_CFG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS3_ANA_OVRDVAL_11_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS3_ANA_OVRDVAL_11 *)&rdata)->ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS0_ANA_OVRDEN_2 *)&rdata)->ovrd_en_ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + } + + /* PDIG Config master */ + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw) { @@ -1275,6 +1695,47 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) return status; } +static int txgbe_e56_set_rxs_ufine_le_max_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + int i = 0; + unsigned int CMVAR_UFINE_MAX = 0; + u32 addr; + + for (i = 0; i < 4; i++) { + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL ) { + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + } + + /* a. Assign software defined variables as below */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* Wait until 1milliseconds or greater */ + msleep(10); + } + } + return status; +} + static inline int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) { @@ -1299,7 +1760,7 @@ int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) ULTRAFINE_CODE = ULTRAFINE_CODE - 1; txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, ULTRAFINE_CODE); - /* Set ovrd_en=1 to overide ASIC value */ + /* Set ovrd_en=1 to override ASIC value */ txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i, 1); /* Wait until 1milliseconds or greater */ @@ -1309,6 +1770,39 @@ int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) return status; } +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane) +{ + int status = 0, i, N, median; + unsigned int rdata; + u32 addr; + int arraySize, RXS_BBCDR_SECOND_ORDER_ST[5]; + + /* Set ovrd_en=0 to read ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* As status update from RXS hardware is asynchronous to read status of SECOND_ORDER, follow sequence mentioned below. */ + N = 5; + for (i = 0; i < N; i = i + 1) { + /* set RXS_BBCDR_SECOND_ORDER_ST[i] = RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + arraySize = sizeof(RXS_BBCDR_SECOND_ORDER_ST) / sizeof(RXS_BBCDR_SECOND_ORDER_ST[0]); + qsort(RXS_BBCDR_SECOND_ORDER_ST, arraySize, sizeof(int), compare); + + median = ((N + 1) / 2 ) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) { int status = 0, i, N, median; @@ -1337,12 +1831,190 @@ int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) RXS_BBCDR_SECOND_ORDER_ST[0]); qsort(RXS_BBCDR_SECOND_ORDER_ST, arraySize, sizeof(int), compare); - median = ((N + 1) / 2) -1; + median = ((N + 1) / 2) - 1; *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; return status; } +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + int i; + u32 addr; + int temperature; + + for (i = 0; i < 4; i++){ + if(speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + DEBUGOUT("Error Speed\n"); + return 0; + } + + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; + + hw->temperature = temperature; + + /* Assign software defined variables as below */ + /* a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER */ + status |= txgbe_e56_rx_rd_second_code_40g(hw, &SECOND_CODE, i); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE + */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + /* Set ovrd_en=1 to override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature tracking occurs Error condition\n"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature tracking occurs Error condition\n"); + } + } + } + return status; +} + /* * 2.3.4 RXS post CDR lock temperature tracking sequence * @@ -1439,7 +2111,7 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, ULTRAFINE_CODE + 1); - /* Set ovrd_en=1 to overide ASIC value */ + /* Set ovrd_en=1 to override ASIC value */ EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); @@ -1451,7 +2123,7 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); /* * Note: All two of above code updates should be written in a single register write - * Set ovrd_en=1 to overide ASIC value + * Set ovrd_en=1 to override ASIC value */ EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; @@ -1466,7 +2138,7 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); /* * Note: All three of above code updates should be written in a single register write - * Set ovrd_en=1 to overide ASIC value + * Set ovrd_en=1 to override ASIC value */ EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; @@ -1510,78 +2182,391 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " "temperature tracking occurs Error condition"); } - } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_calib_adapt_seq_40G(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i, j; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypassCtle = true; + + for (i = 0; i < 4; i++) { + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + + if (bypassCtle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature tracking range + * here. RXS would be enabled at the end of this sequence. For the case when PAM4 KR training + * is not enabled (including PAM4 mode without KR training), wait until + * ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + for (i = 0; i < 4; i++) { + /* 4. Disable VGA and CTLE training so that they don't interfere with ADC calibration */ + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) & 1) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + + if (timer++ > PHYINIT_TIMEOUT) { + break; + } + } + + /* 6. Perform ADC offset adaptation and ADC gain adaptation, repeat them a few times and after that keep it disabled. */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) { + break; + } + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_adc_gain_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) { + break; + } + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ - return status; -} -static inline int -txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) -{ - unsigned int rdata; + /* 7. Perform ADC interleaver adaptation for 10ms or greater, and after that disable it */ + /* a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + /* 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking changes in temperature or voltage */ + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypassCtle == 0) { + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + } + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); - if (speed == TXGBE_LINK_SPEED_40GB_FULL) { - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + if (timer++ > PHYINIT_TIMEOUT) { + break; + } + } - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + if (bypassCtle == 0) { + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) { + break; + } + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypassCtle == 0) { + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + } + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); } - return 0; + return status; } static inline int @@ -1955,20 +2940,42 @@ txgbe_e56_cfg_temp(struct txgbe_hw *hw) return 0; } -static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +static int txgbe_e56_config_rx_40G(struct txgbe_hw *hw, u32 speed) { s32 status; - status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + status = txgbe_e56_rxs_calib_adapt_seq_40G(hw, speed); if (status) return status; /* Step 2 of 2.3.4 */ - txgbe_e56_set_rxs_ufine_le_max(hw, speed); + txgbe_e56_set_rxs_ufine_le_max_40g(hw, speed); /* 2.3.4 RXS post CDR lock temperature tracking sequence */ - txgbe_temp_track_seq(hw, speed); + txgbe_temp_track_seq_40g(hw, speed); + + hw->link_valid = true; + + return 0; +} + +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + txgbe_e56_config_rx_40G(hw, speed); + } else { + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + } return 0; } @@ -1977,6 +2984,151 @@ static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) * Use PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 to powerdown specific RXS lanes. * Completion of RXS powerdown can be confirmed by observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST */ +static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + int i; + + for (i = 0; i < 4; i++) { + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + rdata = 0x0000; + addr = E56G__RXS0_ANA_OVRDEN_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + addr = E56G__PMD_RXS0_OVRDEN_0_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_3_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_DIG_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 2. Disable pattern checker */ + addr = E56G__RXS0_DFT_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_DFT_1, ber_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 3. Disable internal serial loopback mode */ + addr = E56G__RXS0_ANA_OVRDEN_3_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* 4. Enable bypass of clock gates in RXS - */ + addr = E56G__RXS0_RXS_CFG_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en) = 0x1FFF; + wr32_ephy(hw, addr, rdata); + } + + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + addr = E56G__PMD_BASER_PMD_CONTROL_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln1) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln2) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln3) = 0; + wr32_ephy(hw, addr, rdata); + + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + addr = E56G__PMD_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en) = 0x0; + wr32_ephy(hw, addr, rdata); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != 0x21) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + static int txgbe_e56_disable_rx(struct txgbe_hw *hw) { int status = 0; @@ -2048,15 +3200,15 @@ static int txgbe_e56_disable_rx(struct txgbe_hw *hw) txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i, 0); txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i, 0); - //4. Enable bypass of clock gates in RXS */ + /* 4. Enable bypass of clock gates in RXS */ txgbe_e56_ephy_config(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en, 0x1FFF); - //5. Disable KR training mode */ - //a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ txgbe_e56_ephy_config(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0, 0); - //6. Disable RX to TX parallel loopback */ - //a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en, 0); /* @@ -2110,8 +3262,13 @@ int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST * and confirm its value is POWERDN_ST */ - txgbe_e56_disable_rx(hw); - status = txgbe_e56_config_rx(hw, speed); + if (hw->mac.type == txgbe_mac_aml40) { + txgbe_e56_disable_rx40G(hw); + status = txgbe_e56_config_rx_40G(hw, speed); + } else { + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + } addr = E56PHY_INTR_0_ADDR; wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); @@ -2178,6 +3335,86 @@ int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) set_fields_e56(&value, 12, 12, 0); wr32_epcs(hw, SR_AN_CTRL, value); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0x3); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0x4); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_40g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0xf); + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { value = rd32_epcs(hw, SR_PCS_CTRL1); set_fields_e56(&value, 5, 2, 5); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 622049890f..c9b45b0064 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2054,7 +2054,7 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); @@ -3200,7 +3200,7 @@ txgbe_dev_setup_link_thread_handler(void *param) struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) txgbe_dev_setup_link_alarm_handler_aml(hw); else txgbe_dev_setup_link_alarm_handler(dev); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 14/18] net/txgbe: fix link stability for Amber-Lite backplane mode 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (12 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 13/18] net/txgbe: fix link stability for 40G NIC Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 15/18] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang ` (6 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe.h | 2 + drivers/net/txgbe/base/txgbe_aml.c | 65 +- drivers/net/txgbe/base/txgbe_aml40.c | 43 +- drivers/net/txgbe/base/txgbe_e56.c | 28 +- drivers/net/txgbe/base/txgbe_e56.h | 2 + drivers/net/txgbe/base/txgbe_e56_bp.c | 2595 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_hw.c | 6 + drivers/net/txgbe/base/txgbe_hw.h | 4 +- drivers/net/txgbe/base/txgbe_osdep.h | 4 + drivers/net/txgbe/base/txgbe_phy.c | 21 + drivers/net/txgbe/base/txgbe_phy.h | 19 + drivers/net/txgbe/base/txgbe_type.h | 25 +- drivers/net/txgbe/txgbe_ethdev.c | 109 +- drivers/net/txgbe/txgbe_ethdev.h | 2 +- 15 files changed, 2893 insertions(+), 33 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index 305c0291e3..a9a02577ce 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -13,4 +13,5 @@ base_sources = files( 'txgbe_phy.c', 'txgbe_vf.c', 'txgbe_e56.c', + 'txgbe_e56_bp.c', ) diff --git a/drivers/net/txgbe/base/txgbe.h b/drivers/net/txgbe/base/txgbe.h index 673a299860..27c3e3be38 100644 --- a/drivers/net/txgbe/base/txgbe.h +++ b/drivers/net/txgbe/base/txgbe.h @@ -13,5 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_vf.h" #include "txgbe_dcb.h" +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" #endif /* _TXGBE_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index 208f999d78..7fab78f9a5 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -84,6 +85,13 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *speed = TXGBE_LINK_SPEED_UNKNOWN; } + if (txgbe_xpcs_an_enabled(hw)) { + if (!hw->an_done) { + *link_up = false; + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + } + return 0; } @@ -95,23 +103,41 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; + } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + hw->devarg.auto_neg = false; + *autoneg = false; + } else { + *autoneg = true; + } + *speed = hw->phy.fiber_suppport_speed; } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core0 || hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core1 || hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1) { + hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { *speed = TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; - } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { - *speed = TXGBE_LINK_SPEED_25GB_FULL; + } else if (hw->phy.media_type == txgbe_media_type_backplane) { + /* Backplane */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; + /* Backplane supports autonegotiation */ + *autoneg = hw->devarg.auto_neg; + } else if (hw->phy.media_type == txgbe_media_type_fiber) { + /* Fiber */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; } else { - /* SFP */ - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else - *speed = TXGBE_LINK_SPEED_10GB_FULL; - *autoneg = true; + /* Unknown */ + *speed = TXGBE_LINK_SPEED_UNKNOWN; + *autoneg = false; + PMD_DRV_LOG(DEBUG, "GET link capabilities failed"); + return TXGBE_ERR_LINK_SETUP; } return 0; @@ -193,7 +219,7 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) { DEBUGOUT("SFP not detected, skip setup mac link"); return 0; } @@ -216,6 +242,23 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return 0; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { DEBUGOUT("RX LOS"); diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index a9f5715e16..10411046b6 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -14,6 +14,7 @@ #include "txgbe_aml.h" #include "txgbe_aml40.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -98,7 +99,10 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = false; + *autoneg = true; + } else if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = true; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -115,8 +119,22 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) { - UNREFERENCED_PARAMETER(hw); - return txgbe_media_type_fiber_qsfp; + u8 device_type = hw->subsystem_device_id & 0xF0; + enum txgbe_media_type media_type; + + switch (device_type) { + case TXGBE_DEV_ID_KR_KX_KX4: + media_type = txgbe_media_type_backplane; + break; + case TXGBE_DEV_ID_SFP: + media_type = txgbe_media_type_fiber_qsfp; + break; + default: + media_type = txgbe_media_type_unknown; + break; + } + + return media_type; } s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, @@ -135,7 +153,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ @@ -148,6 +166,23 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return status; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 3dd3757c83..ce945bbcb4 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -49,7 +49,7 @@ int compare(const void *a, const void *b) } s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) + bool *link_up) { u32 rdata = 0; u32 links_reg = 0; @@ -97,7 +97,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; pre2 = S25G_TX_FFE_CFG_DAC_PRE2; @@ -115,7 +116,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; pre2 = S40G_TX_FFE_CFG_PRE2; @@ -1490,7 +1492,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1522,7 +1524,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) rdata = rd32_ephy(hw, addr); if (((rdata >> (i * 8)) & 0x3f) == 0x21) { break; } if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1593,7 +1595,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1639,7 +1641,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) rdata = rd32_ephy(hw, addr); if (((rdata >> (i * 8)) & 0x3f) == 0x21) { break; } if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1905,7 +1907,7 @@ int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; } else { - DEBUGOUT("Error Speed\n"); + DEBUGOUT("Error Speed"); return 0; } @@ -1968,7 +1970,7 @@ int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; wr32_ephy(hw, addr, rdata); } else { - DEBUGOUT("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature tracking occurs Error condition\n"); + DEBUGOUT("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature tracking occurs Error condition"); } } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { @@ -2008,7 +2010,7 @@ int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; wr32_ephy(hw, addr, rdata); } else { - DEBUGOUT("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature tracking occurs Error condition\n"); + DEBUGOUT("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature tracking occurs Error condition"); } } } @@ -2081,7 +2083,7 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; } else { - DEBUGOUT("Error Speed\n"); + DEBUGOUT("Error Speed"); return 0; } @@ -3121,7 +3123,7 @@ static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) rdata = rd32_ephy(hw, addr); usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } @@ -3227,7 +3229,7 @@ static int txgbe_e56_disable_rx(struct txgbe_hw *hw) break; usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index d9b3d70cf1..e18b9cfda0 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1742,6 +1742,8 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up); s32 txgbe_e56_fec_set(struct txgbe_hw *hw); s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c new file mode 100644 index 0000000000..9d9eefa73c --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -0,0 +1,2595 @@ +#include "txgbe_e56.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" +#include "txgbe_e56_bp.h" +#include "txgbe.h" +#include "../txgbe_logs.h" + +static int +txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + u32 rdata, addr; + u32 ULTRAFINE_CODE[4] = {0}; + int lane_num = 0, lane_idx = 0; + u32 CMVAR_UFINE_MAX = 0; + + switch (speed) { + case 10: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + case 40: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 4; + break; + case 25: + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* ii get rx ana_bbcdr_ultrafine_i[14, 12] per lane */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE[lane_idx] = FIELD_GET_M(GENMASK(14, 12), rdata); + BP_LOG("ULTRAFINE_CODE[%d] = %d, CMVAR_UFINE_MAX: %x\n", + lane_idx, ULTRAFINE_CODE[lane_idx], CMVAR_UFINE_MAX); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE[lane_idx] > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE[lane_idx] -= 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 12, ULTRAFINE_CODE[lane_idx]); + wr32_ephy(hw, addr, rdata); + + /* ovrd_en_ana_bbcdr_ultrafine=1 override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + wr32_ephy(hw, addr, rdata | BIT(3)); + + /* Wait until 1milliseconds or greater */ + usec_delay(1000); + } + } + return 0; +} + +static int txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, + u32 speed) +{ + int OFFSET_CENTRE_RANGE_H[4] = {0}, OFFSET_CENTRE_RANGE_L[4] = {}, RANGE_FINAL[4] = {}; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int status = 0, lane_num = 0; + int T = 40, lane_id = 0; + u32 addr, rdata; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + switch (speed) { + case 10: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 1; + break; + case 40: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 4; + break; + case 25: + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* 2. Define software variable RX_COARSE_MID_TD */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 1 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_H[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_H[lane_id] = OFFSET_CENTRE_RANGE_H[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_H[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_H[lane_id]; + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 2 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0xf); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 3 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_L[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_L[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_L[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_L[lane_id]; + } + for (lane_id = 0; lane_id < lane_num; lane_id++) { + RANGE_FINAL[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] < + OFFSET_CENTRE_RANGE_H[lane_id] ? + CMVAR_RANGE_L : CMVAR_RANGE_H; + BP_LOG("lane_id:%d-RANGE_L:%x-RANGE_H:%x-RANGE_FINAL:%x\n", + lane_id, OFFSET_CENTRE_RANGE_L[lane_id], + OFFSET_CENTRE_RANGE_H[lane_id], RANGE_FINAL[lane_id]); + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 4 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, RANGE_FINAL[lane_id]); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x0); + wr32_ephy(hw, addr, rdata); + } + + /* Do SEQ::RX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + + return status; +} + +static int txgbe_e56_rxs_post_cdr_lock_temp_track_seq(struct txgbe_hw *hw, + u32 speed) +{ + int status = 0; + u32 rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + + if (speed == 10) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == 25) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } + + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else + BP_LOG("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature tracking occurs Error condition\n"); + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else + BP_LOG("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature tracking occurs Error condition\n"); + } + + return status; +} + +static int txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u8 bplinkmode) +{ + u32 rdata; + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (bplinkmode == 40) { + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_adc_adapt_seq(struct txgbe_hw *hw, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + u32 rdata = 0, addr = 0; + int status = 0; + + int timer = 0, j = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait RXS0-3_OVRDVAL[1]::rxs0-3_rx0_cdr_rdy_o = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(12)), + 100, 2000, hw, 0x1544); + if (status) + BP_LOG("rxs%d_rx0_cdr_rdy_o = %x, %s.\n", + lane_idx, rdata, + status ? "FAILED" : "SUCCESS"); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + //4. Disable VGA and CTLE training so that they don't interfere with ADC calibration + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 14, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 9, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_intl_cal_done_o bit17 = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(17)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_intl_cal_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_ofst_adapt_done_o bit26 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, + !(rdata & BIT(26)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_ofst_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_gain_adapt_done_o bit29 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, !(rdata & BIT(29)), + 100, 2000, hw, addr); + if (status) + BP_LOG( + "rxs0_rx0_adc_gain_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* 7. Perform ADC interleaver adaptation for 10ms or greater, + * and after that disable it + */ + /* a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(20); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + /* set ovrd_en_rxs0_rx0_adc_intl_adapt_en_i=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0); + wr32_ephy(hw, addr, rdata); + + /* 8. Now re-enable VGA and CTLE trainings, so that it continues + * to adapt tracking changes in temperature or voltage + * <1>Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + */ + /* set rxs0_rx0_vga_train_en_i=1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x1); + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* <2>wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 */ + /* set ovrd_en_rxs0_rx0_vga_train_done_o = 0 */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0x0); + wr32_ephy(hw, addr, rdata); + + /* Wait rxs0_rx0_vga_train_done_o bit8 = 0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(8)), + 100, 3000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_vga_train_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + if (bypass_ctle == 0) { + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0); + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + wr32_ephy(hw, addr, rdata); + } + + return status; +} + +static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, + u8 bp_link_mode, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + int status = 0; + u32 rdata, addr; + + switch (bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + } + if (bypass_ctle != 0) + status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); + + status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + + /* Wait an fsm_rx_sts 25G */ + BP_LOG( + "Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); + + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x1b1b1b1b & GENMASK(8 * lane_num - 1, 0))), + 1000, 300, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("wait ctrl_fsm_rx0_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + return status; +} + +static int txgbe_e56_cms_cfg_for_temp_track_range(struct txgbe_hw *hw) +{ + int status = 0, T = 40; + u32 addr, rdata; + + status = txgbe_e56_get_temp(hw, &T); + if (T < 40) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + } else if (T > 70) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + } else { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_10_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + } + return status; +} + +static int txgbe_e56_bp_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_e56_bp_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 0x18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode) +{ + int status = 0; + u32 rdata = 0; + + u32 speed_select = 0; + u32 pcs_type_sel = 0; + u32 cns_en = 0; + u32 rsfec_en = 0; + u32 pma_type = 0; + u32 an0_rate_select = 0; + + switch (bp_link_mode) { + case 10: + bp_link_mode = 10; + speed_select = 0; /* 10 Gb/s */ + pcs_type_sel = 0; /* 10GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0xb; /* 10GBASE-KR PMA/PMD type */ + an0_rate_select = 2; /* 10G-KR */ + break; + case 40: + bp_link_mode = 40; + speed_select = 3; /* 40 Gb/s */ + pcs_type_sel = 4; /* 40GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0b0100001; /* 40GBASE-CR PMA/PMD type */ + an0_rate_select = 4; /* 40G-KR: 3 40G-CR: 4 */ + break; + case 25: + bp_link_mode = 25; + speed_select = 5; /* 25 Gb/s */ + pcs_type_sel = 7; /* 25GBASE-R PCS Type */ + cns_en = 1; /* CNS_EN */ + rsfec_en = 1; /* RS-FEC enable*/ + pma_type = 0b0111001; /* 25GBASE-KR PMA/PMD type */ + an0_rate_select = 9; /* 9/10/17 25GK/CR-S or 25GK/CR */ + break; + default: + BP_LOG("%s %d :Invalid bplinkmode\n", __func__, __LINE__); + break; + } + + hw->curbp_link_mode = bp_link_mode; + /* To switch to the 40G mode Ethernet operation, complete the following steps:*/ + /* 1. Initiate the vendor-specific software reset by programming + * the VR_RST field (bit [15]) of the VR_PCS_DIG_CTRL1 register to 1. + */ + rdata = rd32_epcs(hw, 0x038000); + wr32_epcs(hw, 0x038000, rdata | BIT(15)); + + /* 2. Wait for the hardware to clear the value for the VR_RST + * field (bit [15]) of the VR_PCS_DIG_CTRL1 register. + */ + BP_LOG("Wait for the bit [15] (VR_RST) to get cleared.\n"); + status = kr_read_poll(rd32_ephy, rdata, + FIELD_GET_M(BIT(15), rdata) == 0, 100, + 2000, hw, 0x038000); + BP_LOG("Wait PHY VR_RST = %x, Wait VR_RST %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* 3. Write 4'b0011 to bits [5:2] of the SR_PCS_CTRL1 register. + * 10G: 0 25G: 5 40G: 3 + */ + rdata = rd32_epcs(hw, 0x030000); + set_fields_e56(&rdata, 5, 2, speed_select); + wr32_epcs(hw, 0x030000, rdata); + + /* 4. Write pcs mode sel to bits [3:0] of the SR_PCS_CTRL2 register. + * 10G: 0 25G: 4'b0111 40G: 4'b0100 + */ + rdata = rd32_epcs(hw, 0x030007); + set_fields_e56(&rdata, 3, 0, pcs_type_sel); + wr32_epcs(hw, 0x030007, rdata); + + /* 0 1 1 1 0 0 1 : 25GBASE-KR or 25GBASE-KR-S PMA/PMD type + * 0 1 1 1 0 0 0 : 25GBASE-CR or 25GBASE-CR-S PMA/PMD type + * 0 1 0 0 0 0 1 : 40GBASE-CR4 PMA/PMD type + * 0 1 0 0 0 0 0 : 40GBASE-KR4 PMA/PMD type + * 0 0 0 1 0 1 1 : 10GBASE-KR PMA/PMD type + */ + rdata = rd32_epcs(hw, 0x010007); + set_fields_e56(&rdata, 6, 0, pma_type); + wr32_epcs(hw, 0x010007, rdata); + + /* 5. Write only 25g en to Bits [1:0] of VR_PCS_DIG_CTRL3 register. */ + rdata = rd32_epcs(hw, 0x38003); + set_fields_e56(&rdata, 1, 0, cns_en); + wr32_epcs(hw, 0x38003, rdata); + + /* 6. Program PCS_AM_CNT field of VR_PCS_AM_CNT register to 'd16383 to + * configure the alignment marker interval. To speed-up simulation, + * program a smaller value to this field. + */ + if (bp_link_mode == 40) + wr32_epcs(hw, 0x38018, 16383); + + /* 7. Program bit [2] of SR_PMA_RS_FEC_CTRL register to 0 + * if previously 1 (as RS-FEC is supported in 25G Mode). + */ + + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, rsfec_en); + wr32_epcs(hw, 0x100c8, rdata); + + /* 8. To enable BASE-R FEC (if desired), set bit [0]. + * in SR_PMA_KR_FEC_CTRL register + */ + + /* 3. temp applied */ + //status = E56phyCmsCfgForTempTrackRange(hw, bplinkmode); + + /* 4. set phy an status to 0 */ + //wr32_ephy(hw, 0x1640, 0x0000); + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, 0xe); // anstatus in single mode just set to 0xe + wr32_ephy(hw, 0x1434, rdata); + + /* 9. Program Enterprise 56G PHY regs through its own APB interface: + * a. Program PHY registers as mentioned in Table 6-6 on page 1197 to + * configure the PHY to 40G + * Mode. For fast-simulation mode, additionally program, + * the registers shown in the Table 6-7 on page 1199 + * b. Enable the PMD by setting pmd_en field in PMD_CFG[0] (0x1400) + * register + */ + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&rdata, 29, 29, 0x1); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&rdata, 30, 30, 0x1); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&rdata, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&rdata, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&rdata, 18, 8, 0x294); + set_fields_e56(&rdata, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&rdata, 30, 28, 0x7); + set_fields_e56(&rdata, 26, 24, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) + set_fields_e56(&rdata, 18, 16, 0x5); + else if (bp_link_mode == 25) + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 14, 12, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&rdata, 26, 24, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) { + set_fields_e56(&rdata, 18, 16, 0x5); + set_fields_e56(&rdata, 2, 0, 0x5); + } else if (bp_link_mode == 25) { + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 2, 0, 0x3); + } + wr32_ephy(hw, DATAPATH_CFG1, rdata); + + rdata = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&rdata, 4, 0, an0_rate_select); + wr32_ephy(hw, AN_CFG1, rdata); + + status = txgbe_e56_cms_cfg_for_temp_track_range(hw); + + if (bp_link_mode == 10) + txgbe_e56_bp_cfg_10g(hw); + else if (bp_link_mode == 25) + txgbe_e56_bp_cfg_25g(hw); + else if (bp_link_mode == 40) + txgbe_e56_cfg_40g(hw); + + return status; +} + +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + u8 bplinkmode, u32 need_restart) +{ + int status = 0; + u32 rdata; + + UNREFERENCED_PARAMETER(bplinkmode); + + hw->an_done = false; + if (hw->curbp_link_mode == 10 && !need_restart) + return 0; + BP_LOG("Setup to backplane mode ==========\n"); + + u32 backplane_mode = 0; + u32 fec_advertise = 0; + + hw->an_done = false; + /* pcs + phy rst */ + rdata = rd32(hw, 0x1000c); + if (hw->bus.lan_id == 1) + rdata |= BIT(16); + else + rdata |= BIT(19); + wr32(hw, 0x1000c, rdata); + msleep(20); + + /* clear interrupt */ + wr32_epcs(hw, 0x070000, 0); + wr32_epcs(hw, 0x030000, 0x8000); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + wr32_epcs(hw, 0x078002, 0x0000); + /* pcs case fec en to work around first */ + wr32_epcs(hw, 0x100ab, 1); + + if (txgbe_is_backplane(hw)) { + /* backplane 10G/25G/40G */ + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + /* default all speed */ + if ((hw->device_id & 0xFF) == 0x10) { + backplane_mode |= BIT(7); + fec_advertise |= TXGBE_10G_FEC_ABL; + } else if ((hw->device_id & 0xFF) == 0x25) { + backplane_mode |= BIT(14) | BIT(15); + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } else if ((hw->device_id & 0xFF) == 0x40) { + if (hw->phy.bp_capa == 0) + /* original configure: KR4 + CR4 */ + backplane_mode |= BIT(9) | BIT(8); + else if (hw->phy.bp_capa == 1) + /* only 40GBASE-KR4 */ + backplane_mode |= BIT(8); + else if (hw->phy.bp_capa == 2) + /* only 40GBASE-CR4 */ + backplane_mode |= BIT(9); + fec_advertise |= TXGBE_10G_FEC_ABL; + BP_LOG("Advertised abilities: %d\n", backplane_mode); + } + } else { + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) + == TXGBE_LINK_SPEED_10GB_FULL) { + backplane_mode |= 0x80; + fec_advertise |= TXGBE_10G_FEC_ABL; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) + == TXGBE_LINK_SPEED_25GB_FULL) { + backplane_mode |= 0xc000; + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) + == TXGBE_LINK_SPEED_40GB_FULL) { + backplane_mode |= BIT(9) | BIT(8); + fec_advertise |= TXGBE_10G_FEC_ABL; + } + } + + wr32_epcs(hw, 0x070010, 0x0001); + + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + wr32_epcs(hw, 0x070011, backplane_mode | 0x11); + + /* BASE-R FEC */ + rdata = rd32_epcs(hw, 0x70012); + wr32_epcs(hw, 0x70012, fec_advertise); + + wr32_epcs(hw, 0x070016, 0x0000); + wr32_epcs(hw, 0x070017, 0x0); + wr32_epcs(hw, 0x070018, 0x0); + + /* config timer */ + wr32_epcs(hw, 0x078004, 0x003c); + wr32_epcs(hw, 0x078005, CL74_KRTR_TRAINNING_TIMEOUT); + wr32_epcs(hw, 0x078006, 25); + wr32_epcs(hw, 0x078000, 0x0008 | BIT(2)); + + BP_LOG("1.2 Wait 10G KR phy/pcs mode init ....\n"); + status = txgbe_set_phy_link_mode(hw, 10); + BP_LOG("Wait 10g phy/pcs mode init = %x, %s.\n", rdata, + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status ? "FAILED" : "SUCCESS"); + + /* 5. CM_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, 0x3);//pll en + set_fields_e56(&rdata, 19, 12, 0x0);// tx disable + set_fields_e56(&rdata, 8, 8, 0x0);// pmd mode + set_fields_e56(&rdata, 1, 1, 0x1);// pmd en + wr32_ephy(hw, 0x1400, rdata); + + /* 6, TX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 12, 0x1);// tx en + wr32_ephy(hw, 0x1400, rdata); + + BP_LOG("1.3 Wait 10G PHY RXS....\n"); + status = txgbe_e56_rxs_osc_init_for_temp_track_range(hw, 10); + BP_LOG("Wait 10G PHY/RXS mode init = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* Wait an 10g fsm_rx_sts */ + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0x3f) == 0xb), 1000, + 200, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("Wait 10g fsm_rx_sts = %x, Wait rx_sts %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + BP_LOG("Setup the backplane mode========end ==\n"); + + return status; +} + +static void txgbe_e56_print_page_status(struct txgbe_hw *hw, + struct txgbe_backplane_ability *local_ability, + struct txgbe_backplane_ability *lp_ability) +{ + u32 rdata = 0; + + /* Read the local AN73 Base Page Ability Registers */ + BP_LOG("Read the local Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG1); + local_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70010 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG2); + BP_LOG("\tread 70011 data %0x\n", rdata); + local_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + /* amber-lite only support 10GKR - 25GKR/CR - 25GKR-S/CR-S */ + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + local_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + local_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + local_ability->fec_ability = rdata; + BP_LOG("\tread 70012 data %0x\n", rdata); + + /* Read the link partner AN73 Base Page Ability Registers */ + BP_LOG("Read the link partner Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL1); + lp_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70013 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL2); + lp_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + BP_LOG("\tread 70014 data %0x\n", rdata); + BP_LOG("\tKX : %x\tKX4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_1000BASE_KX) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_10GBASE_KX4) ? 1 : 0); + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + lp_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + lp_ability->fec_ability = rdata; + + hw->phy.fec_mode = 0; + if (rdata & TXGBE_25G_RS_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_RS_FEC_REQ; + if (rdata & TXGBE_25G_BASE_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_BASE_FEC_REQ; + if (rdata & TXGBE_10G_FEC_ABL) + hw->phy.fec_mode |= TXGBE_10G_FEC_ABL; + if (rdata & TXGBE_10G_FEC_REQ) + hw->phy.fec_mode |= TXGBE_10G_FEC_REQ; + BP_LOG("\tread 70015 data %0x\n", rdata); + + BP_LOG("\tread 70016 data %0x\n", rd32_epcs(hw, 0x70016)); + BP_LOG("\tread 70017 data %0x\n", rd32_epcs(hw, 0x70017)); + BP_LOG("\tread 70018 data %0x\n", rd32_epcs(hw, 0x70018)); + BP_LOG("\tread 70019 data %0x\n", rd32_epcs(hw, 0x70019)); + BP_LOG("\tread 7001a data %0x\n", rd32_epcs(hw, 0x7001a)); + BP_LOG("\tread 7001b data %0x\n", rd32_epcs(hw, 0x7001b)); +} + +static int chk_bkp_ability(struct txgbe_hw *hw, + struct txgbe_backplane_ability local_ability, + struct txgbe_backplane_ability lp_ability) +{ + unsigned int comLinkAbility; + + BP_LOG("CheckBkpAn73Ability():\n"); + /* Check the common link ability and take action based on the result*/ + comLinkAbility = local_ability.link_ability & + lp_ability.link_ability; + BP_LOG("comAbility= 0x%x, Ability= 0x%x, lpAbility= 0x%x\n", + comLinkAbility, local_ability.link_ability, + lp_ability.link_ability); + + if (comLinkAbility == 0) { + hw->bp_link_mode = 0; + BP_LOG("Do not support any compatible speed mode!\n"); + return -EINVAL; + } else if (comLinkAbility & BIT(ABILITY_40GBASE_KR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_KR4].\n"); + hw->bp_link_mode = 40; + } else if (comLinkAbility & BIT(ABILITY_40GBASE_CR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_CR4].\n"); + hw->bp_link_mode = 40; + } else if (comLinkAbility & BIT(ABILITY_25GBASE_KRCR_S)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR_S].\n"); + hw->fec_mode = TXGBE_25G_RS_FEC_REQ; + hw->bp_link_mode = 25; + } else if (comLinkAbility & BIT(ABILITY_25GBASE_KRCR)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR].\n"); + hw->bp_link_mode = 25; + } else if (comLinkAbility & BIT(ABILITY_10GBASE_KR)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KR].\n"); + hw->bp_link_mode = 10; + } else if (comLinkAbility & BIT(ABILITY_10GBASE_KX4)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KX4].\n"); + hw->bp_link_mode = 10; + } else if (comLinkAbility & BIT(ABILITY_1000BASE_KX)) { + BP_LOG("Link mode is [ABILITY_1000BASE_KX].\n"); + hw->bp_link_mode = 1; + } else { + BP_LOG("No compatible link mode found!\n"); + return -EINVAL; + } + + return 0; +} + +static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +{ + struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; + u32 an_int, base_page = 0; + int count = 0; + + an_int = rd32_epcs(hw, 0x78002); + /* 500ms timeout */ + if (!(an_int & VR_AN_INTR_PG_RCV)) + return -EINVAL; + + for (count = 0; count < 500; count++) { + u32 fsm = rd32_epcs(hw, 0x78010); + u32 rdata = rd32_epcs(hw, 0x78002); + + BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + an_int = rdata; + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + if (an_int & VR_AN_INTR_PG_RCV) { + u32 addr; + + txgbe_e56_print_page_status(hw, &local_ability, &lp_ability); + addr = base_page == 0 ? 0x70013 : 0x70019; + rdata = rd32_epcs(hw, addr); + if (rdata & BIT(14)) { + if (rdata & BIT(15)) { + /* always set null message */ + wr32_epcs(hw, 0x70016, 0x2001); + BP_LOG("write 70016 0x%0x\n", + 0x2001); + } + base_page = 1; + } + } + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } + usec_delay(100); + } + +check_ability: + return chk_bkp_ability(hw, local_ability, lp_ability); +} + +static int txgbe_e56_cl72_trainning(struct txgbe_hw *hw) +{ + u32 bylinkmode = hw->bp_link_mode; + u8 bypass_ctle = hw->bypass_ctle; + int status = 0, pTempData = 0; + u32 lane_num = 0, lane_idx = 0; + u32 __rte_unused pmd_ctrl = 0, txffe = 0; + int ret = 0; + u32 rdata; + + u8 pll_en_cfg = 0; + u8 pmd_mode = 0; + + switch (bylinkmode) { + case 10: + bylinkmode = 10; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + case 40: + bylinkmode = 40; + lane_num = 4; + pll_en_cfg = 0; /* pll_en_cfg : single link to 0 */ + pmd_mode = 1; /* pmd mode : 1 - single link */ + break; + case 25: + bylinkmode = 25; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); + status = txgbe_set_phy_link_mode(hw, bylinkmode); + + /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1434, rdata); + + /* 14 and 15. kr training: set BASER_PMD_CONTROL[0, 7] for lane0-4 */ + rdata = rd32_ephy(hw, 0x1640); + set_fields_e56(&rdata, 7, 0, GENMASK(2 * lane_num - 1, 0)); + wr32_ephy(hw, 0x1640, rdata); + + /* 16. enable CMS and its internal PLL */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, pll_en_cfg); + set_fields_e56(&rdata, 19, 12, 0); /* tx/rx off */ + set_fields_e56(&rdata, 8, 8, pmd_mode); + set_fields_e56(&rdata, 1, 1, 0x1); /* pmd en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 17. tx enable PMD_CFG[0] */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 15, 12, GENMASK(lane_num - 1, 0)); /* tx en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 18 */ + /* 19. rxs calibration and adaotation sequeence */ + BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); + ret |= status; + /* 20 */ + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + status = txgbe_e56_get_temp(hw, &pTempData); + if (bylinkmode == 40) + status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); + else + status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + /* 21 */ + BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0xe) & GENMASK(lane_num, 1)) == + (0xe & GENMASK(lane_num, 1)), 100, + 10000, hw, 0x163c); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, status ? "FAILED" : "SUCCESS", + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + ret |= status; + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } + + /* 22 */ + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + + return ret; +} + +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw) +{ + int status = 0; + u32 rdata; + + BP_LOG("2.1 Wait page changed ....\n"); + status = txgbe_e56_exchange_page(hw); + if (status) { + BP_LOG("Exchange page failed\n"); + return status; + } + + BP_LOG("2.2 Wait page changed ..done..\n"); + wr32_epcs(hw, 0x100ab, 0); + if (AN_TRAINNING_MODE) { + rdata = rd32_epcs(hw, 0x70000); + BP_LOG("read 0x70000 data %0x\n", rdata); + wr32_epcs(hw, 0x70000, 0); + BP_LOG("write 0x70000 0x%0x\n", 0); + } + + rdata = rd32_epcs(hw, 0x78002); + BP_LOG("read 78002 data %0x and clear page int\n", rdata); + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + + /* dis phy tx/rx lane */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, 0x1400, rdata); + BP_LOG("Ephy Write A: 0x%x, D: 0x%x\n", 0x1400, rdata); + + /* wait rx/tx/cm powerdn_st */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + if (hw->phy.fec_mode & TXGBE_25G_RS_FEC_REQ) { + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, 1); + wr32_epcs(hw, 0x100c8, rdata); + BP_LOG("Advertised FEC modes : %s\n", "RS-FEC"); + hw->cur_fec_link = TXGBE_PHY_FEC_RS; + } else if (hw->phy.fec_mode & TXGBE_25G_BASE_FEC_REQ) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "25GBASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else if (hw->fec_mode & (TXGBE_10G_FEC_REQ)) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "BASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else { + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "NONE"); + hw->cur_fec_link = TXGBE_PHY_FEC_OFF; + } + + status = txgbe_e56_cl72_trainning(hw); + + rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, rdata); + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + return status; +} diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 3b683eaa04..1a297acaa6 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4069,6 +4069,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } +bool txgbe_is_backplane(struct txgbe_hw *hw) +{ + return hw->phy.get_media_type(hw) == txgbe_media_type_backplane ? + true : false; +} + bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index bc34d639eb..b44190bc34 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -118,6 +118,6 @@ s32 txgbe_reinit_fdir_tables(struct txgbe_hw *hw); bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw); s32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr); s32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr, u32 *data); -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up); +bool txgbe_is_backplane(struct txgbe_hw *hw); +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask); #endif /* _TXGBE_HW_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index 91ad36f4d4..ab9982d13d 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -154,6 +154,10 @@ static inline u64 REVERT_BIT_MASK64(u64 mask) ((mask & 0xFFFFFFFF00000000) >> 32); } +#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) +#define GENMASK(h, l) \ + (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + #define IOMEM #define BIT(nr) (1UL << (nr)) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index bf7260a295..f3e3491b30 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -2503,6 +2503,27 @@ void txgbe_set_phy_temp(struct txgbe_hw *hw) } } +int txgbe_is_dac_cable(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) + return true; + + return false; +} + +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) +{ + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) + return false; + + return hw->devarg.auto_neg ? true : false; +} + /** * txgbe_kr_handle - Handle the interrupt of auto-negotiation * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index c02be3cc34..71e97b1217 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -105,6 +105,8 @@ #define VR_AN_INTR_CMPLT MS16(0, 0x1) #define VR_AN_INTR_LINK MS16(1, 0x1) #define VR_AN_INTR_PG_RCV MS16(2, 0x1) +#define TXGBE_E56_AN_TXDIS MS16(3, 0x1) +#define TXGBE_E56_AN_PG_RCV MS16(4, 0x1) #define VR_AN_KR_MODE_CL 0x078003 #define VR_AN_KR_MODE_CL_PDET MS16(0, 0x1) #define VR_XS_OR_PCS_MMD_DIGI_CTL1 0x038000 @@ -428,6 +430,21 @@ #define TXGBE_BP_M_NAUTO 0 #define TXGBE_BP_M_AUTO 1 +#define kr_read_poll(op, val, cond, sleep_us, \ + times, args...) \ +({ \ + unsigned long __sleep_us = (sleep_us); \ + u32 __times = (times); \ + u32 i; \ + for (i = 0; i < __times; i++) { \ + (val) = op(args); \ + if (cond) \ + break; \ + usleep(__sleep_us);\ + } \ + (cond) ? 0 : -1; \ +}) + #ifndef CL72_KRTR_PRBS_MODE_EN #define CL72_KRTR_PRBS_MODE_EN 0xFFFF /* open kr prbs check */ #endif @@ -490,6 +507,8 @@ void txgbe_autoc_write(struct txgbe_hw *hw, u64 value); void txgbe_bp_mode_set(struct txgbe_hw *hw); void txgbe_set_phy_temp(struct txgbe_hw *hw); void txgbe_bp_down_event(struct txgbe_hw *hw); +int txgbe_is_dac_cable(struct txgbe_hw *hw); +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw); s32 txgbe_kr_handle(struct txgbe_hw *hw); #endif /* _TXGBE_PHY_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 421abc1145..aa882e87b8 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -719,6 +719,7 @@ struct txgbe_phy_info { u32 addr; u32 id; enum txgbe_sfp_type sfp_type; + u32 fiber_suppport_speed; bool sfp_setup_needed; u32 revision; u32 media_type; @@ -740,6 +741,7 @@ struct txgbe_phy_info { u16 ffe_pre2; u16 ffe_post; u16 fec_mode; + u16 bp_capa; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -895,7 +897,28 @@ struct txgbe_hw { u32 cur_fec_link; int temperature; u32 bp_link_mode; -}; + bool dac_sfp; + bool bypass_ctle; + u32 curbp_link_mode; + bool an_done; + u32 fsm; + u64 bp_event_interval; +}; + +typedef enum { + ABILITY_1000BASE_KX, + ABILITY_10GBASE_KX4, + ABILITY_10GBASE_KR, + ABILITY_40GBASE_KR4, + ABILITY_40GBASE_CR4, + ABILITY_100GBASE_CR10, + ABILITY_100GBASE_KP4, + ABILITY_100GBASE_KR4, + ABILITY_100GBASE_CR4, + ABILITY_25GBASE_KRCR_S, + ABILITY_25GBASE_KRCR, + ABILITY_MAX, +} ability_filed_encding; struct txgbe_backplane_ability { u32 next_page; /* Next Page (bit0) */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index c9b45b0064..c28afbe7aa 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2010,6 +2010,10 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_l2_tunnel_conf(dev); txgbe_filter_restore(dev); + hw->bp_event_interval = 100 * 1000; + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); + if (tm_conf->root && !tm_conf->committed) PMD_DRV_LOG(WARNING, "please call hierarchy_commit() " @@ -2054,8 +2058,10 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + } rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); @@ -2920,6 +2926,107 @@ txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) return NULL; } +void txgbe_dev_e56_check_bp_event(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + u32 an_int1 = 0, value = 0, fsm = 0; + u32 __rte_unused an_int = 0; + int ret = 0; + bool need_link_update = false; + + if (!hw) + return; + + if (!(txgbe_xpcs_an_enabled(hw))) + return; + + if (!hw->devarg.auto_neg) + return; + + /* only continue if link is down */ + if (dev->data->dev_link.link_status) + goto out; + + value = rd32_epcs(hw, VR_AN_INTR); + an_int = value; + if (value & 0xF) + hw->bp_event_interval = 100 * 1000; + + if (value & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + value &= ~VR_AN_INTR_CMPLT; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & VR_AN_INTR_LINK) { + value &= ~VR_AN_INTR_LINK; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & TXGBE_E56_AN_TXDIS) { + value &= ~TXGBE_E56_AN_TXDIS; + wr32_epcs(hw, VR_AN_INTR, value); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + goto an_status; + } + + if (value & VR_AN_INTR_PG_RCV) { + BP_LOG("%d Enter training\n", hw->port_id); + ret = handle_e56_bkp_an73_flow(hw); + if (!AN_TRAINNING_MODE) { + fsm = rd32_epcs(hw, 0x78010); + if (fsm & 0x8) + goto an_status; + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + BP_LOG("ALL SUCCEEDED\n"); + } + } else { + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + hw->an_done = true; + } + } + } + +an_status: + an_int1 = rd32_epcs(hw, 0x78002); + if (an_int1 & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + } + + BP_LOG("%d RLU:%x MLU:%x INT:%x-%x CTL:%x fsm:%x pmd_cfg0:%x an_done:%d\n", + hw->port_id, rd32_epcs(hw, 0x30001), rd32(hw, 0x14404), + an_int, an_int1, + rd32_epcs(hw, 0x70000), + rd32_epcs(hw, 0x78010), + rd32_ephy(hw, 0x1400), + hw->an_done); + + if (need_link_update) + txgbe_dev_link_update(dev, 0); + + if (dev->data->dev_link.link_status) + hw->bp_event_interval = 2000 * 1000; + +out: + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); +} + static void txgbe_dev_detect_sfp(void *param) { diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 1ec8e096cc..309db3bfe9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -747,5 +747,5 @@ void txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on); void txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, int mask); - +void txgbe_dev_e56_check_bp_event(void *param); #endif /* _TXGBE_ETHDEV_H_ */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 15/18] net/txgbe: fix FEC mode configuration on 25G NIC 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (13 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 14/18] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 16/18] net/txgbe: fix SFP module identification Zaiyu Wang ` (5 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The 25G NIC offers off, RS, Base-R, and auto FEC modes. When reconfiguring the PHY, the FEC mode must match on both sides; otherwise, the link cannot come up. The current driver fails to maintain this requirement, causing link instability. Add proper FEC mode handling during PHY reconfiguration to guarantee link establishment. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index 7fab78f9a5..6eb63a8f06 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -282,6 +282,14 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, !(hw->fec_mode & hw->cur_fec_link))) goto out; + if (speed == TXGBE_LINK_SPEED_25GB_FULL && + link_speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + + if (link_up) + goto out; + } + rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); rte_spinlock_unlock(&hw->phy_lock); @@ -360,7 +368,10 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* If we already have link at this speed, just jump out */ txgbe_e56_check_phy_link(hw, &link_speed, &link_up); - if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up) + hw->cur_fec_link = txgbe_phy_fec_get(hw); + + if ((link_speed == TXGBE_LINK_SPEED_25GB_FULL) && link_up && + hw->fec_mode & hw->cur_fec_link) goto out; /* Allow module to change analog characteristics (10G -> 25G) */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 16/18] net/txgbe: fix SFP module identification 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (14 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 15/18] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 17/18] net/txgbe: fix get module info operation Zaiyu Wang ` (4 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Some optical modules were not correctly recognized due to ambiguous classification in the original detection flow. Rework the module identification logic to cover all module types. Also narrow the I2C lock scope to avoid potential race conditions during module access. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 2 - drivers/net/txgbe/base/txgbe_phy.c | 339 ++++++++++------------------ drivers/net/txgbe/base/txgbe_phy.h | 18 +- drivers/net/txgbe/base/txgbe_type.h | 2 + 4 files changed, 132 insertions(+), 229 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 1a297acaa6..a57f7ea097 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -2907,8 +2907,6 @@ s32 txgbe_init_ops_generic(struct txgbe_hw *hw) phy->read_i2c_eeprom = txgbe_read_i2c_eeprom; phy->write_i2c_eeprom = txgbe_write_i2c_eeprom; phy->identify_sfp = txgbe_identify_module; - phy->read_i2c_byte_unlocked = txgbe_read_i2c_byte_unlocked; - phy->write_i2c_byte_unlocked = txgbe_write_i2c_byte_unlocked; phy->check_overtemp = txgbe_check_overtemp; phy->reset = txgbe_reset_phy; phy->set_link_hostif = txgbe_hic_ephy_set_link; diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index f3e3491b30..e46a5d7957 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -830,6 +830,10 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) return TXGBE_ERR_SFP_NOT_PRESENT; } + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, &identifier); if (err != 0) { @@ -839,11 +843,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.id = 0; hw->phy.type = txgbe_phy_unknown; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_PRESENT; } if (identifier != TXGBE_SFF_IDENTIFIER_SFP) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -888,7 +894,42 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) * 11 SFP_1g_sx_CORE0 - chip-specific * 12 SFP_1g_sx_CORE1 - chip-specific */ - if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; + else + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->dac_sfp = true; + } + + if (comp_copper_len == TXGBE_SFF_COPPER_1M) + hw->bypass_ctle = true; + else + hw->bypass_ctle = false; + + if (comp_codes_25g == TXGBE_SFF_25GBASECR_91FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_74FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_NOFEC) { + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_25GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + } else { + hw->phy.fiber_suppport_speed |= + TXGBE_LINK_SPEED_10GB_FULL; + } + } else if (comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_12 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_12) { + hw->dac_sfp = false; + hw->phy.sfp_type = (hw->bus.lan_id == 0 + ? txgbe_sfp_type_25g_aoc_core0 + : txgbe_sfp_type_25g_aoc_core1); + } else if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + hw->dac_sfp = false; err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_CABLE_SPEC_COMP, &cable_spec); if (err != 0) @@ -1005,6 +1046,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) /* Allow any DA cable vendor */ if (cable_tech & (TXGBE_SFF_CABLE_DA_PASSIVE | TXGBE_SFF_CABLE_DA_ACTIVE)) { + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; } @@ -1017,6 +1059,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -1031,9 +1074,11 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { DEBUGOUT("SFP+ module not supported"); hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; } @@ -1046,28 +1091,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) { s32 err = TXGBE_ERR_PHY_ADDR_INVALID; - u32 vendor_oui = 0; - enum txgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; - u8 identifier = 0; - u8 comp_codes_1g = 0; - u8 comp_codes_10g = 0; - u8 oui_bytes[3] = {0, 0, 0}; - u16 enforce_sfp = 0; - u8 connector = 0; - u8 cable_length = 0; - u8 device_tech = 0; - bool active_cable = false; + u8 identifier = 0, transceiver_type = 0; u32 value; - if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { - hw->phy.sfp_type = txgbe_sfp_type_not_present; - err = TXGBE_ERR_SFP_NOT_PRESENT; - goto out; - } + /* config GPIO before read i2c */ + wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); if (hw->mac.type == txgbe_mac_aml40) { - /* config GPIO before read i2c */ - wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { hw->phy.sfp_type = txgbe_sfp_type_not_present; @@ -1075,175 +1105,68 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) } } - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, - &identifier); -ERR_I2C: - if (err != 0) { + if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { hw->phy.sfp_type = txgbe_sfp_type_not_present; - hw->phy.id = 0; - hw->phy.type = txgbe_phy_unknown; return TXGBE_ERR_SFP_NOT_PRESENT; } - if (identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; - } - hw->phy.id = identifier; + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_10GBE_COMP, - &comp_codes_10g); + err = hw->phy.read_i2c_sff8636(hw, 0, TXGBE_SFF_IDENTIFIER, + &identifier); if (err != 0) - goto ERR_I2C; + goto err_read_i2c_eeprom; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_1GBE_COMP, - &comp_codes_1g); - - if (err != 0) - goto ERR_I2C; + if (identifier != TXGBE_SFF_IDENTIFIER_QSFP && + identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { + PMD_INIT_LOG(ERR, "port[%d] QSFP module not supported, identifier = 0x%x", + hw->bus.lan_id, identifier); + hw->phy.type = txgbe_phy_sfp_unsupported; + err = TXGBE_ERR_SFP_NOT_SUPPORTED; + } else { + err = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_ETHERNET_COMP_OFFSET, + &transceiver_type); + if (err != 0) + goto err_read_i2c_eeprom; - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_PASSIVE_CABLE) { - hw->phy.type = txgbe_phy_qsfp_unknown_passive; - if (hw->mac.type == txgbe_mac_aml40) { + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core0; else hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core1; - } else { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; - } - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_SR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_LR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; - } else if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_srlr_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_srlr_core1; - } else { - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_ACTIVE_CABLE) - active_cable = true; - - if (!active_cable) { - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CONNECTOR, - &connector); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CABLE_LENGTH, - &cable_length); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_DEVICE_TECH, - &device_tech); - - if (connector == - TXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE && - cable_length > 0 && - ((device_tech >> 4) == - TXGBE_SFF_QSFP_TRANSMITTER_850NM_VCSEL)) - active_cable = true; + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } - if (active_cable) { - hw->phy.type = txgbe_phy_qsfp_unknown_active; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_SR4) { if (hw->bus.lan_id == 0) - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core0; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; else - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core1; - } else { - /* unsupported module type */ - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; } - } - - if (hw->phy.sfp_type != stored_sfp_type) - hw->phy.sfp_setup_needed = true; - - /* Determine if the QSFP+ PHY is dual speed or not. */ - hw->phy.multispeed_fiber = false; - if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) || - ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE))) - hw->phy.multispeed_fiber = true; - - /* Determine PHY vendor for optical modules */ - if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0, - &oui_bytes[0]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1, - &oui_bytes[1]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE2, - &oui_bytes[2]); - if (err != 0) - goto ERR_I2C; - - vendor_oui = - ((oui_bytes[0] << 24) | - (oui_bytes[1] << 16) | - (oui_bytes[2] << 8)); - - if (vendor_oui == TXGBE_SFF_VENDOR_OUI_INTEL) - hw->phy.type = txgbe_phy_qsfp_intel; - else - hw->phy.type = txgbe_phy_qsfp_unknown; - - hw->mac.get_device_caps(hw, &enforce_sfp); - if (!(enforce_sfp & TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) { - /* Make sure we're a supported PHY type */ - if (hw->phy.type == txgbe_phy_qsfp_intel) { - err = 0; - } else { - if (hw->allow_unsupported_sfp) { - DEBUGOUT("WARNING: Wangxun (R) Network Connections are quality tested using Wangxun (R) Ethernet Optics. " - "Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. " - "Wangxun Corporation is not responsible for any harm caused by using untested modules."); - err = 0; - } else { - DEBUGOUT("QSFP module not supported"); - hw->phy.type = - txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - } - } - } else { - err = 0; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_LR4) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } } -out: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; + +err_read_i2c_eeprom: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + hw->phy.id = 0; + hw->phy.type = txgbe_phy_unknown; + return TXGBE_ERR_SFP_NOT_PRESENT; } /** @@ -1278,6 +1201,26 @@ s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, sff8472_data); } +/** + * txgbe_read_i2c_sff8636 - Reads 8 bit word over I2C interface + * @hw: pointer to hardware structure + * @byte_offset: byte offset at address 0xA2 + * @eeprom_data: value read + * + * Performs byte read operation to SFP module's SFF-8472 data over I2C + **/ +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data) +{ + hw->phy.write_i2c_byte(hw, TXGBE_SFF_QSFP_PAGE_SELECT, + TXGBE_I2C_EEPROM_DEV_ADDR, + page); + + return hw->phy.read_i2c_byte(hw, byte_offset, + TXGBE_I2C_EEPROM_DEV_ADDR, + sff8636_data); +} + /** * txgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure @@ -1295,7 +1238,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte_unlocked - Reads 8 bit word over I2C + * txgbe_read_i2c_byte - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: address to read from @@ -1304,7 +1247,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, +s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { txgbe_i2c_start(hw, dev_addr); @@ -1334,30 +1277,7 @@ s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte - Reads 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to read - * @dev_addr: address to read from - * @data: value read - * - * Performs byte read operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_read_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - return err; -} - -/** - * txgbe_write_i2c_byte_unlocked - Writes 8 bit word over I2C + * txgbe_write_i2c_byte - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: address to write to @@ -1366,54 +1286,29 @@ s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) +s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data) { txgbe_i2c_start(hw, dev_addr); /* wait tx empty */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY, - TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) { + TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) return -TERR_TIMEOUT; - } - wr32(hw, TXGBE_I2CDATA, byte_offset | TXGBE_I2CDATA_STOP); + wr32(hw, TXGBE_I2CDATA, byte_offset); wr32(hw, TXGBE_I2CDATA, data | TXGBE_I2CDATA_WRITE); /* wait for write complete */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_RXFULL, - TXGBE_I2CICR_RXFULL, NULL, 100, 100)) { + TXGBE_I2CICR_RXFULL, NULL, 100, 100)) return -TERR_TIMEOUT; - } + txgbe_i2c_stop(hw); return 0; } -/** - * txgbe_write_i2c_byte - Writes 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to write - * @dev_addr: address to write to - * @data: value to write - * - * Performs byte write operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_write_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - - return err; -} - /** * txgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 71e97b1217..796a0f6748 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -261,7 +261,9 @@ #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0 0xA5 #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1 0xA6 @@ -289,6 +291,9 @@ #define TXGBE_SFF_4x10GBASESR_CAP 0x11 #define TXGBE_SFF_40GBASEPSM4_PARALLEL 0x12 #define TXGBE_SFF_40GBASE_SWMD4_CAP 0x1f +#define TXGBE_SFF_COPPER_5M 0x5 +#define TXGBE_SFF_COPPER_3M 0x3 +#define TXGBE_SFF_COPPER_1M 0x1 #define TXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 #define TXGBE_SFF_25GAUI_C2M_AOC_BER_5 0x1 @@ -296,6 +301,11 @@ #define TXGBE_SFF_25GAUI_C2M_AOC_BER_12 0x18 #define TXGBE_SFF_25GAUI_C2M_ACC_BER_12 0x19 +#define TXGBE_ETHERNET_COMP_OFFSET 0x83 +#define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) +#define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) +#define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) + #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_1G 0x0 @@ -490,14 +500,12 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw); s32 txgbe_check_overtemp(struct txgbe_hw *hw); s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data); s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data); s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, - u8 *sff8472_data); + u8 *sff8472_data); +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page ,u8 byte_offset, + u8 *sff8636_data); s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index aa882e87b8..051609bbfe 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -702,6 +702,8 @@ struct txgbe_phy_info { u8 dev_addr, u8 data); s32 (*read_i2c_sff8472)(struct txgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); + s32 (*read_i2c_sff8636)(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data); s32 (*read_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 (*write_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 17/18] net/txgbe: fix get module info operation 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (15 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 16/18] net/txgbe: fix SFP module identification Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-23 3:40 ` [PATCH 18/18] net/txgbe: fix get eeprom operation Zaiyu Wang ` (3 subsequent siblings) 20 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.h | 6 +- drivers/net/txgbe/txgbe_ethdev.c | 116 ++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 796a0f6748..fe6c0dd170 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -257,11 +257,15 @@ #define TXGBE_SFF_CABLE_DA_PASSIVE 0x4 #define TXGBE_SFF_CABLE_DA_ACTIVE 0x8 #define TXGBE_SFF_CABLE_SPEC_COMP 0x3C +#define TXGBE_SFF_DDM_IMPLEMENTED 0x40 #define TXGBE_SFF_SFF_8472_SWAP 0x5C #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 -#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_SFF_REVISION_ADDR 0x01 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F + +#define TXGBE_MODULE_QSFP_MAX_LEN 640 #define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index c28afbe7aa..41ec432983 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5342,41 +5342,105 @@ txgbe_get_module_info(struct rte_eth_dev *dev, struct txgbe_hw *hw = TXGBE_DEV_HW(dev); uint32_t status; uint8_t sff8472_rev, addr_mode; + u8 identifier = 0; + u8 sff8636_rev = 0; bool page_swap = false; + u32 value; - /* Check whether we support SFF-8472 or not */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_COMP, - &sff8472_rev); - if (status != 0) - return -EIO; - - /* addressing mode is not supported */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_SWAP, - &addr_mode); - if (status != 0) - return -EIO; + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } - if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { - PMD_DRV_LOG(ERR, - "Address change required to access page 0xA2, " - "but not supported. Please report the module " - "type to the driver maintainers."); - page_swap = true; + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; } - if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap) { - /* We have a SFP, but it does not support SFF-8472 */ - modinfo->type = RTE_ETH_MODULE_SFF_8079; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; + + if (hw->mac.type == txgbe_mac_aml40) { + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_IDENTIFIER, + &identifier); } else { - /* We have a SFP which supports a revision of SFF-8472. */ - modinfo->type = RTE_ETH_MODULE_SFF_8472; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); } + if (status != 0) + goto ERROR_IO; + + switch (identifier) { + case TXGBE_SFF_IDENTIFIER_SFP: + /* Check whether we support SFF-8472 or not */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_COMP, + &sff8472_rev); + if (status != 0) + goto ERROR_IO; + + /* addressing mode is not supported */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_SWAP, + &addr_mode); + if (status != 0) + goto ERROR_IO; + + if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { + PMD_DRV_LOG(ERR, + "Address change required to access page 0xA2, " + "but not supported. Please report the module " + "type to the driver maintainers."); + page_swap = true; + } + + if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap || + !(addr_mode & TXGBE_SFF_DDM_IMPLEMENTED)) { + /* We have a SFP, but it does not support SFF-8472 */ + modinfo->type = RTE_ETH_MODULE_SFF_8079; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + } else { + /* We have a SFP which supports a revision of SFF-8472. */ + modinfo->type = RTE_ETH_MODULE_SFF_8472; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + } + break; + case TXGBE_SFF_IDENTIFIER_QSFP: + case TXGBE_SFF_IDENTIFIER_QSFP_PLUS: + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_SFF_REVISION_ADDR, + &sff8636_rev); + if (status != 0) + goto ERROR_IO; + /* Check revision compliance */ + if (sff8636_rev > 0x02) { + /* Module is SFF-8636 compliant */ + modinfo->type = RTE_ETH_MODULE_SFF_8636; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } else { + modinfo->type = RTE_ETH_MODULE_SFF_8436; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } + break; + default: + PMD_DRV_LOG(ERR, "SFF Module Type not recognized."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EINVAL; + } + + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } static int -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH 18/18] net/txgbe: fix get eeprom operation 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (16 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 17/18] net/txgbe: fix get module info operation Zaiyu Wang @ 2026-04-23 3:40 ` Zaiyu Wang 2026-04-24 21:59 ` Stephen Hemminger 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (2 subsequent siblings) 20 siblings, 1 reply; 92+ messages in thread From: Zaiyu Wang @ 2026-04-23 3:40 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 67 ++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 41ec432983..17fda66756 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5452,23 +5452,76 @@ txgbe_get_module_eeprom(struct rte_eth_dev *dev, uint8_t databyte = 0xFF; uint8_t *data = info->data; uint32_t i = 0; + bool is_sfp = false; + u32 value; + u8 identifier = 0; + u16 offset; + u8 page = 0; + + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } + + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; + } if (info->length == 0) return -EINVAL; - for (i = info->offset; i < info->offset + info->length; i++) { - if (i < RTE_ETH_MODULE_SFF_8079_LEN) - status = hw->phy.read_i2c_eeprom(hw, i, &databyte); - else - status = hw->phy.read_i2c_sff8472(hw, i, &databyte); + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; - if (status != 0) - return -EIO; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); + if (status != 0) + goto ERROR_IO; + if (identifier == TXGBE_SFF_IDENTIFIER_SFP) + is_sfp = true; + + memset(data, 0, info->length); + + for (i = info->offset; i < info->offset + info->length; i++) { + if (is_sfp) { + if (i < RTE_ETH_MODULE_SFF_8079_LEN) + status = hw->phy.read_i2c_eeprom(hw, i, + &databyte); + else + status = hw->phy.read_i2c_sff8472(hw, i, + &databyte); + + if (status != 0) + goto ERROR_IO; + } else { + offset = i; + while (offset >= RTE_ETH_MODULE_SFF_8436_LEN) { + offset -= RTE_ETH_MODULE_SFF_8436_LEN / 2; + page++; + } + if (page == 0 || !(data[0x2] & 0x4)) { + status = hw->phy.read_i2c_sff8636(hw, page, offset, + &databyte); + if (status != 0) + goto ERROR_IO; + } + } data[i - info->offset] = databyte; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } bool -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* Re: [PATCH 18/18] net/txgbe: fix get eeprom operation 2026-04-23 3:40 ` [PATCH 18/18] net/txgbe: fix get eeprom operation Zaiyu Wang @ 2026-04-24 21:59 ` Stephen Hemminger 0 siblings, 0 replies; 92+ messages in thread From: Stephen Hemminger @ 2026-04-24 21:59 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev, stable, Jiawen Wu On Thu, 23 Apr 2026 11:40:23 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > The original I2C access flow in the module information retrieval > process was flawed. Correct the implementation to properly fetch > module info. > > Cc: stable@dpdk.org > > Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> Build errors. Must fix. clang -Idrivers/libtmp_rte_net_txgbe.a.p -Idrivers -I../drivers -Idrivers/net/txgbe -I../drivers/net/txgbe -Idrivers/net/txgbe/base -I../drivers/net/txgbe/base -Ilib/ethdev -I../lib/ethdev -Ilib/eal/common -I../lib/eal/common -I. -I.. -Iconfig -I../config -Ilib/eal/include -I../lib/eal/include -Ilib/eal/linux/include -I../lib/eal/linux/include -Ilib/eal/x86/include -I../lib/eal/x86/include -I../kernel/linux -Ilib/eal -I../lib/eal -Ilib/kvargs -I../lib/kvargs -Ilib/log -I../lib/log -Ilib/metrics -I../lib/metrics -Ilib/telemetry -I../lib/telemetry -Ilib/argparse -I../lib/argparse -Ilib/net -I../lib/net -Ilib/mbuf -I../lib/mbuf -Ilib/mempool -I../lib/mempool -Ilib/ring -I../lib/ring -Ilib/meter -I../lib/meter -Idrivers/bus/pci -I../drivers/bus/pci -I../drivers/bus/pci/linux -Ilib/pci -I../lib/pci -Idrivers/bus/vdev -I../drivers/bus/vdev -Ilib/hash -I../lib/hash -Ilib/rcu -I../lib/rcu -Ilib/security -I../lib/security -Ilib/cryptodev -I../lib/cryptodev -Xclang -fcolor-diagnostics -pipe -D _FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wextra -Werror -std=c11 -O3 -include rte_config.h -Wvla -Wcast-qual -Wcomma -Wdeprecated -Wformat -Wformat-nonliteral -Wformat-security -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wold-style-definition -Wpointer-arith -Wshadow -Wsign-compare -Wstrict-prototypes -Wundef -Wwrite-strings -Wno-missing-field-initializers -D_GNU_SOURCE -fPIC -march=native -mrtm -DALLOW_EXPERIMENTAL_API -DALLOW_INTERNAL_API -Wno-format-truncation -Wno-address-of-packed-member -Wno-vla -Wno-shadow -DRTE_LOG_DEFAULT_LOGTYPE=pmd.net.txgbe -DRTE_ANNOTATE_LOCKS -Wthread-safety -MD -MQ drivers/libtmp_rte_net_txgbe.a.p/net_txgbe_base_txgbe_e56_bp.c.o -MF drivers/libtmp_rte_net_txgbe.a.p/net_txgbe_base_txgbe_e56_bp.c.o.d -o drivers/libtmp_rte_net_txgbe.a.p/net_txgbe_base_txgbe_e56_bp.c.o -c ../drivers/net/txgbe/base/txgbe_e56_bp.c ../drivers/net/txgbe/base/txgbe_e56_bp.c:352:13: error: variable 'CMVAR_SEC_LOW_TH' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized] 352 | } else if (speed == 25) { | ^~~~~~~~~~~ ../drivers/net/txgbe/base/txgbe_e56_bp.c:376:21: note: uninitialized use occurs here 376 | if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { | ^~~~~~~~~~~~~~~~ ../drivers/net/txgbe/base/txgbe_e56_bp.c:352:9: note: remove the 'if' if its condition is always true 352 | } else if (speed == 25) { | ^~~~~~~~~~~~~~~~ ../drivers/net/txgbe/base/txgbe_e56_bp.c:322:22: note: initialize the variable 'CMVAR_SEC_LOW_TH' to silence this warning 322 | int CMVAR_SEC_LOW_TH; | ^ | = 0 1 error generated. ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v2 00/20] Wangxun Fixes 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (17 preceding siblings ...) 2026-04-23 3:40 ` [PATCH 18/18] net/txgbe: fix get eeprom operation Zaiyu Wang @ 2026-04-29 10:24 ` Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang ` (19 more replies) 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang 20 siblings, 20 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:24 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series fixes several issues found on Wangxun Emerald, Sapphire and Amber-lite NICs, with a focus on link-related problems. Zaiyu Wang (20): net/txgbe: remove duplicate xstats counters net/ngbe: remove duplicate xstats counters net/ngbe: add missing CDR config for YT PHY net/ngbe: fix VF promiscuous and allmulticast net/txgbe: fix inaccuracy in TX rate limiting net/txgbe: fix link status check condition net/txgbe: fix Tx desc free logic net/txgbe: fix link flow control registers for Amber-Lite net/txgbe: fix link flow control config for Sapphire net/txgbe: fix a mass of unknown interrupts net/txgbe: fix traffic class priority configuration net/txgbe: fix link stability for 25G NIC net/txgbe: fix link stability for 40G NIC net/txgbe: fix link stability for Amber-Lite backplane mode net/txgbe: fix FEC mode configuration on 25G NIC net/txgbe: fix SFP module identification net/txgbe: fix get module info operation net/txgbe: fix get eeprom operation net/txgbe: fix to reset Tx write-back pointer net/txgbe: fix to enable Tx desc check drivers/net/ngbe/base/ngbe_phy_yt.c | 3 + drivers/net/ngbe/ngbe_ethdev.c | 5 - drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +- drivers/net/txgbe/base/meson.build | 2 + drivers/net/txgbe/base/txgbe.h | 2 + drivers/net/txgbe/base/txgbe_aml.c | 187 +- drivers/net/txgbe/base/txgbe_aml.h | 6 +- drivers/net/txgbe/base/txgbe_aml40.c | 113 +- drivers/net/txgbe/base/txgbe_aml40.h | 6 +- drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- drivers/net/txgbe/base/txgbe_e56.c | 3774 +++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56.h | 1744 ++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.c | 2593 ++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 278 ++ drivers/net/txgbe/base/txgbe_hw.c | 52 +- drivers/net/txgbe/base/txgbe_hw.h | 4 +- drivers/net/txgbe/base/txgbe_osdep.h | 4 + drivers/net/txgbe/base/txgbe_phy.c | 360 +- drivers/net/txgbe/base/txgbe_phy.h | 45 +- drivers/net/txgbe/base/txgbe_regs.h | 10 +- drivers/net/txgbe/base/txgbe_type.h | 39 +- drivers/net/txgbe/txgbe_ethdev.c | 390 ++- drivers/net/txgbe/txgbe_ethdev.h | 6 +- drivers/net/txgbe/txgbe_rxtx.c | 95 +- drivers/net/txgbe/txgbe_rxtx.h | 1 + drivers/net/txgbe/txgbe_rxtx_vec_common.h | 14 +- 26 files changed, 9327 insertions(+), 419 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56.c create mode 100644 drivers/net/txgbe/base/txgbe_e56.h create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h -- 2.21.0.windows.1 ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v2 01/20] net/txgbe: remove duplicate xstats counters 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang @ 2026-04-29 10:24 ` Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 02/20] net/ngbe: " Zaiyu Wang ` (18 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:24 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Fixes: 91fe49c87d76 ("net/txgbe: support device xstats") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 5d360f8305..779874aac9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -261,11 +261,6 @@ static const struct rte_txgbe_xstats_name_off rte_txgbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 02/20] net/ngbe: remove duplicate xstats counters 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang @ 2026-04-29 10:24 ` Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang ` (17 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:24 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Fixes: 8b433d04adc9 ("net/ngbe: support device xstats") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 8b9d6371fb..6df53f3266 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -227,11 +227,6 @@ static const struct rte_ngbe_xstats_name_off rte_ngbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 03/20] net/ngbe: add missing CDR config for YT PHY 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 02/20] net/ngbe: " Zaiyu Wang @ 2026-04-29 10:24 ` Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang ` (16 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:24 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu According to the PHY vendor, when YT8531S operates in UTP-to-Fiber or RGMII-to-Fiber mode with auto-negotiation disabled (Force mode), additional CDR (Clock Data Recovery) configuration is required to improve link connectivity. Without this config, link may be unstable or fail to establish. Fixes: f1268369403d ("net/ngbe: support autoneg on/off for external PHY SFI mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/base/ngbe_phy_yt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c index d110fbc8b2..ab0778d246 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.c +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -264,6 +264,9 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed, value = YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN | YT_BCR_DUPLEX | YT_BCR_SPEED_SELECT1; } else { + /* force mode need to config cdr */ + ngbe_write_phy_reg_sds_ext_yt(hw, 0x3, 0, 0x1434); + ngbe_write_phy_reg_sds_ext_yt(hw, 0xe, 0, 0x163); value = YT_BCR_RESET | YT_BCR_DUPLEX; if (speed & NGBE_LINK_SPEED_1GB_FULL) value |= YT_BCR_SPEED_SELECT1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 04/20] net/ngbe: fix VF promiscuous and allmulticast 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (2 preceding siblings ...) 2026-04-29 10:24 ` [PATCH v2 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang @ 2026-04-29 10:24 ` Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 05/20] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang ` (15 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:24 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The configuration of allmulti and promiscuous modes conflicts together. For instance, if we enable promiscuous mode, then enable and disable allmulti, then the promiscuous mode is wrongly disabled. Fix this behavior by: - doing nothing when we set/unset allmulti if promiscuous mode is on - restorting the proper mode (none or allmulti) when we disable promiscuous mode Fixes: 7744e90805b5 ("net/ngbe: add promiscuous and allmulticast ops for VF device") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev_vf.c b/drivers/net/ngbe/ngbe_ethdev_vf.c index 6406df40d0..81511fed8a 100644 --- a/drivers/net/ngbe/ngbe_ethdev_vf.c +++ b/drivers/net/ngbe/ngbe_ethdev_vf.c @@ -1196,9 +1196,13 @@ static int ngbevf_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct ngbe_hw *hw = ngbe_dev_hw(dev); + int mode = NGBEVF_XCAST_MODE_NONE; int ret; - switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_NONE)) { + if (dev->data->all_multicast) + mode = NGBEVF_XCAST_MODE_ALLMULTI; + + switch (hw->mac.update_xcast_mode(hw, mode)) { case 0: ret = 0; break; @@ -1219,7 +1223,7 @@ ngbevf_dev_allmulticast_enable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; - if (dev->data->promiscuous == 1) + if (dev->data->promiscuous) return 0; switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_ALLMULTI)) { @@ -1243,6 +1247,9 @@ ngbevf_dev_allmulticast_disable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; + if (dev->data->promiscuous) + return 0; + switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_MULTI)) { case 0: ret = 0; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 05/20] net/txgbe: fix inaccuracy in TX rate limiting 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (3 preceding siblings ...) 2026-04-29 10:24 ` [PATCH v2 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang @ 2026-04-29 10:24 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 06/20] net/txgbe: fix link status check condition Zaiyu Wang ` (14 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:24 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Amber-lite NIC's TX rate limiting has large deviations for small packets. To fix this issue, there are some changes: 1. Set TDM_RL_ADJ (0x1820c) to 21B (includes 7B Ethernet preamble, 1B SFD, 1B EFD, and 12B IPG). 2) Remove the rate offset in the driver (e.g., 105 / 100, a rough compensation value from Linux kernel driver tests). After these changes, accuracy deviation for 64B packets is within ~5%, while large packets show lower deviation. Fixes: a309ab43acf3 ("net/txgbe: support Tx queue rate limiting for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_regs.h | 1 + drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 95c585a025..060757323a 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1670,6 +1670,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_TDM_FACTOR_INT_SHIFT 16 #define TXGBE_TDM_FACTOR_FRA_SHIFT 2 +#define TXGBE_TDM_RL_ADJ 0x1820C #define TXGBE_TDM_RL_VM_IDX 0x018218 #define TXGBE_TDM_RL_VM_CFG 0x01821C #define TXGBE_TDM_RL_CFG 0x018400 diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 779874aac9..414107d7a7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -4314,7 +4314,6 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, u16 frac; link_speed = dev->data->dev_link.link_speed; - tx_rate = tx_rate * 105 / 100; /* Calculate the rate factor values to set */ factor_int = link_speed / tx_rate; frac = (link_speed % tx_rate) * 10000 / tx_rate; @@ -4324,6 +4323,7 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, factor_fra = 0; } + wr32(hw, TXGBE_TDM_RL_ADJ, 21); wr32(hw, TXGBE_TDM_RL_QUEUE_IDX, queue_idx); wr32m(hw, TXGBE_TDM_RL_QUEUE_CFG, TXGBE_TDM_FACTOR_INT_MASK, factor_int << TXGBE_TDM_FACTOR_INT_SHIFT); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 06/20] net/txgbe: fix link status check condition 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (4 preceding siblings ...) 2026-04-29 10:24 ` [PATCH v2 05/20] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang ` (13 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original code incorrectly used 'if (link_up)' instead of 'if (*link_up)', causing the condition to always evaluate to true because the pointer itself is non-NULL. This led to incorrect speed assignment. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 2 +- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index b376eca5b5..de9a1b1c93 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -67,7 +67,7 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { switch (links_reg & TXGBE_CFG_PORT_ST_AML_LINK_MASK) { case TXGBE_CFG_PORT_ST_AML_LINK_25G: *speed = TXGBE_LINK_SPEED_25GB_FULL; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 733bbac13a..eefd7119fd 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -68,7 +68,7 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 07/20] net/txgbe: fix Tx desc free logic 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (5 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 06/20] net/txgbe: fix link status check condition Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang ` (12 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On some server environments, this driver caused TDM non-fatal errors or PCIe request errors during Tx operation In Amber-Lite NIC's Tx head write-back mode, the hardware periodically writes back a head index pointing to the next descriptor it is adout to process in Tx ring. All descriptors before the head are considered processed by hardware and can be safely freed by the driver. The root cause is that the driver can safely free a batch of descriptors only when the hardware's write-back head pointer has advanced beyond all descriptors in that batch, meaning they have all been processed by the hardware. If the driver frees a descriptor before the hardware has finished processing it, invalid memory access may occur, leading to the observed bug. To fix the issue, correct the boundary check in all three Tx cleanup functions, each of which was missing the proper condition to prevent freeing unprocessed descriptors. Fixes: 8ada71d0bb7f ("net/txgbe: add Tx head write-back mode for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 9 ++++++++- drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index e2cd9b8841..72a4965693 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -100,7 +100,9 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) @@ -652,6 +654,11 @@ txgbe_xmit_cleanup(struct txgbe_tx_queue *txq) /* we have caught up to head, no work left to do */ if (desc_to_clean_to == head) return -(1); + else if (desc_to_clean_to > head && head > last_desc_cleaned) + return -(1); + else if (last_desc_cleaned > desc_to_clean_to && + (head > last_desc_cleaned || head < desc_to_clean_to)) + return -(1); } else { if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) { PMD_TX_FREE_LOG(DEBUG, diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h index 00847d087b..edf3586b77 100644 --- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h +++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h @@ -94,8 +94,11 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) txq->tx_next_dd - txq->tx_free_thresh; if (tx_last_dd >= txq->nb_tx_desc) tx_last_dd -= txq->nb_tx_desc; - volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + + volatile uint16_t head = (uint16_t)*txq->headwb_mem; + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 08/20] net/txgbe: fix link flow control registers for Amber-Lite 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (6 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 15:10 ` Stephen Hemminger 2026-04-29 10:25 ` [PATCH v2 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang ` (11 subsequent siblings) 19 siblings, 1 reply; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The flow control counter registers on AML NICs differ from those on SP NICs. Update the register offsets accordingly to ensure the counters work correctly. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 5 +++++ drivers/net/txgbe/base/txgbe_regs.h | 2 ++ drivers/net/txgbe/txgbe_ethdev.c | 10 ++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0f3db3a1ad..52fead6171 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -394,6 +394,11 @@ s32 txgbe_clear_hw_cntrs(struct txgbe_hw *hw) rd32(hw, TXGBE_PBTXLNKXON); rd32(hw, TXGBE_PBTXLNKXOFF); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + wr32(hw, TXGBE_PBRXLNKXON_AML, 0); + wr32(hw, TXGBE_PBRXLNKXOFF_AML, 0); + } + /* DMA Stats */ rd32(hw, TXGBE_DMARXPKT); rd32(hw, TXGBE_DMATXPKT); diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 060757323a..de382601c9 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1085,6 +1085,8 @@ enum txgbe_5tuple_protocol { #define TXGBE_PBRXDROP 0x019068 #define TXGBE_PBRXLNKXOFF 0x011988 #define TXGBE_PBRXLNKXON 0x011E0C +#define TXGBE_PBRXLNKXOFF_AML 0x011F80 +#define TXGBE_PBRXLNKXON_AML 0x011F84 #define TXGBE_PBRXUPXON(up) (0x011E30 + (up) * 4) #define TXGBE_PBRXUPXOFF(up) (0x011E10 + (up) * 4) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 414107d7a7..e3492c9cd7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2331,8 +2331,14 @@ txgbe_read_stats_registers(struct txgbe_hw *hw, hw_stats->up[i].rx_up_dropped += rd32(hw, TXGBE_PBRXMISS(i)); } - hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); - hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + hw_stats->rx_xon_packets = rd32(hw, TXGBE_PBRXLNKXON_AML); + hw_stats->rx_xoff_packets = rd32(hw, TXGBE_PBRXLNKXOFF_AML); + } else { + hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); + hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + } hw_stats->tx_xon_packets += rd32(hw, TXGBE_PBTXLNKXON); hw_stats->tx_xoff_packets += rd32(hw, TXGBE_PBTXLNKXOFF); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* Re: [PATCH v2 08/20] net/txgbe: fix link flow control registers for Amber-Lite 2026-04-29 10:25 ` [PATCH v2 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang @ 2026-04-29 15:10 ` Stephen Hemminger 0 siblings, 0 replies; 92+ messages in thread From: Stephen Hemminger @ 2026-04-29 15:10 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev, stable, Jiawen Wu On Wed, 29 Apr 2026 18:25:02 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > The flow control counter registers on AML NICs differ from those on SP > NICs. Update the register offsets accordingly to ensure the counters > work correctly. > > Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") > Cc: stable@dpdk.org > > Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> > --- AI review warning: Warning: txgbe_ethdev.c, in the AML branch added in txgbe_read_stats_registers(), uses assignment instead of accumulation:  if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { hw_stats->rx_xon_packets = rd32(hw, TXGBE_PBRXLNKXON_AML); hw_stats->rx_xoff_packets = rd32(hw, TXGBE_PBRXLNKXOFF_AML); } else { hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); The AML registers are write-clearable (cleared with wr32(reg, 0) in txgbe_clear_hw_cntrs) rather than read-on-clear. Reads return the absolute count from the hardware. txgbe_dev_stats_reset() zeros hw_stats but does not clear the hardware register, so on the next stats_get() the counters will jump back to the absolute hardware value rather than restarting from zero. The AML path needs the same offset-tracking pattern that UPDATE_QP_COUNTER_32bit uses (or the AML registers need to be cleared in stats_reset). ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v2 09/20] net/txgbe: fix link flow control config for Sapphire 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (7 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang ` (10 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit SP chips have a hardware bug preventing XON flow control support, so the driver disables it. Fixes: 69ce8c8a4ce3 ("net/txgbe: support flow control") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 52fead6171..0719b56e3c 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -1035,8 +1035,10 @@ s32 txgbe_fc_enable(struct txgbe_hw *hw) for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { if ((hw->fc.current_mode & txgbe_fc_tx_pause) && hw->fc.high_water[i]) { - fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]) | - TXGBE_FCWTRLO_XON; + fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]); + /* SP doesn't support xon */ + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + fcrtl |= TXGBE_FCWTRLO_XON; fcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[i]) | TXGBE_FCWTRHI_XOFF; } else { -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 10/20] net/txgbe: fix a mass of unknown interrupts 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (8 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang ` (9 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit When RSC is enabled, Rx ring IVAR is set to configure ITR. It causes Rx ring interrupts report on the default msix_vector. Thus a mass of unknown interrupts occupy CPU. Fix the issue by setting ring IVAR only when the rxq interrupt is enabled. Fixes: be797cbf4582 ("net/txgbe: add Rx and Tx init") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 72a4965693..be279dc4ec 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -4354,6 +4354,8 @@ static int txgbe_set_rsc(struct rte_eth_dev *dev) { struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = pci_dev->intr_handle; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct rte_eth_dev_info dev_info = { 0 }; bool rsc_capable = false; @@ -4404,8 +4406,6 @@ txgbe_set_rsc(struct rte_eth_dev *dev) rd32(hw, TXGBE_RXCFG(rxq->reg_idx)); uint32_t psrtype = rd32(hw, TXGBE_POOLRSS(rxq->reg_idx)); - uint32_t eitr = - rd32(hw, TXGBE_ITR(rxq->reg_idx)); /* * txgbe PMD doesn't support header-split at the moment. @@ -4424,6 +4424,9 @@ txgbe_set_rsc(struct rte_eth_dev *dev) srrctl |= txgbe_get_rscctl_maxdesc(rxq->mb_pool); psrtype |= TXGBE_POOLRSS_L4HDR; + wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); + wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); + /* * RSC: Set ITR interval corresponding to 2K ints/s. * @@ -4437,19 +4440,20 @@ txgbe_set_rsc(struct rte_eth_dev *dev) * For a sparse streaming case this setting will yield * at most 500us latency for a single RSC aggregation. */ - eitr &= ~TXGBE_ITR_IVAL_MASK; - eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); - eitr |= TXGBE_ITR_WRDSA; + if (rte_intr_dp_is_en(intr_handle)) { + uint32_t eitr = rd32(hw, TXGBE_ITR(rxq->reg_idx)); - wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); - wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); - wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); + eitr &= ~TXGBE_ITR_IVAL_MASK; + eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); + eitr |= TXGBE_ITR_WRDSA; + wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); - /* - * RSC requires the mapping of the queue to the - * interrupt vector. - */ - txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + /* + * RSC requires the mapping of the queue to the + * interrupt vector. + */ + txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + } } dev->data->lro = 1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (9 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 15:11 ` Stephen Hemminger 2026-04-29 10:25 ` [PATCH v2 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang ` (8 subsequent siblings) 19 siblings, 1 reply; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit After applying the following testpmd command, 802.1Q packets with specific priorities were not properly directed to the corresponding traffic classes: port config 0 dcb vt off 4 pfc off The old driver had two issues: 1. The hardware uses a 4-bit mapping register per traffic class for priority-to-TC mapping, but the driver incorrectly configured it as 3 bits. 2. The DCB TX configuration mistakenly wrote to the RX register. Fix both issues, ensuring that tc-prio mapping works as expected. Fixes: 8bdc7882f376 ("net/txgbe: support DCB") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- drivers/net/txgbe/base/txgbe_regs.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_dcb_hw.c b/drivers/net/txgbe/base/txgbe_dcb_hw.c index 75c91a6b6a..79e1da447b 100644 --- a/drivers/net/txgbe/base/txgbe_dcb_hw.c +++ b/drivers/net/txgbe/base/txgbe_dcb_hw.c @@ -154,7 +154,7 @@ s32 txgbe_dcb_config_tx_data_arbiter_raptor(struct txgbe_hw *hw, u16 *refill, for (i = 0; i < TXGBE_DCB_UP_MAX; i++) reg |= TXGBE_DCBUP2TC_MAP(i, map[i]); - wr32(hw, TXGBE_PBRXUP2TC, reg); + wr32(hw, TXGBE_PBTXUP2TC, reg); /* Configure traffic class credits and priority */ for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index de382601c9..bc73f28ca2 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -503,9 +503,8 @@ #define TXGBE_PBRXCTL 0x019000 #define TXGBE_PBRXCTL_ST MS(0, 0x1) #define TXGBE_PBRXCTL_ENA MS(31, 0x1) -#define TXGBE_PBRXUP2TC 0x019008 #define TXGBE_PBTXUP2TC 0x01C800 -#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 3 * (tc), 0x7) +#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 4 * (tc), 0x7) #define TXGBE_DCBUP2TC_DEC(tc, r) RS(r, 3 * (tc), 0x7) #define TXGBE_PBRXSIZE(tc) (0x019020 + (tc) * 4) #define TXGBE_PBRXSIZE_KB(v) LS(v, 10, 0x3FF) @@ -1703,7 +1702,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_RDM_PF_HIDE(_i) (0x12090 + ((_i) * 4)) #define TXGBE_RPUP2TC 0x019008 -#define TXGBE_RPUP2TC_UP_SHIFT 3 +#define TXGBE_RPUP2TC_UP_SHIFT 4 #define TXGBE_RPUP2TC_UP_MASK 0x7 #define TXGBE_RDM_DCACHE_CTL 0x0120A8 -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* Re: [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration 2026-04-29 10:25 ` [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang @ 2026-04-29 15:11 ` Stephen Hemminger 2026-05-09 11:06 ` Zaiyu Wang 0 siblings, 1 reply; 92+ messages in thread From: Stephen Hemminger @ 2026-04-29 15:11 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev, stable, Jiawen Wu, Ferruh Yigit On Wed, 29 Apr 2026 18:25:05 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > After applying the following testpmd command, 802.1Q packets with specific > priorities were not properly directed to the corresponding traffic classes: > port config 0 dcb vt off 4 pfc off > > The old driver had two issues: > 1. The hardware uses a 4-bit mapping register per traffic class for > priority-to-TC mapping, but the driver incorrectly configured it > as 3 bits. > 2. The DCB TX configuration mistakenly wrote to the RX register. > > Fix both issues, ensuring that tc-prio mapping works as expected. > > Fixes: 8bdc7882f376 ("net/txgbe: support DCB") > Cc: stable@dpdk.org > > Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> > --- AI review spotted issues: Error: The fix is incomplete. The same priority-to-TC layout is also written in drivers/net/txgbe/txgbe_rxtx.c around line 3380 in txgbe_vmdq_dcb_configure(): for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) /* * mapping is done with 3 bits per priority, * so shift by i*3 each time */ queue_mapping |= ((cfg->dcb_tc[i] & 0x07) << (i * 3)); wr32(hw, TXGBE_RPUP2TC, queue_mapping); This writes the same TXGBE_RPUP2TC register (0x019008) the patch is fixing, using a hardcoded i*3 shift and a comment claiming 3 bits per priority. After this patch, txgbe_dcb_config_rx_arbiter_raptor() encodes priorities at 4-bit positions (via the updated TXGBE_RPUP2TC_UP_SHIFT=4), but txgbe_vmdq_dcb_configure() still uses 3-bit positions. The VMDQ+DCB path will produce a wrong tc-prio mapping. txgbe_vmdq_dcb_configure() needs the same fix (use TXGBE_RPUP2TC_UP_SHIFT and update the comment). Warning: TXGBE_DCBUP2TC_DEC and TXGBE_DCBUP2TC_MAP are now inconsistent. After this patch: #define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 4 * (tc), 0x7) #define TXGBE_DCBUP2TC_DEC(tc, r) RS(r, 3 * (tc), 0x7) DEC will not decode what MAP encoded for any tc > 0. TXGBE_DCBUP2TC_DEC isn't currently used in tree, so this is not a runtime bug, but it's a latent trap. Either update DEC to also use 4*(tc), or remove DEC since it has no callers. ^ permalink raw reply [flat|nested] 92+ messages in thread
* RE: [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration 2026-04-29 15:11 ` Stephen Hemminger @ 2026-05-09 11:06 ` Zaiyu Wang 0 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:06 UTC (permalink / raw) To: 'Stephen Hemminger'; +Cc: dev, stable > -----Original Message----- > From: Stephen Hemminger <stephen@networkplumber.org> > Sent: Wednesday, April 29, 2026 11:12 PM > To: Zaiyu Wang <zaiyuwang@trustnetic.com>; Zaiyu Wang > <zaiyuwang@trustnetic.com> > Cc: dev@dpdk.org; stable@dpdk.org; Jiawen Wu <jiawenwu@trustnetic.com>; > Ferruh Yigit <ferruh.yigit@amd.com>; dev@dpdk.org; stable@dpdk.org; Jiawen > Wu <jiawenwu@trustnetic.com>; Ferruh Yigit <ferruh.yigit@amd.com> > Subject: Re: [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration > > On Wed, 29 Apr 2026 18:25:05 +0800 > Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > > > After applying the following testpmd command, 802.1Q packets with > > specific priorities were not properly directed to the corresponding traffic classes: > > port config 0 dcb vt off 4 pfc off > > > > The old driver had two issues: > > 1. The hardware uses a 4-bit mapping register per traffic class for > > priority-to-TC mapping, but the driver incorrectly configured it > > as 3 bits. > > 2. The DCB TX configuration mistakenly wrote to the RX register. > > > > Fix both issues, ensuring that tc-prio mapping works as expected. > > > > Fixes: 8bdc7882f376 ("net/txgbe: support DCB") > > Cc: stable@dpdk.org > > > > Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> > > --- > > AI review spotted issues: > > Error: The fix is incomplete. The same priority-to-TC layout is also written in > drivers/net/txgbe/txgbe_rxtx.c around line 3380 in txgbe_vmdq_dcb_configure(): > for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) > /* > * mapping is done with 3 bits per priority, > * so shift by i*3 each time > */ > queue_mapping |= ((cfg->dcb_tc[i] & 0x07) << (i * 3)); > > wr32(hw, TXGBE_RPUP2TC, queue_mapping); > This writes the same TXGBE_RPUP2TC register (0x019008) the patch is fixing, > using a hardcoded i*3 shift and a comment claiming 3 bits per priority. After this > patch, txgbe_dcb_config_rx_arbiter_raptor() encodes priorities at 4-bit positions > (via the updated TXGBE_RPUP2TC_UP_SHIFT=4), but txgbe_vmdq_dcb_configure() > still uses 3-bit positions. The VMDQ+DCB path will produce a wrong tc-prio > mapping. txgbe_vmdq_dcb_configure() needs the same fix (use > TXGBE_RPUP2TC_UP_SHIFT and update the comment). > Warning: TXGBE_DCBUP2TC_DEC and TXGBE_DCBUP2TC_MAP are now > inconsistent. After this patch: > #define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 4 * (tc), 0x7) > #define TXGBE_DCBUP2TC_DEC(tc, r) RS(r, 3 * (tc), 0x7) > DEC will not decode what MAP encoded for any tc > 0. TXGBE_DCBUP2TC_DEC > isn't currently used in tree, so this is not a runtime bug, but it's a latent trap. Either > update DEC to also use 4*(tc), or remove DEC since it has no callers. > Hi Stephen, Thank you for the thorough AI‑assisted review. I really appreciate it. I have addressed all the issues you raised, and an updated patch set will be sent shortly. ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v2 12/20] net/txgbe: fix link stability for 25G NIC 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (10 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 15:12 ` Stephen Hemminger 2026-04-29 10:25 ` [PATCH v2 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang ` (7 subsequent siblings) 19 siblings, 1 reply; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe_aml.c | 107 +- drivers/net/txgbe/base/txgbe_aml.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 2489 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56.h | 1742 +++++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 275 +++ drivers/net/txgbe/base/txgbe_hw.c | 35 +- drivers/net/txgbe/base/txgbe_phy.h | 1 - drivers/net/txgbe/base/txgbe_regs.h | 2 + drivers/net/txgbe/base/txgbe_type.h | 12 + drivers/net/txgbe/txgbe_ethdev.c | 83 +- drivers/net/txgbe/txgbe_ethdev.h | 4 + 12 files changed, 4699 insertions(+), 58 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56.c create mode 100644 drivers/net/txgbe/base/txgbe_e56.h create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index ac4a05005e..305c0291e3 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -12,4 +12,5 @@ base_sources = files( 'txgbe_mng.c', 'txgbe_phy.c', 'txgbe_vf.c', + 'txgbe_e56.c', ) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index de9a1b1c93..cdaa13c763 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -12,6 +12,7 @@ #include "txgbe_mng.h" #include "txgbe_hw.h" #include "txgbe_aml.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -23,6 +24,7 @@ void txgbe_init_ops_aml(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml; + phy->setup_link_core = txgbe_setup_phy_link_aml; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml; @@ -175,16 +177,21 @@ void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed) } } -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; - u32 value = 0; + u32 value; + + *need_reset = false; if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { DEBUGOUT("SFP not detected, skip setup mac link"); @@ -197,33 +204,80 @@ s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, if (status) return status; + /* setup the highest link when no autoneg */ + if (!autoneg) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + speed = TXGBE_LINK_SPEED_25GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + } + speed &= link_capabilities; if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - value = rd32(hw, TXGBE_GPIOEXT); - if (value & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | + TXGBE_SFP1_RX_LOS_LS)) { + DEBUGOUT("RX LOS"); return status; + } - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) { + DEBUGOUT("check phy link_up"); + break; + } + msleep(250); + } - if (link_up && speed == TXGBE_LINK_SPEED_25GB_FULL) + if (speed == TXGBE_LINK_SPEED_25GB_FULL) hw->cur_fec_link = txgbe_phy_fec_get(hw); if (link_speed == speed && link_up && - !(speed == TXGBE_LINK_SPEED_25GB_FULL && - !(hw->fec_mode & hw->cur_fec_link))) - return status; + !(speed == TXGBE_LINK_SPEED_25GB_FULL && + !(hw->fec_mode & hw->cur_fec_link))) + goto out; - if (speed & TXGBE_LINK_SPEED_25GB_FULL) - speed = 0x10; - else if (speed & TXGBE_LINK_SPEED_10GB_FULL) - speed = 0x08; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) { + hw->link_valid = false; + *need_reset = true; + goto out; + } else { + hw->link_valid = true; + } + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + } else { + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + DEBUGOUT("MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + DEBUGOUT("MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + DEBUGOUT("Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -269,9 +323,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (10G -> 25G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, + bool need_reset; + + status = hw->phy.setup_link_core(hw, TXGBE_LINK_SPEED_25GB_FULL, - autoneg_wait_to_complete); + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -297,8 +354,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (25G->10G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, TXGBE_LINK_SPEED_10GB_FULL, - autoneg_wait_to_complete); + bool need_reset; + + status = hw->phy.setup_link_core(hw, + TXGBE_LINK_SPEED_10GB_FULL, + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -348,10 +409,8 @@ void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw) if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->setup_link = txgbe_setup_mac_link_multispeed_fiber_aml; - mac->setup_mac_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } else { - mac->setup_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } } diff --git a/drivers/net/txgbe/base/txgbe_aml.h b/drivers/net/txgbe/base/txgbe_aml.h index e98c952787..bfb01b4968 100644 --- a/drivers/net/txgbe/base/txgbe_aml.h +++ b/drivers/net/txgbe/base/txgbe_aml.h @@ -16,7 +16,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml(struct txgbe_hw *hw); void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed); -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw); #endif /* _TXGBE_AML_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c new file mode 100644 index 0000000000..a73b247f59 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -0,0 +1,2489 @@ +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" +#include "../txgbe_logs.h" + +void +set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value) +{ + unsigned int i; + + /* Single bit field handling */ + if (bit_high == bit_low) { + if (set_value == 0) { + /* clear single bit */ + *src_data &= ~(1 << bit_low); + } else { + /* set single bit */ + *src_data |= (1 << bit_low); + } + } else { + /* first, clear the bit fields */ + for (i = bit_low; i <= bit_high; i++) { + /* clear single bit */ + *src_data &= ~(1 << i); + } + + /* second, or the bit fields with set value */ + *src_data |= (set_value << bit_low); + } +} + +/* + * compare function for qsort() + */ +static inline +int compare(const void *a, const void *b) +{ + const int *num1 = (const int *)a; + const int *num2 = (const int *)b; + + if (*num1 < *num2) + return -1; + + else if (*num1 > *num2) + return 1; + + else + return 0; +} + +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up) +{ + u32 rdata = 0; + u32 links_reg = 0; + + /* must read it twice because the state may + * not be correct the first time you read it + */ + rdata = rd32_epcs(hw, 0x30001); + rdata = rd32_epcs(hw, 0x30001); + + if (rdata & TXGBE_E56_PHY_LINK_UP) + *link_up = true; + else + *link_up = false; + + if (!hw->link_valid) + *link_up = false; + + links_reg = rd32(hw, TXGBE_PORTSTAT); + if (*link_up) { + if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == + TXGBE_CFG_PORT_ST_AML_LINK_40G) + *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == + TXGBE_CFG_PORT_ST_AML_LINK_25G) + *speed = TXGBE_LINK_SPEED_25GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; + } else { + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + + return 0; +} + +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) +{ + u32 ffe_main = 0, pre1 = 0, pre2 = 0, post = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_MAIN; + pre1 = S25G_TX_FFE_CFG_PRE1; + pre2 = S25G_TX_FFE_CFG_PRE2; + post = S25G_TX_FFE_CFG_POST; + } + } + + if (hw->phy.ffe_set) { + ffe_main = hw->phy.ffe_main; + pre1 = hw->phy.ffe_pre; + pre2 = hw->phy.ffe_pre2; + post = hw->phy.ffe_post; + } + + DEBUGOUT("main = 0x%x, pre1 = 0x%x, pre2 = 0x%x, post = 0x%x", + ffe_main, pre1, pre2, post); + + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_1_ADDR, ffe_main); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_2_ADDR, pre1); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_3_ADDR, pre2); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_4_ADDR, post); + + return 0; +} + +int +txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) +{ + int data_code, temp_data, temp_fraction; + u32 rdata; + u32 timer = 0; + + while (1) { + rdata = rd32(hw, 0x1033c); + if (((rdata >> 12) & 0x1) != 0) + break; + if (timer++ > PHYINIT_TIMEOUT) + return -1; + } + + data_code = rdata & 0xFFF; + temp_data = 419400 + 2205 * (data_code * 1000 / 4094 - 500); + + /* Change double Temperature to int */ + *temp = temp_data / 10000; + temp_fraction = temp_data - (*temp * 10000); + if (temp_fraction >= 5000) + *temp += 1; + + return 0; +} + +u32 +txgbe_e56_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + /* change 0x90 to 0x0 to fix 25G link up keep when cable unplugged */ + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S25G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S25G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S25G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +u32 +txgbe_e56_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static inline int +txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int addr, rdata, timer; + int T = 40; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int OFFSET_CENTRE_RANGE_H, OFFSET_CENTRE_RANGE_L, RANGE_FINAL; + int i = 0; + int lane_num = 1; + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* + * 2. Define software variable RX_COARSE_MID_TD + * (RX Coarse Code mid value dependent upon temperature) + */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + } + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + lane_num = 4; + + /* 3. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_H */ + for (i = 0; i < lane_num; i++) { + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 4. Do SEQ::RX_ENABLE to enable RXS, and let it stop after oscillator calibration. + * This needs to be done by blocking the RX power-up fsm at the state following + * the oscillator calibration state. + * Follow below steps to do the same before SEQ::RX_ENABLE. + * a. ALIAS::PDIG::CTRL_FSM_RX_ST can be stopped at RX_SAMP_CAL_ST which is the + * state after RX_OSC_CAL_ST by configuring ALIAS::RXS::SAMP_CAL_DONE=0b0 + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Do SEQ::RX_ENABLE to enable RXS */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* b. Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm its value is RX_SAMP_CAL_ST */ + rdata = 0; + timer = 0; + while ((rdata >> (i * 8) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (rdata & (0x100 << i)) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* 5/6.Define software variable as OFFSET_CENTRE_RANGE_H = ALIAS::RXS::COARSE */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_H > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_H = OFFSET_CENTRE_RANGE_H - RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_H = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_H; + + /* + * 7. Do SEQ::RX_DISABLE to disable RXS. + * Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm. + */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) + break; + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 8. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, + * it is possible the timeout interrupt is set. + * Clear the same by clearing ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. + * Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + usec_delay(500); + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 9. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_L */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 10. Do SEQ::RX_ENABLE to enable RXS, + * and let it stop after oscillator calibration. + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* poll CTRL_FSM_RX_ST */ + timer = 0; + while (((rdata >> (i * 8)) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x100) == 0x100) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 11/12.Define software variable as OFFSET_CENTRE_RANGE_L = ALIAS::RXS::COARSE - + * RX_COARSE_MID_TD. Clear the INTR. + */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_L > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_L = OFFSET_CENTRE_RANGE_L - RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_L = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_L; + + /* + * 13. Perform below calculation in software. Goal is to pick range value + * which is closer to RX_COARSE_MID_TD. + */ + if (OFFSET_CENTRE_RANGE_L < OFFSET_CENTRE_RANGE_H) + RANGE_FINAL = CMVAR_RANGE_L; + else + RANGE_FINAL = CMVAR_RANGE_H; + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) + break; + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 15. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, + * it is possible the timeout interrupt is set. Clear the same by clearing + * ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR + * which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(500); + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 16. Program ALIAS::RXS::RANGE_SEL = RANGE_FINAL */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, RANGE_FINAL); + wr32_ephy(hw, addr, rdata); + + /* + * 17. Program following before enabling RXS. Purpose is to disable power-up + * FSM control on ADC offset adaptation. + * Note: this step will be done in 2.3.3 RXS calibration and adaptation sequence + * 18. After this SEQ::RX_ENABLE can be done at any time. Note to ensure that + * ALIAS::RXS::RANGE_SEL = RANGE_FINAL configuration is retained. + * Rmove the OVRDEN on rxs0_rx0_samp_cal_done_o + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + } + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0xf); + else + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x1); + wr32_ephy(hw, addr, rdata); + + return status; +} + +static inline +int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + + unsigned int CMVAR_UFINE_MAX = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + else if (speed == TXGBE_LINK_SPEED_25GB_FULL) + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + + /* a. Assign software defined variables as below */ + /* ii. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE); + /* Set ovrd_en=1 to override ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i, + 1); + /* Wait until 1milliseconds or greater */ + msleep(10); + } + + return status; +} + +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) +{ + int status = 0, i, N, median; + unsigned int rdata; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + + /* Set ovrd_en=0 to read ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + + /* + * As status update from RXS hardware is asynchronous to read status + * of SECOND_ORDER, follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + /* set RXS_BBCDR_SECOND_ORDER_ST[i] = + * RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), compare); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ + +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + int temperature; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + PMD_DRV_LOG(ERR, "Error Speed"); + return 0; + } + + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; + + hw->temperature = temperature; + + /* + * Assign software defined variables as below + * a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER + */ + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + /* Set ovrd_en=1 to override ASIC value */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All two of above code updates should be written + * in a single register write + * Set ovrd_en=1 to override ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All three of above code updates should be written + * in a single register write + * Set ovrd_en=1 to override ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature " + "tracking occurs Error condition"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " + "temperature tracking occurs Error condition"); + } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static inline int +txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypass_ctle = 1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + bypass_ctle = 0; + + if (hw->mac.type == txgbe_mac_aml) { + msleep(350); + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { + if (rdata & TXGBE_SFP1_MOD_ABS_LS) + DEBUGOUT("E56phyRxsCalibAdaptSeq TXGBE_SFP1_MOD_ABS_LS"); + else if (rdata & TXGBE_SFP1_RX_LOS_LS) + DEBUGOUT("E56phyRxsCalibAdaptSeq TXGBE_SFP1_RX_LOS_LS"); + return TXGBE_ERR_PHY_INIT_NOT_DONE; + } + } + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + if (bypass_ctle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature + * tracking range here. RXS would be enabled at the end of this sequence. For the case + * when PAM4 KR training is not enabled (including PAM4 mode without KR training), + * wait until ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, + ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + EPHY_RREG(E56G__PMD_CTRL_FSM_RX_STAT_0); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + /* + * 4. Disable VGA and CTLE training so that they don't interfere with ADC calibration + * a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 5. Perform ADC interleaver calibration + * a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE + */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) & 1) + != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* + * 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (i = 0; i < 16; i++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_gain_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* + * 7. Perform ADC interleaver adaptation for 10ms or greater, and after that disable it + * a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_intl_adapt_en_i, 0); + + /* + * 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking + * changes in temperature or voltage + * <1> Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + * Set ALIAS::RXS::CTLE_TRAIN_EN = 0b1 + */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + /* + * <2> wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 + * wait for ALIAS::RXS::CTLE_TRAIN_DONE = 1 + */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_vga_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + if (bypass_ctle == 0) { + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + return status; +} + +static inline u32 +txgbe_e56_cfg_temp(struct txgbe_hw *hw) +{ + u32 status; + u32 value; + int temp; + + status = txgbe_e56_get_temp(hw, &temp); + if (status) + temp = DEFAULT_TEMP; + + if (temp < DEFAULT_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else if (temp > HIGH_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else { + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 4, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL4); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL4, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL5); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 23, 23, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL9); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL9, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL10); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL10, value); + } + + return 0; +} + +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + + return 0; +} + +/* + * 2.2.10 SEQ::RX_DISABLE + * Use PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 to powerdown specific RXS lanes. + * Completion of RXS powerdown can be confirmed by + * observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST + */ +static int txgbe_e56_disable_rx(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i, 0); + + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o, 0); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_2); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_2); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_3); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_3); + + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_RREG(E56G__RXS0_DIG_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + EPHY_WREG(E56G__RXS0_DIG_OVRDEN_1); + + /* 2. Disable pattern checker */ + txgbe_e56_ephy_config(E56G__RXS0_DFT_1, ber_en, 0); + + /* 3. Disable internal serial loopback mode */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i, 0); + + /* 4. Enable bypass of clock gates in RXS */ + txgbe_e56_ephy_config(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en, 0x1FFF); + + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0, 0); + + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en, 0); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + while (1) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x3f) == 0x21) + break; + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) +{ + u32 addr; + u32 rdata; + int status = 0; + + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + + if (hw->mac.type == txgbe_mac_aml) { + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) + return TXGBE_ERR_TIMEOUT; + } + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, 0x0); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, 0x0); + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); + + addr = E56PHY_INTR_1_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_1_IDLE_EXIT1); + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + hw->mac.enable_sec_tx_path(hw); + + return status; +} + +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) +{ + u32 value = 0; + u32 ppl_lock = false; + int status = 0; + u32 reset = 0; + + DEBUGOUT("port[%d] force set speed: 0x%x", hw->bus.lan_id, speed); + + if ((rd32(hw, TXGBE_EPHY_STAT) & TXGBE_EPHY_STAT_PPL_LOCK) == + TXGBE_EPHY_STAT_PPL_LOCK) { + ppl_lock = true; + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.disable_tx_laser(hw); + + if (hw->bus.lan_id == 0) + reset = TXGBE_RST_EPHY_LAN_0; + + else + reset = TXGBE_RST_EPHY_LAN_1; + + wr32(hw, TXGBE_RST, + reset | rd32(hw, TXGBE_RST)); + txgbe_flush(hw); + usec_delay(10); + + /* XLGPCS REGS Start */ + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + value |= 0x8000; + wr32_epcs(hw, VR_PCS_DIG_CTRL1, value); + + usec_delay(1000); + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + if ((value & 0x8000)) { + status = TXGBE_ERR_PHY_INIT_NOT_DONE; + hw->mac.enable_tx_laser(hw); + goto out; + } + + value = rd32_epcs(hw, SR_AN_CTRL); + set_fields_e56(&value, 12, 12, 0); + wr32_epcs(hw, SR_AN_CTRL, value); + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 5); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 7); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0x39); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + /* Update to 0 for PIN CLKP/N: Enable the termination of the input buffer */ + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 2, 0, 0x3); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x9); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_25g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0xb); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_10g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.enable_tx_laser(hw); + + status = txgbe_e56_config_rx(hw, speed); + + value = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, value); + + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + if (hw->fec_mode != TXGBE_PHY_FEC_AUTO) { + hw->cur_fec_link = hw->fec_mode; + txgbe_e56_fec_set(hw); + } + +out: + if (ppl_lock) { + hw->mac.enable_sec_tx_path(hw); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + TXGBE_MACRXCFG_ENA); + } + + return status; +} + +s32 txgbe_e56_fec_set(struct txgbe_hw *hw) +{ + u32 value; + + if (hw->cur_fec_link & TXGBE_PHY_FEC_RS) { + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + + /* enable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 1); + wr32_epcs(hw, 0x100c8, value); + } else if (hw->cur_fec_link & TXGBE_PHY_FEC_BASER) { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* enable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 1); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } else { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } + + return 0; +} + +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up) +{ + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + s32 i = 0, j = 0; + + do { + if (!(hw->fec_mode & BIT(j))) { + j += 1; + continue; + } + + hw->cur_fec_link = hw->fec_mode & BIT(j); + + /* + * If in fec auto mode, try another fec mode after no link in 1s + * for lr sfp, enable KR-FEC to link up with mellonax and intel + */ + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_fec_set(hw); + rte_spinlock_unlock(&hw->phy_lock); + + for (i = 0; i < 4; i++) { + msleep(250); + txgbe_e56_check_phy_link(hw, &link_speed, link_up); + if (*link_up) + return 0; + } + j += 1; + } while (j < 3); + + return 0; +} diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h new file mode 100644 index 0000000000..eaa3ea5085 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -0,0 +1,1742 @@ +#ifndef _TXGBE_E56_H_ +#define _TXGBE_E56_H_ + +#include "txgbe_type.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" + +#define EPHY_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_ephy(hw, REG##_ADDR); \ + } while (0) + +#define EPCS_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_epcs(hw, REG##_ADDR); \ + } while (0) + +#define EPHY_WREG(REG) wr32_ephy(hw, REG##_ADDR, rdata) +#define EPCS_WREG(REG) wr32_epcs(hw, REG##_ADDR, rdata) + +#define txgbe_e56_ephy_config(reg, field, val) \ + do { \ + EPHY_RREG(reg); \ + EPHY_XFLD(reg, field) = (val); \ + EPHY_WREG(reg); \ + } while (0) + +#define txgbe_e56_epcs_config(reg, field, val) \ + do { \ + EPCS_RREG(reg); \ + EPCS_XFLD(reg, field) = (val); \ + EPCS_WREG(reg); \ + } while (0) + +/* + * LAN GPIO define for SFP+ module + * -- Fields + */ +#define SFP1_RS0 5, 5 +#define SFP1_RS1 4, 4 +#define SFP1_RX_LOS 3, 3 +#define SFP1_MOD_ABS 2, 2 +#define SFP1_TX_DISABLE 1, 1 +#define SFP1_TX_FAULT 0, 0 + +#define EPHY_XFLD(REG, FLD) (((REG *)&rdata)->FLD) +#define EPCS_XFLD(REG, FLD) (((REG *)&rdata)->FLD) + +typedef union { + struct { + u32 ana_refclk_buf_daisy_en_i : 1; + u32 ana_refclk_buf_pad_en_i : 1; + u32 ana_vddinoff_dcore_dig_o : 1; + u32 ana_lcpll_en_clkout_hf_left_top_i : 1; + u32 ana_lcpll_en_clkout_hf_right_top_i : 1; + u32 ana_lcpll_en_clkout_hf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_hf_right_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_left_top_i : 1; + u32 ana_lcpll_en_clkout_lf_right_top_i : 1; + u32 ana_lcpll_en_clkout_lf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_right_bot_i : 1; + u32 ana_bg_en_i : 1; + u32 ana_en_rescal_i : 1; + u32 ana_rescal_comp_o : 1; + u32 ana_en_ldo_core_i : 1; + u32 ana_lcpll_hf_en_bias_i : 1; + u32 ana_lcpll_hf_en_loop_i : 1; + u32 ana_lcpll_hf_en_cp_i : 1; + u32 ana_lcpll_hf_set_lpf_i : 1; + u32 ana_lcpll_hf_en_vco_i : 1; + u32 ana_lcpll_hf_vco_amp_status_o : 1; + u32 ana_lcpll_hf_en_odiv_i : 1; + u32 ana_lcpll_lf_en_bias_i : 1; + u32 ana_lcpll_lf_en_loop_i : 1; + u32 ana_lcpll_lf_en_cp_i : 1; + u32 ana_lcpll_lf_set_lpf_i : 1; + u32 ana_lcpll_lf_en_vco_i : 1; + u32 ana_lcpll_lf_vco_amp_status_o : 1; + u32 ana_lcpll_lf_en_odiv_i : 1; + u32 ana_lcpll_hf_refclk_select_i : 1; + u32 ana_lcpll_lf_refclk_select_i : 1; + u32 rsvd0 : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_0; + +/* AMLITE ETH PHY Registers */ +#define VR_PCS_DIG_CTRL1 0x38000 +#define SR_PCS_CTRL1 0x30000 +#define SR_PCS_CTRL2 0x30007 +#define SR_PMA_CTRL2 0x10007 +#define VR_PCS_DIG_CTRL3 0x38003 +#define VR_PMA_CTRL3 0x180a8 +#define VR_PMA_CTRL4 0x180a9 +#define SR_PMA_RS_FEC_CTRL 0x100c8 +#define CMS_ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN1 0xca8 +#define ANA_OVRDVAL0 0xcb0 +#define ANA_OVRDVAL5 0xcc4 +#define OSC_CAL_N_CDR4 0x14 +#define PLL0_CFG0 0xc10 +#define PLL0_CFG2 0xc18 +#define PLL0_DIV_CFG0 0xc1c +#define PLL1_CFG0 0xc48 +#define PLL1_CFG2 0xc50 +#define CMS_PIN_OVRDEN0 0xc8c +#define CMS_PIN_OVRDVAL0 0xc94 +#define DATAPATH_CFG0 0x142c +#define DATAPATH_CFG1 0x1430 +#define AN_CFG1 0x1438 +#define SPARE52 0x16fc +#define RXS_CFG0 0x000 +#define PMD_CFG0 0x1400 +#define SR_PCS_STS1 0x30001 +#define PMD_CTRL_FSM_TX_STAT0 0x14dc +#define CMS_ANA_OVRDEN0 0xca4 +#define CMS_ANA_OVRDEN1 0xca8 +#define CMS_ANA_OVRDVAL2 0xcb8 +#define CMS_ANA_OVRDVAL4 0xcc0 +#define CMS_ANA_OVRDVAL5 0xcc4 +#define CMS_ANA_OVRDVAL7 0xccc +#define CMS_ANA_OVRDVAL9 0xcd4 +#define CMS_ANA_OVRDVAL10 0xcd8 + +#define TXS_TXS_CFG1 0x804 +#define TXS_WKUP_CNT 0x808 +#define TXS_PIN_OVRDEN0 0x80c +#define TXS_PIN_OVRDVAL6 0x82c +#define TXS_ANA_OVRDVAL1 0x854 + +#define E56PHY_CMS_BASE_ADDR 0x0C00 + +#define E56PHY_CMS_PIN_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x8C) +#define E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I 12, 12 + +#define E56PHY_CMS_PIN_OVRDVAL_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x94) +#define E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I 10, 10 + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) + +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I 29, 29 + +#define E56PHY_CMS_ANA_OVRDEN_1_ADDR (E56PHY_CMS_BASE_ADDR + 0xA8) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I 4, 4 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ADDR (E56PHY_CMS_BASE_ADDR + 0xB8) + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I 31, 28 + +#define E56PHY_CMS_ANA_OVRDVAL_4_ADDR (E56PHY_CMS_BASE_ADDR + 0xC0) + +#define E56PHY_TXS_BASE_ADDR 0x0800 +#define E56PHY_TXS1_BASE_ADDR 0x0900 +#define E56PHY_TXS2_BASE_ADDR 0x0A00 +#define E56PHY_TXS3_BASE_ADDR 0x0B00 +#define E56PHY_TXS_OFFSET 0x0100 + +#define E56PHY_PMD_RX_OFFSET 0x02C + +#define E56PHY_TXS_TXS_CFG_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x04) +#define E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256 7, 4 +#define E56PHY_TXS_WKUP_CNT_ADDR (E56PHY_TXS_BASE_ADDR + 0x08) +#define E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32 7, 0 +#define E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32 15, 8 + +#define E56PHY_TXS_PIN_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x0C) +#define E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I 28, 28 + +#define E56PHY_TXS_PIN_OVRDVAL_6_ADDR (E56PHY_TXS_BASE_ADDR + 0x2C) + +#define E56PHY_TXS_ANA_OVRDVAL_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x54) +#define E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I 23, 8 + +#define E56PHY_TXS_ANA_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x44) +#define E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I 13, 13 + +#define E56PHY_RXS_BASE_ADDR 0x0000 +#define E56PHY_RXS1_BASE_ADDR 0x0200 +#define E56PHY_RXS2_BASE_ADDR 0x0400 +#define E56PHY_RXS3_BASE_ADDR 0x0600 +#define E56PHY_RXS_OFFSET 0x0200 + +#define E56PHY_RXS_RXS_CFG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x000) +#define E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL 1, 1 +#define E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN 17, 4 + +#define E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x008) +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1 15, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1_LSB 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1 31, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1_LSB 16 + +#define E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x014) +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT 18, 8 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1 21, 21 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1 27, 26 + +#define E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x018) +#define E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK 15, 12 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK 19, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK 23, 20 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK 27, 24 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT 30, 28 + +#define E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x01C) +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK 3, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK 7, 4 + +#define E56PHY_RXS_INTL_CONFIG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x020) +#define E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1 31, 16 + +#define E56PHY_RXS_INTL_CONFIG_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x028) +#define E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1 1, 1 + +#define E56PHY_RXS_TXFFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x02C) +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH 18, 12 +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH 26, 20 + +#define E56PHY_RXS_TXFFE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x030) +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x034) +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x038) +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH 20, 12 +#define E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE 26, 21 + +#define E56PHY_RXS_VGA_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x04C) +#define E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET 18, 12 + +#define E56PHY_RXS_VGA_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x050) +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0 4, 0 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0 12, 8 +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123 20, 16 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123 28, 24 + +#define E56PHY_RXS_CTLE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x054) +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0 24, 20 +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123 31, 27 + +#define E56PHY_RXS_CTLE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x058) +#define E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT 24, 0 + +#define E56PHY_RXS_CTLE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x05C) +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1 5, 0 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2 13, 8 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3 21, 16 + +#define E56PHY_RXS_CTLE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x060) +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1 9, 8 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2 11, 10 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3 13, 12 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x064) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT 5, 4 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT 9, 8 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8 31, 28 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x068) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG 31, 28 + +#define E56PHY_RXS_FFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x070) +#define E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN 23, 8 + +#define E56PHY_RXS_IDLE_DETECT_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x088) +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX 22, 16 +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN 30, 24 + +#define E56PHY_RXS_ANA_OVRDEN_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x08C) +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_TRIM_RTERM_I 1, 1 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I 29, 29 + +#define E56PHY_RXS_ANA_OVRDEN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x090) +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I 9, 9 + +#define E56PHY_RXS_ANA_OVRDEN_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x098) +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I 15, 15 +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I 25, 25 + +#define E56PHY_RXS_ANA_OVRDEN_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x09C) +#define E56PHY_RXS_ANA_OVRDVAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x0A0) +#define E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I 0, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B8) +#define E56PHY_RXS_ANA_OVRDVAL_14_ADDR (E56PHY_RXS_BASE_ADDR + 0x0D8) +#define E56PHY_RXS_ANA_OVRDVAL_15_ADDR (E56PHY_RXS_BASE_ADDR + 0x0DC) +#define E56PHY_RXS_ANA_OVRDVAL_17_ADDR (E56PHY_RXS_BASE_ADDR + 0x0E4) +#define E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I 18, 16 + +#define E56PHY_RXS_EYE_SCAN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x1A4) +#define E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER 31, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B4) +#define E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I 1, 0 + +#define E56PHY_RXS_RINGO_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x1FC) + +#define E56PHY_PMD_BASE_ADDR 0x1400 +#define E56PHY_PMD_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x000) +#define E56PHY_PMD_CFG_0_RX_EN_CFG 19, 16 + +#define E56PHY_PMD_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x00C) +#define E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K 31, 24 +#define E56PHY_PMD_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x010) +#define E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K 7, 0 +#define E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K 15, 8 +#define E56PHY_PMD_CFG_5_ADDR (E56PHY_PMD_BASE_ADDR + 0x014) +#define E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET 12, 12 +#define E56PHY_CTRL_FSM_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x040) +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_OFST_CAL_ERR 4, 4 +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR 5, 5 +#define E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL 9, 8 +#define E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN 31, 24 + +#define E56PHY_CTRL_FSM_CFG_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x044) +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x048) +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x04C) +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096 7, 0 + +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x050) +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_7_ADDR (E56PHY_PMD_BASE_ADDR + 0x05C) +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_8_ADDR (E56PHY_PMD_BASE_ADDR + 0x060) +#define E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_12_ADDR (E56PHY_PMD_BASE_ADDR + 0x070) +#define E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_13_ADDR (E56PHY_PMD_BASE_ADDR + 0x074) +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_14_ADDR (E56PHY_PMD_BASE_ADDR + 0x078) +#define E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_15_ADDR (E56PHY_PMD_BASE_ADDR + 0x07C) +#define E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_17_ADDR (E56PHY_PMD_BASE_ADDR + 0x084) +#define E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_18_ADDR (E56PHY_PMD_BASE_ADDR + 0x088) +#define E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_29_ADDR (E56PHY_PMD_BASE_ADDR + 0x0B4) +#define E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_33_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C4) +#define E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_CFG_34_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C8) +#define E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_RX_STAT_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x0FC) +#define E56PHY_RXS0_OVRDEN_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x130) +#define E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O 27, 27 + +#define E56PHY_RXS0_OVRDEN_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x134) +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I 14, 14 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I 16, 16 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CDR_EN_I 18, 18 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I 23, 23 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O 24, 24 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 24 + +#define E56PHY_RXS0_OVRDEN_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x138) +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I 0, 0 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 3, 3 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I 6, 6 + +#define E56PHY_RXS0_OVRDVAL_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x140) +#define E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O 22, 22 + +#define E56PHY_RXS0_OVRDVAL_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x144) +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I 7, 7 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I 9, 9 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CDR_EN_I 11, 11 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I 16, 16 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O 17, 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I 25, 25 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 28, 28 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I 31, 31 + +#define E56PHY_INTR_0_IDLE_ENTRY1 0x10000000 +#define E56PHY_INTR_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x1EC) +#define E56PHY_INTR_0_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E0) + +#define E56PHY_INTR_1_IDLE_EXIT1 0x1 +#define E56PHY_INTR_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x1F0) +#define E56PHY_INTR_1_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E4) + +#define E56PHY_KRT_TFSM_CFG_ADDR (E56PHY_PMD_BASE_ADDR + 0x2B8) +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K 7, 0 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K 15, 8 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 + +#define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 + +#define PHYINIT_TIMEOUT 1000 /* PHY initialization timeout value in 0.5ms unit */ + +#define E56G__BASEADDR 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_7; +#define E56G_CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDEN_1; + +#define E56G_CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_9; + +#define E56G_CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_vcofilt_byp_i : 1; + u32 ovrd_en_ana_bbcdr_coarse_i : 1; + u32 ovrd_en_ana_bbcdr_fine_i : 1; + u32 ovrd_en_ana_bbcdr_ultrafine_i : 1; + u32 ovrd_en_ana_en_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_divctrl_i : 1; + u32 ovrd_en_ana_bbcdr_int_cstm_i : 1; + u32 ovrd_en_ana_bbcdr_prop_step_i : 1; + u32 ovrd_en_ana_en_bbcdr_clk_i : 1; + u32 ovrd_en_ana_test_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_270_o : 1; + u32 ovrd_en_ana_en_bbcdr_samp_dac_i : 1; + u32 ovrd_en_ana_bbcdr_dac0_i : 1; + u32 ovrd_en_ana_bbcdr_dac90_i : 1; + u32 ovrd_en_ana_vga2_cload_in_cstm_i : 1; + u32 ovrd_en_ana_intlvr_cut_bw_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_1; + +#define E56G__RXS0_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0x90) + +typedef union { + struct { + u32 prediv0 : 16; + u32 target_cnt0 : 16; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_0; + +#define E56G_RXS0_OSC_CAL_N_CDR_0_ADDR (E56G__BASEADDR + 0x4) + +typedef union { + struct { + u32 osc_range_sel0 : 2; + u32 osc_range_sel1 : 2; + u32 osc_range_sel2 : 2; + u32 osc_range_sel3 : 2; + u32 vco_code_init : 11; + u32 calibrate_range_sel : 1; + u32 osc_current_boost_en0 : 1; + u32 osc_current_boost_en1 : 1; + u32 osc_current_boost_en2 : 1; + u32 osc_current_boost_en3 : 1; + u32 bbcdr_current_boost0 : 2; + u32 bbcdr_current_boost1 : 2; + u32 bbcdr_current_boost2 : 2; + u32 bbcdr_current_boost3 : 2; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_4; + +#define E56G_RXS0_OSC_CAL_N_CDR_4_ADDR (E56G__BASEADDR + 0x14) + +typedef union { + struct { + u32 adc_intl2slice_delay0 : 16; + u32 adc_intl2slice_delay1 : 16; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_0; + +#define E56G_RXS0_INTL_CONFIG_0_ADDR (E56G__BASEADDR + 0x20) + +typedef union { + struct { + u32 interleaver_hbw_disable0 : 1; + u32 interleaver_hbw_disable1 : 1; + u32 interleaver_hbw_disable2 : 1; + u32 interleaver_hbw_disable3 : 1; + u32 rsvd0 : 28; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_2; + +#define E56G_RXS0_INTL_CONFIG_2_ADDR (E56G__BASEADDR + 0x28) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_dac180_i : 1; + u32 ovrd_en_ana_bbcdr_dac270_i : 1; + u32 ovrd_en_ana_bbcdr_en_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_0_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_90_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_180_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_270_o : 1; + u32 ovrd_en_ana_en_adcbuf1_i : 1; + u32 ovrd_en_ana_test_adcbuf1_i : 1; + u32 ovrd_en_ana_en_adc_clk4ui_i : 1; + u32 ovrd_en_ana_adc_clk_skew0_i : 1; + u32 ovrd_en_ana_adc_clk_skew90_i : 1; + u32 ovrd_en_ana_adc_clk_skew180_i : 1; + u32 ovrd_en_ana_adc_clk_skew270_i : 1; + u32 ovrd_en_ana_adc_update_skew_i : 1; + u32 ovrd_en_ana_en_adc_pi_i : 1; + u32 ovrd_en_ana_adc_pictrl_quad_i : 1; + u32 ovrd_en_ana_adc_pctrl_code_i : 1; + u32 ovrd_en_ana_adc_clkdiv_i : 1; + u32 ovrd_en_ana_test_adc_clkgen_i : 1; + u32 ovrd_en_ana_en_adc_i : 1; + u32 ovrd_en_ana_en_adc_vref_i : 1; + u32 ovrd_en_ana_vref_cnfg_i : 1; + u32 ovrd_en_ana_adc_data_cstm_o : 1; + u32 ovrd_en_ana_en_adccal_lpbk_i : 1; + u32 ovrd_en_ana_sel_adcoffset_cal_i : 1; + u32 ovrd_en_ana_sel_adcgain_cal_i : 1; + u32 ovrd_en_ana_adcgain_cal_swing_ctrl_i : 1; + u32 ovrd_en_ana_adc_gain_i : 1; + u32 ovrd_en_ana_vga_cload_out_cstm_i : 1; + u32 ovrd_en_ana_vga2_cload_out_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_2; + +#define E56G__RXS0_ANA_OVRDEN_2_ADDR (E56G__BASEADDR + 0x94) + +typedef union { + struct { + u32 ovrd_en_ana_adc_offset_i : 1; + u32 ovrd_en_ana_adc_slice_addr_i : 1; + u32 ovrd_en_ana_slice_wr_i : 1; + u32 ovrd_en_ana_test_adc_i : 1; + u32 ovrd_en_ana_test_adc_o : 1; + u32 ovrd_en_ana_spare_o : 8; + u32 ovrd_en_ana_sel_lpbk_i : 1; + u32 ovrd_en_ana_ana_debug_sel_i : 1; + u32 ovrd_en_ana_anabs_config_i : 1; + u32 ovrd_en_ana_en_anabs_i : 1; + u32 ovrd_en_ana_anabs_rxn_o : 1; + u32 ovrd_en_ana_anabs_rxp_o : 1; + u32 ovrd_en_ana_dser_clk_en_i : 1; + u32 ovrd_en_ana_dser_clk_config_i : 1; + u32 ovrd_en_ana_en_mmcdr_clk_obs_i : 1; + u32 ovrd_en_ana_skew_coarse0_fine1_i : 1; + u32 ovrd_en_ana_vddinoff_acore_dig_o : 1; + u32 ovrd_en_ana_vddinoff_dcore_dig_o : 1; + u32 ovrd_en_ana_vga2_boost_cstm_i : 1; + u32 ovrd_en_ana_adc_sel_vbgr_bias_i : 1; + u32 ovrd_en_ana_adc_nbuf_cnfg_i : 1; + u32 ovrd_en_ana_adc_pbuf_cnfg_i : 1; + u32 rsvd0 : 3; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_3; + +#define E56G__RXS0_ANA_OVRDEN_3_NUM 1 +#define E56G__RXS0_ANA_OVRDEN_3_ADDR (E56G__BASEADDR + 0x98) + +typedef union { + struct { + u32 pam4_ab_swap_en : 1; + u32 dser_data_sel : 1; + u32 signal_type : 1; + u32 precode_en : 1; + u32 train_clk_gate_bypass_en : 14; + u32 rsvd0 : 14; + }; + u32 reg; +} E56G__RXS0_RXS_CFG_0; + +#define E56G__RXS0_RXS_CFG_0_NUM 1 +#define E56G__RXS0_RXS_CFG_0_ADDR (E56G__BASEADDR + 0x0) + +typedef union { + struct { + u32 restart_training_ln0 : 1; + u32 training_enable_ln0 : 1; + u32 restart_training_ln1 : 1; + u32 training_enable_ln1 : 1; + u32 restart_training_ln2 : 1; + u32 training_enable_ln2 : 1; + u32 restart_training_ln3 : 1; + u32 training_enable_ln3 : 1; + u32 rsvd0 : 24; + }; + u32 reg; +} E56G__PMD_BASER_PMD_CONTROL; + +#define E56G__PMD_BASER_PMD_CONTROL_NUM 1 +#define E56G__PMD_BASER_PMD_CONTROL_ADDR (E56G__BASEADDR + 0x1640) + +typedef union { + struct { + u32 rx_to_tx_lpbk_en : 4; + u32 sel_wp_pmt_out : 4; + u32 sel_wp_pmt_clkout : 4; + u32 use_recent_marker_offset : 1; + u32 interrupt_debug_mode : 1; + u32 rsvd0 : 2; + u32 tx_ffe_coeff_update : 4; + u32 rsvd1 : 12; + }; + u32 reg; +} E56G__PMD_PMD_CFG_5; + +#define E56G__PMD_PMD_CFG_5_NUM 1 +#define E56G__PMD_PMD_CFG_5_ADDR (E56G__BASEADDR + 0x1414) + +typedef union { + struct { + u32 soft_reset : 1; + u32 pmd_en : 1; + u32 rsvd0 : 2; + u32 pll_refclk_sel : 2; + u32 rsvd1 : 2; + u32 pmd_mode : 1; + u32 rsvd2 : 3; + u32 tx_en_cfg : 4; + u32 rx_en_cfg : 4; + u32 pll_en_cfg : 2; + u32 rsvd3 : 2; + u32 pam4_precode_no_krt_en : 4; + u32 rsvd4 : 4; + }; + u32 reg; +} E56G__PMD_PMD_CFG_0; + +#define E56G__PMD_PMD_CFG_0_NUM 1 +#define E56G__PMD_PMD_CFG_0_ADDR (E56G__BASEADDR + 0x1400) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_rstn_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_divctrl_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_rate_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_width_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_o : 1; + u32 ovrd_en_rxs0_rx0_precode_en_i : 1; + u32 ovrd_en_rxs0_rx0_signal_type_i : 1; + u32 ovrd_en_rxs0_rx0_sync_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_sync_o : 1; + u32 ovrd_en_rxs0_rx0_rate_select_i : 1; + u32 ovrd_en_rxs0_rx0_rterm_en_i : 1; + u32 ovrd_en_rxs0_rx0_bias_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_rdy_i : 1; + u32 ovrd_en_rxs0_rx0_blwc_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_sel_i : 1; + u32 ovrd_en_rxs0_rx0_osc_en_i : 1; + u32 ovrd_en_rxs0_rx0_clkgencdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctlecdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_osc_freq_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_err_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_error_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_0; + +#define E56G__PMD_RXS0_OVRDEN_0_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_0_ADDR (E56G__BASEADDR + 0x1530) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_sparein_i : 8; + u32 ovrd_en_rxs0_rx0_spareout_o : 8; + u32 rsvd0 : 16; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_3; + +#define E56G__PMD_RXS0_OVRDEN_3_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_3_ADDR (E56G__BASEADDR + 0x153c) + +typedef union { + struct { + u32 vco_code_cont_adj_done_ovrd_en : 1; + u32 dfe_coeffl_ovrd_en : 1; + u32 dfe_coeffh_ovrd_en : 1; + u32 rsvd0 : 1; + u32 top_comp_th_ovrd_en : 1; + u32 mid_comp_th_ovrd_en : 1; + u32 bot_comp_th_ovrd_en : 1; + u32 rsvd1 : 1; + u32 level_target_ovrd_en : 4; + u32 ffe_coeff_c0to3_ovrd_en : 4; + u32 ffe_coeff_c4to7_ovrd_en : 4; + u32 ffe_coeff_c8to11_ovrd_en : 4; + u32 ffe_coeff_c12to15_ovrd_en : 4; + u32 ffe_coeff_update_ovrd_en : 1; + u32 rsvd2 : 3; + }; + u32 reg; +} E56G__RXS0_DIG_OVRDEN_1; + +#define E56G__RXS0_DIG_OVRDEN_1_NUM 1 +#define E56G__RXS0_DIG_OVRDEN_1_ADDR (E56G__BASEADDR + 0x160) + +typedef union { + struct { + u32 ber_en : 1; + u32 rsvd0 : 3; + u32 read_mode_en : 1; + u32 rsvd1 : 3; + u32 err_cnt_mode_all0_one1 : 1; + u32 rsvd2 : 3; + u32 init_lfsr_mode_continue0_restart1 : 1; + u32 rsvd3 : 3; + u32 pattern_sel : 4; + u32 rsvd4 : 12; + }; + u32 reg; +} E56G__RXS0_DFT_1; + +#define E56G__RXS0_DFT_1_NUM 1 +#define E56G__RXS0_DFT_1_ADDR (E56G__BASEADDR + 0xec) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_efuse_bits_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_in_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_out_o : 1; + u32 rsvd0 : 15; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_2; + +#define E56G__PMD_RXS0_OVRDEN_2_ADDR (E56G__BASEADDR + 0x1538) + +typedef union { + struct { + u32 ana_bbcdr_osc_range_sel_i : 2; + u32 rsvd0 : 2; + u32 ana_bbcdr_coarse_i : 4; + u32 ana_bbcdr_fine_i : 3; + u32 rsvd1 : 1; + u32 ana_bbcdr_ultrafine_i : 3; + u32 rsvd2 : 1; + u32 ana_bbcdr_divctrl_i : 2; + u32 rsvd3 : 2; + u32 ana_bbcdr_int_cstm_i : 5; + u32 rsvd4 : 3; + u32 ana_bbcdr_prop_step_i : 4; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_5; + +#define E56G__RXS0_ANA_OVRDVAL_5_ADDR (E56G__BASEADDR + 0xb4) + +typedef union { + struct { + u32 ana_adc_pictrl_quad_i : 2; + u32 rsvd0 : 2; + u32 ana_adc_clkdiv_i : 2; + u32 rsvd1 : 2; + u32 ana_test_adc_clkgen_i : 4; + u32 ana_vref_cnfg_i : 4; + u32 ana_adcgain_cal_swing_ctrl_i : 4; + u32 ana_adc_gain_i : 4; + u32 ana_adc_offset_i : 4; + u32 ana_ana_debug_sel_i : 4; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_11; + +#define E56G__RXS3_ANA_OVRDVAL_11_ADDR (E56G__BASEADDR + 0x6cc) + +typedef union { + struct { + u32 rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 rxs0_rx0_fom_en_i : 1; + u32 rxs0_rx0_idle_detect_en_i : 1; + u32 rxs0_rx0_idle_o : 1; + u32 rxs0_rx0_txffe_train_en_i : 1; + u32 rxs0_rx0_txffe_train_enack_o : 1; + u32 rxs0_rx0_txffe_train_done_o : 1; + u32 rxs0_rx0_vga_train_en_i : 1; + u32 rxs0_rx0_vga_train_done_o : 1; + u32 rxs0_rx0_ctle_train_en_i : 1; + u32 rxs0_rx0_ctle_train_done_o : 1; + u32 rxs0_rx0_cdr_en_i : 1; + u32 rxs0_rx0_cdr_rdy_o : 1; + u32 rxs0_rx0_ffe_train_en_i : 1; + u32 rxs0_rx0_ffe_train_done_o : 1; + u32 rxs0_rx0_mmpd_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_done_o : 1; + u32 rxs0_rx0_adc_intl_cal_error_o : 1; + u32 rxs0_rx0_dfe_train_en_i : 1; + u32 rxs0_rx0_dfe_train_done_o : 1; + u32 rxs0_rx0_vga_adapt_en_i : 1; + u32 rxs0_rx0_vga_adapt_done_o : 1; + u32 rxs0_rx0_ctle_adapt_en_i : 1; + u32 rxs0_rx0_ctle_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 rxs0_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDVAL_1; +#define E56G__PMD_RXS0_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1544) + +typedef union { + struct { + u32 rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 rxs1_rx0_fom_en_i : 1; + u32 rxs1_rx0_idle_detect_en_i : 1; + u32 rxs1_rx0_idle_o : 1; + u32 rxs1_rx0_txffe_train_en_i : 1; + u32 rxs1_rx0_txffe_train_enack_o : 1; + u32 rxs1_rx0_txffe_train_done_o : 1; + u32 rxs1_rx0_vga_train_en_i : 1; + u32 rxs1_rx0_vga_train_done_o : 1; + u32 rxs1_rx0_ctle_train_en_i : 1; + u32 rxs1_rx0_ctle_train_done_o : 1; + u32 rxs1_rx0_cdr_en_i : 1; + u32 rxs1_rx0_cdr_rdy_o : 1; + u32 rxs1_rx0_ffe_train_en_i : 1; + u32 rxs1_rx0_ffe_train_done_o : 1; + u32 rxs1_rx0_mmpd_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_done_o : 1; + u32 rxs1_rx0_adc_intl_cal_error_o : 1; + u32 rxs1_rx0_dfe_train_en_i : 1; + u32 rxs1_rx0_dfe_train_done_o : 1; + u32 rxs1_rx0_vga_adapt_en_i : 1; + u32 rxs1_rx0_vga_adapt_done_o : 1; + u32 rxs1_rx0_ctle_adapt_en_i : 1; + u32 rxs1_rx0_ctle_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs1_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs1_rx0_adc_gain_adapt_en_i : 1; + u32 rxs1_rx0_adc_gain_adapt_done_o : 1; + u32 rxs1_rx0_adc_gain_adapt_error_o : 1; + u32 rxs1_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDVAL_1; + +#define E56G__PMD_RXS1_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1570) + +typedef union { + struct { + u32 rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 rxs2_rx0_fom_en_i : 1; + u32 rxs2_rx0_idle_detect_en_i : 1; + u32 rxs2_rx0_idle_o : 1; + u32 rxs2_rx0_txffe_train_en_i : 1; + u32 rxs2_rx0_txffe_train_enack_o : 1; + u32 rxs2_rx0_txffe_train_done_o : 1; + u32 rxs2_rx0_vga_train_en_i : 1; + u32 rxs2_rx0_vga_train_done_o : 1; + u32 rxs2_rx0_ctle_train_en_i : 1; + u32 rxs2_rx0_ctle_train_done_o : 1; + u32 rxs2_rx0_cdr_en_i : 1; + u32 rxs2_rx0_cdr_rdy_o : 1; + u32 rxs2_rx0_ffe_train_en_i : 1; + u32 rxs2_rx0_ffe_train_done_o : 1; + u32 rxs2_rx0_mmpd_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_done_o : 1; + u32 rxs2_rx0_adc_intl_cal_error_o : 1; + u32 rxs2_rx0_dfe_train_en_i : 1; + u32 rxs2_rx0_dfe_train_done_o : 1; + u32 rxs2_rx0_vga_adapt_en_i : 1; + u32 rxs2_rx0_vga_adapt_done_o : 1; + u32 rxs2_rx0_ctle_adapt_en_i : 1; + u32 rxs2_rx0_ctle_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs2_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs2_rx0_adc_gain_adapt_en_i : 1; + u32 rxs2_rx0_adc_gain_adapt_done_o : 1; + u32 rxs2_rx0_adc_gain_adapt_error_o : 1; + u32 rxs2_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDVAL_1; + +#define E56G__PMD_RXS2_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x159c) + +typedef union { + struct { + u32 rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 rxs3_rx0_fom_en_i : 1; + u32 rxs3_rx0_idle_detect_en_i : 1; + u32 rxs3_rx0_idle_o : 1; + u32 rxs3_rx0_txffe_train_en_i : 1; + u32 rxs3_rx0_txffe_train_enack_o : 1; + u32 rxs3_rx0_txffe_train_done_o : 1; + u32 rxs3_rx0_vga_train_en_i : 1; + u32 rxs3_rx0_vga_train_done_o : 1; + u32 rxs3_rx0_ctle_train_en_i : 1; + u32 rxs3_rx0_ctle_train_done_o : 1; + u32 rxs3_rx0_cdr_en_i : 1; + u32 rxs3_rx0_cdr_rdy_o : 1; + u32 rxs3_rx0_ffe_train_en_i : 1; + u32 rxs3_rx0_ffe_train_done_o : 1; + u32 rxs3_rx0_mmpd_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_done_o : 1; + u32 rxs3_rx0_adc_intl_cal_error_o : 1; + u32 rxs3_rx0_dfe_train_en_i : 1; + u32 rxs3_rx0_dfe_train_done_o : 1; + u32 rxs3_rx0_vga_adapt_en_i : 1; + u32 rxs3_rx0_vga_adapt_done_o : 1; + u32 rxs3_rx0_ctle_adapt_en_i : 1; + u32 rxs3_rx0_ctle_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs3_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs3_rx0_adc_gain_adapt_en_i : 1; + u32 rxs3_rx0_adc_gain_adapt_done_o : 1; + u32 rxs3_rx0_adc_gain_adapt_error_o : 1; + u32 rxs3_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDVAL_1; + +#define E56G__PMD_RXS3_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x15c8) + +typedef union { + struct { + u32 ctrl_fsm_rx0_st : 6; + u32 rsvd0 : 2; + u32 ctrl_fsm_rx1_st : 6; + u32 rsvd1 : 2; + u32 ctrl_fsm_rx2_st : 6; + u32 rsvd2 : 2; + u32 ctrl_fsm_rx3_st : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_CTRL_FSM_RX_STAT_0; + +#define E56G__PMD_CTRL_FSM_RX_STAT_0_ADDR (E56G__BASEADDR + 0x14fc) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_0; +#define E56G__RXS0_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0xa0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_0; + +#define E56G__RXS1_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x2a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_0; + +#define E56G__RXS2_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x4a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_0; + +#define E56G__RXS3_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x6a0) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_0; + +#define E56G__RXS0_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x8c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDEN_0; + +#define E56G__RXS1_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x28c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDEN_0; + +#define E56G__RXS2_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x48c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDEN_0; + +#define E56G__RXS3_ANA_OVRDEN_0_NUM 1 +#define E56G__RXS3_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x68c) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_3; + +#define E56G__RXS0_ANA_OVRDVAL_3_NUM 1 +#define E56G__RXS0_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0xac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_3; + +#define E56G__RXS1_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x2ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_3; + +#define E56G__RXS2_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x4ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_3; + +#define E56G__RXS3_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x6ac) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fom_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs0_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_1; + +#define E56G__PMD_RXS0_OVRDEN_1_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1534) + +typedef union { + struct { + u32 ovrd_en_rxs1_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fom_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs1_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs1_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDEN_1; + +#define E56G__PMD_RXS1_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1560) + +typedef union { + struct { + u32 ovrd_en_rxs2_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fom_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs2_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs2_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDEN_1; + +#define E56G__PMD_RXS2_OVRDEN_1_ADDR (E56G__BASEADDR + 0x158c) + +typedef union { + struct { + u32 ovrd_en_rxs3_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fom_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs3_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs3_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDEN_1; + +#define E56G__PMD_RXS3_OVRDEN_1_ADDR (E56G__BASEADDR + 0x15b8) + +#define E56G__RXS0_FOM_18__ADDR (E56G__BASEADDR + 0x1f8) +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB 11 +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB 0 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB 23 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB 12 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB 25 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB 25 + +#define DEFAULT_TEMP 40 +#define HIGH_TEMP 70 + +#define E56PHY_RX_RDY_ST 0x1B + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 + +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 +#define S25G_CMVAR_SEC_LOW_TH 0x1A +#define S25G_CMVAR_SEC_HIGH_TH 0x1D +#define S25G_CMVAR_UFINE_MAX 0x2 +#define S25G_CMVAR_FINE_MAX 0x7 +#define S25G_CMVAR_COARSE_MAX 0xF +#define S25G_CMVAR_UFINE_UMAX_WRAP 0x0 +#define S25G_CMVAR_UFINE_FMAX_WRAP 0x0 +#define S25G_CMVAR_FINE_FMAX_WRAP 0x2 +#define S25G_CMVAR_UFINE_MIN 0x0 +#define S25G_CMVAR_FINE_MIN 0x0 +#define S25G_CMVAR_COARSE_MIN 0x1 +#define S25G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S25G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S25G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S10G_CMVAR_SEC_LOW_TH 0x1A +#define S10G_CMVAR_SEC_HIGH_TH 0x1D +#define S10G_CMVAR_UFINE_MAX 0x7 +#define S10G_CMVAR_FINE_MAX 0x7 +#define S10G_CMVAR_COARSE_MAX 0xF +#define S10G_CMVAR_UFINE_UMAX_WRAP 0x6 +#define S10G_CMVAR_UFINE_FMAX_WRAP 0x7 +#define S10G_CMVAR_FINE_FMAX_WRAP 0x1 +#define S10G_CMVAR_UFINE_MIN 0x0 +#define S10G_CMVAR_FINE_MIN 0x0 +#define S10G_CMVAR_COARSE_MIN 0x1 +#define S10G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S10G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S10G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_TX_FFE_CFG_MAIN 0x2c2c2c2c +#define S10G_TX_FFE_CFG_PRE1 0x0 +#define S10G_TX_FFE_CFG_PRE2 0x0 +#define S10G_TX_FFE_CFG_POST 0x06060606 +#define S25G_TX_FFE_CFG_MAIN 0x31 +#define S25G_TX_FFE_CFG_PRE1 0x4 +#define S25G_TX_FFE_CFG_PRE2 0x1 +#define S25G_TX_FFE_CFG_POST 0x9 + +#define S25G_TX_FFE_CFG_DAC_MAIN 0x2a +#define S25G_TX_FFE_CFG_DAC_PRE1 0x03 +#define S25G_TX_FFE_CFG_DAC_PRE2 0x0 +#define S25G_TX_FFE_CFG_DAC_POST 0x11 + +#define S40G_TX_FFE_CFG_MAIN 0x2b2b2b2b +#define S40G_TX_FFE_CFG_PRE1 0x03030303 +#define S40G_TX_FFE_CFG_PRE2 0x0 +#define S40G_TX_FFE_CFG_POST 0x11111111 + +#define BYPASS_CTLE_TAG 0x0 + +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S10G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S25G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define TXGBE_E56_PHY_LINK_UP 0x4 + +void set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value); +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane); +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE); +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_10g(struct txgbe_hw *hw); +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed); +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_fec_set(struct txgbe_hw *hw); +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); + +#endif /* _TXGBE_E56_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h new file mode 100644 index 0000000000..c58c061ea1 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -0,0 +1,275 @@ +#ifndef _TXGBE_E56_BP_H_ +#define _TXGBE_E56_BP_H_ + +#define TXGBE_10G_FEC_REQ BIT(15) +#define TXGBE_10G_FEC_ABL BIT(14) +#define TXGBE_25G_BASE_FEC_REQ BIT(13) +#define TXGBE_25G_RS_FEC_REQ BIT(12) + +#ifndef __bf_shf +#define __bf_shf(x) (__builtin_ffsll(x) - 1) +#endif +/** + * FIELD_GET_M() - extract a bitfield element + * @_mask: shifted mask defining the field's length and position + * @_reg: value of entire bitfield + * + * FIELD_GET_M() extracts the field specified by @_mask from the + * bitfield passed in as @_reg by masking and shifting it down. + */ +#define FIELD_GET_M(_mask, _reg) \ + ({ \ + (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ + }) + +typedef union { + struct { + u32 tx0_cursor_factor : 7; + u32 rsvd0 : 1; + u32 tx1_cursor_factor : 7; + u32 rsvd1 : 1; + u32 tx2_cursor_factor : 7; + u32 rsvd2 : 1; + u32 tx3_cursor_factor : 7; + u32 rsvd3 : 1; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_1; + +#define E56G__PMD_TX_FFE_CFG_1_NUM 1 +#define E56G__PMD_TX_FFE_CFG_1_ADDR (E56G__BASEADDR + 0x141c) +#define E56G__PMD_TX_FFE_CFG_1_PTR ((E56G__PMD_TX_FFE_CFG_1 *)(E56G__PMD_TX_FFE_CFG_1_ADDR)) +#define E56G__PMD_TX_FFE_CFG_1_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_1_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_READ_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_RESET_VALUE 0x3f3f3f3f + +typedef union { + struct { + u32 tx0_precursor1_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor1_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor1_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor1_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_2; + +#define E56G__PMD_TX_FFE_CFG_2_NUM 1 +#define E56G__PMD_TX_FFE_CFG_2_ADDR (E56G__BASEADDR + 0x1420) +#define E56G__PMD_TX_FFE_CFG_2_PTR ((E56G__PMD_TX_FFE_CFG_2 *)(E56G__PMD_TX_FFE_CFG_2_ADDR)) +#define E56G__PMD_TX_FFE_CFG_2_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_2_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_precursor2_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor2_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor2_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor2_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_3; +#define E56G__PMD_TX_FFE_CFG_3_NUM 1 +#define E56G__PMD_TX_FFE_CFG_3_ADDR (E56G__BASEADDR + 0x1424) +#define E56G__PMD_TX_FFE_CFG_3_PTR ((E56G__PMD_TX_FFE_CFG_3 *)(E56G__PMD_TX_FFE_CFG_3_ADDR)) +#define E56G__PMD_TX_FFE_CFG_3_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_3_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_postcursor_factor : 6; + u32 rsvd0 : 2; + u32 tx1_postcursor_factor : 6; + u32 rsvd1 : 2; + u32 tx2_postcursor_factor : 6; + u32 rsvd2 : 2; + u32 tx3_postcursor_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_4; +#define E56G__PMD_TX_FFE_CFG_4_NUM 1 +#define E56G__PMD_TX_FFE_CFG_4_ADDR (E56G__BASEADDR + 0x1428) +#define E56G__PMD_TX_FFE_CFG_4_PTR ((E56G__PMD_TX_FFE_CFG_4 *)(E56G__PMD_TX_FFE_CFG_4_ADDR)) +#define E56G__PMD_TX_FFE_CFG_4_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_4_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_7; +#define E56G__CMS_ANA_OVRDVAL_7_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) +#define E56G__CMS_ANA_OVRDVAL_7_PTR ((E56G__CMS_ANA_OVRDVAL_7 *)(E56G__CMS_ANA_OVRDVAL_7_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_7_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_7_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_READ_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G__CMS_ANA_OVRDEN_1; +#define E56G__CMS_ANA_OVRDEN_1_NUM 1 +#define E56G__CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) +#define E56G__CMS_ANA_OVRDEN_1_PTR ((E56G__CMS_ANA_OVRDEN_1 *)(E56G__CMS_ANA_OVRDEN_1_ADDR)) +#define E56G__CMS_ANA_OVRDEN_1_STRIDE 4 +#define E56G__CMS_ANA_OVRDEN_1_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_READ_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_READ_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_9; +#define E56G__CMS_ANA_OVRDVAL_9_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) +#define E56G__CMS_ANA_OVRDVAL_9_PTR ((E56G__CMS_ANA_OVRDVAL_9 *)(E56G__CMS_ANA_OVRDVAL_9_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_9_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_9_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_READ_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_RESET_VALUE 0x0 + +#define SFP2_RS0 5 +#define SFP2_RS1 4 +#define SFP2_TX_DISABLE 1 +#define SFP2_TX_FAULT 0 +#define SFP2_RX_LOS_BIT 3 +#ifdef PHYINIT_TIMEOUT +#undef PHYINIT_TIMEOUT +#define PHYINIT_TIMEOUT 2000 +#endif + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_DAISY_EN_I 0, 0 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I 1, 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I_LSB 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_VDDINOFF_DCORE_DIG_O 2, 2 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I 11, 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I_LSB 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I 12, 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I_LSB 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I 13, 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I_LSB 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O 14, 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O_LSB 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I 15, 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I_LSB 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I 16, 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I_LSB 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I 17, 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I_LSB 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I 18, 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I_LSB 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I 19, 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I_LSB 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I 20, 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I_LSB 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I 21, 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I_LSB 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I 22, 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I_LSB 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I 23, 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I_LSB 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I 24, 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I_LSB 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 25, 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I_LSB 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_SET_LPF_I 26, 26 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 20, 16 +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 12, 12 +#define E56PHY_CMS_ANA_OVRDVAL_7_ADDR (E56PHY_CMS_BASE_ADDR + 0xCC) +#define E56PHY_CMS_ANA_OVRDVAL_5_ADDR (E56PHY_CMS_BASE_ADDR + 0xC4) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I 23, 23 +#define E56PHY_CMS_ANA_OVRDVAL_9_ADDR (E56PHY_CMS_BASE_ADDR + 0xD4) +#define E56PHY_CMS_ANA_OVRDVAL_10_ADDR (E56PHY_CMS_BASE_ADDR + 0xD8) +#define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 + +#endif diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0719b56e3c..3b683eaa04 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4069,37 +4069,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { - u32 rdata = 0; - u32 links_reg = 0; + u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); - /* must read it twice because the state may - * not be correct the first time you read it - */ - rdata = rd32_epcs(hw, 0x30001); - rdata = rd32_epcs(hw, 0x30001); - - if (rdata & TXGBE_AML_PHY_LINK_UP) - *link_up = true; - else - *link_up = false; - - links_reg = rd32(hw, TXGBE_PORTSTAT); - if (*link_up) { - if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == - TXGBE_CFG_PORT_ST_AML_LINK_40G) - *speed = TXGBE_LINK_SPEED_40GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == - TXGBE_CFG_PORT_ST_AML_LINK_25G) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == - TXGBE_CFG_PORT_ST_AML_LINK_10G) - *speed = TXGBE_LINK_SPEED_10GB_FULL; - } else { - *speed = TXGBE_LINK_SPEED_UNKNOWN; - } + if (gpio_ext & gpio_ext_mask) + return true; - return 0; + return false; } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index f1849c8400..c02be3cc34 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -40,7 +40,6 @@ #define SR_PMA_KR_LD_CESTS_RR MS16(15, 0x1) #define SR_PMA_KR_FEC_CTRL 0x0100AB #define SR_PMA_KR_FEC_CTRL_EN MS16(0, 0x1) -#define SR_PMA_RS_FEC_CTRL 0x0100C8 #define SR_MII_MMD_CTL 0x1F0000 #define SR_MII_MMD_CTL_AN_EN 0x1000 #define SR_MII_MMD_CTL_RESTART_AN 0x0200 diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index bc73f28ca2..85d0aee8ff 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -158,6 +158,8 @@ #define TXGBE_RST_SW MS(0, 0x1) #define TXGBE_RST_LAN(i) MS(((i) + 1), 0x1) #define TXGBE_RST_FW MS(3, 0x1) +#define TXGBE_RST_EPHY_LAN_1 MS(16, 0x1) +#define TXGBE_RST_EPHY_LAN_0 MS(19, 0x1) #define TXGBE_RST_MAC_LAN_1 MS(17, 0x1) #define TXGBE_RST_MAC_LAN_0 MS(20, 0x1) #define TXGBE_RST_ETH(i) MS(((i) + 29), 0x1) diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index ede780321f..421abc1145 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -64,6 +64,9 @@ #define TXGBE_AML_ALARM_THRE_MASK 0x1FFE0000U #define TXGBE_AML_DALARM_THRE_MASK 0x0001FFE0U +#define CL74_KRTR_TRAINNING_TIMEOUT 6000 /* 3000ms c74 trainning timeout */ +#define AN_TRAINNING_MODE 0 /* 0: not dis an 1: dis an */ + struct txgbe_thermal_diode_data { s16 temp; s16 alarm_thresh; @@ -690,6 +693,8 @@ struct txgbe_phy_info { s32 (*setup_link_speed)(struct txgbe_hw *hw, u32 speed, bool autoneg_wait_to_complete); s32 (*check_link)(struct txgbe_hw *hw, u32 *speed, bool *link_up); + s32 (*setup_link_core)(struct txgbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete, bool *need_reset); s32 (*get_fw_version)(struct txgbe_hw *hw, u32 *fw_version); s32 (*read_i2c_byte)(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); @@ -732,7 +737,9 @@ struct txgbe_phy_info { u16 ffe_set; u16 ffe_main; u16 ffe_pre; + u16 ffe_pre2; u16 ffe_post; + u16 fec_mode; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -823,6 +830,7 @@ struct txgbe_devargs { struct txgbe_hw { void IOMEM *hw_addr; void *back; + void *dev_back; struct txgbe_mac_info mac; struct txgbe_addr_filter_info addr_ctrl; struct txgbe_fc_info fc; @@ -881,8 +889,12 @@ struct txgbe_hw { /*amlite: new SW-FW mbox */ u8 swfw_index; rte_atomic32_t swfw_busy; + bool link_valid; + bool reconfig_rx; u32 fec_mode; u32 cur_fec_link; + int temperature; + u32 bp_link_mode; }; struct txgbe_backplane_ability { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index e3492c9cd7..32563937b5 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -592,6 +592,17 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) fdir_conf->drop_queue = drop_queue; } +static void +txgbe_override_mac_ops(struct txgbe_hw *hw) +{ + struct txgbe_mac_info *mac = &hw->mac; + + if (hw->phy.multispeed_fiber) + mac->setup_mac_link = txgbe_setup_mac_link_aml; + else + mac->setup_link = txgbe_setup_mac_link_aml; +} + static int eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { @@ -651,6 +662,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) /* Vendor and Device ID need to be set before init of shared code */ hw->back = pci_dev; + hw->dev_back = eth_dev; hw->port_id = eth_dev->data->port_id; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; @@ -686,6 +698,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + if (hw->mac.type == txgbe_mac_aml) + txgbe_override_mac_ops(hw); + /* Unlock any pending hardware semaphore */ txgbe_swfw_lock_reset(hw); @@ -2039,6 +2054,9 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + if (hw->mac.type == txgbe_mac_aml) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); @@ -3087,6 +3105,65 @@ txgbe_tx_ring_recovery(struct rte_eth_dev *dev) } } +void +txgbe_dev_setup_link_alarm_handler_aml(void *param) +{ + struct txgbe_hw *hw = (struct txgbe_hw *)param; + struct rte_eth_dev *dev = (struct rte_eth_dev *)hw->dev_back; + struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev); + u32 speed; + bool autoneg = false; + u32 gssr = hw->phy.phy_semaphore_mask; + + if (!hw) + return; + + speed = hw->phy.autoneg_advertised; + if (!speed) + hw->mac.get_link_capabilities(hw, &speed, &autoneg); + + /* firmware is configuring phy now, delay host driver config action */ + if (hw->mac.acquire_swfw_sync(hw, gssr) != 0) { + rte_eal_alarm_set(1000 * 1000 * 2, + txgbe_dev_setup_link_alarm_handler_aml, hw); + PMD_DRV_LOG(DEBUG, "delay config ephy"); + return; + } + + hw->mac.setup_link(hw, speed, true); + + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + bool link_up = false; + + hw->mac.check_link(hw, &link_speed, &link_up, false); + if (link_up) { + PMD_DRV_LOG(DEBUG, "LINK UP IN HANDLER"); + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; + txgbe_dev_link_update_share(dev, 0); + } + + hw->mac.release_swfw_sync(hw, gssr); + + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; +} + +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete) +{ + bool need_reset = false; + s32 status = 0; + + status = hw->phy.setup_link_core(hw, speed, autoneg_wait_to_complete, &need_reset); + if (status) + return status; + + if (!hw->adapter_stopped && need_reset) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_setup_link_alarm_handler_aml, hw); + + return status; +} + /* * If @timeout_ms was 0, it means that it will not return until link complete. * It returns 1 on complete, return 0 on timeout. @@ -3120,9 +3197,13 @@ txgbe_dev_setup_link_thread_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_adapter *ad = TXGBE_DEV_ADAPTER(dev); + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - txgbe_dev_setup_link_alarm_handler(dev); + if (hw->mac.type == txgbe_mac_aml) + txgbe_dev_setup_link_alarm_handler_aml(hw); + else + txgbe_dev_setup_link_alarm_handler(dev); rte_atomic_store_explicit(&ad->link_thread_running, 0, rte_memory_order_seq_cst); return 0; } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 189fbac541..1ec8e096cc 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -733,6 +733,10 @@ int txgbe_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); void txgbe_dev_setup_link_alarm_handler(void *param); +void txgbe_dev_setup_link_alarm_handler_aml(void *param); +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete); void txgbe_read_stats_registers(struct txgbe_hw *hw, struct txgbe_hw_stats *hw_stats); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* Re: [PATCH v2 12/20] net/txgbe: fix link stability for 25G NIC 2026-04-29 10:25 ` [PATCH v2 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang @ 2026-04-29 15:12 ` Stephen Hemminger 0 siblings, 0 replies; 92+ messages in thread From: Stephen Hemminger @ 2026-04-29 15:12 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev, stable, Jiawen Wu On Wed, 29 Apr 2026 18:25:06 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > The link was previously configured via firmware, but this approach > resulted in unstable link behavior. To resolve the issue, re-add the > PHY configuration flow directly into the driver. > > Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") > Cc: stable@dpdk.org > > Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> > --- AI review feedback spotted some things: Review of this patch is partial; the patch adds 2,489 lines in a new txgbe_e56.c file plus 1,742-line and 275-line headers, and a full per-function trace was not completed. From what I have looked at: Info: drivers/net/txgbe/base/txgbe_e56.c defines a generic file-scope helper named compare for qsort. Even though it's static, the name is unhelpfully generic; consider txgbe_e56_int_cmp or similar. Warning: txgbe_setup_phy_link_aml(): when txgbe_set_link_to_amlite() returns TXGBE_ERR_TIMEOUT the function falls through to the out: label, which then reads TXGBE_PORTSTAT and re-checks link_up. But in the timeout path link_up is whatever the earlier check_phy_link loop left it as, and the function clears hw->link_valid only in this branch — yet check_phy_link reads if (!hw->link_valid) *link_up = false;. After clearing link_valid, no further check_phy_link is called before the out: block reads link_up, so the logic still works, but it's fragile. Worth a comment or restructure. ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v2 13/20] net/txgbe: fix link stability for 40G NIC 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (11 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang ` (6 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 70 +- drivers/net/txgbe/base/txgbe_aml40.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 1471 ++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.c | 4 +- 4 files changed, 1438 insertions(+), 113 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index eefd7119fd..84c130704a 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -24,6 +25,7 @@ void txgbe_init_ops_aml40(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml40; + phy->setup_link_core = txgbe_setup_phy_link_aml40; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml40; @@ -52,6 +54,13 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if (link_up_wait_to_complete) { for (i = 0; i < hw->mac.max_link_up_time; i++) { + if (!hw->link_valid) { + *link_up = false; + + msleep(100); + continue; + } + if (!(links_reg & TXGBE_PORTSTAT_UP)) { *link_up = false; } else { @@ -68,6 +77,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } + if (!hw->link_valid) + *link_up = false; + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) @@ -107,20 +119,24 @@ u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) return txgbe_media_type_fiber_qsfp; } -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; + u32 value; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { - DEBUGOUT("SFP not detected, skip setup mac link"); - return 0; - } + *need_reset = false; + + if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ status = hw->mac.get_link_capabilities(hw, @@ -132,18 +148,43 @@ s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + break; + msleep(250); + } if (link_speed == speed && link_up) - return status; + goto out; - if (speed & TXGBE_LINK_SPEED_40GB_FULL) - speed = 0x20; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) + hw->link_valid = false; + + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + DEBUGOUT("MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + DEBUGOUT("MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + DEBUGOUT("Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -159,6 +200,5 @@ void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw) mac->flap_tx_laser = txgbe_flap_tx_laser_multispeed_fiber; - mac->setup_link = txgbe_setup_mac_link_aml40; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } diff --git a/drivers/net/txgbe/base/txgbe_aml40.h b/drivers/net/txgbe/base/txgbe_aml40.h index f31360c899..d97654fbf8 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.h +++ b/drivers/net/txgbe/base/txgbe_aml40.h @@ -14,7 +14,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw); -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw); #endif /* _TXGBE_AML40_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index a73b247f59..4a880b0a35 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -98,11 +98,29 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + pre1 = S25G_TX_FFE_CFG_DAC_PRE1; + pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + post = S25G_TX_FFE_CFG_DAC_POST; + } else { ffe_main = S25G_TX_FFE_CFG_MAIN; pre1 = S25G_TX_FFE_CFG_PRE1; pre2 = S25G_TX_FFE_CFG_PRE2; post = S25G_TX_FFE_CFG_POST; } + } else if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + ffe_main = S40G_TX_FFE_CFG_MAIN; + pre1 = S40G_TX_FFE_CFG_PRE1; + pre2 = S40G_TX_FFE_CFG_PRE2; + post = S40G_TX_FFE_CFG_POST; + } } if (hw->phy.ffe_set) { @@ -150,6 +168,416 @@ txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) return 0; } +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + int i; + + /* CMS Config Master */ + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + /* TXS Config Master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_TXS_TXS_CFG_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_40GB_FULL); + + /* RXS Config master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_RXS_RXS_CFG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS3_ANA_OVRDVAL_11_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS3_ANA_OVRDVAL_11 *)&rdata)->ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS0_ANA_OVRDEN_2 *)&rdata)->ovrd_en_ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + } + + /* PDIG Config master */ + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw) { @@ -1294,6 +1722,46 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) return status; } +static int txgbe_e56_set_rxs_ufine_le_max_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + int i = 0; + unsigned int CMVAR_UFINE_MAX = 0; + u32 addr; + + for (i = 0; i < 4; i++) { + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + else if (speed == TXGBE_LINK_SPEED_25GB_FULL) + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + + /* a. Assign software defined variables as below */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* Wait until 1milliseconds or greater */ + msleep(10); + } + } + return status; +} + static inline int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) { @@ -1328,38 +1796,269 @@ int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) return status; } -int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) -{ - int status = 0, i, N, median; - unsigned int rdata; - int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane) +{ + int status = 0, i, N, median; + unsigned int rdata; + u32 addr; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + /* Set ovrd_en=0 to read ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* + * As status update from RXS hardware is asynchronous to read status of SECOND_ORDER, + * follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), compare); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) +{ + int status = 0, i, N, median; + unsigned int rdata; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + + /* Set ovrd_en=0 to read ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + + /* + * As status update from RXS hardware is asynchronous to read status + * of SECOND_ORDER, follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), compare); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + int i; + u32 addr; + int temperature; + + for (i = 0; i < 4; i++) { + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + DEBUGOUT("Error Speed\n"); + return 0; + } + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; - /* Set ovrd_en=0 to read ASIC value */ - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + hw->temperature = temperature; - /* - * As status update from RXS hardware is asynchronous to read status - * of SECOND_ORDER, follow sequence mentioned below. - */ - N = 5; - for (i = 0; i < N; i = i + 1) { - /* set RXS_BBCDR_SECOND_ORDER_ST[i] = - * RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] + /* Assign software defined variables as below */ + /* a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER */ + status |= txgbe_e56_rx_rd_second_code_40g(hw, &SECOND_CODE, i); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE */ - EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); - RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, - ana_bbcdr_int_cstm_i); - usec_delay(100); + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + /* Set ovrd_en=1 to override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = FINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_coarse_i) = COARSE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature " + "tracking occurs Error condition"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = FINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_coarse_i) = COARSE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature " + "tracking occurs Error condition"); + } + } } - - /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ - array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); - qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), compare); - - median = ((N + 1) / 2) - 1; - *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; - return status; } @@ -1534,78 +2233,410 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " "temperature tracking occurs Error condition"); } - } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_calib_adapt_seq_40G(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i, j; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypass_ctle = true; + + for (i = 0; i < 4; i++) { + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + + if (bypass_ctle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature tracking + * range here. RXS would be enabled at the end of this sequence. For the case when PAM4 KR + * training is not enabled (including PAM4 mode without KR training), wait until + * ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + for (i = 0; i < 4; i++) { + /* 4. Disable VGA and CTLE training so they don't interfere with ADC calibration */ + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) + & 1) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* + * 6. Perform ADC offset adaptation and ADC gain adaptation, repeat them a few + * times and after that keep it disabled. + */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_gain_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ - return status; -} -static inline int -txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) -{ - unsigned int rdata; + /* + * 7. Perform ADC interleaver adaptation for 10ms or greater, + * and after that disable it + * a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + /* + * 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking + * changes in temperature or voltage + */ + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); - if (speed == TXGBE_LINK_SPEED_40GB_FULL) { - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + if (timer++ > PHYINIT_TIMEOUT) + break; + } - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + if (bypass_ctle == 0) { + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); } - return 0; + return status; } static inline int @@ -1978,20 +3009,42 @@ txgbe_e56_cfg_temp(struct txgbe_hw *hw) return 0; } -static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +static int txgbe_e56_config_rx_40G(struct txgbe_hw *hw, u32 speed) { s32 status; - status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + status = txgbe_e56_rxs_calib_adapt_seq_40G(hw, speed); if (status) return status; /* Step 2 of 2.3.4 */ - txgbe_e56_set_rxs_ufine_le_max(hw, speed); + txgbe_e56_set_rxs_ufine_le_max_40g(hw, speed); /* 2.3.4 RXS post CDR lock temperature tracking sequence */ - txgbe_temp_track_seq(hw, speed); + txgbe_temp_track_seq_40g(hw, speed); + + hw->link_valid = true; + + return 0; +} +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + txgbe_e56_config_rx_40G(hw, speed); + } else { + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + } return 0; } @@ -2001,6 +3054,151 @@ static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) * Completion of RXS powerdown can be confirmed by * observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST */ +static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + int i; + + for (i = 0; i < 4; i++) { + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + rdata = 0x0000; + addr = E56G__RXS0_ANA_OVRDEN_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + addr = E56G__PMD_RXS0_OVRDEN_0_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_3_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_DIG_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 2. Disable pattern checker */ + addr = E56G__RXS0_DFT_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_DFT_1, ber_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 3. Disable internal serial loopback mode */ + addr = E56G__RXS0_ANA_OVRDEN_3_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* 4. Enable bypass of clock gates in RXS - */ + addr = E56G__RXS0_RXS_CFG_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en) = 0x1FFF; + wr32_ephy(hw, addr, rdata); + } + + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + addr = E56G__PMD_BASER_PMD_CONTROL_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln1) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln2) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln3) = 0; + wr32_ephy(hw, addr, rdata); + + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + addr = E56G__PMD_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en) = 0x0; + wr32_ephy(hw, addr, rdata); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != 0x21) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + static int txgbe_e56_disable_rx(struct txgbe_hw *hw) { int status = 0; @@ -2133,8 +3331,13 @@ int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST * and confirm its value is POWERDN_ST */ - txgbe_e56_disable_rx(hw); - status = txgbe_e56_config_rx(hw, speed); + if (hw->mac.type == txgbe_mac_aml40) { + txgbe_e56_disable_rx40G(hw); + status = txgbe_e56_config_rx_40G(hw, speed); + } else { + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + } addr = E56PHY_INTR_0_ADDR; wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); @@ -2201,6 +3404,86 @@ int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) set_fields_e56(&value, 12, 12, 0); wr32_epcs(hw, SR_AN_CTRL, value); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0x3); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0x4); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_40g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0xf); + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { value = rd32_epcs(hw, SR_PCS_CTRL1); set_fields_e56(&value, 5, 2, 5); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 32563937b5..d515419028 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2054,7 +2054,7 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); @@ -3200,7 +3200,7 @@ txgbe_dev_setup_link_thread_handler(void *param) struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) txgbe_dev_setup_link_alarm_handler_aml(hw); else txgbe_dev_setup_link_alarm_handler(dev); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (12 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang ` (5 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe.h | 2 + drivers/net/txgbe/base/txgbe_aml.c | 65 +- drivers/net/txgbe/base/txgbe_aml40.c | 43 +- drivers/net/txgbe/base/txgbe_e56.c | 22 +- drivers/net/txgbe/base/txgbe_e56.h | 2 + drivers/net/txgbe/base/txgbe_e56_bp.c | 2593 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 3 + drivers/net/txgbe/base/txgbe_hw.c | 6 + drivers/net/txgbe/base/txgbe_hw.h | 4 +- drivers/net/txgbe/base/txgbe_osdep.h | 4 + drivers/net/txgbe/base/txgbe_phy.c | 21 + drivers/net/txgbe/base/txgbe_phy.h | 22 + drivers/net/txgbe/base/txgbe_type.h | 25 +- drivers/net/txgbe/txgbe_ethdev.c | 109 +- drivers/net/txgbe/txgbe_ethdev.h | 2 +- 16 files changed, 2894 insertions(+), 30 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index 305c0291e3..a9a02577ce 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -13,4 +13,5 @@ base_sources = files( 'txgbe_phy.c', 'txgbe_vf.c', 'txgbe_e56.c', + 'txgbe_e56_bp.c', ) diff --git a/drivers/net/txgbe/base/txgbe.h b/drivers/net/txgbe/base/txgbe.h index 673a299860..27c3e3be38 100644 --- a/drivers/net/txgbe/base/txgbe.h +++ b/drivers/net/txgbe/base/txgbe.h @@ -13,5 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_vf.h" #include "txgbe_dcb.h" +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" #endif /* _TXGBE_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index cdaa13c763..5cc8741f10 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -84,6 +85,13 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *speed = TXGBE_LINK_SPEED_UNKNOWN; } + if (txgbe_xpcs_an_enabled(hw)) { + if (!hw->an_done) { + *link_up = false; + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + } + return 0; } @@ -95,23 +103,41 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; + } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + hw->devarg.auto_neg = false; + *autoneg = false; + } else { + *autoneg = true; + } + *speed = hw->phy.fiber_suppport_speed; } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core0 || hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core1 || hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1) { + hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { *speed = TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; - } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { - *speed = TXGBE_LINK_SPEED_25GB_FULL; + } else if (hw->phy.media_type == txgbe_media_type_backplane) { + /* Backplane */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; + /* Backplane supports autonegotiation */ + *autoneg = hw->devarg.auto_neg; + } else if (hw->phy.media_type == txgbe_media_type_fiber) { + /* Fiber */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; } else { - /* SFP */ - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else - *speed = TXGBE_LINK_SPEED_10GB_FULL; - *autoneg = true; + /* Unknown */ + *speed = TXGBE_LINK_SPEED_UNKNOWN; + *autoneg = false; + PMD_DRV_LOG(DEBUG, "GET link capabilities failed"); + return TXGBE_ERR_LINK_SETUP; } return 0; @@ -193,7 +219,7 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) { DEBUGOUT("SFP not detected, skip setup mac link"); return 0; } @@ -216,6 +242,23 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return 0; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { DEBUGOUT("RX LOS"); diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 84c130704a..d350f18c4b 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -14,6 +14,7 @@ #include "txgbe_aml.h" #include "txgbe_aml40.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -98,7 +99,10 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = false; + *autoneg = true; + } else if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = true; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -115,8 +119,22 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) { - UNREFERENCED_PARAMETER(hw); - return txgbe_media_type_fiber_qsfp; + u8 device_type = hw->subsystem_device_id & 0xF0; + enum txgbe_media_type media_type; + + switch (device_type) { + case TXGBE_DEV_ID_KR_KX_KX4: + media_type = txgbe_media_type_backplane; + break; + case TXGBE_DEV_ID_SFP: + media_type = txgbe_media_type_fiber_qsfp; + break; + default: + media_type = txgbe_media_type_unknown; + break; + } + + return media_type; } s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, @@ -135,7 +153,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ @@ -148,6 +166,23 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return status; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 4a880b0a35..5725b8d944 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -49,7 +49,7 @@ int compare(const void *a, const void *b) } s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) + bool *link_up) { u32 rdata = 0; u32 links_reg = 0; @@ -97,7 +97,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; pre2 = S25G_TX_FFE_CFG_DAC_PRE2; @@ -115,7 +116,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; pre2 = S40G_TX_FFE_CFG_PRE2; @@ -1504,7 +1506,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1539,7 +1541,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) if (((rdata >> (i * 8)) & 0x3f) == 0x21) break; if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1616,7 +1618,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1663,7 +1665,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) if (((rdata >> (i * 8)) & 0x3f) == 0x21) break; if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1932,7 +1934,7 @@ int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; } else { - DEBUGOUT("Error Speed\n"); + DEBUGOUT("Error Speed"); return 0; } @@ -3191,7 +3193,7 @@ static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) rdata = rd32_ephy(hw, addr); usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } @@ -3297,7 +3299,7 @@ static int txgbe_e56_disable_rx(struct txgbe_hw *hw) break; usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index eaa3ea5085..67ccdc8c7c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1735,6 +1735,8 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up); s32 txgbe_e56_fec_set(struct txgbe_hw *hw); s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c new file mode 100644 index 0000000000..4928c888bb --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -0,0 +1,2593 @@ +#include "txgbe_e56.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" +#include "txgbe_e56_bp.h" +#include "txgbe.h" +#include "../txgbe_logs.h" + +static int +txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + u32 rdata, addr; + u32 ULTRAFINE_CODE[4] = {0}; + int lane_num = 0, lane_idx = 0; + u32 CMVAR_UFINE_MAX = 0; + + switch (speed) { + case 10: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + case 40: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 4; + break; + case 25: + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* ii get rx ana_bbcdr_ultrafine_i[14, 12] per lane */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE[lane_idx] = FIELD_GET_M(GENMASK(14, 12), rdata); + BP_LOG("ULTRAFINE_CODE[%d] = %d, CMVAR_UFINE_MAX: %x\n", + lane_idx, ULTRAFINE_CODE[lane_idx], CMVAR_UFINE_MAX); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE[lane_idx] > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE[lane_idx] -= 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 12, ULTRAFINE_CODE[lane_idx]); + wr32_ephy(hw, addr, rdata); + + /* ovrd_en_ana_bbcdr_ultrafine=1 override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + wr32_ephy(hw, addr, rdata | BIT(3)); + + /* Wait until 1milliseconds or greater */ + usec_delay(1000); + } + } + return 0; +} + +static int txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, + u32 speed) +{ + int OFFSET_CENTRE_RANGE_H[4] = {0}, OFFSET_CENTRE_RANGE_L[4] = {}, RANGE_FINAL[4] = {}; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int status = 0, lane_num = 0; + int T = 40, lane_id = 0; + u32 addr, rdata; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + switch (speed) { + case 10: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 1; + break; + case 40: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 4; + break; + case 25: + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* 2. Define software variable RX_COARSE_MID_TD */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 1 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_H[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_H[lane_id] = OFFSET_CENTRE_RANGE_H[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_H[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_H[lane_id]; + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 2 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0xf); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 3 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_L[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_L[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_L[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_L[lane_id]; + } + for (lane_id = 0; lane_id < lane_num; lane_id++) { + RANGE_FINAL[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] < + OFFSET_CENTRE_RANGE_H[lane_id] ? + CMVAR_RANGE_L : CMVAR_RANGE_H; + BP_LOG("lane_id:%d-RANGE_L:%x-RANGE_H:%x-RANGE_FINAL:%x\n", + lane_id, OFFSET_CENTRE_RANGE_L[lane_id], + OFFSET_CENTRE_RANGE_H[lane_id], RANGE_FINAL[lane_id]); + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 4 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, RANGE_FINAL[lane_id]); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x0); + wr32_ephy(hw, addr, rdata); + } + + /* Do SEQ::RX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + + return status; +} + +static int txgbe_e56_rxs_post_cdr_lock_temp_track_seq(struct txgbe_hw *hw, + u32 speed) +{ + int status = 0; + u32 rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH = 0; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX = 0; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX = 0; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH = 0; + int CMVAR_UFINE_MIN = 0; + int CMVAR_FINE_MIN = 0; + int CMVAR_UFINE_UMIN_WRAP = 0; + int CMVAR_COARSE_MIN = 0; + int CMVAR_UFINE_FMIN_WRAP = 0; + int CMVAR_FINE_FMIN_WRAP = 0; + + if (speed == 10) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == 25) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } + + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + BP_LOG("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature tracking occurs Error condition\n"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + BP_LOG("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature tracking occurs Error condition\n"); + } + } + + return status; +} + +static int txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u8 bp_link_mode) +{ + u32 rdata; + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (bp_link_mode == 40) { + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_adc_adapt_seq(struct txgbe_hw *hw, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + u32 rdata = 0, addr = 0; + int status = 0; + + int timer = 0, j = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait RXS0-3_OVRDVAL[1]::rxs0-3_rx0_cdr_rdy_o = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(12)), + 100, 2000, hw, 0x1544); + if (status) + BP_LOG("rxs%d_rx0_cdr_rdy_o = %x, %s.\n", + lane_idx, rdata, + status ? "FAILED" : "SUCCESS"); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* 4. Disable VGA and CTLE training so they don't interfere with ADC calibration */ + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 14, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 9, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_intl_cal_done_o bit17 = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(17)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_intl_cal_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_ofst_adapt_done_o bit26 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, + !(rdata & BIT(26)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_ofst_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_gain_adapt_done_o bit29 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, !(rdata & BIT(29)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_gain_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* 7. Perform ADC interleaver adaptation for 10ms or greater, + * and after that disable it + */ + /* a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(20); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + /* set ovrd_en_rxs0_rx0_adc_intl_adapt_en_i=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0); + wr32_ephy(hw, addr, rdata); + + /* 8. Now re-enable VGA and CTLE trainings, so that it continues + * to adapt tracking changes in temperature or voltage + * <1>Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + */ + /* set rxs0_rx0_vga_train_en_i=1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x1); + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* <2>wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 */ + /* set ovrd_en_rxs0_rx0_vga_train_done_o = 0 */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0x0); + wr32_ephy(hw, addr, rdata); + + /* Wait rxs0_rx0_vga_train_done_o bit8 = 0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(8)), + 100, 3000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_vga_train_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + if (bypass_ctle == 0) { + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0); + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + wr32_ephy(hw, addr, rdata); + } + + return status; +} + +static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, + u8 bp_link_mode, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + int status = 0; + u32 rdata, addr; + + switch (bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + } + if (bypass_ctle != 0) + status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); + + status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + + /* Wait an fsm_rx_sts 25G */ + BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); + + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x1b1b1b1b & GENMASK(8 * lane_num - 1, 0))), + 1000, 300, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("wait ctrl_fsm_rx0_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + return status; +} + +static int txgbe_e56_cms_cfg_for_temp_track_range(struct txgbe_hw *hw) +{ + int status = 0, T = 40; + u32 addr, rdata; + + status = txgbe_e56_get_temp(hw, &T); + if (T < 40) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + } else if (T > 70) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + } else { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_10_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + } + return status; +} + +static int txgbe_e56_bp_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_e56_bp_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 0x18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode) +{ + int status = 0; + u32 rdata = 0; + + u32 speed_select = 0; + u32 pcs_type_sel = 0; + u32 cns_en = 0; + u32 rsfec_en = 0; + u32 pma_type = 0; + u32 an0_rate_select = 0; + + switch (bp_link_mode) { + case 10: + bp_link_mode = 10; + speed_select = 0; /* 10 Gb/s */ + pcs_type_sel = 0; /* 10GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0xb; /* 10GBASE-KR PMA/PMD type */ + an0_rate_select = 2; /* 10G-KR */ + break; + case 40: + bp_link_mode = 40; + speed_select = 3; /* 40 Gb/s */ + pcs_type_sel = 4; /* 40GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0b0100001; /* 40GBASE-CR PMA/PMD type */ + an0_rate_select = 4; /* 40G-KR: 3 40G-CR: 4 */ + break; + case 25: + bp_link_mode = 25; + speed_select = 5; /* 25 Gb/s */ + pcs_type_sel = 7; /* 25GBASE-R PCS Type */ + cns_en = 1; /* CNS_EN */ + rsfec_en = 1; /* RS-FEC enable*/ + pma_type = 0b0111001; /* 25GBASE-KR PMA/PMD type */ + an0_rate_select = 9; /* 9/10/17 25GK/CR-S or 25GK/CR */ + break; + default: + BP_LOG("%s %d :Invalid bp_link_mode\n", __func__, __LINE__); + break; + } + + hw->curbp_link_mode = bp_link_mode; + /* To switch to the 40G mode Ethernet operation, complete the following steps:*/ + /* 1. Initiate the vendor-specific software reset by programming + * the VR_RST field (bit [15]) of the VR_PCS_DIG_CTRL1 register to 1. + */ + rdata = rd32_epcs(hw, 0x038000); + wr32_epcs(hw, 0x038000, rdata | BIT(15)); + + /* 2. Wait for the hardware to clear the value for the VR_RST + * field (bit [15]) of the VR_PCS_DIG_CTRL1 register. + */ + BP_LOG("Wait for the bit [15] (VR_RST) to get cleared.\n"); + status = kr_read_poll(rd32_ephy, rdata, + FIELD_GET_M(BIT(15), rdata) == 0, 100, + 2000, hw, 0x038000); + BP_LOG("Wait PHY VR_RST = %x, Wait VR_RST %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* 3. Write 4'b0011 to bits [5:2] of the SR_PCS_CTRL1 register. + * 10G: 0 25G: 5 40G: 3 + */ + rdata = rd32_epcs(hw, 0x030000); + set_fields_e56(&rdata, 5, 2, speed_select); + wr32_epcs(hw, 0x030000, rdata); + + /* 4. Write pcs mode sel to bits [3:0] of the SR_PCS_CTRL2 register. + * 10G: 0 25G: 4'b0111 40G: 4'b0100 + */ + rdata = rd32_epcs(hw, 0x030007); + set_fields_e56(&rdata, 3, 0, pcs_type_sel); + wr32_epcs(hw, 0x030007, rdata); + + /* 0 1 1 1 0 0 1 : 25GBASE-KR or 25GBASE-KR-S PMA/PMD type + * 0 1 1 1 0 0 0 : 25GBASE-CR or 25GBASE-CR-S PMA/PMD type + * 0 1 0 0 0 0 1 : 40GBASE-CR4 PMA/PMD type + * 0 1 0 0 0 0 0 : 40GBASE-KR4 PMA/PMD type + * 0 0 0 1 0 1 1 : 10GBASE-KR PMA/PMD type + */ + rdata = rd32_epcs(hw, 0x010007); + set_fields_e56(&rdata, 6, 0, pma_type); + wr32_epcs(hw, 0x010007, rdata); + + /* 5. Write only 25g en to Bits [1:0] of VR_PCS_DIG_CTRL3 register. */ + rdata = rd32_epcs(hw, 0x38003); + set_fields_e56(&rdata, 1, 0, cns_en); + wr32_epcs(hw, 0x38003, rdata); + + /* 6. Program PCS_AM_CNT field of VR_PCS_AM_CNT register to 'd16383 to + * configure the alignment marker interval. To speed-up simulation, + * program a smaller value to this field. + */ + if (bp_link_mode == 40) + wr32_epcs(hw, 0x38018, 16383); + + /* 7. Program bit [2] of SR_PMA_RS_FEC_CTRL register to 0 + * if previously 1 (as RS-FEC is supported in 25G Mode). + */ + + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, rsfec_en); + wr32_epcs(hw, 0x100c8, rdata); + + /* 8. To enable BASE-R FEC (if desired), set bit [0]. + * in SR_PMA_KR_FEC_CTRL register + */ + + /* 4. set phy an status to 0 */ + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, 0xe); + wr32_ephy(hw, 0x1434, rdata); + + /* 9. Program Enterprise 56G PHY regs through its own APB interface: + * a. Program PHY registers as mentioned in Table 6-6 on page 1197 to + * configure the PHY to 40G + * Mode. For fast-simulation mode, additionally program, + * the registers shown in the Table 6-7 on page 1199 + * b. Enable the PMD by setting pmd_en field in PMD_CFG[0] (0x1400) + * register + */ + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&rdata, 29, 29, 0x1); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&rdata, 30, 30, 0x1); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&rdata, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&rdata, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&rdata, 18, 8, 0x294); + set_fields_e56(&rdata, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&rdata, 30, 28, 0x7); + set_fields_e56(&rdata, 26, 24, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) + set_fields_e56(&rdata, 18, 16, 0x5); + else if (bp_link_mode == 25) + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 14, 12, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&rdata, 26, 24, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) { + set_fields_e56(&rdata, 18, 16, 0x5); + set_fields_e56(&rdata, 2, 0, 0x5); + } else if (bp_link_mode == 25) { + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 2, 0, 0x3); + } + wr32_ephy(hw, DATAPATH_CFG1, rdata); + + rdata = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&rdata, 4, 0, an0_rate_select); + wr32_ephy(hw, AN_CFG1, rdata); + + status = txgbe_e56_cms_cfg_for_temp_track_range(hw); + + if (bp_link_mode == 10) + txgbe_e56_bp_cfg_10g(hw); + else if (bp_link_mode == 25) + txgbe_e56_bp_cfg_25g(hw); + else if (bp_link_mode == 40) + txgbe_e56_cfg_40g(hw); + + return status; +} + +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode, u32 need_restart) +{ + int status = 0; + u32 rdata; + + UNREFERENCED_PARAMETER(bp_link_mode); + + hw->an_done = false; + if (hw->curbp_link_mode == 10 && !need_restart) + return 0; + BP_LOG("Setup to backplane mode ==========\n"); + + u32 backplane_mode = 0; + u32 fec_advertise = 0; + + hw->an_done = false; + /* pcs + phy rst */ + rdata = rd32(hw, 0x1000c); + if (hw->bus.lan_id == 1) + rdata |= BIT(16); + else + rdata |= BIT(19); + wr32(hw, 0x1000c, rdata); + msleep(20); + + /* clear interrupt */ + wr32_epcs(hw, 0x070000, 0); + wr32_epcs(hw, 0x030000, 0x8000); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + wr32_epcs(hw, 0x078002, 0x0000); + /* pcs case fec en to work around first */ + wr32_epcs(hw, 0x100ab, 1); + + if (txgbe_is_backplane(hw)) { + /* backplane 10G/25G/40G */ + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + /* default all speed */ + if ((hw->device_id & 0xFF) == 0x10) { + backplane_mode |= BIT(7); + fec_advertise |= TXGBE_10G_FEC_ABL; + } else if ((hw->device_id & 0xFF) == 0x25) { + backplane_mode |= BIT(14) | BIT(15); + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } else if ((hw->device_id & 0xFF) == 0x40) { + if (hw->phy.bp_capa == 0) + /* original configure: KR4 + CR4 */ + backplane_mode |= BIT(9) | BIT(8); + else if (hw->phy.bp_capa == 1) + /* only 40GBASE-KR4 */ + backplane_mode |= BIT(8); + else if (hw->phy.bp_capa == 2) + /* only 40GBASE-CR4 */ + backplane_mode |= BIT(9); + fec_advertise |= TXGBE_10G_FEC_ABL; + BP_LOG("Advertised abilities: %d\n", backplane_mode); + } + } else { + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) + == TXGBE_LINK_SPEED_10GB_FULL) { + backplane_mode |= 0x80; + fec_advertise |= TXGBE_10G_FEC_ABL; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) + == TXGBE_LINK_SPEED_25GB_FULL) { + backplane_mode |= 0xc000; + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) + == TXGBE_LINK_SPEED_40GB_FULL) { + backplane_mode |= BIT(9) | BIT(8); + fec_advertise |= TXGBE_10G_FEC_ABL; + } + } + + wr32_epcs(hw, 0x070010, 0x0001); + + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + wr32_epcs(hw, 0x070011, backplane_mode | 0x11); + + /* BASE-R FEC */ + rdata = rd32_epcs(hw, 0x70012); + wr32_epcs(hw, 0x70012, fec_advertise); + + wr32_epcs(hw, 0x070016, 0x0000); + wr32_epcs(hw, 0x070017, 0x0); + wr32_epcs(hw, 0x070018, 0x0); + + /* config timer */ + wr32_epcs(hw, 0x078004, 0x003c); + wr32_epcs(hw, 0x078005, CL74_KRTR_TRAINNING_TIMEOUT); + wr32_epcs(hw, 0x078006, 25); + wr32_epcs(hw, 0x078000, 0x0008 | BIT(2)); + + BP_LOG("1.2 Wait 10G KR phy/pcs mode init ....\n"); + status = txgbe_set_phy_link_mode(hw, 10); + BP_LOG("Wait 10g phy/pcs mode init = %x, %s.\n", rdata, + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status ? "FAILED" : "SUCCESS"); + + /* 5. CM_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, 0x3); /* pll en */ + set_fields_e56(&rdata, 19, 12, 0x0); /* tx disable */ + set_fields_e56(&rdata, 8, 8, 0x0); /* pmd mode */ + set_fields_e56(&rdata, 1, 1, 0x1); /* pmd en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 6, TX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 12, 0x1); /* tx en */ + wr32_ephy(hw, 0x1400, rdata); + + BP_LOG("1.3 Wait 10G PHY RXS....\n"); + status = txgbe_e56_rxs_osc_init_for_temp_track_range(hw, 10); + BP_LOG("Wait 10G PHY/RXS mode init = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* Wait an 10g fsm_rx_sts */ + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0x3f) == 0xb), 1000, + 200, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("Wait 10g fsm_rx_sts = %x, Wait rx_sts %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + BP_LOG("Setup the backplane mode========end ==\n"); + + return status; +} + +static void txgbe_e56_print_page_status(struct txgbe_hw *hw, + struct txgbe_backplane_ability *local_ability, + struct txgbe_backplane_ability *lp_ability) +{ + u32 rdata = 0; + + /* Read the local AN73 Base Page Ability Registers */ + BP_LOG("Read the local Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG1); + local_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70010 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG2); + BP_LOG("\tread 70011 data %0x\n", rdata); + local_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + /* amber-lite only support 10GKR - 25GKR/CR - 25GKR-S/CR-S */ + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + local_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + local_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + local_ability->fec_ability = rdata; + BP_LOG("\tread 70012 data %0x\n", rdata); + + /* Read the link partner AN73 Base Page Ability Registers */ + BP_LOG("Read the link partner Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL1); + lp_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70013 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL2); + lp_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + BP_LOG("\tread 70014 data %0x\n", rdata); + BP_LOG("\tKX : %x\tKX4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_1000BASE_KX) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_10GBASE_KX4) ? 1 : 0); + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + lp_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + lp_ability->fec_ability = rdata; + + hw->phy.fec_mode = 0; + if (rdata & TXGBE_25G_RS_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_RS_FEC_REQ; + if (rdata & TXGBE_25G_BASE_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_BASE_FEC_REQ; + if (rdata & TXGBE_10G_FEC_ABL) + hw->phy.fec_mode |= TXGBE_10G_FEC_ABL; + if (rdata & TXGBE_10G_FEC_REQ) + hw->phy.fec_mode |= TXGBE_10G_FEC_REQ; + BP_LOG("\tread 70015 data %0x\n", rdata); + + BP_LOG("\tread 70016 data %0x\n", rd32_epcs(hw, 0x70016)); + BP_LOG("\tread 70017 data %0x\n", rd32_epcs(hw, 0x70017)); + BP_LOG("\tread 70018 data %0x\n", rd32_epcs(hw, 0x70018)); + BP_LOG("\tread 70019 data %0x\n", rd32_epcs(hw, 0x70019)); + BP_LOG("\tread 7001a data %0x\n", rd32_epcs(hw, 0x7001a)); + BP_LOG("\tread 7001b data %0x\n", rd32_epcs(hw, 0x7001b)); +} + +static int chk_bkp_ability(struct txgbe_hw *hw, + struct txgbe_backplane_ability local_ability, + struct txgbe_backplane_ability lp_ability) +{ + unsigned int com_link_ability; + + BP_LOG("CheckBkpAn73Ability():\n"); + /* Check the common link ability and take action based on the result*/ + com_link_ability = local_ability.link_ability & + lp_ability.link_ability; + BP_LOG("comAbility= 0x%x, Ability= 0x%x, lpAbility= 0x%x\n", + com_link_ability, local_ability.link_ability, + lp_ability.link_ability); + + if (com_link_ability == 0) { + hw->bp_link_mode = 0; + BP_LOG("Do not support any compatible speed mode!\n"); + return -EINVAL; + } else if (com_link_ability & BIT(ABILITY_40GBASE_KR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_KR4].\n"); + hw->bp_link_mode = 40; + } else if (com_link_ability & BIT(ABILITY_40GBASE_CR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_CR4].\n"); + hw->bp_link_mode = 40; + } else if (com_link_ability & BIT(ABILITY_25GBASE_KRCR_S)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR_S].\n"); + hw->fec_mode = TXGBE_25G_RS_FEC_REQ; + hw->bp_link_mode = 25; + } else if (com_link_ability & BIT(ABILITY_25GBASE_KRCR)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR].\n"); + hw->bp_link_mode = 25; + } else if (com_link_ability & BIT(ABILITY_10GBASE_KR)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KR].\n"); + hw->bp_link_mode = 10; + } else if (com_link_ability & BIT(ABILITY_10GBASE_KX4)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KX4].\n"); + hw->bp_link_mode = 10; + } else if (com_link_ability & BIT(ABILITY_1000BASE_KX)) { + BP_LOG("Link mode is [ABILITY_1000BASE_KX].\n"); + hw->bp_link_mode = 1; + } else { + BP_LOG("No compatible link mode found!\n"); + return -EINVAL; + } + + return 0; +} + +static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +{ + struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; + u32 an_int, base_page = 0; + int count = 0; + + an_int = rd32_epcs(hw, 0x78002); + /* 500ms timeout */ + if (!(an_int & VR_AN_INTR_PG_RCV)) + return -EINVAL; + + for (count = 0; count < 500; count++) { + u32 fsm = rd32_epcs(hw, 0x78010); + u32 rdata = rd32_epcs(hw, 0x78002); + + BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + an_int = rdata; + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + if (an_int & VR_AN_INTR_PG_RCV) { + u32 addr; + + txgbe_e56_print_page_status(hw, &local_ability, &lp_ability); + addr = base_page == 0 ? 0x70013 : 0x70019; + rdata = rd32_epcs(hw, addr); + if (rdata & BIT(14)) { + if (rdata & BIT(15)) { + /* always set null message */ + wr32_epcs(hw, 0x70016, 0x2001); + BP_LOG("write 70016 0x%0x\n", + 0x2001); + } + base_page = 1; + } + } + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } + usec_delay(100); + } + +check_ability: + return chk_bkp_ability(hw, local_ability, lp_ability); +} + +static int txgbe_e56_cl72_trainning(struct txgbe_hw *hw) +{ + u32 bylinkmode = hw->bp_link_mode; + u8 bypass_ctle = hw->bypass_ctle; + int status = 0, temp_data = 0; + u32 lane_num = 0, lane_idx = 0; + u32 __rte_unused pmd_ctrl = 0, txffe = 0; + int ret = 0; + u32 rdata; + + u8 pll_en_cfg = 0; + u8 pmd_mode = 0; + + switch (bylinkmode) { + case 10: + bylinkmode = 10; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + case 40: + bylinkmode = 40; + lane_num = 4; + pll_en_cfg = 0; /* pll_en_cfg : single link to 0 */ + pmd_mode = 1; /* pmd mode : 1 - single link */ + break; + case 25: + bylinkmode = 25; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); + status = txgbe_set_phy_link_mode(hw, bylinkmode); + + /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1434, rdata); + + /* 14 and 15. kr training: set BASER_PMD_CONTROL[0, 7] for lane0-4 */ + rdata = rd32_ephy(hw, 0x1640); + set_fields_e56(&rdata, 7, 0, GENMASK(2 * lane_num - 1, 0)); + wr32_ephy(hw, 0x1640, rdata); + + /* 16. enable CMS and its internal PLL */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, pll_en_cfg); + set_fields_e56(&rdata, 19, 12, 0); /* tx/rx off */ + set_fields_e56(&rdata, 8, 8, pmd_mode); + set_fields_e56(&rdata, 1, 1, 0x1); /* pmd en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 17. tx enable PMD_CFG[0] */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 15, 12, GENMASK(lane_num - 1, 0)); /* tx en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 18 */ + /* 19. rxs calibration and adaotation sequeence */ + BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); + ret |= status; + /* 20 */ + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + status = txgbe_e56_get_temp(hw, &temp_data); + if (bylinkmode == 40) + status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); + else + status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + /* 21 */ + BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0xe) & GENMASK(lane_num, 1)) == + (0xe & GENMASK(lane_num, 1)), 100, + 10000, hw, 0x163c); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, status ? "FAILED" : "SUCCESS", + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + ret |= status; + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } + + /* 22 */ + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + + return ret; +} + +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw) +{ + int status = 0; + u32 rdata; + + BP_LOG("2.1 Wait page changed ....\n"); + status = txgbe_e56_exchange_page(hw); + if (status) { + BP_LOG("Exchange page failed\n"); + return status; + } + + BP_LOG("2.2 Wait page changed ..done..\n"); + wr32_epcs(hw, 0x100ab, 0); + if (AN_TRAINNING_MODE) { + rdata = rd32_epcs(hw, 0x70000); + BP_LOG("read 0x70000 data %0x\n", rdata); + wr32_epcs(hw, 0x70000, 0); + BP_LOG("write 0x70000 0x%0x\n", 0); + } + + rdata = rd32_epcs(hw, 0x78002); + BP_LOG("read 78002 data %0x and clear page int\n", rdata); + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + + /* dis phy tx/rx lane */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, 0x1400, rdata); + BP_LOG("Ephy Write A: 0x%x, D: 0x%x\n", 0x1400, rdata); + + /* wait rx/tx/cm powerdn_st */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + if (hw->phy.fec_mode & TXGBE_25G_RS_FEC_REQ) { + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, 1); + wr32_epcs(hw, 0x100c8, rdata); + BP_LOG("Advertised FEC modes : %s\n", "RS-FEC"); + hw->cur_fec_link = TXGBE_PHY_FEC_RS; + } else if (hw->phy.fec_mode & TXGBE_25G_BASE_FEC_REQ) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "25GBASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else if (hw->fec_mode & (TXGBE_10G_FEC_REQ)) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "BASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else { + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "NONE"); + hw->cur_fec_link = TXGBE_PHY_FEC_OFF; + } + + status = txgbe_e56_cl72_trainning(hw); + + rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, rdata); + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + return status; +} diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index c58c061ea1..3e08d68545 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -272,4 +272,7 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_10_ADDR (E56PHY_CMS_BASE_ADDR + 0xD8) #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode, u32 need_restart); +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 3b683eaa04..1a297acaa6 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4069,6 +4069,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } +bool txgbe_is_backplane(struct txgbe_hw *hw) +{ + return hw->phy.get_media_type(hw) == txgbe_media_type_backplane ? + true : false; +} + bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index bc34d639eb..b44190bc34 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -118,6 +118,6 @@ s32 txgbe_reinit_fdir_tables(struct txgbe_hw *hw); bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw); s32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr); s32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr, u32 *data); -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up); +bool txgbe_is_backplane(struct txgbe_hw *hw); +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask); #endif /* _TXGBE_HW_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index f4282b3241..da069e94f6 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -162,6 +162,10 @@ static inline u64 REVERT_BIT_MASK64(u64 mask) ((mask & 0xFFFFFFFF00000000) >> 32); } +#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) +#define GENMASK(h, l) \ + (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + #define IOMEM #define BIT(nr) (1UL << (nr)) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index bf7260a295..f3e3491b30 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -2503,6 +2503,27 @@ void txgbe_set_phy_temp(struct txgbe_hw *hw) } } +int txgbe_is_dac_cable(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) + return true; + + return false; +} + +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) +{ + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) + return false; + + return hw->devarg.auto_neg ? true : false; +} + /** * txgbe_kr_handle - Handle the interrupt of auto-negotiation * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index c02be3cc34..3fe7a34409 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -105,6 +105,8 @@ #define VR_AN_INTR_CMPLT MS16(0, 0x1) #define VR_AN_INTR_LINK MS16(1, 0x1) #define VR_AN_INTR_PG_RCV MS16(2, 0x1) +#define TXGBE_E56_AN_TXDIS MS16(3, 0x1) +#define TXGBE_E56_AN_PG_RCV MS16(4, 0x1) #define VR_AN_KR_MODE_CL 0x078003 #define VR_AN_KR_MODE_CL_PDET MS16(0, 0x1) #define VR_XS_OR_PCS_MMD_DIGI_CTL1 0x038000 @@ -428,6 +430,24 @@ #define TXGBE_BP_M_NAUTO 0 #define TXGBE_BP_M_AUTO 1 +#define kr_read_poll(op, val, cond, sleep_us, \ + times, args...) \ +({ \ + unsigned long __sleep_us = (sleep_us); \ + u32 __times = (times); \ + u32 i; \ + int __cond = 0; \ + for (i = 0; i < __times; i++) { \ + (val) = op(args); \ + if (cond) { \ + __cond = 1; \ + break; \ + } \ + usleep(__sleep_us);\ + } \ + (__cond) ? 0 : -1; \ +}) + #ifndef CL72_KRTR_PRBS_MODE_EN #define CL72_KRTR_PRBS_MODE_EN 0xFFFF /* open kr prbs check */ #endif @@ -490,6 +510,8 @@ void txgbe_autoc_write(struct txgbe_hw *hw, u64 value); void txgbe_bp_mode_set(struct txgbe_hw *hw); void txgbe_set_phy_temp(struct txgbe_hw *hw); void txgbe_bp_down_event(struct txgbe_hw *hw); +int txgbe_is_dac_cable(struct txgbe_hw *hw); +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw); s32 txgbe_kr_handle(struct txgbe_hw *hw); #endif /* _TXGBE_PHY_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 421abc1145..aa882e87b8 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -719,6 +719,7 @@ struct txgbe_phy_info { u32 addr; u32 id; enum txgbe_sfp_type sfp_type; + u32 fiber_suppport_speed; bool sfp_setup_needed; u32 revision; u32 media_type; @@ -740,6 +741,7 @@ struct txgbe_phy_info { u16 ffe_pre2; u16 ffe_post; u16 fec_mode; + u16 bp_capa; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -895,7 +897,28 @@ struct txgbe_hw { u32 cur_fec_link; int temperature; u32 bp_link_mode; -}; + bool dac_sfp; + bool bypass_ctle; + u32 curbp_link_mode; + bool an_done; + u32 fsm; + u64 bp_event_interval; +}; + +typedef enum { + ABILITY_1000BASE_KX, + ABILITY_10GBASE_KX4, + ABILITY_10GBASE_KR, + ABILITY_40GBASE_KR4, + ABILITY_40GBASE_CR4, + ABILITY_100GBASE_CR10, + ABILITY_100GBASE_KP4, + ABILITY_100GBASE_KR4, + ABILITY_100GBASE_CR4, + ABILITY_25GBASE_KRCR_S, + ABILITY_25GBASE_KRCR, + ABILITY_MAX, +} ability_filed_encding; struct txgbe_backplane_ability { u32 next_page; /* Next Page (bit0) */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index d515419028..2221153347 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2010,6 +2010,10 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_l2_tunnel_conf(dev); txgbe_filter_restore(dev); + hw->bp_event_interval = 100 * 1000; + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); + if (tm_conf->root && !tm_conf->committed) PMD_DRV_LOG(WARNING, "please call hierarchy_commit() " @@ -2054,8 +2058,10 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + } rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); @@ -2920,6 +2926,107 @@ txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) return NULL; } +void txgbe_dev_e56_check_bp_event(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + u32 an_int1 = 0, value = 0, fsm = 0; + u32 __rte_unused an_int = 0; + int ret = 0; + bool need_link_update = false; + + if (!hw) + return; + + if (!(txgbe_xpcs_an_enabled(hw))) + return; + + if (!hw->devarg.auto_neg) + return; + + /* only continue if link is down */ + if (dev->data->dev_link.link_status) + goto out; + + value = rd32_epcs(hw, VR_AN_INTR); + an_int = value; + if (value & 0xF) + hw->bp_event_interval = 100 * 1000; + + if (value & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + value &= ~VR_AN_INTR_CMPLT; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & VR_AN_INTR_LINK) { + value &= ~VR_AN_INTR_LINK; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & TXGBE_E56_AN_TXDIS) { + value &= ~TXGBE_E56_AN_TXDIS; + wr32_epcs(hw, VR_AN_INTR, value); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + goto an_status; + } + + if (value & VR_AN_INTR_PG_RCV) { + BP_LOG("%d Enter training\n", hw->port_id); + ret = handle_e56_bkp_an73_flow(hw); + if (!AN_TRAINNING_MODE) { + fsm = rd32_epcs(hw, 0x78010); + if (fsm & 0x8) + goto an_status; + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + BP_LOG("ALL SUCCEEDED\n"); + } + } else { + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + hw->an_done = true; + } + } + } + +an_status: + an_int1 = rd32_epcs(hw, 0x78002); + if (an_int1 & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + } + + BP_LOG("%d RLU:%x MLU:%x INT:%x-%x CTL:%x fsm:%x pmd_cfg0:%x an_done:%d\n", + hw->port_id, rd32_epcs(hw, 0x30001), rd32(hw, 0x14404), + an_int, an_int1, + rd32_epcs(hw, 0x70000), + rd32_epcs(hw, 0x78010), + rd32_ephy(hw, 0x1400), + hw->an_done); + + if (need_link_update) + txgbe_dev_link_update(dev, 0); + + if (dev->data->dev_link.link_status) + hw->bp_event_interval = 2000 * 1000; + +out: + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); +} + static void txgbe_dev_detect_sfp(void *param) { diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 1ec8e096cc..309db3bfe9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -747,5 +747,5 @@ void txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on); void txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, int mask); - +void txgbe_dev_e56_check_bp_event(void *param); #endif /* _TXGBE_ETHDEV_H_ */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 15/20] net/txgbe: fix FEC mode configuration on 25G NIC 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (13 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 16/20] net/txgbe: fix SFP module identification Zaiyu Wang ` (4 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The 25G NIC offers off, RS, Base-R, and auto FEC modes. When reconfiguring the PHY, the FEC mode must match on both sides; otherwise, the link cannot come up. The current driver fails to maintain this requirement, causing link instability. Add proper FEC mode handling during PHY reconfiguration to guarantee link establishment. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index 5cc8741f10..72a894c4ae 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -282,6 +282,14 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, !(hw->fec_mode & hw->cur_fec_link))) goto out; + if (speed == TXGBE_LINK_SPEED_25GB_FULL && + link_speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + + if (link_up) + goto out; + } + rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); rte_spinlock_unlock(&hw->phy_lock); @@ -360,7 +368,10 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* If we already have link at this speed, just jump out */ txgbe_e56_check_phy_link(hw, &link_speed, &link_up); - if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up) + hw->cur_fec_link = txgbe_phy_fec_get(hw); + + if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up && + hw->fec_mode & hw->cur_fec_link) goto out; /* Allow module to change analog characteristics (10G -> 25G) */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 16/20] net/txgbe: fix SFP module identification 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (14 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 17/20] net/txgbe: fix get module info operation Zaiyu Wang ` (3 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Some optical modules were not correctly recognized due to ambiguous classification in the original detection flow. Rework the module identification logic to cover all module types. Also narrow the I2C lock scope to avoid potential race conditions during module access. Fixes: ab191e6d9189 ("net/txgbe: support new SFP/QSFP modules") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 2 - drivers/net/txgbe/base/txgbe_phy.c | 339 ++++++++++------------------ drivers/net/txgbe/base/txgbe_phy.h | 18 +- drivers/net/txgbe/base/txgbe_type.h | 2 + 4 files changed, 132 insertions(+), 229 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 1a297acaa6..a57f7ea097 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -2907,8 +2907,6 @@ s32 txgbe_init_ops_generic(struct txgbe_hw *hw) phy->read_i2c_eeprom = txgbe_read_i2c_eeprom; phy->write_i2c_eeprom = txgbe_write_i2c_eeprom; phy->identify_sfp = txgbe_identify_module; - phy->read_i2c_byte_unlocked = txgbe_read_i2c_byte_unlocked; - phy->write_i2c_byte_unlocked = txgbe_write_i2c_byte_unlocked; phy->check_overtemp = txgbe_check_overtemp; phy->reset = txgbe_reset_phy; phy->set_link_hostif = txgbe_hic_ephy_set_link; diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index f3e3491b30..ac06f9530a 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -830,6 +830,10 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) return TXGBE_ERR_SFP_NOT_PRESENT; } + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, &identifier); if (err != 0) { @@ -839,11 +843,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.id = 0; hw->phy.type = txgbe_phy_unknown; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_PRESENT; } if (identifier != TXGBE_SFF_IDENTIFIER_SFP) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -888,7 +894,42 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) * 11 SFP_1g_sx_CORE0 - chip-specific * 12 SFP_1g_sx_CORE1 - chip-specific */ - if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; + else + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->dac_sfp = true; + } + + if (comp_copper_len == TXGBE_SFF_COPPER_1M) + hw->bypass_ctle = true; + else + hw->bypass_ctle = false; + + if (comp_codes_25g == TXGBE_SFF_25GBASECR_91FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_74FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_NOFEC) { + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_25GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + } else { + hw->phy.fiber_suppport_speed |= + TXGBE_LINK_SPEED_10GB_FULL; + } + } else if (comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_12 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_12) { + hw->dac_sfp = false; + hw->phy.sfp_type = (hw->bus.lan_id == 0 + ? txgbe_sfp_type_25g_aoc_core0 + : txgbe_sfp_type_25g_aoc_core1); + } else if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + hw->dac_sfp = false; err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_CABLE_SPEC_COMP, &cable_spec); if (err != 0) @@ -1005,6 +1046,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) /* Allow any DA cable vendor */ if (cable_tech & (TXGBE_SFF_CABLE_DA_PASSIVE | TXGBE_SFF_CABLE_DA_ACTIVE)) { + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; } @@ -1017,6 +1059,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -1031,9 +1074,11 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { DEBUGOUT("SFP+ module not supported"); hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; } @@ -1046,28 +1091,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) { s32 err = TXGBE_ERR_PHY_ADDR_INVALID; - u32 vendor_oui = 0; - enum txgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; - u8 identifier = 0; - u8 comp_codes_1g = 0; - u8 comp_codes_10g = 0; - u8 oui_bytes[3] = {0, 0, 0}; - u16 enforce_sfp = 0; - u8 connector = 0; - u8 cable_length = 0; - u8 device_tech = 0; - bool active_cable = false; + u8 identifier = 0, transceiver_type = 0; u32 value; - if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { - hw->phy.sfp_type = txgbe_sfp_type_not_present; - err = TXGBE_ERR_SFP_NOT_PRESENT; - goto out; - } + /* config GPIO before read i2c */ + wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); if (hw->mac.type == txgbe_mac_aml40) { - /* config GPIO before read i2c */ - wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { hw->phy.sfp_type = txgbe_sfp_type_not_present; @@ -1075,175 +1105,68 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) } } - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, - &identifier); -ERR_I2C: - if (err != 0) { + if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { hw->phy.sfp_type = txgbe_sfp_type_not_present; - hw->phy.id = 0; - hw->phy.type = txgbe_phy_unknown; return TXGBE_ERR_SFP_NOT_PRESENT; } - if (identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; - } - hw->phy.id = identifier; + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_10GBE_COMP, - &comp_codes_10g); + err = hw->phy.read_i2c_sff8636(hw, 0, TXGBE_SFF_IDENTIFIER, + &identifier); if (err != 0) - goto ERR_I2C; + goto err_read_i2c_eeprom; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_1GBE_COMP, - &comp_codes_1g); - - if (err != 0) - goto ERR_I2C; + if (identifier != TXGBE_SFF_IDENTIFIER_QSFP && + identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { + PMD_INIT_LOG(ERR, "port[%d] QSFP module not supported, identifier = 0x%x", + hw->bus.lan_id, identifier); + hw->phy.type = txgbe_phy_sfp_unsupported; + err = TXGBE_ERR_SFP_NOT_SUPPORTED; + } else { + err = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_ETHERNET_COMP_OFFSET, + &transceiver_type); + if (err != 0) + goto err_read_i2c_eeprom; - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_PASSIVE_CABLE) { - hw->phy.type = txgbe_phy_qsfp_unknown_passive; - if (hw->mac.type == txgbe_mac_aml40) { + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core0; else hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core1; - } else { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; - } - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_SR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_LR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; - } else if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_srlr_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_srlr_core1; - } else { - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_ACTIVE_CABLE) - active_cable = true; - - if (!active_cable) { - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CONNECTOR, - &connector); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CABLE_LENGTH, - &cable_length); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_DEVICE_TECH, - &device_tech); - - if (connector == - TXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE && - cable_length > 0 && - ((device_tech >> 4) == - TXGBE_SFF_QSFP_TRANSMITTER_850NM_VCSEL)) - active_cable = true; + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } - if (active_cable) { - hw->phy.type = txgbe_phy_qsfp_unknown_active; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_SR4) { if (hw->bus.lan_id == 0) - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core0; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; else - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core1; - } else { - /* unsupported module type */ - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; } - } - - if (hw->phy.sfp_type != stored_sfp_type) - hw->phy.sfp_setup_needed = true; - - /* Determine if the QSFP+ PHY is dual speed or not. */ - hw->phy.multispeed_fiber = false; - if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) || - ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE))) - hw->phy.multispeed_fiber = true; - - /* Determine PHY vendor for optical modules */ - if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0, - &oui_bytes[0]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1, - &oui_bytes[1]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE2, - &oui_bytes[2]); - if (err != 0) - goto ERR_I2C; - - vendor_oui = - ((oui_bytes[0] << 24) | - (oui_bytes[1] << 16) | - (oui_bytes[2] << 8)); - - if (vendor_oui == TXGBE_SFF_VENDOR_OUI_INTEL) - hw->phy.type = txgbe_phy_qsfp_intel; - else - hw->phy.type = txgbe_phy_qsfp_unknown; - - hw->mac.get_device_caps(hw, &enforce_sfp); - if (!(enforce_sfp & TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) { - /* Make sure we're a supported PHY type */ - if (hw->phy.type == txgbe_phy_qsfp_intel) { - err = 0; - } else { - if (hw->allow_unsupported_sfp) { - DEBUGOUT("WARNING: Wangxun (R) Network Connections are quality tested using Wangxun (R) Ethernet Optics. " - "Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. " - "Wangxun Corporation is not responsible for any harm caused by using untested modules."); - err = 0; - } else { - DEBUGOUT("QSFP module not supported"); - hw->phy.type = - txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - } - } - } else { - err = 0; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_LR4) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } } -out: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; + +err_read_i2c_eeprom: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + hw->phy.id = 0; + hw->phy.type = txgbe_phy_unknown; + return TXGBE_ERR_SFP_NOT_PRESENT; } /** @@ -1278,6 +1201,26 @@ s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, sff8472_data); } +/** + * txgbe_read_i2c_sff8636 - Reads 8 bit word over I2C interface + * @hw: pointer to hardware structure + * @byte_offset: byte offset at address 0xA2 + * @eeprom_data: value read + * + * Performs byte read operation to SFP module's SFF-8472 data over I2C + **/ +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data) +{ + hw->phy.write_i2c_byte(hw, TXGBE_SFF_QSFP_PAGE_SELECT, + TXGBE_I2C_EEPROM_DEV_ADDR, + page); + + return hw->phy.read_i2c_byte(hw, byte_offset, + TXGBE_I2C_EEPROM_DEV_ADDR, + sff8636_data); +} + /** * txgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure @@ -1295,7 +1238,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte_unlocked - Reads 8 bit word over I2C + * txgbe_read_i2c_byte - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: address to read from @@ -1304,7 +1247,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, +s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { txgbe_i2c_start(hw, dev_addr); @@ -1334,30 +1277,7 @@ s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte - Reads 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to read - * @dev_addr: address to read from - * @data: value read - * - * Performs byte read operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_read_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - return err; -} - -/** - * txgbe_write_i2c_byte_unlocked - Writes 8 bit word over I2C + * txgbe_write_i2c_byte - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: address to write to @@ -1366,54 +1286,29 @@ s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) +s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data) { txgbe_i2c_start(hw, dev_addr); /* wait tx empty */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY, - TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) { + TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) return -TERR_TIMEOUT; - } - wr32(hw, TXGBE_I2CDATA, byte_offset | TXGBE_I2CDATA_STOP); + wr32(hw, TXGBE_I2CDATA, byte_offset); wr32(hw, TXGBE_I2CDATA, data | TXGBE_I2CDATA_WRITE); /* wait for write complete */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_RXFULL, - TXGBE_I2CICR_RXFULL, NULL, 100, 100)) { + TXGBE_I2CICR_RXFULL, NULL, 100, 100)) return -TERR_TIMEOUT; - } + txgbe_i2c_stop(hw); return 0; } -/** - * txgbe_write_i2c_byte - Writes 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to write - * @dev_addr: address to write to - * @data: value to write - * - * Performs byte write operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_write_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - - return err; -} - /** * txgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 3fe7a34409..4da4be0d5f 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -261,7 +261,9 @@ #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0 0xA5 #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1 0xA6 @@ -289,6 +291,9 @@ #define TXGBE_SFF_4x10GBASESR_CAP 0x11 #define TXGBE_SFF_40GBASEPSM4_PARALLEL 0x12 #define TXGBE_SFF_40GBASE_SWMD4_CAP 0x1f +#define TXGBE_SFF_COPPER_5M 0x5 +#define TXGBE_SFF_COPPER_3M 0x3 +#define TXGBE_SFF_COPPER_1M 0x1 #define TXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 #define TXGBE_SFF_25GAUI_C2M_AOC_BER_5 0x1 @@ -296,6 +301,11 @@ #define TXGBE_SFF_25GAUI_C2M_AOC_BER_12 0x18 #define TXGBE_SFF_25GAUI_C2M_ACC_BER_12 0x19 +#define TXGBE_ETHERNET_COMP_OFFSET 0x83 +#define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) +#define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) +#define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) + #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_1G 0x0 @@ -493,14 +503,12 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw); s32 txgbe_check_overtemp(struct txgbe_hw *hw); s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data); s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data); s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, - u8 *sff8472_data); + u8 *sff8472_data); +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data); s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index aa882e87b8..051609bbfe 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -702,6 +702,8 @@ struct txgbe_phy_info { u8 dev_addr, u8 data); s32 (*read_i2c_sff8472)(struct txgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); + s32 (*read_i2c_sff8636)(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data); s32 (*read_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 (*write_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 17/20] net/txgbe: fix get module info operation 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (15 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 16/20] net/txgbe: fix SFP module identification Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 18/20] net/txgbe: fix get eeprom operation Zaiyu Wang ` (2 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.h | 6 +- drivers/net/txgbe/txgbe_ethdev.c | 116 ++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 4da4be0d5f..581f667bdc 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -257,11 +257,15 @@ #define TXGBE_SFF_CABLE_DA_PASSIVE 0x4 #define TXGBE_SFF_CABLE_DA_ACTIVE 0x8 #define TXGBE_SFF_CABLE_SPEC_COMP 0x3C +#define TXGBE_SFF_DDM_IMPLEMENTED 0x40 #define TXGBE_SFF_SFF_8472_SWAP 0x5C #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 -#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_SFF_REVISION_ADDR 0x01 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F + +#define TXGBE_MODULE_QSFP_MAX_LEN 640 #define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 2221153347..4e9da14697 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5342,41 +5342,105 @@ txgbe_get_module_info(struct rte_eth_dev *dev, struct txgbe_hw *hw = TXGBE_DEV_HW(dev); uint32_t status; uint8_t sff8472_rev, addr_mode; + u8 identifier = 0; + u8 sff8636_rev = 0; bool page_swap = false; + u32 value; - /* Check whether we support SFF-8472 or not */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_COMP, - &sff8472_rev); - if (status != 0) - return -EIO; - - /* addressing mode is not supported */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_SWAP, - &addr_mode); - if (status != 0) - return -EIO; + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } - if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { - PMD_DRV_LOG(ERR, - "Address change required to access page 0xA2, " - "but not supported. Please report the module " - "type to the driver maintainers."); - page_swap = true; + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; } - if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap) { - /* We have a SFP, but it does not support SFF-8472 */ - modinfo->type = RTE_ETH_MODULE_SFF_8079; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; + + if (hw->mac.type == txgbe_mac_aml40) { + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_IDENTIFIER, + &identifier); } else { - /* We have a SFP which supports a revision of SFF-8472. */ - modinfo->type = RTE_ETH_MODULE_SFF_8472; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); } + if (status != 0) + goto ERROR_IO; + + switch (identifier) { + case TXGBE_SFF_IDENTIFIER_SFP: + /* Check whether we support SFF-8472 or not */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_COMP, + &sff8472_rev); + if (status != 0) + goto ERROR_IO; + + /* addressing mode is not supported */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_SWAP, + &addr_mode); + if (status != 0) + goto ERROR_IO; + + if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { + PMD_DRV_LOG(ERR, + "Address change required to access page 0xA2, " + "but not supported. Please report the module " + "type to the driver maintainers."); + page_swap = true; + } + + if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap || + !(addr_mode & TXGBE_SFF_DDM_IMPLEMENTED)) { + /* We have a SFP, but it does not support SFF-8472 */ + modinfo->type = RTE_ETH_MODULE_SFF_8079; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + } else { + /* We have a SFP which supports a revision of SFF-8472. */ + modinfo->type = RTE_ETH_MODULE_SFF_8472; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + } + break; + case TXGBE_SFF_IDENTIFIER_QSFP: + case TXGBE_SFF_IDENTIFIER_QSFP_PLUS: + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_SFF_REVISION_ADDR, + &sff8636_rev); + if (status != 0) + goto ERROR_IO; + /* Check revision compliance */ + if (sff8636_rev > 0x02) { + /* Module is SFF-8636 compliant */ + modinfo->type = RTE_ETH_MODULE_SFF_8636; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } else { + modinfo->type = RTE_ETH_MODULE_SFF_8436; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } + break; + default: + PMD_DRV_LOG(ERR, "SFF Module Type not recognized."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EINVAL; + } + + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } static int -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 18/20] net/txgbe: fix get eeprom operation 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (16 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 17/20] net/txgbe: fix get module info operation Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 67 ++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 4e9da14697..9c9606cc92 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5452,23 +5452,76 @@ txgbe_get_module_eeprom(struct rte_eth_dev *dev, uint8_t databyte = 0xFF; uint8_t *data = info->data; uint32_t i = 0; + bool is_sfp = false; + u32 value; + u8 identifier = 0; + u16 offset; + u8 page = 0; + + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } + + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; + } if (info->length == 0) return -EINVAL; - for (i = info->offset; i < info->offset + info->length; i++) { - if (i < RTE_ETH_MODULE_SFF_8079_LEN) - status = hw->phy.read_i2c_eeprom(hw, i, &databyte); - else - status = hw->phy.read_i2c_sff8472(hw, i, &databyte); + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; - if (status != 0) - return -EIO; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); + if (status != 0) + goto ERROR_IO; + if (identifier == TXGBE_SFF_IDENTIFIER_SFP) + is_sfp = true; + + memset(data, 0, info->length); + + for (i = info->offset; i < info->offset + info->length; i++) { + if (is_sfp) { + if (i < RTE_ETH_MODULE_SFF_8079_LEN) + status = hw->phy.read_i2c_eeprom(hw, i, + &databyte); + else + status = hw->phy.read_i2c_sff8472(hw, i, + &databyte); + + if (status != 0) + goto ERROR_IO; + } else { + offset = i; + while (offset >= RTE_ETH_MODULE_SFF_8436_LEN) { + offset -= RTE_ETH_MODULE_SFF_8436_LEN / 2; + page++; + } + if (page == 0 || !(data[0x2] & 0x4)) { + status = hw->phy.read_i2c_sff8636(hw, page, offset, + &databyte); + if (status != 0) + goto ERROR_IO; + } + } data[i - info->offset] = databyte; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } bool -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 19/20] net/txgbe: fix to reset Tx write-back pointer 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (17 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 18/20] net/txgbe: fix get eeprom operation Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The write-back pointer was not reset when the Tx queue was reset. This leads to the wrong Tx desc free logic. Move the resetting of pointer into txq->ops->reset(txq). Fixes: 8ada71d0bb7f ("net/txgbe: add Tx head write-back mode for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 45 +++++++++++++---------- drivers/net/txgbe/txgbe_rxtx.h | 1 + drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 ++++ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index be279dc4ec..956d1cbad8 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -2320,6 +2320,12 @@ txgbe_reset_tx_queue(struct txgbe_tx_queue *txq) txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); txq->tx_tail = 0; + /* Zero out headwb_mem memory */ + if (txq->headwb_mem) { + for (i = 0; i < txq->headwb_size; i++) + txq->headwb_mem[i] = 0; + } + /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition @@ -2419,7 +2425,7 @@ txgbe_get_tx_port_offloads(struct rte_eth_dev *dev) return tx_offload_capa; } -static int +static void txgbe_setup_headwb_resources(struct rte_eth_dev *dev, void *tx_queue, unsigned int socket_id) @@ -2427,33 +2433,33 @@ txgbe_setup_headwb_resources(struct rte_eth_dev *dev, struct txgbe_hw *hw = TXGBE_DEV_HW(dev); const struct rte_memzone *headwb; struct txgbe_tx_queue *txq = tx_queue; - u8 i, headwb_size = 0; + u8 headwb_size = 0; - if (hw->mac.type != txgbe_mac_aml && hw->mac.type != txgbe_mac_aml40) { - txq->headwb_mem = NULL; - return 0; - } + if (hw->mac.type != txgbe_mac_aml && hw->mac.type != txgbe_mac_aml40) + goto out; + + if (!hw->devarg.tx_headwb) + goto out; - headwb_size = hw->devarg.tx_headwb_size; + headwb_size = txq->headwb_size; headwb = rte_eth_dma_zone_reserve(dev, "tx_headwb_mem", txq->queue_id, sizeof(u32) * headwb_size, TXGBE_ALIGN, socket_id); if (headwb == NULL) { - DEBUGOUT("Fail to setup headwb resources: no mem"); - txgbe_tx_queue_release(txq); - return -ENOMEM; + PMD_DRV_LOG(INFO, + "Failed to allocate headwb memory for Tx queue %u, change to SP mode", + txq->queue_id); + goto out; } txq->headwb = headwb; txq->headwb_dma = TMZ_PADDR(headwb); txq->headwb_mem = (uint32_t *)TMZ_VADDR(headwb); + return; - /* Zero out headwb_mem memory */ - for (i = 0; i < headwb_size; i++) - txq->headwb_mem[i] = 0; - - return 0; +out: + txq->headwb_mem = NULL; } int __rte_cold @@ -2549,6 +2555,7 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, txq->offloads = offloads; txq->ops = &def_txq_ops; txq->tx_deferred_start = tx_conf->tx_deferred_start; + txq->headwb_size = hw->devarg.tx_headwb_size; #ifdef RTE_LIB_SECURITY txq->using_ipsec = !!(dev->data->dev_conf.txmode.offloads & RTE_ETH_TX_OFFLOAD_SECURITY); @@ -2584,8 +2591,7 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, /* set up scalar TX function as appropriate */ txgbe_set_tx_function(dev, txq); - if (hw->devarg.tx_headwb) - err = txgbe_setup_headwb_resources(dev, txq, socket_id); + txgbe_setup_headwb_resources(dev, txq, socket_id); txq->ops->reset(txq); txq->desc_error = 0; @@ -4765,15 +4771,14 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) wr32(hw, TXGBE_TXRP(txq->reg_idx), 0); wr32(hw, TXGBE_TXWP(txq->reg_idx), 0); - if ((hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) && - hw->devarg.tx_headwb) { + if (txq->headwb_mem) { uint32_t txdctl; wr32(hw, TXGBE_PX_TR_HEAD_ADDRL(txq->reg_idx), (uint32_t)(txq->headwb_dma & BIT_MASK32)); wr32(hw, TXGBE_PX_TR_HEAD_ADDRH(txq->reg_idx), (uint32_t)(txq->headwb_dma >> 32)); - if (hw->devarg.tx_headwb_size == 16) + if (txq->headwb_size == 16) txdctl = TXGBE_PX_TR_CFG_HEAD_WB | TXGBE_PX_TR_CFG_HEAD_WB_64BYTE; else diff --git a/drivers/net/txgbe/txgbe_rxtx.h b/drivers/net/txgbe/txgbe_rxtx.h index 02e2617cce..237bb64697 100644 --- a/drivers/net/txgbe/txgbe_rxtx.h +++ b/drivers/net/txgbe/txgbe_rxtx.h @@ -416,6 +416,7 @@ struct txgbe_tx_queue { uint64_t desc_error; bool resetting; const struct rte_memzone *headwb; + uint16_t headwb_size; uint64_t headwb_dma; volatile uint32_t *headwb_mem; }; diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h index edf3586b77..594886c5b1 100644 --- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h +++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h @@ -255,6 +255,13 @@ _txgbe_reset_tx_queue_vec(struct txgbe_tx_queue *txq) txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); txq->tx_tail = 0; + + /* Zero out headwb_mem memory */ + if (txq->headwb_mem) { + for (i = 0; i < txq->headwb_size; i++) + txq->headwb_mem[i] = 0; + } + /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v2 20/20] net/txgbe: fix to enable Tx desc check 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang ` (18 preceding siblings ...) 2026-04-29 10:25 ` [PATCH v2 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang @ 2026-04-29 10:25 ` Zaiyu Wang 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-04-29 10:25 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Now lib security is enabled by default, and cannot be disabled if the driver is intended to be used. So Tdm_desc_chk is always unable to enable. Remove this restriction, and just enable the corresponding queue check. Fixes: 0eabdfcd4af4 ("net/txgbe: enable Tx descriptor error interrupt") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 956d1cbad8..2403aff920 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -4771,6 +4771,12 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) wr32(hw, TXGBE_TXRP(txq->reg_idx), 0); wr32(hw, TXGBE_TXWP(txq->reg_idx), 0); +#ifdef RTE_LIBRTE_SECURITY + if (!(txq->using_ipsec)) +#endif + wr32m(hw, TXGBE_TDM_DESC_CHK(txq->reg_idx / 32), + BIT(txq->reg_idx % 32), BIT(txq->reg_idx % 32)); + if (txq->headwb_mem) { uint32_t txdctl; @@ -4788,11 +4794,6 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) } } -#ifndef RTE_LIB_SECURITY - for (i = 0; i < 4; i++) - wr32(hw, TXGBE_TDM_DESC_CHK(i), 0xFFFFFFFF); -#endif - /* Device configured with multiple TX queues. */ txgbe_dev_mq_tx_configure(dev); } -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 00/20] Wangxun Fixes 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (18 preceding siblings ...) 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang ` (21 more replies) 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang 20 siblings, 22 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series fixes several issues found on Wangxun Emerald, Sapphire and Amber-lite NICs, with a focus on link-related problems. --- v3: - Addressed Stephen's comments --- v2: - Fixed compilation error and code style issues --- Zaiyu Wang (20): net/txgbe: remove duplicate xstats counters net/ngbe: remove duplicate xstats counters net/ngbe: add missing CDR config for YT PHY net/ngbe: fix VF promiscuous and allmulticast net/txgbe: fix inaccuracy in TX rate limiting net/txgbe: fix link status check condition net/txgbe: fix Tx desc free logic net/txgbe: fix link flow control registers for Amber-Lite net/txgbe: fix link flow control config for Sapphire net/txgbe: fix a mass of unknown interrupts net/txgbe: fix traffic class priority configuration net/txgbe: fix link stability for 25G NIC net/txgbe: fix link stability for 40G NIC net/txgbe: fix link stability for Amber-Lite backplane mode net/txgbe: fix FEC mode configuration on 25G NIC net/txgbe: fix SFP module identification net/txgbe: fix get module info operation net/txgbe: fix get eeprom operation net/txgbe: fix to reset Tx write-back pointer net/txgbe: fix to enable Tx desc check drivers/net/ngbe/base/ngbe_phy_yt.c | 3 + drivers/net/ngbe/ngbe_ethdev.c | 5 - drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +- drivers/net/txgbe/base/meson.build | 2 + drivers/net/txgbe/base/txgbe.h | 2 + drivers/net/txgbe/base/txgbe_aml.c | 187 +- drivers/net/txgbe/base/txgbe_aml.h | 6 +- drivers/net/txgbe/base/txgbe_aml40.c | 113 +- drivers/net/txgbe/base/txgbe_aml40.h | 6 +- drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- drivers/net/txgbe/base/txgbe_e56.c | 3774 +++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56.h | 1744 ++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.c | 2593 ++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 278 ++ drivers/net/txgbe/base/txgbe_hw.c | 54 +- drivers/net/txgbe/base/txgbe_hw.h | 4 +- drivers/net/txgbe/base/txgbe_osdep.h | 4 + drivers/net/txgbe/base/txgbe_phy.c | 360 +- drivers/net/txgbe/base/txgbe_phy.h | 45 +- drivers/net/txgbe/base/txgbe_regs.h | 11 +- drivers/net/txgbe/base/txgbe_type.h | 43 +- drivers/net/txgbe/txgbe_ethdev.c | 414 ++- drivers/net/txgbe/txgbe_ethdev.h | 6 +- drivers/net/txgbe/txgbe_rxtx.c | 102 +- drivers/net/txgbe/txgbe_rxtx.h | 1 + drivers/net/txgbe/txgbe_rxtx_vec_common.h | 14 +- 26 files changed, 9350 insertions(+), 434 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56.c create mode 100644 drivers/net/txgbe/base/txgbe_e56.h create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h -- 2.21.0.windows.1 ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v3 01/20] net/txgbe: remove duplicate xstats counters 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 02/20] net/ngbe: " Zaiyu Wang ` (20 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Fixes: 91fe49c87d76 ("net/txgbe: support device xstats") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 5d360f8305..779874aac9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -261,11 +261,6 @@ static const struct rte_txgbe_xstats_name_off rte_txgbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 02/20] net/ngbe: remove duplicate xstats counters 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang ` (19 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Fixes: 8b433d04adc9 ("net/ngbe: support device xstats") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 8b9d6371fb..6df53f3266 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -227,11 +227,6 @@ static const struct rte_ngbe_xstats_name_off rte_ngbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 03/20] net/ngbe: add missing CDR config for YT PHY 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 02/20] net/ngbe: " Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang ` (18 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu According to the PHY vendor, when YT8531S operates in UTP-to-Fiber or RGMII-to-Fiber mode with auto-negotiation disabled (Force mode), additional CDR (Clock Data Recovery) configuration is required to improve link connectivity. Without this config, link may be unstable or fail to establish. Fixes: f1268369403d ("net/ngbe: support autoneg on/off for external PHY SFI mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/base/ngbe_phy_yt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c index d110fbc8b2..ab0778d246 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.c +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -264,6 +264,9 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed, value = YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN | YT_BCR_DUPLEX | YT_BCR_SPEED_SELECT1; } else { + /* force mode need to config cdr */ + ngbe_write_phy_reg_sds_ext_yt(hw, 0x3, 0, 0x1434); + ngbe_write_phy_reg_sds_ext_yt(hw, 0xe, 0, 0x163); value = YT_BCR_RESET | YT_BCR_DUPLEX; if (speed & NGBE_LINK_SPEED_1GB_FULL) value |= YT_BCR_SPEED_SELECT1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 04/20] net/ngbe: fix VF promiscuous and allmulticast 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (2 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 05/20] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang ` (17 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The configuration of allmulti and promiscuous modes conflicts together. For instance, if we enable promiscuous mode, then enable and disable allmulti, then the promiscuous mode is wrongly disabled. Fix this behavior by: - doing nothing when we set/unset allmulti if promiscuous mode is on - restorting the proper mode (none or allmulti) when we disable promiscuous mode Fixes: 7744e90805b5 ("net/ngbe: add promiscuous and allmulticast ops for VF device") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev_vf.c b/drivers/net/ngbe/ngbe_ethdev_vf.c index 6406df40d0..81511fed8a 100644 --- a/drivers/net/ngbe/ngbe_ethdev_vf.c +++ b/drivers/net/ngbe/ngbe_ethdev_vf.c @@ -1196,9 +1196,13 @@ static int ngbevf_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct ngbe_hw *hw = ngbe_dev_hw(dev); + int mode = NGBEVF_XCAST_MODE_NONE; int ret; - switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_NONE)) { + if (dev->data->all_multicast) + mode = NGBEVF_XCAST_MODE_ALLMULTI; + + switch (hw->mac.update_xcast_mode(hw, mode)) { case 0: ret = 0; break; @@ -1219,7 +1223,7 @@ ngbevf_dev_allmulticast_enable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; - if (dev->data->promiscuous == 1) + if (dev->data->promiscuous) return 0; switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_ALLMULTI)) { @@ -1243,6 +1247,9 @@ ngbevf_dev_allmulticast_disable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; + if (dev->data->promiscuous) + return 0; + switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_MULTI)) { case 0: ret = 0; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 05/20] net/txgbe: fix inaccuracy in TX rate limiting 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (3 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 06/20] net/txgbe: fix link status check condition Zaiyu Wang ` (16 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Amber-lite NIC's TX rate limiting has large deviations for small packets. To fix this issue, there are some changes: 1. Set TDM_RL_ADJ (0x1820c) to 21B (includes 7B Ethernet preamble, 1B SFD, 1B EFD, and 12B IPG). 2) Remove the rate offset in the driver (e.g., 105 / 100, a rough compensation value from Linux kernel driver tests). After these changes, accuracy deviation for 64B packets is within ~5%, while large packets show lower deviation. Fixes: a309ab43acf3 ("net/txgbe: support Tx queue rate limiting for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_regs.h | 1 + drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 95c585a025..060757323a 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1670,6 +1670,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_TDM_FACTOR_INT_SHIFT 16 #define TXGBE_TDM_FACTOR_FRA_SHIFT 2 +#define TXGBE_TDM_RL_ADJ 0x1820C #define TXGBE_TDM_RL_VM_IDX 0x018218 #define TXGBE_TDM_RL_VM_CFG 0x01821C #define TXGBE_TDM_RL_CFG 0x018400 diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 779874aac9..414107d7a7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -4314,7 +4314,6 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, u16 frac; link_speed = dev->data->dev_link.link_speed; - tx_rate = tx_rate * 105 / 100; /* Calculate the rate factor values to set */ factor_int = link_speed / tx_rate; frac = (link_speed % tx_rate) * 10000 / tx_rate; @@ -4324,6 +4323,7 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, factor_fra = 0; } + wr32(hw, TXGBE_TDM_RL_ADJ, 21); wr32(hw, TXGBE_TDM_RL_QUEUE_IDX, queue_idx); wr32m(hw, TXGBE_TDM_RL_QUEUE_CFG, TXGBE_TDM_FACTOR_INT_MASK, factor_int << TXGBE_TDM_FACTOR_INT_SHIFT); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 06/20] net/txgbe: fix link status check condition 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (4 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 05/20] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang ` (15 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original code incorrectly used 'if (link_up)' instead of 'if (*link_up)', causing the condition to always evaluate to true because the pointer itself is non-NULL. This led to incorrect speed assignment. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 2 +- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index b376eca5b5..de9a1b1c93 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -67,7 +67,7 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { switch (links_reg & TXGBE_CFG_PORT_ST_AML_LINK_MASK) { case TXGBE_CFG_PORT_ST_AML_LINK_25G: *speed = TXGBE_LINK_SPEED_25GB_FULL; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 733bbac13a..eefd7119fd 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -68,7 +68,7 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 07/20] net/txgbe: fix Tx desc free logic 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (5 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 06/20] net/txgbe: fix link status check condition Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang ` (14 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On some server environments, this driver caused TDM non-fatal errors or PCIe request errors during Tx operation In Amber-Lite NIC's Tx head write-back mode, the hardware periodically writes back a head index pointing to the next descriptor it is adout to process in Tx ring. All descriptors before the head are considered processed by hardware and can be safely freed by the driver. The root cause is that the driver can safely free a batch of descriptors only when the hardware's write-back head pointer has advanced beyond all descriptors in that batch, meaning they have all been processed by the hardware. If the driver frees a descriptor before the hardware has finished processing it, invalid memory access may occur, leading to the observed bug. To fix the issue, correct the boundary check in all three Tx cleanup functions, each of which was missing the proper condition to prevent freeing unprocessed descriptors. Fixes: 8ada71d0bb7f ("net/txgbe: add Tx head write-back mode for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 9 ++++++++- drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index e2cd9b8841..72a4965693 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -100,7 +100,9 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) @@ -652,6 +654,11 @@ txgbe_xmit_cleanup(struct txgbe_tx_queue *txq) /* we have caught up to head, no work left to do */ if (desc_to_clean_to == head) return -(1); + else if (desc_to_clean_to > head && head > last_desc_cleaned) + return -(1); + else if (last_desc_cleaned > desc_to_clean_to && + (head > last_desc_cleaned || head < desc_to_clean_to)) + return -(1); } else { if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) { PMD_TX_FREE_LOG(DEBUG, diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h index 00847d087b..edf3586b77 100644 --- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h +++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h @@ -94,8 +94,11 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) txq->tx_next_dd - txq->tx_free_thresh; if (tx_last_dd >= txq->nb_tx_desc) tx_last_dd -= txq->nb_tx_desc; - volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + + volatile uint16_t head = (uint16_t)*txq->headwb_mem; + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 08/20] net/txgbe: fix link flow control registers for Amber-Lite 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (6 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang ` (13 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The flow control counter registers on AML NICs differ from those on SP NICs. Update the register offsets accordingly to ensure the counters work correctly. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 7 ++++++ drivers/net/txgbe/base/txgbe_regs.h | 2 ++ drivers/net/txgbe/base/txgbe_type.h | 4 ++++ drivers/net/txgbe/txgbe_ethdev.c | 34 +++++++++++++++++++---------- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0f3db3a1ad..0d3310e15c 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -394,6 +394,13 @@ s32 txgbe_clear_hw_cntrs(struct txgbe_hw *hw) rd32(hw, TXGBE_PBTXLNKXON); rd32(hw, TXGBE_PBTXLNKXOFF); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + wr32(hw, TXGBE_PBRXLNKXON_AML, 0); + wr32(hw, TXGBE_PBRXLNKXOFF_AML, 0); + hw->last_stats.rx_xon_packets = 0; + hw->last_stats.rx_xoff_packets = 0; + } + /* DMA Stats */ rd32(hw, TXGBE_DMARXPKT); rd32(hw, TXGBE_DMATXPKT); diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 060757323a..de382601c9 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1085,6 +1085,8 @@ enum txgbe_5tuple_protocol { #define TXGBE_PBRXDROP 0x019068 #define TXGBE_PBRXLNKXOFF 0x011988 #define TXGBE_PBRXLNKXON 0x011E0C +#define TXGBE_PBRXLNKXOFF_AML 0x011F80 +#define TXGBE_PBRXLNKXON_AML 0x011F84 #define TXGBE_PBRXUPXON(up) (0x011E30 + (up) * 4) #define TXGBE_PBRXUPXOFF(up) (0x011E10 + (up) * 4) diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index ede780321f..505f598fb7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -876,6 +876,10 @@ struct txgbe_hw { u64 tx_qp_bytes; u64 rx_qp_mc_packets; } qp_last[TXGBE_MAX_QP]; + struct { + u64 rx_xon_packets; + u64 rx_xoff_packets; + } last_stats; rte_spinlock_t phy_lock; /*amlite: new SW-FW mbox */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 414107d7a7..3ae233f70a 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2264,16 +2264,18 @@ txgbe_dev_reset(struct rte_eth_dev *dev) return ret; } +#define TXGBE_UPDATE_COUNTER_32BIT_GENERIC(reg, last, count, reset) \ + do { \ + uint32_t current = rd32(hw, reg); \ + if ((current) < (last)) \ + current += 0x100000000ULL; \ + if (reset) \ + (last) = current; \ + (count) = (uint32_t)((current) - (last)); \ + } while (0) + #define UPDATE_QP_COUNTER_32bit(reg, last_counter, counter) \ - { \ - uint32_t current_counter = rd32(hw, reg); \ - if (current_counter < last_counter) \ - current_counter += 0x100000000LL; \ - if (!hw->offset_loaded) \ - last_counter = current_counter; \ - counter = current_counter - last_counter; \ - counter &= 0xFFFFFFFFLL; \ - } + TXGBE_UPDATE_COUNTER_32BIT_GENERIC(reg, last_counter, counter, !hw->offset_loaded) #define UPDATE_QP_COUNTER_36bit(reg_lsb, reg_msb, last_counter, counter) \ { \ @@ -2331,8 +2333,18 @@ txgbe_read_stats_registers(struct txgbe_hw *hw, hw_stats->up[i].rx_up_dropped += rd32(hw, TXGBE_PBRXMISS(i)); } - hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); - hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + TXGBE_UPDATE_COUNTER_32BIT_GENERIC(TXGBE_PBRXLNKXON_AML, + hw->last_stats.rx_xon_packets, + hw_stats->rx_xon_packets, !hw->offset_loaded); + TXGBE_UPDATE_COUNTER_32BIT_GENERIC(TXGBE_PBRXLNKXOFF_AML, + hw->last_stats.rx_xoff_packets, + hw_stats->rx_xoff_packets, !hw->offset_loaded); + } else { + hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); + hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + } hw_stats->tx_xon_packets += rd32(hw, TXGBE_PBTXLNKXON); hw_stats->tx_xoff_packets += rd32(hw, TXGBE_PBTXLNKXOFF); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 09/20] net/txgbe: fix link flow control config for Sapphire 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (7 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang ` (12 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit SP chips have a hardware bug preventing XON flow control support, so the driver disables it. Fixes: 69ce8c8a4ce3 ("net/txgbe: support flow control") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0d3310e15c..b1a1483dab 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -1037,8 +1037,10 @@ s32 txgbe_fc_enable(struct txgbe_hw *hw) for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { if ((hw->fc.current_mode & txgbe_fc_tx_pause) && hw->fc.high_water[i]) { - fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]) | - TXGBE_FCWTRLO_XON; + fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]); + /* SP doesn't support xon */ + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + fcrtl |= TXGBE_FCWTRLO_XON; fcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[i]) | TXGBE_FCWTRHI_XOFF; } else { -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 10/20] net/txgbe: fix a mass of unknown interrupts 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (8 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang ` (11 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit When RSC is enabled, Rx ring IVAR is set to configure ITR. It causes Rx ring interrupts report on the default msix_vector. Thus a mass of unknown interrupts occupy CPU. Fix the issue by setting ring IVAR only when the rxq interrupt is enabled. Fixes: be797cbf4582 ("net/txgbe: add Rx and Tx init") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 72a4965693..be279dc4ec 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -4354,6 +4354,8 @@ static int txgbe_set_rsc(struct rte_eth_dev *dev) { struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = pci_dev->intr_handle; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct rte_eth_dev_info dev_info = { 0 }; bool rsc_capable = false; @@ -4404,8 +4406,6 @@ txgbe_set_rsc(struct rte_eth_dev *dev) rd32(hw, TXGBE_RXCFG(rxq->reg_idx)); uint32_t psrtype = rd32(hw, TXGBE_POOLRSS(rxq->reg_idx)); - uint32_t eitr = - rd32(hw, TXGBE_ITR(rxq->reg_idx)); /* * txgbe PMD doesn't support header-split at the moment. @@ -4424,6 +4424,9 @@ txgbe_set_rsc(struct rte_eth_dev *dev) srrctl |= txgbe_get_rscctl_maxdesc(rxq->mb_pool); psrtype |= TXGBE_POOLRSS_L4HDR; + wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); + wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); + /* * RSC: Set ITR interval corresponding to 2K ints/s. * @@ -4437,19 +4440,20 @@ txgbe_set_rsc(struct rte_eth_dev *dev) * For a sparse streaming case this setting will yield * at most 500us latency for a single RSC aggregation. */ - eitr &= ~TXGBE_ITR_IVAL_MASK; - eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); - eitr |= TXGBE_ITR_WRDSA; + if (rte_intr_dp_is_en(intr_handle)) { + uint32_t eitr = rd32(hw, TXGBE_ITR(rxq->reg_idx)); - wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); - wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); - wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); + eitr &= ~TXGBE_ITR_IVAL_MASK; + eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); + eitr |= TXGBE_ITR_WRDSA; + wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); - /* - * RSC requires the mapping of the queue to the - * interrupt vector. - */ - txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + /* + * RSC requires the mapping of the queue to the + * interrupt vector. + */ + txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + } } dev->data->lro = 1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 11/20] net/txgbe: fix traffic class priority configuration 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (9 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang ` (10 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit After applying the following testpmd command, 802.1Q packets with specific priorities were not properly directed to the corresponding traffic classes: port config 0 dcb vt off 4 pfc off The old driver had two issues: 1. The hardware uses a 4-bit mapping register per traffic class for priority-to-TC mapping, but the driver incorrectly configured it as 3 bits. 2. The DCB TX configuration mistakenly wrote to the RX register. Fix both issues, ensuring that tc-prio mapping works as expected. Additionally, remove the stale and inconsistent TXGBE_DCBUP2TC_DEC macro as it has no callers. Fixes: 8bdc7882f376 ("net/txgbe: support DCB") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- drivers/net/txgbe/base/txgbe_regs.h | 6 ++---- drivers/net/txgbe/txgbe_rxtx.c | 7 ++----- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_dcb_hw.c b/drivers/net/txgbe/base/txgbe_dcb_hw.c index 75c91a6b6a..79e1da447b 100644 --- a/drivers/net/txgbe/base/txgbe_dcb_hw.c +++ b/drivers/net/txgbe/base/txgbe_dcb_hw.c @@ -154,7 +154,7 @@ s32 txgbe_dcb_config_tx_data_arbiter_raptor(struct txgbe_hw *hw, u16 *refill, for (i = 0; i < TXGBE_DCB_UP_MAX; i++) reg |= TXGBE_DCBUP2TC_MAP(i, map[i]); - wr32(hw, TXGBE_PBRXUP2TC, reg); + wr32(hw, TXGBE_PBTXUP2TC, reg); /* Configure traffic class credits and priority */ for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index de382601c9..25aaf8ea68 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -503,10 +503,8 @@ #define TXGBE_PBRXCTL 0x019000 #define TXGBE_PBRXCTL_ST MS(0, 0x1) #define TXGBE_PBRXCTL_ENA MS(31, 0x1) -#define TXGBE_PBRXUP2TC 0x019008 #define TXGBE_PBTXUP2TC 0x01C800 -#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 3 * (tc), 0x7) -#define TXGBE_DCBUP2TC_DEC(tc, r) RS(r, 3 * (tc), 0x7) +#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 4 * (tc), 0x7) #define TXGBE_PBRXSIZE(tc) (0x019020 + (tc) * 4) #define TXGBE_PBRXSIZE_KB(v) LS(v, 10, 0x3FF) @@ -1703,7 +1701,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_RDM_PF_HIDE(_i) (0x12090 + ((_i) * 4)) #define TXGBE_RPUP2TC 0x019008 -#define TXGBE_RPUP2TC_UP_SHIFT 3 +#define TXGBE_RPUP2TC_UP_SHIFT 4 #define TXGBE_RPUP2TC_UP_MASK 0x7 #define TXGBE_RDM_DCACHE_CTL 0x0120A8 diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index be279dc4ec..851cd122d8 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -3385,11 +3385,8 @@ txgbe_vmdq_dcb_configure(struct rte_eth_dev *dev) queue_mapping = 0; for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) - /* - * mapping is done with 3 bits per priority, - * so shift by i*3 each time - */ - queue_mapping |= ((cfg->dcb_tc[i] & 0x07) << (i * 3)); + queue_mapping |= ((cfg->dcb_tc[i] & TXGBE_RPUP2TC_UP_MASK) << + (i * TXGBE_RPUP2TC_UP_SHIFT)); wr32(hw, TXGBE_RPUP2TC, queue_mapping); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 12/20] net/txgbe: fix link stability for 25G NIC 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (10 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang ` (9 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe_aml.c | 107 +- drivers/net/txgbe/base/txgbe_aml.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 2489 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56.h | 1742 +++++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 275 +++ drivers/net/txgbe/base/txgbe_hw.c | 35 +- drivers/net/txgbe/base/txgbe_phy.h | 1 - drivers/net/txgbe/base/txgbe_regs.h | 2 + drivers/net/txgbe/base/txgbe_type.h | 12 + drivers/net/txgbe/txgbe_ethdev.c | 83 +- drivers/net/txgbe/txgbe_ethdev.h | 4 + 12 files changed, 4699 insertions(+), 58 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56.c create mode 100644 drivers/net/txgbe/base/txgbe_e56.h create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index ac4a05005e..305c0291e3 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -12,4 +12,5 @@ base_sources = files( 'txgbe_mng.c', 'txgbe_phy.c', 'txgbe_vf.c', + 'txgbe_e56.c', ) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index de9a1b1c93..008b0245e5 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -12,6 +12,7 @@ #include "txgbe_mng.h" #include "txgbe_hw.h" #include "txgbe_aml.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -23,6 +24,7 @@ void txgbe_init_ops_aml(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml; + phy->setup_link_core = txgbe_setup_phy_link_aml; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml; @@ -175,16 +177,21 @@ void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed) } } -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; - u32 value = 0; + u32 value; + + *need_reset = false; if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { DEBUGOUT("SFP not detected, skip setup mac link"); @@ -197,33 +204,80 @@ s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, if (status) return status; + /* setup the highest link when no autoneg */ + if (!autoneg) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + speed = TXGBE_LINK_SPEED_25GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + } + speed &= link_capabilities; if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - value = rd32(hw, TXGBE_GPIOEXT); - if (value & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | + TXGBE_SFP1_RX_LOS_LS)) { + DEBUGOUT("RX LOS"); return status; + } - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) { + DEBUGOUT("check phy link_up"); + break; + } + msleep(250); + } - if (link_up && speed == TXGBE_LINK_SPEED_25GB_FULL) + if (speed == TXGBE_LINK_SPEED_25GB_FULL) hw->cur_fec_link = txgbe_phy_fec_get(hw); if (link_speed == speed && link_up && - !(speed == TXGBE_LINK_SPEED_25GB_FULL && - !(hw->fec_mode & hw->cur_fec_link))) - return status; + !(speed == TXGBE_LINK_SPEED_25GB_FULL && + !(hw->fec_mode & hw->cur_fec_link))) + goto out; - if (speed & TXGBE_LINK_SPEED_25GB_FULL) - speed = 0x10; - else if (speed & TXGBE_LINK_SPEED_10GB_FULL) - speed = 0x08; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) { + hw->link_valid = false; + link_up = false; + goto out; + } else { + hw->link_valid = true; + } + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + } else { + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + DEBUGOUT("MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + DEBUGOUT("MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + DEBUGOUT("Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -269,9 +323,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (10G -> 25G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, + bool need_reset; + + status = hw->phy.setup_link_core(hw, TXGBE_LINK_SPEED_25GB_FULL, - autoneg_wait_to_complete); + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -297,8 +354,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (25G->10G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, TXGBE_LINK_SPEED_10GB_FULL, - autoneg_wait_to_complete); + bool need_reset; + + status = hw->phy.setup_link_core(hw, + TXGBE_LINK_SPEED_10GB_FULL, + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -348,10 +409,8 @@ void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw) if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->setup_link = txgbe_setup_mac_link_multispeed_fiber_aml; - mac->setup_mac_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } else { - mac->setup_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } } diff --git a/drivers/net/txgbe/base/txgbe_aml.h b/drivers/net/txgbe/base/txgbe_aml.h index e98c952787..bfb01b4968 100644 --- a/drivers/net/txgbe/base/txgbe_aml.h +++ b/drivers/net/txgbe/base/txgbe_aml.h @@ -16,7 +16,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml(struct txgbe_hw *hw); void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed); -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw); #endif /* _TXGBE_AML_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c new file mode 100644 index 0000000000..3c4b054ef6 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -0,0 +1,2489 @@ +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" +#include "../txgbe_logs.h" + +void +set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value) +{ + unsigned int i; + + /* Single bit field handling */ + if (bit_high == bit_low) { + if (set_value == 0) { + /* clear single bit */ + *src_data &= ~(1 << bit_low); + } else { + /* set single bit */ + *src_data |= (1 << bit_low); + } + } else { + /* first, clear the bit fields */ + for (i = bit_low; i <= bit_high; i++) { + /* clear single bit */ + *src_data &= ~(1 << i); + } + + /* second, or the bit fields with set value */ + *src_data |= (set_value << bit_low); + } +} + +/* + * compare function for qsort() + */ +static inline +int txgbe_e56_int_cmp(const void *a, const void *b) +{ + const int *num1 = (const int *)a; + const int *num2 = (const int *)b; + + if (*num1 < *num2) + return -1; + + else if (*num1 > *num2) + return 1; + + else + return 0; +} + +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up) +{ + u32 rdata = 0; + u32 links_reg = 0; + + /* must read it twice because the state may + * not be correct the first time you read it + */ + rdata = rd32_epcs(hw, 0x30001); + rdata = rd32_epcs(hw, 0x30001); + + if (rdata & TXGBE_E56_PHY_LINK_UP) + *link_up = true; + else + *link_up = false; + + if (!hw->link_valid) + *link_up = false; + + links_reg = rd32(hw, TXGBE_PORTSTAT); + if (*link_up) { + if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == + TXGBE_CFG_PORT_ST_AML_LINK_40G) + *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == + TXGBE_CFG_PORT_ST_AML_LINK_25G) + *speed = TXGBE_LINK_SPEED_25GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; + } else { + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + + return 0; +} + +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) +{ + u32 ffe_main = 0, pre1 = 0, pre2 = 0, post = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_MAIN; + pre1 = S25G_TX_FFE_CFG_PRE1; + pre2 = S25G_TX_FFE_CFG_PRE2; + post = S25G_TX_FFE_CFG_POST; + } + } + + if (hw->phy.ffe_set) { + ffe_main = hw->phy.ffe_main; + pre1 = hw->phy.ffe_pre; + pre2 = hw->phy.ffe_pre2; + post = hw->phy.ffe_post; + } + + DEBUGOUT("main = 0x%x, pre1 = 0x%x, pre2 = 0x%x, post = 0x%x", + ffe_main, pre1, pre2, post); + + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_1_ADDR, ffe_main); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_2_ADDR, pre1); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_3_ADDR, pre2); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_4_ADDR, post); + + return 0; +} + +int +txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) +{ + int data_code, temp_data, temp_fraction; + u32 rdata; + u32 timer = 0; + + while (1) { + rdata = rd32(hw, 0x1033c); + if (((rdata >> 12) & 0x1) != 0) + break; + if (timer++ > PHYINIT_TIMEOUT) + return -1; + } + + data_code = rdata & 0xFFF; + temp_data = 419400 + 2205 * (data_code * 1000 / 4094 - 500); + + /* Change double Temperature to int */ + *temp = temp_data / 10000; + temp_fraction = temp_data - (*temp * 10000); + if (temp_fraction >= 5000) + *temp += 1; + + return 0; +} + +u32 +txgbe_e56_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + /* change 0x90 to 0x0 to fix 25G link up keep when cable unplugged */ + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S25G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S25G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S25G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +u32 +txgbe_e56_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static inline int +txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int addr, rdata, timer; + int T = 40; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int OFFSET_CENTRE_RANGE_H, OFFSET_CENTRE_RANGE_L, RANGE_FINAL; + int i = 0; + int lane_num = 1; + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* + * 2. Define software variable RX_COARSE_MID_TD + * (RX Coarse Code mid value dependent upon temperature) + */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + } + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + lane_num = 4; + + /* 3. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_H */ + for (i = 0; i < lane_num; i++) { + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 4. Do SEQ::RX_ENABLE to enable RXS, and let it stop after oscillator calibration. + * This needs to be done by blocking the RX power-up fsm at the state following + * the oscillator calibration state. + * Follow below steps to do the same before SEQ::RX_ENABLE. + * a. ALIAS::PDIG::CTRL_FSM_RX_ST can be stopped at RX_SAMP_CAL_ST which is the + * state after RX_OSC_CAL_ST by configuring ALIAS::RXS::SAMP_CAL_DONE=0b0 + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Do SEQ::RX_ENABLE to enable RXS */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* b. Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm its value is RX_SAMP_CAL_ST */ + rdata = 0; + timer = 0; + while ((rdata >> (i * 8) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (rdata & (0x100 << i)) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* 5/6.Define software variable as OFFSET_CENTRE_RANGE_H = ALIAS::RXS::COARSE */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_H > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_H = OFFSET_CENTRE_RANGE_H - RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_H = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_H; + + /* + * 7. Do SEQ::RX_DISABLE to disable RXS. + * Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm. + */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) + break; + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 8. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, + * it is possible the timeout interrupt is set. + * Clear the same by clearing ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. + * Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + usec_delay(500); + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 9. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_L */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 10. Do SEQ::RX_ENABLE to enable RXS, + * and let it stop after oscillator calibration. + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* poll CTRL_FSM_RX_ST */ + timer = 0; + while (((rdata >> (i * 8)) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x100) == 0x100) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 11/12.Define software variable as OFFSET_CENTRE_RANGE_L = ALIAS::RXS::COARSE - + * RX_COARSE_MID_TD. Clear the INTR. + */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_L > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_L = OFFSET_CENTRE_RANGE_L - RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_L = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_L; + + /* + * 13. Perform below calculation in software. Goal is to pick range value + * which is closer to RX_COARSE_MID_TD. + */ + if (OFFSET_CENTRE_RANGE_L < OFFSET_CENTRE_RANGE_H) + RANGE_FINAL = CMVAR_RANGE_L; + else + RANGE_FINAL = CMVAR_RANGE_H; + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) + break; + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 15. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, + * it is possible the timeout interrupt is set. Clear the same by clearing + * ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR + * which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(500); + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 16. Program ALIAS::RXS::RANGE_SEL = RANGE_FINAL */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, RANGE_FINAL); + wr32_ephy(hw, addr, rdata); + + /* + * 17. Program following before enabling RXS. Purpose is to disable power-up + * FSM control on ADC offset adaptation. + * Note: this step will be done in 2.3.3 RXS calibration and adaptation sequence + * 18. After this SEQ::RX_ENABLE can be done at any time. Note to ensure that + * ALIAS::RXS::RANGE_SEL = RANGE_FINAL configuration is retained. + * Rmove the OVRDEN on rxs0_rx0_samp_cal_done_o + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + } + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0xf); + else + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x1); + wr32_ephy(hw, addr, rdata); + + return status; +} + +static inline +int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + + unsigned int CMVAR_UFINE_MAX = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + else if (speed == TXGBE_LINK_SPEED_25GB_FULL) + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + + /* a. Assign software defined variables as below */ + /* ii. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE); + /* Set ovrd_en=1 to override ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i, + 1); + /* Wait until 1milliseconds or greater */ + msleep(10); + } + + return status; +} + +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) +{ + int status = 0, i, N, median; + unsigned int rdata; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + + /* Set ovrd_en=0 to read ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + + /* + * As status update from RXS hardware is asynchronous to read status + * of SECOND_ORDER, follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + /* set RXS_BBCDR_SECOND_ORDER_ST[i] = + * RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ + +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + int temperature; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + PMD_DRV_LOG(ERR, "Error Speed"); + return 0; + } + + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; + + hw->temperature = temperature; + + /* + * Assign software defined variables as below + * a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER + */ + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + /* Set ovrd_en=1 to override ASIC value */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All two of above code updates should be written + * in a single register write + * Set ovrd_en=1 to override ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All three of above code updates should be written + * in a single register write + * Set ovrd_en=1 to override ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature " + "tracking occurs Error condition"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " + "temperature tracking occurs Error condition"); + } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static inline int +txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypass_ctle = 1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + bypass_ctle = 0; + + if (hw->mac.type == txgbe_mac_aml) { + msleep(350); + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { + if (rdata & TXGBE_SFP1_MOD_ABS_LS) + DEBUGOUT("E56phyRxsCalibAdaptSeq TXGBE_SFP1_MOD_ABS_LS"); + else if (rdata & TXGBE_SFP1_RX_LOS_LS) + DEBUGOUT("E56phyRxsCalibAdaptSeq TXGBE_SFP1_RX_LOS_LS"); + return TXGBE_ERR_PHY_INIT_NOT_DONE; + } + } + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + if (bypass_ctle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature + * tracking range here. RXS would be enabled at the end of this sequence. For the case + * when PAM4 KR training is not enabled (including PAM4 mode without KR training), + * wait until ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, + ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + EPHY_RREG(E56G__PMD_CTRL_FSM_RX_STAT_0); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + /* + * 4. Disable VGA and CTLE training so that they don't interfere with ADC calibration + * a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 5. Perform ADC interleaver calibration + * a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE + */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) & 1) + != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* + * 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (i = 0; i < 16; i++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_gain_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* + * 7. Perform ADC interleaver adaptation for 10ms or greater, and after that disable it + * a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_intl_adapt_en_i, 0); + + /* + * 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking + * changes in temperature or voltage + * <1> Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + * Set ALIAS::RXS::CTLE_TRAIN_EN = 0b1 + */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + /* + * <2> wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 + * wait for ALIAS::RXS::CTLE_TRAIN_DONE = 1 + */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_vga_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + if (bypass_ctle == 0) { + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + return status; +} + +static inline u32 +txgbe_e56_cfg_temp(struct txgbe_hw *hw) +{ + u32 status; + u32 value; + int temp; + + status = txgbe_e56_get_temp(hw, &temp); + if (status) + temp = DEFAULT_TEMP; + + if (temp < DEFAULT_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else if (temp > HIGH_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else { + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 4, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL4); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL4, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL5); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 23, 23, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL9); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL9, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL10); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL10, value); + } + + return 0; +} + +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + + return 0; +} + +/* + * 2.2.10 SEQ::RX_DISABLE + * Use PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 to powerdown specific RXS lanes. + * Completion of RXS powerdown can be confirmed by + * observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST + */ +static int txgbe_e56_disable_rx(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i, 0); + + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o, 0); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_2); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_2); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_3); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_3); + + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_RREG(E56G__RXS0_DIG_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + EPHY_WREG(E56G__RXS0_DIG_OVRDEN_1); + + /* 2. Disable pattern checker */ + txgbe_e56_ephy_config(E56G__RXS0_DFT_1, ber_en, 0); + + /* 3. Disable internal serial loopback mode */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i, 0); + + /* 4. Enable bypass of clock gates in RXS */ + txgbe_e56_ephy_config(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en, 0x1FFF); + + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0, 0); + + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en, 0); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + while (1) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x3f) == 0x21) + break; + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) +{ + u32 addr; + u32 rdata; + int status = 0; + + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + + if (hw->mac.type == txgbe_mac_aml) { + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) + return TXGBE_ERR_TIMEOUT; + } + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, 0x0); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, 0x0); + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); + + addr = E56PHY_INTR_1_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_1_IDLE_EXIT1); + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + hw->mac.enable_sec_tx_path(hw); + + return status; +} + +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) +{ + u32 value = 0; + u32 ppl_lock = false; + int status = 0; + u32 reset = 0; + + DEBUGOUT("port[%d] force set speed: 0x%x", hw->bus.lan_id, speed); + + if ((rd32(hw, TXGBE_EPHY_STAT) & TXGBE_EPHY_STAT_PPL_LOCK) == + TXGBE_EPHY_STAT_PPL_LOCK) { + ppl_lock = true; + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.disable_tx_laser(hw); + + if (hw->bus.lan_id == 0) + reset = TXGBE_RST_EPHY_LAN_0; + + else + reset = TXGBE_RST_EPHY_LAN_1; + + wr32(hw, TXGBE_RST, + reset | rd32(hw, TXGBE_RST)); + txgbe_flush(hw); + usec_delay(10); + + /* XLGPCS REGS Start */ + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + value |= 0x8000; + wr32_epcs(hw, VR_PCS_DIG_CTRL1, value); + + usec_delay(1000); + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + if ((value & 0x8000)) { + status = TXGBE_ERR_PHY_INIT_NOT_DONE; + hw->mac.enable_tx_laser(hw); + goto out; + } + + value = rd32_epcs(hw, SR_AN_CTRL); + set_fields_e56(&value, 12, 12, 0); + wr32_epcs(hw, SR_AN_CTRL, value); + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 5); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 7); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0x39); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + /* Update to 0 for PIN CLKP/N: Enable the termination of the input buffer */ + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 2, 0, 0x3); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x9); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_25g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0xb); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_10g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.enable_tx_laser(hw); + + status = txgbe_e56_config_rx(hw, speed); + + value = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, value); + + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + if (hw->fec_mode != TXGBE_PHY_FEC_AUTO) { + hw->cur_fec_link = hw->fec_mode; + txgbe_e56_fec_set(hw); + } + +out: + if (ppl_lock) { + hw->mac.enable_sec_tx_path(hw); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + TXGBE_MACRXCFG_ENA); + } + + return status; +} + +s32 txgbe_e56_fec_set(struct txgbe_hw *hw) +{ + u32 value; + + if (hw->cur_fec_link & TXGBE_PHY_FEC_RS) { + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + + /* enable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 1); + wr32_epcs(hw, 0x100c8, value); + } else if (hw->cur_fec_link & TXGBE_PHY_FEC_BASER) { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* enable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 1); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } else { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } + + return 0; +} + +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up) +{ + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + s32 i = 0, j = 0; + + do { + if (!(hw->fec_mode & BIT(j))) { + j += 1; + continue; + } + + hw->cur_fec_link = hw->fec_mode & BIT(j); + + /* + * If in fec auto mode, try another fec mode after no link in 1s + * for lr sfp, enable KR-FEC to link up with mellonax and intel + */ + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_fec_set(hw); + rte_spinlock_unlock(&hw->phy_lock); + + for (i = 0; i < 4; i++) { + msleep(250); + txgbe_e56_check_phy_link(hw, &link_speed, link_up); + if (*link_up) + return 0; + } + j += 1; + } while (j < 3); + + return 0; +} diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h new file mode 100644 index 0000000000..eaa3ea5085 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -0,0 +1,1742 @@ +#ifndef _TXGBE_E56_H_ +#define _TXGBE_E56_H_ + +#include "txgbe_type.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" + +#define EPHY_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_ephy(hw, REG##_ADDR); \ + } while (0) + +#define EPCS_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_epcs(hw, REG##_ADDR); \ + } while (0) + +#define EPHY_WREG(REG) wr32_ephy(hw, REG##_ADDR, rdata) +#define EPCS_WREG(REG) wr32_epcs(hw, REG##_ADDR, rdata) + +#define txgbe_e56_ephy_config(reg, field, val) \ + do { \ + EPHY_RREG(reg); \ + EPHY_XFLD(reg, field) = (val); \ + EPHY_WREG(reg); \ + } while (0) + +#define txgbe_e56_epcs_config(reg, field, val) \ + do { \ + EPCS_RREG(reg); \ + EPCS_XFLD(reg, field) = (val); \ + EPCS_WREG(reg); \ + } while (0) + +/* + * LAN GPIO define for SFP+ module + * -- Fields + */ +#define SFP1_RS0 5, 5 +#define SFP1_RS1 4, 4 +#define SFP1_RX_LOS 3, 3 +#define SFP1_MOD_ABS 2, 2 +#define SFP1_TX_DISABLE 1, 1 +#define SFP1_TX_FAULT 0, 0 + +#define EPHY_XFLD(REG, FLD) (((REG *)&rdata)->FLD) +#define EPCS_XFLD(REG, FLD) (((REG *)&rdata)->FLD) + +typedef union { + struct { + u32 ana_refclk_buf_daisy_en_i : 1; + u32 ana_refclk_buf_pad_en_i : 1; + u32 ana_vddinoff_dcore_dig_o : 1; + u32 ana_lcpll_en_clkout_hf_left_top_i : 1; + u32 ana_lcpll_en_clkout_hf_right_top_i : 1; + u32 ana_lcpll_en_clkout_hf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_hf_right_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_left_top_i : 1; + u32 ana_lcpll_en_clkout_lf_right_top_i : 1; + u32 ana_lcpll_en_clkout_lf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_right_bot_i : 1; + u32 ana_bg_en_i : 1; + u32 ana_en_rescal_i : 1; + u32 ana_rescal_comp_o : 1; + u32 ana_en_ldo_core_i : 1; + u32 ana_lcpll_hf_en_bias_i : 1; + u32 ana_lcpll_hf_en_loop_i : 1; + u32 ana_lcpll_hf_en_cp_i : 1; + u32 ana_lcpll_hf_set_lpf_i : 1; + u32 ana_lcpll_hf_en_vco_i : 1; + u32 ana_lcpll_hf_vco_amp_status_o : 1; + u32 ana_lcpll_hf_en_odiv_i : 1; + u32 ana_lcpll_lf_en_bias_i : 1; + u32 ana_lcpll_lf_en_loop_i : 1; + u32 ana_lcpll_lf_en_cp_i : 1; + u32 ana_lcpll_lf_set_lpf_i : 1; + u32 ana_lcpll_lf_en_vco_i : 1; + u32 ana_lcpll_lf_vco_amp_status_o : 1; + u32 ana_lcpll_lf_en_odiv_i : 1; + u32 ana_lcpll_hf_refclk_select_i : 1; + u32 ana_lcpll_lf_refclk_select_i : 1; + u32 rsvd0 : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_0; + +/* AMLITE ETH PHY Registers */ +#define VR_PCS_DIG_CTRL1 0x38000 +#define SR_PCS_CTRL1 0x30000 +#define SR_PCS_CTRL2 0x30007 +#define SR_PMA_CTRL2 0x10007 +#define VR_PCS_DIG_CTRL3 0x38003 +#define VR_PMA_CTRL3 0x180a8 +#define VR_PMA_CTRL4 0x180a9 +#define SR_PMA_RS_FEC_CTRL 0x100c8 +#define CMS_ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN1 0xca8 +#define ANA_OVRDVAL0 0xcb0 +#define ANA_OVRDVAL5 0xcc4 +#define OSC_CAL_N_CDR4 0x14 +#define PLL0_CFG0 0xc10 +#define PLL0_CFG2 0xc18 +#define PLL0_DIV_CFG0 0xc1c +#define PLL1_CFG0 0xc48 +#define PLL1_CFG2 0xc50 +#define CMS_PIN_OVRDEN0 0xc8c +#define CMS_PIN_OVRDVAL0 0xc94 +#define DATAPATH_CFG0 0x142c +#define DATAPATH_CFG1 0x1430 +#define AN_CFG1 0x1438 +#define SPARE52 0x16fc +#define RXS_CFG0 0x000 +#define PMD_CFG0 0x1400 +#define SR_PCS_STS1 0x30001 +#define PMD_CTRL_FSM_TX_STAT0 0x14dc +#define CMS_ANA_OVRDEN0 0xca4 +#define CMS_ANA_OVRDEN1 0xca8 +#define CMS_ANA_OVRDVAL2 0xcb8 +#define CMS_ANA_OVRDVAL4 0xcc0 +#define CMS_ANA_OVRDVAL5 0xcc4 +#define CMS_ANA_OVRDVAL7 0xccc +#define CMS_ANA_OVRDVAL9 0xcd4 +#define CMS_ANA_OVRDVAL10 0xcd8 + +#define TXS_TXS_CFG1 0x804 +#define TXS_WKUP_CNT 0x808 +#define TXS_PIN_OVRDEN0 0x80c +#define TXS_PIN_OVRDVAL6 0x82c +#define TXS_ANA_OVRDVAL1 0x854 + +#define E56PHY_CMS_BASE_ADDR 0x0C00 + +#define E56PHY_CMS_PIN_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x8C) +#define E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I 12, 12 + +#define E56PHY_CMS_PIN_OVRDVAL_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x94) +#define E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I 10, 10 + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) + +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I 29, 29 + +#define E56PHY_CMS_ANA_OVRDEN_1_ADDR (E56PHY_CMS_BASE_ADDR + 0xA8) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I 4, 4 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ADDR (E56PHY_CMS_BASE_ADDR + 0xB8) + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I 31, 28 + +#define E56PHY_CMS_ANA_OVRDVAL_4_ADDR (E56PHY_CMS_BASE_ADDR + 0xC0) + +#define E56PHY_TXS_BASE_ADDR 0x0800 +#define E56PHY_TXS1_BASE_ADDR 0x0900 +#define E56PHY_TXS2_BASE_ADDR 0x0A00 +#define E56PHY_TXS3_BASE_ADDR 0x0B00 +#define E56PHY_TXS_OFFSET 0x0100 + +#define E56PHY_PMD_RX_OFFSET 0x02C + +#define E56PHY_TXS_TXS_CFG_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x04) +#define E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256 7, 4 +#define E56PHY_TXS_WKUP_CNT_ADDR (E56PHY_TXS_BASE_ADDR + 0x08) +#define E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32 7, 0 +#define E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32 15, 8 + +#define E56PHY_TXS_PIN_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x0C) +#define E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I 28, 28 + +#define E56PHY_TXS_PIN_OVRDVAL_6_ADDR (E56PHY_TXS_BASE_ADDR + 0x2C) + +#define E56PHY_TXS_ANA_OVRDVAL_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x54) +#define E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I 23, 8 + +#define E56PHY_TXS_ANA_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x44) +#define E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I 13, 13 + +#define E56PHY_RXS_BASE_ADDR 0x0000 +#define E56PHY_RXS1_BASE_ADDR 0x0200 +#define E56PHY_RXS2_BASE_ADDR 0x0400 +#define E56PHY_RXS3_BASE_ADDR 0x0600 +#define E56PHY_RXS_OFFSET 0x0200 + +#define E56PHY_RXS_RXS_CFG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x000) +#define E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL 1, 1 +#define E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN 17, 4 + +#define E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x008) +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1 15, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1_LSB 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1 31, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1_LSB 16 + +#define E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x014) +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT 18, 8 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1 21, 21 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1 27, 26 + +#define E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x018) +#define E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK 15, 12 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK 19, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK 23, 20 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK 27, 24 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT 30, 28 + +#define E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x01C) +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK 3, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK 7, 4 + +#define E56PHY_RXS_INTL_CONFIG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x020) +#define E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1 31, 16 + +#define E56PHY_RXS_INTL_CONFIG_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x028) +#define E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1 1, 1 + +#define E56PHY_RXS_TXFFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x02C) +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH 18, 12 +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH 26, 20 + +#define E56PHY_RXS_TXFFE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x030) +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x034) +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x038) +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH 20, 12 +#define E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE 26, 21 + +#define E56PHY_RXS_VGA_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x04C) +#define E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET 18, 12 + +#define E56PHY_RXS_VGA_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x050) +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0 4, 0 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0 12, 8 +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123 20, 16 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123 28, 24 + +#define E56PHY_RXS_CTLE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x054) +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0 24, 20 +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123 31, 27 + +#define E56PHY_RXS_CTLE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x058) +#define E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT 24, 0 + +#define E56PHY_RXS_CTLE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x05C) +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1 5, 0 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2 13, 8 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3 21, 16 + +#define E56PHY_RXS_CTLE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x060) +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1 9, 8 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2 11, 10 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3 13, 12 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x064) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT 5, 4 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT 9, 8 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8 31, 28 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x068) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG 31, 28 + +#define E56PHY_RXS_FFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x070) +#define E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN 23, 8 + +#define E56PHY_RXS_IDLE_DETECT_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x088) +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX 22, 16 +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN 30, 24 + +#define E56PHY_RXS_ANA_OVRDEN_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x08C) +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_TRIM_RTERM_I 1, 1 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I 29, 29 + +#define E56PHY_RXS_ANA_OVRDEN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x090) +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I 9, 9 + +#define E56PHY_RXS_ANA_OVRDEN_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x098) +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I 15, 15 +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I 25, 25 + +#define E56PHY_RXS_ANA_OVRDEN_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x09C) +#define E56PHY_RXS_ANA_OVRDVAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x0A0) +#define E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I 0, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B8) +#define E56PHY_RXS_ANA_OVRDVAL_14_ADDR (E56PHY_RXS_BASE_ADDR + 0x0D8) +#define E56PHY_RXS_ANA_OVRDVAL_15_ADDR (E56PHY_RXS_BASE_ADDR + 0x0DC) +#define E56PHY_RXS_ANA_OVRDVAL_17_ADDR (E56PHY_RXS_BASE_ADDR + 0x0E4) +#define E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I 18, 16 + +#define E56PHY_RXS_EYE_SCAN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x1A4) +#define E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER 31, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B4) +#define E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I 1, 0 + +#define E56PHY_RXS_RINGO_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x1FC) + +#define E56PHY_PMD_BASE_ADDR 0x1400 +#define E56PHY_PMD_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x000) +#define E56PHY_PMD_CFG_0_RX_EN_CFG 19, 16 + +#define E56PHY_PMD_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x00C) +#define E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K 31, 24 +#define E56PHY_PMD_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x010) +#define E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K 7, 0 +#define E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K 15, 8 +#define E56PHY_PMD_CFG_5_ADDR (E56PHY_PMD_BASE_ADDR + 0x014) +#define E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET 12, 12 +#define E56PHY_CTRL_FSM_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x040) +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_OFST_CAL_ERR 4, 4 +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR 5, 5 +#define E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL 9, 8 +#define E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN 31, 24 + +#define E56PHY_CTRL_FSM_CFG_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x044) +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x048) +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x04C) +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096 7, 0 + +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x050) +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_7_ADDR (E56PHY_PMD_BASE_ADDR + 0x05C) +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_8_ADDR (E56PHY_PMD_BASE_ADDR + 0x060) +#define E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_12_ADDR (E56PHY_PMD_BASE_ADDR + 0x070) +#define E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_13_ADDR (E56PHY_PMD_BASE_ADDR + 0x074) +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_14_ADDR (E56PHY_PMD_BASE_ADDR + 0x078) +#define E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_15_ADDR (E56PHY_PMD_BASE_ADDR + 0x07C) +#define E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_17_ADDR (E56PHY_PMD_BASE_ADDR + 0x084) +#define E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_18_ADDR (E56PHY_PMD_BASE_ADDR + 0x088) +#define E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_29_ADDR (E56PHY_PMD_BASE_ADDR + 0x0B4) +#define E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_33_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C4) +#define E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_CFG_34_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C8) +#define E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_RX_STAT_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x0FC) +#define E56PHY_RXS0_OVRDEN_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x130) +#define E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O 27, 27 + +#define E56PHY_RXS0_OVRDEN_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x134) +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I 14, 14 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I 16, 16 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CDR_EN_I 18, 18 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I 23, 23 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O 24, 24 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 24 + +#define E56PHY_RXS0_OVRDEN_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x138) +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I 0, 0 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 3, 3 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I 6, 6 + +#define E56PHY_RXS0_OVRDVAL_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x140) +#define E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O 22, 22 + +#define E56PHY_RXS0_OVRDVAL_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x144) +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I 7, 7 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I 9, 9 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CDR_EN_I 11, 11 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I 16, 16 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O 17, 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I 25, 25 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 28, 28 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I 31, 31 + +#define E56PHY_INTR_0_IDLE_ENTRY1 0x10000000 +#define E56PHY_INTR_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x1EC) +#define E56PHY_INTR_0_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E0) + +#define E56PHY_INTR_1_IDLE_EXIT1 0x1 +#define E56PHY_INTR_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x1F0) +#define E56PHY_INTR_1_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E4) + +#define E56PHY_KRT_TFSM_CFG_ADDR (E56PHY_PMD_BASE_ADDR + 0x2B8) +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K 7, 0 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K 15, 8 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 + +#define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 + +#define PHYINIT_TIMEOUT 1000 /* PHY initialization timeout value in 0.5ms unit */ + +#define E56G__BASEADDR 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_7; +#define E56G_CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDEN_1; + +#define E56G_CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_9; + +#define E56G_CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_vcofilt_byp_i : 1; + u32 ovrd_en_ana_bbcdr_coarse_i : 1; + u32 ovrd_en_ana_bbcdr_fine_i : 1; + u32 ovrd_en_ana_bbcdr_ultrafine_i : 1; + u32 ovrd_en_ana_en_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_divctrl_i : 1; + u32 ovrd_en_ana_bbcdr_int_cstm_i : 1; + u32 ovrd_en_ana_bbcdr_prop_step_i : 1; + u32 ovrd_en_ana_en_bbcdr_clk_i : 1; + u32 ovrd_en_ana_test_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_270_o : 1; + u32 ovrd_en_ana_en_bbcdr_samp_dac_i : 1; + u32 ovrd_en_ana_bbcdr_dac0_i : 1; + u32 ovrd_en_ana_bbcdr_dac90_i : 1; + u32 ovrd_en_ana_vga2_cload_in_cstm_i : 1; + u32 ovrd_en_ana_intlvr_cut_bw_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_1; + +#define E56G__RXS0_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0x90) + +typedef union { + struct { + u32 prediv0 : 16; + u32 target_cnt0 : 16; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_0; + +#define E56G_RXS0_OSC_CAL_N_CDR_0_ADDR (E56G__BASEADDR + 0x4) + +typedef union { + struct { + u32 osc_range_sel0 : 2; + u32 osc_range_sel1 : 2; + u32 osc_range_sel2 : 2; + u32 osc_range_sel3 : 2; + u32 vco_code_init : 11; + u32 calibrate_range_sel : 1; + u32 osc_current_boost_en0 : 1; + u32 osc_current_boost_en1 : 1; + u32 osc_current_boost_en2 : 1; + u32 osc_current_boost_en3 : 1; + u32 bbcdr_current_boost0 : 2; + u32 bbcdr_current_boost1 : 2; + u32 bbcdr_current_boost2 : 2; + u32 bbcdr_current_boost3 : 2; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_4; + +#define E56G_RXS0_OSC_CAL_N_CDR_4_ADDR (E56G__BASEADDR + 0x14) + +typedef union { + struct { + u32 adc_intl2slice_delay0 : 16; + u32 adc_intl2slice_delay1 : 16; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_0; + +#define E56G_RXS0_INTL_CONFIG_0_ADDR (E56G__BASEADDR + 0x20) + +typedef union { + struct { + u32 interleaver_hbw_disable0 : 1; + u32 interleaver_hbw_disable1 : 1; + u32 interleaver_hbw_disable2 : 1; + u32 interleaver_hbw_disable3 : 1; + u32 rsvd0 : 28; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_2; + +#define E56G_RXS0_INTL_CONFIG_2_ADDR (E56G__BASEADDR + 0x28) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_dac180_i : 1; + u32 ovrd_en_ana_bbcdr_dac270_i : 1; + u32 ovrd_en_ana_bbcdr_en_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_0_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_90_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_180_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_270_o : 1; + u32 ovrd_en_ana_en_adcbuf1_i : 1; + u32 ovrd_en_ana_test_adcbuf1_i : 1; + u32 ovrd_en_ana_en_adc_clk4ui_i : 1; + u32 ovrd_en_ana_adc_clk_skew0_i : 1; + u32 ovrd_en_ana_adc_clk_skew90_i : 1; + u32 ovrd_en_ana_adc_clk_skew180_i : 1; + u32 ovrd_en_ana_adc_clk_skew270_i : 1; + u32 ovrd_en_ana_adc_update_skew_i : 1; + u32 ovrd_en_ana_en_adc_pi_i : 1; + u32 ovrd_en_ana_adc_pictrl_quad_i : 1; + u32 ovrd_en_ana_adc_pctrl_code_i : 1; + u32 ovrd_en_ana_adc_clkdiv_i : 1; + u32 ovrd_en_ana_test_adc_clkgen_i : 1; + u32 ovrd_en_ana_en_adc_i : 1; + u32 ovrd_en_ana_en_adc_vref_i : 1; + u32 ovrd_en_ana_vref_cnfg_i : 1; + u32 ovrd_en_ana_adc_data_cstm_o : 1; + u32 ovrd_en_ana_en_adccal_lpbk_i : 1; + u32 ovrd_en_ana_sel_adcoffset_cal_i : 1; + u32 ovrd_en_ana_sel_adcgain_cal_i : 1; + u32 ovrd_en_ana_adcgain_cal_swing_ctrl_i : 1; + u32 ovrd_en_ana_adc_gain_i : 1; + u32 ovrd_en_ana_vga_cload_out_cstm_i : 1; + u32 ovrd_en_ana_vga2_cload_out_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_2; + +#define E56G__RXS0_ANA_OVRDEN_2_ADDR (E56G__BASEADDR + 0x94) + +typedef union { + struct { + u32 ovrd_en_ana_adc_offset_i : 1; + u32 ovrd_en_ana_adc_slice_addr_i : 1; + u32 ovrd_en_ana_slice_wr_i : 1; + u32 ovrd_en_ana_test_adc_i : 1; + u32 ovrd_en_ana_test_adc_o : 1; + u32 ovrd_en_ana_spare_o : 8; + u32 ovrd_en_ana_sel_lpbk_i : 1; + u32 ovrd_en_ana_ana_debug_sel_i : 1; + u32 ovrd_en_ana_anabs_config_i : 1; + u32 ovrd_en_ana_en_anabs_i : 1; + u32 ovrd_en_ana_anabs_rxn_o : 1; + u32 ovrd_en_ana_anabs_rxp_o : 1; + u32 ovrd_en_ana_dser_clk_en_i : 1; + u32 ovrd_en_ana_dser_clk_config_i : 1; + u32 ovrd_en_ana_en_mmcdr_clk_obs_i : 1; + u32 ovrd_en_ana_skew_coarse0_fine1_i : 1; + u32 ovrd_en_ana_vddinoff_acore_dig_o : 1; + u32 ovrd_en_ana_vddinoff_dcore_dig_o : 1; + u32 ovrd_en_ana_vga2_boost_cstm_i : 1; + u32 ovrd_en_ana_adc_sel_vbgr_bias_i : 1; + u32 ovrd_en_ana_adc_nbuf_cnfg_i : 1; + u32 ovrd_en_ana_adc_pbuf_cnfg_i : 1; + u32 rsvd0 : 3; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_3; + +#define E56G__RXS0_ANA_OVRDEN_3_NUM 1 +#define E56G__RXS0_ANA_OVRDEN_3_ADDR (E56G__BASEADDR + 0x98) + +typedef union { + struct { + u32 pam4_ab_swap_en : 1; + u32 dser_data_sel : 1; + u32 signal_type : 1; + u32 precode_en : 1; + u32 train_clk_gate_bypass_en : 14; + u32 rsvd0 : 14; + }; + u32 reg; +} E56G__RXS0_RXS_CFG_0; + +#define E56G__RXS0_RXS_CFG_0_NUM 1 +#define E56G__RXS0_RXS_CFG_0_ADDR (E56G__BASEADDR + 0x0) + +typedef union { + struct { + u32 restart_training_ln0 : 1; + u32 training_enable_ln0 : 1; + u32 restart_training_ln1 : 1; + u32 training_enable_ln1 : 1; + u32 restart_training_ln2 : 1; + u32 training_enable_ln2 : 1; + u32 restart_training_ln3 : 1; + u32 training_enable_ln3 : 1; + u32 rsvd0 : 24; + }; + u32 reg; +} E56G__PMD_BASER_PMD_CONTROL; + +#define E56G__PMD_BASER_PMD_CONTROL_NUM 1 +#define E56G__PMD_BASER_PMD_CONTROL_ADDR (E56G__BASEADDR + 0x1640) + +typedef union { + struct { + u32 rx_to_tx_lpbk_en : 4; + u32 sel_wp_pmt_out : 4; + u32 sel_wp_pmt_clkout : 4; + u32 use_recent_marker_offset : 1; + u32 interrupt_debug_mode : 1; + u32 rsvd0 : 2; + u32 tx_ffe_coeff_update : 4; + u32 rsvd1 : 12; + }; + u32 reg; +} E56G__PMD_PMD_CFG_5; + +#define E56G__PMD_PMD_CFG_5_NUM 1 +#define E56G__PMD_PMD_CFG_5_ADDR (E56G__BASEADDR + 0x1414) + +typedef union { + struct { + u32 soft_reset : 1; + u32 pmd_en : 1; + u32 rsvd0 : 2; + u32 pll_refclk_sel : 2; + u32 rsvd1 : 2; + u32 pmd_mode : 1; + u32 rsvd2 : 3; + u32 tx_en_cfg : 4; + u32 rx_en_cfg : 4; + u32 pll_en_cfg : 2; + u32 rsvd3 : 2; + u32 pam4_precode_no_krt_en : 4; + u32 rsvd4 : 4; + }; + u32 reg; +} E56G__PMD_PMD_CFG_0; + +#define E56G__PMD_PMD_CFG_0_NUM 1 +#define E56G__PMD_PMD_CFG_0_ADDR (E56G__BASEADDR + 0x1400) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_rstn_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_divctrl_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_rate_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_width_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_o : 1; + u32 ovrd_en_rxs0_rx0_precode_en_i : 1; + u32 ovrd_en_rxs0_rx0_signal_type_i : 1; + u32 ovrd_en_rxs0_rx0_sync_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_sync_o : 1; + u32 ovrd_en_rxs0_rx0_rate_select_i : 1; + u32 ovrd_en_rxs0_rx0_rterm_en_i : 1; + u32 ovrd_en_rxs0_rx0_bias_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_rdy_i : 1; + u32 ovrd_en_rxs0_rx0_blwc_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_sel_i : 1; + u32 ovrd_en_rxs0_rx0_osc_en_i : 1; + u32 ovrd_en_rxs0_rx0_clkgencdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctlecdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_osc_freq_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_err_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_error_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_0; + +#define E56G__PMD_RXS0_OVRDEN_0_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_0_ADDR (E56G__BASEADDR + 0x1530) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_sparein_i : 8; + u32 ovrd_en_rxs0_rx0_spareout_o : 8; + u32 rsvd0 : 16; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_3; + +#define E56G__PMD_RXS0_OVRDEN_3_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_3_ADDR (E56G__BASEADDR + 0x153c) + +typedef union { + struct { + u32 vco_code_cont_adj_done_ovrd_en : 1; + u32 dfe_coeffl_ovrd_en : 1; + u32 dfe_coeffh_ovrd_en : 1; + u32 rsvd0 : 1; + u32 top_comp_th_ovrd_en : 1; + u32 mid_comp_th_ovrd_en : 1; + u32 bot_comp_th_ovrd_en : 1; + u32 rsvd1 : 1; + u32 level_target_ovrd_en : 4; + u32 ffe_coeff_c0to3_ovrd_en : 4; + u32 ffe_coeff_c4to7_ovrd_en : 4; + u32 ffe_coeff_c8to11_ovrd_en : 4; + u32 ffe_coeff_c12to15_ovrd_en : 4; + u32 ffe_coeff_update_ovrd_en : 1; + u32 rsvd2 : 3; + }; + u32 reg; +} E56G__RXS0_DIG_OVRDEN_1; + +#define E56G__RXS0_DIG_OVRDEN_1_NUM 1 +#define E56G__RXS0_DIG_OVRDEN_1_ADDR (E56G__BASEADDR + 0x160) + +typedef union { + struct { + u32 ber_en : 1; + u32 rsvd0 : 3; + u32 read_mode_en : 1; + u32 rsvd1 : 3; + u32 err_cnt_mode_all0_one1 : 1; + u32 rsvd2 : 3; + u32 init_lfsr_mode_continue0_restart1 : 1; + u32 rsvd3 : 3; + u32 pattern_sel : 4; + u32 rsvd4 : 12; + }; + u32 reg; +} E56G__RXS0_DFT_1; + +#define E56G__RXS0_DFT_1_NUM 1 +#define E56G__RXS0_DFT_1_ADDR (E56G__BASEADDR + 0xec) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_efuse_bits_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_in_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_out_o : 1; + u32 rsvd0 : 15; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_2; + +#define E56G__PMD_RXS0_OVRDEN_2_ADDR (E56G__BASEADDR + 0x1538) + +typedef union { + struct { + u32 ana_bbcdr_osc_range_sel_i : 2; + u32 rsvd0 : 2; + u32 ana_bbcdr_coarse_i : 4; + u32 ana_bbcdr_fine_i : 3; + u32 rsvd1 : 1; + u32 ana_bbcdr_ultrafine_i : 3; + u32 rsvd2 : 1; + u32 ana_bbcdr_divctrl_i : 2; + u32 rsvd3 : 2; + u32 ana_bbcdr_int_cstm_i : 5; + u32 rsvd4 : 3; + u32 ana_bbcdr_prop_step_i : 4; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_5; + +#define E56G__RXS0_ANA_OVRDVAL_5_ADDR (E56G__BASEADDR + 0xb4) + +typedef union { + struct { + u32 ana_adc_pictrl_quad_i : 2; + u32 rsvd0 : 2; + u32 ana_adc_clkdiv_i : 2; + u32 rsvd1 : 2; + u32 ana_test_adc_clkgen_i : 4; + u32 ana_vref_cnfg_i : 4; + u32 ana_adcgain_cal_swing_ctrl_i : 4; + u32 ana_adc_gain_i : 4; + u32 ana_adc_offset_i : 4; + u32 ana_ana_debug_sel_i : 4; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_11; + +#define E56G__RXS3_ANA_OVRDVAL_11_ADDR (E56G__BASEADDR + 0x6cc) + +typedef union { + struct { + u32 rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 rxs0_rx0_fom_en_i : 1; + u32 rxs0_rx0_idle_detect_en_i : 1; + u32 rxs0_rx0_idle_o : 1; + u32 rxs0_rx0_txffe_train_en_i : 1; + u32 rxs0_rx0_txffe_train_enack_o : 1; + u32 rxs0_rx0_txffe_train_done_o : 1; + u32 rxs0_rx0_vga_train_en_i : 1; + u32 rxs0_rx0_vga_train_done_o : 1; + u32 rxs0_rx0_ctle_train_en_i : 1; + u32 rxs0_rx0_ctle_train_done_o : 1; + u32 rxs0_rx0_cdr_en_i : 1; + u32 rxs0_rx0_cdr_rdy_o : 1; + u32 rxs0_rx0_ffe_train_en_i : 1; + u32 rxs0_rx0_ffe_train_done_o : 1; + u32 rxs0_rx0_mmpd_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_done_o : 1; + u32 rxs0_rx0_adc_intl_cal_error_o : 1; + u32 rxs0_rx0_dfe_train_en_i : 1; + u32 rxs0_rx0_dfe_train_done_o : 1; + u32 rxs0_rx0_vga_adapt_en_i : 1; + u32 rxs0_rx0_vga_adapt_done_o : 1; + u32 rxs0_rx0_ctle_adapt_en_i : 1; + u32 rxs0_rx0_ctle_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 rxs0_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDVAL_1; +#define E56G__PMD_RXS0_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1544) + +typedef union { + struct { + u32 rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 rxs1_rx0_fom_en_i : 1; + u32 rxs1_rx0_idle_detect_en_i : 1; + u32 rxs1_rx0_idle_o : 1; + u32 rxs1_rx0_txffe_train_en_i : 1; + u32 rxs1_rx0_txffe_train_enack_o : 1; + u32 rxs1_rx0_txffe_train_done_o : 1; + u32 rxs1_rx0_vga_train_en_i : 1; + u32 rxs1_rx0_vga_train_done_o : 1; + u32 rxs1_rx0_ctle_train_en_i : 1; + u32 rxs1_rx0_ctle_train_done_o : 1; + u32 rxs1_rx0_cdr_en_i : 1; + u32 rxs1_rx0_cdr_rdy_o : 1; + u32 rxs1_rx0_ffe_train_en_i : 1; + u32 rxs1_rx0_ffe_train_done_o : 1; + u32 rxs1_rx0_mmpd_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_done_o : 1; + u32 rxs1_rx0_adc_intl_cal_error_o : 1; + u32 rxs1_rx0_dfe_train_en_i : 1; + u32 rxs1_rx0_dfe_train_done_o : 1; + u32 rxs1_rx0_vga_adapt_en_i : 1; + u32 rxs1_rx0_vga_adapt_done_o : 1; + u32 rxs1_rx0_ctle_adapt_en_i : 1; + u32 rxs1_rx0_ctle_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs1_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs1_rx0_adc_gain_adapt_en_i : 1; + u32 rxs1_rx0_adc_gain_adapt_done_o : 1; + u32 rxs1_rx0_adc_gain_adapt_error_o : 1; + u32 rxs1_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDVAL_1; + +#define E56G__PMD_RXS1_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1570) + +typedef union { + struct { + u32 rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 rxs2_rx0_fom_en_i : 1; + u32 rxs2_rx0_idle_detect_en_i : 1; + u32 rxs2_rx0_idle_o : 1; + u32 rxs2_rx0_txffe_train_en_i : 1; + u32 rxs2_rx0_txffe_train_enack_o : 1; + u32 rxs2_rx0_txffe_train_done_o : 1; + u32 rxs2_rx0_vga_train_en_i : 1; + u32 rxs2_rx0_vga_train_done_o : 1; + u32 rxs2_rx0_ctle_train_en_i : 1; + u32 rxs2_rx0_ctle_train_done_o : 1; + u32 rxs2_rx0_cdr_en_i : 1; + u32 rxs2_rx0_cdr_rdy_o : 1; + u32 rxs2_rx0_ffe_train_en_i : 1; + u32 rxs2_rx0_ffe_train_done_o : 1; + u32 rxs2_rx0_mmpd_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_done_o : 1; + u32 rxs2_rx0_adc_intl_cal_error_o : 1; + u32 rxs2_rx0_dfe_train_en_i : 1; + u32 rxs2_rx0_dfe_train_done_o : 1; + u32 rxs2_rx0_vga_adapt_en_i : 1; + u32 rxs2_rx0_vga_adapt_done_o : 1; + u32 rxs2_rx0_ctle_adapt_en_i : 1; + u32 rxs2_rx0_ctle_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs2_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs2_rx0_adc_gain_adapt_en_i : 1; + u32 rxs2_rx0_adc_gain_adapt_done_o : 1; + u32 rxs2_rx0_adc_gain_adapt_error_o : 1; + u32 rxs2_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDVAL_1; + +#define E56G__PMD_RXS2_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x159c) + +typedef union { + struct { + u32 rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 rxs3_rx0_fom_en_i : 1; + u32 rxs3_rx0_idle_detect_en_i : 1; + u32 rxs3_rx0_idle_o : 1; + u32 rxs3_rx0_txffe_train_en_i : 1; + u32 rxs3_rx0_txffe_train_enack_o : 1; + u32 rxs3_rx0_txffe_train_done_o : 1; + u32 rxs3_rx0_vga_train_en_i : 1; + u32 rxs3_rx0_vga_train_done_o : 1; + u32 rxs3_rx0_ctle_train_en_i : 1; + u32 rxs3_rx0_ctle_train_done_o : 1; + u32 rxs3_rx0_cdr_en_i : 1; + u32 rxs3_rx0_cdr_rdy_o : 1; + u32 rxs3_rx0_ffe_train_en_i : 1; + u32 rxs3_rx0_ffe_train_done_o : 1; + u32 rxs3_rx0_mmpd_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_done_o : 1; + u32 rxs3_rx0_adc_intl_cal_error_o : 1; + u32 rxs3_rx0_dfe_train_en_i : 1; + u32 rxs3_rx0_dfe_train_done_o : 1; + u32 rxs3_rx0_vga_adapt_en_i : 1; + u32 rxs3_rx0_vga_adapt_done_o : 1; + u32 rxs3_rx0_ctle_adapt_en_i : 1; + u32 rxs3_rx0_ctle_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs3_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs3_rx0_adc_gain_adapt_en_i : 1; + u32 rxs3_rx0_adc_gain_adapt_done_o : 1; + u32 rxs3_rx0_adc_gain_adapt_error_o : 1; + u32 rxs3_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDVAL_1; + +#define E56G__PMD_RXS3_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x15c8) + +typedef union { + struct { + u32 ctrl_fsm_rx0_st : 6; + u32 rsvd0 : 2; + u32 ctrl_fsm_rx1_st : 6; + u32 rsvd1 : 2; + u32 ctrl_fsm_rx2_st : 6; + u32 rsvd2 : 2; + u32 ctrl_fsm_rx3_st : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_CTRL_FSM_RX_STAT_0; + +#define E56G__PMD_CTRL_FSM_RX_STAT_0_ADDR (E56G__BASEADDR + 0x14fc) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_0; +#define E56G__RXS0_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0xa0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_0; + +#define E56G__RXS1_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x2a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_0; + +#define E56G__RXS2_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x4a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_0; + +#define E56G__RXS3_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x6a0) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_0; + +#define E56G__RXS0_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x8c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDEN_0; + +#define E56G__RXS1_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x28c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDEN_0; + +#define E56G__RXS2_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x48c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDEN_0; + +#define E56G__RXS3_ANA_OVRDEN_0_NUM 1 +#define E56G__RXS3_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x68c) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_3; + +#define E56G__RXS0_ANA_OVRDVAL_3_NUM 1 +#define E56G__RXS0_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0xac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_3; + +#define E56G__RXS1_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x2ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_3; + +#define E56G__RXS2_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x4ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_3; + +#define E56G__RXS3_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x6ac) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fom_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs0_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_1; + +#define E56G__PMD_RXS0_OVRDEN_1_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1534) + +typedef union { + struct { + u32 ovrd_en_rxs1_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fom_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs1_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs1_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDEN_1; + +#define E56G__PMD_RXS1_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1560) + +typedef union { + struct { + u32 ovrd_en_rxs2_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fom_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs2_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs2_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDEN_1; + +#define E56G__PMD_RXS2_OVRDEN_1_ADDR (E56G__BASEADDR + 0x158c) + +typedef union { + struct { + u32 ovrd_en_rxs3_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fom_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs3_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs3_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDEN_1; + +#define E56G__PMD_RXS3_OVRDEN_1_ADDR (E56G__BASEADDR + 0x15b8) + +#define E56G__RXS0_FOM_18__ADDR (E56G__BASEADDR + 0x1f8) +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB 11 +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB 0 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB 23 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB 12 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB 25 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB 25 + +#define DEFAULT_TEMP 40 +#define HIGH_TEMP 70 + +#define E56PHY_RX_RDY_ST 0x1B + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 + +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 +#define S25G_CMVAR_SEC_LOW_TH 0x1A +#define S25G_CMVAR_SEC_HIGH_TH 0x1D +#define S25G_CMVAR_UFINE_MAX 0x2 +#define S25G_CMVAR_FINE_MAX 0x7 +#define S25G_CMVAR_COARSE_MAX 0xF +#define S25G_CMVAR_UFINE_UMAX_WRAP 0x0 +#define S25G_CMVAR_UFINE_FMAX_WRAP 0x0 +#define S25G_CMVAR_FINE_FMAX_WRAP 0x2 +#define S25G_CMVAR_UFINE_MIN 0x0 +#define S25G_CMVAR_FINE_MIN 0x0 +#define S25G_CMVAR_COARSE_MIN 0x1 +#define S25G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S25G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S25G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S10G_CMVAR_SEC_LOW_TH 0x1A +#define S10G_CMVAR_SEC_HIGH_TH 0x1D +#define S10G_CMVAR_UFINE_MAX 0x7 +#define S10G_CMVAR_FINE_MAX 0x7 +#define S10G_CMVAR_COARSE_MAX 0xF +#define S10G_CMVAR_UFINE_UMAX_WRAP 0x6 +#define S10G_CMVAR_UFINE_FMAX_WRAP 0x7 +#define S10G_CMVAR_FINE_FMAX_WRAP 0x1 +#define S10G_CMVAR_UFINE_MIN 0x0 +#define S10G_CMVAR_FINE_MIN 0x0 +#define S10G_CMVAR_COARSE_MIN 0x1 +#define S10G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S10G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S10G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_TX_FFE_CFG_MAIN 0x2c2c2c2c +#define S10G_TX_FFE_CFG_PRE1 0x0 +#define S10G_TX_FFE_CFG_PRE2 0x0 +#define S10G_TX_FFE_CFG_POST 0x06060606 +#define S25G_TX_FFE_CFG_MAIN 0x31 +#define S25G_TX_FFE_CFG_PRE1 0x4 +#define S25G_TX_FFE_CFG_PRE2 0x1 +#define S25G_TX_FFE_CFG_POST 0x9 + +#define S25G_TX_FFE_CFG_DAC_MAIN 0x2a +#define S25G_TX_FFE_CFG_DAC_PRE1 0x03 +#define S25G_TX_FFE_CFG_DAC_PRE2 0x0 +#define S25G_TX_FFE_CFG_DAC_POST 0x11 + +#define S40G_TX_FFE_CFG_MAIN 0x2b2b2b2b +#define S40G_TX_FFE_CFG_PRE1 0x03030303 +#define S40G_TX_FFE_CFG_PRE2 0x0 +#define S40G_TX_FFE_CFG_POST 0x11111111 + +#define BYPASS_CTLE_TAG 0x0 + +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S10G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S25G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define TXGBE_E56_PHY_LINK_UP 0x4 + +void set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value); +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane); +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE); +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_10g(struct txgbe_hw *hw); +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed); +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_fec_set(struct txgbe_hw *hw); +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); + +#endif /* _TXGBE_E56_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h new file mode 100644 index 0000000000..c58c061ea1 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -0,0 +1,275 @@ +#ifndef _TXGBE_E56_BP_H_ +#define _TXGBE_E56_BP_H_ + +#define TXGBE_10G_FEC_REQ BIT(15) +#define TXGBE_10G_FEC_ABL BIT(14) +#define TXGBE_25G_BASE_FEC_REQ BIT(13) +#define TXGBE_25G_RS_FEC_REQ BIT(12) + +#ifndef __bf_shf +#define __bf_shf(x) (__builtin_ffsll(x) - 1) +#endif +/** + * FIELD_GET_M() - extract a bitfield element + * @_mask: shifted mask defining the field's length and position + * @_reg: value of entire bitfield + * + * FIELD_GET_M() extracts the field specified by @_mask from the + * bitfield passed in as @_reg by masking and shifting it down. + */ +#define FIELD_GET_M(_mask, _reg) \ + ({ \ + (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ + }) + +typedef union { + struct { + u32 tx0_cursor_factor : 7; + u32 rsvd0 : 1; + u32 tx1_cursor_factor : 7; + u32 rsvd1 : 1; + u32 tx2_cursor_factor : 7; + u32 rsvd2 : 1; + u32 tx3_cursor_factor : 7; + u32 rsvd3 : 1; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_1; + +#define E56G__PMD_TX_FFE_CFG_1_NUM 1 +#define E56G__PMD_TX_FFE_CFG_1_ADDR (E56G__BASEADDR + 0x141c) +#define E56G__PMD_TX_FFE_CFG_1_PTR ((E56G__PMD_TX_FFE_CFG_1 *)(E56G__PMD_TX_FFE_CFG_1_ADDR)) +#define E56G__PMD_TX_FFE_CFG_1_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_1_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_READ_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_RESET_VALUE 0x3f3f3f3f + +typedef union { + struct { + u32 tx0_precursor1_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor1_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor1_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor1_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_2; + +#define E56G__PMD_TX_FFE_CFG_2_NUM 1 +#define E56G__PMD_TX_FFE_CFG_2_ADDR (E56G__BASEADDR + 0x1420) +#define E56G__PMD_TX_FFE_CFG_2_PTR ((E56G__PMD_TX_FFE_CFG_2 *)(E56G__PMD_TX_FFE_CFG_2_ADDR)) +#define E56G__PMD_TX_FFE_CFG_2_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_2_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_precursor2_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor2_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor2_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor2_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_3; +#define E56G__PMD_TX_FFE_CFG_3_NUM 1 +#define E56G__PMD_TX_FFE_CFG_3_ADDR (E56G__BASEADDR + 0x1424) +#define E56G__PMD_TX_FFE_CFG_3_PTR ((E56G__PMD_TX_FFE_CFG_3 *)(E56G__PMD_TX_FFE_CFG_3_ADDR)) +#define E56G__PMD_TX_FFE_CFG_3_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_3_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_postcursor_factor : 6; + u32 rsvd0 : 2; + u32 tx1_postcursor_factor : 6; + u32 rsvd1 : 2; + u32 tx2_postcursor_factor : 6; + u32 rsvd2 : 2; + u32 tx3_postcursor_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_4; +#define E56G__PMD_TX_FFE_CFG_4_NUM 1 +#define E56G__PMD_TX_FFE_CFG_4_ADDR (E56G__BASEADDR + 0x1428) +#define E56G__PMD_TX_FFE_CFG_4_PTR ((E56G__PMD_TX_FFE_CFG_4 *)(E56G__PMD_TX_FFE_CFG_4_ADDR)) +#define E56G__PMD_TX_FFE_CFG_4_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_4_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_7; +#define E56G__CMS_ANA_OVRDVAL_7_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) +#define E56G__CMS_ANA_OVRDVAL_7_PTR ((E56G__CMS_ANA_OVRDVAL_7 *)(E56G__CMS_ANA_OVRDVAL_7_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_7_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_7_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_READ_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G__CMS_ANA_OVRDEN_1; +#define E56G__CMS_ANA_OVRDEN_1_NUM 1 +#define E56G__CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) +#define E56G__CMS_ANA_OVRDEN_1_PTR ((E56G__CMS_ANA_OVRDEN_1 *)(E56G__CMS_ANA_OVRDEN_1_ADDR)) +#define E56G__CMS_ANA_OVRDEN_1_STRIDE 4 +#define E56G__CMS_ANA_OVRDEN_1_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_READ_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_READ_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_9; +#define E56G__CMS_ANA_OVRDVAL_9_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) +#define E56G__CMS_ANA_OVRDVAL_9_PTR ((E56G__CMS_ANA_OVRDVAL_9 *)(E56G__CMS_ANA_OVRDVAL_9_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_9_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_9_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_READ_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_RESET_VALUE 0x0 + +#define SFP2_RS0 5 +#define SFP2_RS1 4 +#define SFP2_TX_DISABLE 1 +#define SFP2_TX_FAULT 0 +#define SFP2_RX_LOS_BIT 3 +#ifdef PHYINIT_TIMEOUT +#undef PHYINIT_TIMEOUT +#define PHYINIT_TIMEOUT 2000 +#endif + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_DAISY_EN_I 0, 0 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I 1, 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I_LSB 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_VDDINOFF_DCORE_DIG_O 2, 2 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I 11, 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I_LSB 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I 12, 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I_LSB 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I 13, 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I_LSB 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O 14, 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O_LSB 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I 15, 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I_LSB 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I 16, 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I_LSB 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I 17, 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I_LSB 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I 18, 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I_LSB 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I 19, 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I_LSB 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I 20, 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I_LSB 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I 21, 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I_LSB 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I 22, 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I_LSB 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I 23, 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I_LSB 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I 24, 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I_LSB 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 25, 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I_LSB 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_SET_LPF_I 26, 26 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 20, 16 +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 12, 12 +#define E56PHY_CMS_ANA_OVRDVAL_7_ADDR (E56PHY_CMS_BASE_ADDR + 0xCC) +#define E56PHY_CMS_ANA_OVRDVAL_5_ADDR (E56PHY_CMS_BASE_ADDR + 0xC4) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I 23, 23 +#define E56PHY_CMS_ANA_OVRDVAL_9_ADDR (E56PHY_CMS_BASE_ADDR + 0xD4) +#define E56PHY_CMS_ANA_OVRDVAL_10_ADDR (E56PHY_CMS_BASE_ADDR + 0xD8) +#define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 + +#endif diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index b1a1483dab..0c6a74c562 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4071,37 +4071,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { - u32 rdata = 0; - u32 links_reg = 0; + u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); - /* must read it twice because the state may - * not be correct the first time you read it - */ - rdata = rd32_epcs(hw, 0x30001); - rdata = rd32_epcs(hw, 0x30001); - - if (rdata & TXGBE_AML_PHY_LINK_UP) - *link_up = true; - else - *link_up = false; - - links_reg = rd32(hw, TXGBE_PORTSTAT); - if (*link_up) { - if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == - TXGBE_CFG_PORT_ST_AML_LINK_40G) - *speed = TXGBE_LINK_SPEED_40GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == - TXGBE_CFG_PORT_ST_AML_LINK_25G) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == - TXGBE_CFG_PORT_ST_AML_LINK_10G) - *speed = TXGBE_LINK_SPEED_10GB_FULL; - } else { - *speed = TXGBE_LINK_SPEED_UNKNOWN; - } + if (gpio_ext & gpio_ext_mask) + return true; - return 0; + return false; } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index f1849c8400..c02be3cc34 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -40,7 +40,6 @@ #define SR_PMA_KR_LD_CESTS_RR MS16(15, 0x1) #define SR_PMA_KR_FEC_CTRL 0x0100AB #define SR_PMA_KR_FEC_CTRL_EN MS16(0, 0x1) -#define SR_PMA_RS_FEC_CTRL 0x0100C8 #define SR_MII_MMD_CTL 0x1F0000 #define SR_MII_MMD_CTL_AN_EN 0x1000 #define SR_MII_MMD_CTL_RESTART_AN 0x0200 diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 25aaf8ea68..e2ba7acc4c 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -158,6 +158,8 @@ #define TXGBE_RST_SW MS(0, 0x1) #define TXGBE_RST_LAN(i) MS(((i) + 1), 0x1) #define TXGBE_RST_FW MS(3, 0x1) +#define TXGBE_RST_EPHY_LAN_1 MS(16, 0x1) +#define TXGBE_RST_EPHY_LAN_0 MS(19, 0x1) #define TXGBE_RST_MAC_LAN_1 MS(17, 0x1) #define TXGBE_RST_MAC_LAN_0 MS(20, 0x1) #define TXGBE_RST_ETH(i) MS(((i) + 29), 0x1) diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 505f598fb7..7fb4bcc513 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -64,6 +64,9 @@ #define TXGBE_AML_ALARM_THRE_MASK 0x1FFE0000U #define TXGBE_AML_DALARM_THRE_MASK 0x0001FFE0U +#define CL74_KRTR_TRAINNING_TIMEOUT 6000 /* 3000ms c74 trainning timeout */ +#define AN_TRAINNING_MODE 0 /* 0: not dis an 1: dis an */ + struct txgbe_thermal_diode_data { s16 temp; s16 alarm_thresh; @@ -690,6 +693,8 @@ struct txgbe_phy_info { s32 (*setup_link_speed)(struct txgbe_hw *hw, u32 speed, bool autoneg_wait_to_complete); s32 (*check_link)(struct txgbe_hw *hw, u32 *speed, bool *link_up); + s32 (*setup_link_core)(struct txgbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete, bool *need_reset); s32 (*get_fw_version)(struct txgbe_hw *hw, u32 *fw_version); s32 (*read_i2c_byte)(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); @@ -732,7 +737,9 @@ struct txgbe_phy_info { u16 ffe_set; u16 ffe_main; u16 ffe_pre; + u16 ffe_pre2; u16 ffe_post; + u16 fec_mode; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -823,6 +830,7 @@ struct txgbe_devargs { struct txgbe_hw { void IOMEM *hw_addr; void *back; + void *dev_back; struct txgbe_mac_info mac; struct txgbe_addr_filter_info addr_ctrl; struct txgbe_fc_info fc; @@ -885,8 +893,12 @@ struct txgbe_hw { /*amlite: new SW-FW mbox */ u8 swfw_index; rte_atomic32_t swfw_busy; + bool link_valid; + bool reconfig_rx; u32 fec_mode; u32 cur_fec_link; + int temperature; + u32 bp_link_mode; }; struct txgbe_backplane_ability { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 3ae233f70a..0e3d7649d8 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -592,6 +592,17 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) fdir_conf->drop_queue = drop_queue; } +static void +txgbe_override_mac_ops(struct txgbe_hw *hw) +{ + struct txgbe_mac_info *mac = &hw->mac; + + if (hw->phy.multispeed_fiber) + mac->setup_mac_link = txgbe_setup_mac_link_aml; + else + mac->setup_link = txgbe_setup_mac_link_aml; +} + static int eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { @@ -651,6 +662,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) /* Vendor and Device ID need to be set before init of shared code */ hw->back = pci_dev; + hw->dev_back = eth_dev; hw->port_id = eth_dev->data->port_id; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; @@ -686,6 +698,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + if (hw->mac.type == txgbe_mac_aml) + txgbe_override_mac_ops(hw); + /* Unlock any pending hardware semaphore */ txgbe_swfw_lock_reset(hw); @@ -2039,6 +2054,9 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + if (hw->mac.type == txgbe_mac_aml) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); @@ -3093,6 +3111,65 @@ txgbe_tx_ring_recovery(struct rte_eth_dev *dev) } } +void +txgbe_dev_setup_link_alarm_handler_aml(void *param) +{ + struct txgbe_hw *hw = (struct txgbe_hw *)param; + struct rte_eth_dev *dev = (struct rte_eth_dev *)hw->dev_back; + struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev); + u32 speed; + bool autoneg = false; + u32 gssr = hw->phy.phy_semaphore_mask; + + if (!hw) + return; + + speed = hw->phy.autoneg_advertised; + if (!speed) + hw->mac.get_link_capabilities(hw, &speed, &autoneg); + + /* firmware is configuring phy now, delay host driver config action */ + if (hw->mac.acquire_swfw_sync(hw, gssr) != 0) { + rte_eal_alarm_set(1000 * 1000 * 2, + txgbe_dev_setup_link_alarm_handler_aml, hw); + PMD_DRV_LOG(DEBUG, "delay config ephy"); + return; + } + + hw->mac.setup_link(hw, speed, true); + + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + bool link_up = false; + + hw->mac.check_link(hw, &link_speed, &link_up, false); + if (link_up) { + PMD_DRV_LOG(DEBUG, "LINK UP IN HANDLER"); + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; + txgbe_dev_link_update_share(dev, 0); + } + + hw->mac.release_swfw_sync(hw, gssr); + + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; +} + +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete) +{ + bool need_reset = false; + s32 status = 0; + + status = hw->phy.setup_link_core(hw, speed, autoneg_wait_to_complete, &need_reset); + if (status) + return status; + + if (!hw->adapter_stopped && need_reset) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_setup_link_alarm_handler_aml, hw); + + return status; +} + /* * If @timeout_ms was 0, it means that it will not return until link complete. * It returns 1 on complete, return 0 on timeout. @@ -3126,9 +3203,13 @@ txgbe_dev_setup_link_thread_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_adapter *ad = TXGBE_DEV_ADAPTER(dev); + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - txgbe_dev_setup_link_alarm_handler(dev); + if (hw->mac.type == txgbe_mac_aml) + txgbe_dev_setup_link_alarm_handler_aml(hw); + else + txgbe_dev_setup_link_alarm_handler(dev); rte_atomic_store_explicit(&ad->link_thread_running, 0, rte_memory_order_seq_cst); return 0; } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 189fbac541..1ec8e096cc 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -733,6 +733,10 @@ int txgbe_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); void txgbe_dev_setup_link_alarm_handler(void *param); +void txgbe_dev_setup_link_alarm_handler_aml(void *param); +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete); void txgbe_read_stats_registers(struct txgbe_hw *hw, struct txgbe_hw_stats *hw_stats); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 13/20] net/txgbe: fix link stability for 40G NIC 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (11 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang ` (8 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 70 +- drivers/net/txgbe/base/txgbe_aml40.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 1471 ++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.c | 4 +- 4 files changed, 1438 insertions(+), 113 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index eefd7119fd..84c130704a 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -24,6 +25,7 @@ void txgbe_init_ops_aml40(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml40; + phy->setup_link_core = txgbe_setup_phy_link_aml40; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml40; @@ -52,6 +54,13 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if (link_up_wait_to_complete) { for (i = 0; i < hw->mac.max_link_up_time; i++) { + if (!hw->link_valid) { + *link_up = false; + + msleep(100); + continue; + } + if (!(links_reg & TXGBE_PORTSTAT_UP)) { *link_up = false; } else { @@ -68,6 +77,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } + if (!hw->link_valid) + *link_up = false; + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) @@ -107,20 +119,24 @@ u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) return txgbe_media_type_fiber_qsfp; } -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; + u32 value; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { - DEBUGOUT("SFP not detected, skip setup mac link"); - return 0; - } + *need_reset = false; + + if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ status = hw->mac.get_link_capabilities(hw, @@ -132,18 +148,43 @@ s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + break; + msleep(250); + } if (link_speed == speed && link_up) - return status; + goto out; - if (speed & TXGBE_LINK_SPEED_40GB_FULL) - speed = 0x20; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) + hw->link_valid = false; + + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + DEBUGOUT("MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + DEBUGOUT("MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + DEBUGOUT("Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -159,6 +200,5 @@ void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw) mac->flap_tx_laser = txgbe_flap_tx_laser_multispeed_fiber; - mac->setup_link = txgbe_setup_mac_link_aml40; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } diff --git a/drivers/net/txgbe/base/txgbe_aml40.h b/drivers/net/txgbe/base/txgbe_aml40.h index f31360c899..d97654fbf8 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.h +++ b/drivers/net/txgbe/base/txgbe_aml40.h @@ -14,7 +14,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw); -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw); #endif /* _TXGBE_AML40_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index 3c4b054ef6..ebeae16e34 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -98,11 +98,29 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + pre1 = S25G_TX_FFE_CFG_DAC_PRE1; + pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + post = S25G_TX_FFE_CFG_DAC_POST; + } else { ffe_main = S25G_TX_FFE_CFG_MAIN; pre1 = S25G_TX_FFE_CFG_PRE1; pre2 = S25G_TX_FFE_CFG_PRE2; post = S25G_TX_FFE_CFG_POST; } + } else if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + ffe_main = S40G_TX_FFE_CFG_MAIN; + pre1 = S40G_TX_FFE_CFG_PRE1; + pre2 = S40G_TX_FFE_CFG_PRE2; + post = S40G_TX_FFE_CFG_POST; + } } if (hw->phy.ffe_set) { @@ -150,6 +168,416 @@ txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) return 0; } +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + int i; + + /* CMS Config Master */ + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + /* TXS Config Master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_TXS_TXS_CFG_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_40GB_FULL); + + /* RXS Config master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_RXS_RXS_CFG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS3_ANA_OVRDVAL_11_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS3_ANA_OVRDVAL_11 *)&rdata)->ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS0_ANA_OVRDEN_2 *)&rdata)->ovrd_en_ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + } + + /* PDIG Config master */ + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw) { @@ -1294,6 +1722,46 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) return status; } +static int txgbe_e56_set_rxs_ufine_le_max_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + int i = 0; + unsigned int CMVAR_UFINE_MAX = 0; + u32 addr; + + for (i = 0; i < 4; i++) { + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + else if (speed == TXGBE_LINK_SPEED_25GB_FULL) + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + + /* a. Assign software defined variables as below */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* Wait until 1milliseconds or greater */ + msleep(10); + } + } + return status; +} + static inline int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) { @@ -1328,38 +1796,269 @@ int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) return status; } -int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) -{ - int status = 0, i, N, median; - unsigned int rdata; - int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane) +{ + int status = 0, i, N, median; + unsigned int rdata; + u32 addr; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + /* Set ovrd_en=0 to read ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* + * As status update from RXS hardware is asynchronous to read status of SECOND_ORDER, + * follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) +{ + int status = 0, i, N, median; + unsigned int rdata; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + + /* Set ovrd_en=0 to read ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + + /* + * As status update from RXS hardware is asynchronous to read status + * of SECOND_ORDER, follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + int i; + u32 addr; + int temperature; + + for (i = 0; i < 4; i++) { + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + DEBUGOUT("Error Speed\n"); + return 0; + } + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; - /* Set ovrd_en=0 to read ASIC value */ - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + hw->temperature = temperature; - /* - * As status update from RXS hardware is asynchronous to read status - * of SECOND_ORDER, follow sequence mentioned below. - */ - N = 5; - for (i = 0; i < N; i = i + 1) { - /* set RXS_BBCDR_SECOND_ORDER_ST[i] = - * RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] + /* Assign software defined variables as below */ + /* a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER */ + status |= txgbe_e56_rx_rd_second_code_40g(hw, &SECOND_CODE, i); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE */ - EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); - RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, - ana_bbcdr_int_cstm_i); - usec_delay(100); + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + /* Set ovrd_en=1 to override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = FINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_coarse_i) = COARSE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature " + "tracking occurs Error condition"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = FINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_coarse_i) = COARSE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature " + "tracking occurs Error condition"); + } + } } - - /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ - array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); - qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); - - median = ((N + 1) / 2) - 1; - *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; - return status; } @@ -1534,78 +2233,410 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " "temperature tracking occurs Error condition"); } - } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_calib_adapt_seq_40G(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i, j; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypass_ctle = true; + + for (i = 0; i < 4; i++) { + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + + if (bypass_ctle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature tracking + * range here. RXS would be enabled at the end of this sequence. For the case when PAM4 KR + * training is not enabled (including PAM4 mode without KR training), wait until + * ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + for (i = 0; i < 4; i++) { + /* 4. Disable VGA and CTLE training so they don't interfere with ADC calibration */ + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) + & 1) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* + * 6. Perform ADC offset adaptation and ADC gain adaptation, repeat them a few + * times and after that keep it disabled. + */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_gain_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ - return status; -} -static inline int -txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) -{ - unsigned int rdata; + /* + * 7. Perform ADC interleaver adaptation for 10ms or greater, + * and after that disable it + * a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + /* + * 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking + * changes in temperature or voltage + */ + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); - if (speed == TXGBE_LINK_SPEED_40GB_FULL) { - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + if (timer++ > PHYINIT_TIMEOUT) + break; + } - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + if (bypass_ctle == 0) { + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); } - return 0; + return status; } static inline int @@ -1978,20 +3009,42 @@ txgbe_e56_cfg_temp(struct txgbe_hw *hw) return 0; } -static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +static int txgbe_e56_config_rx_40G(struct txgbe_hw *hw, u32 speed) { s32 status; - status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + status = txgbe_e56_rxs_calib_adapt_seq_40G(hw, speed); if (status) return status; /* Step 2 of 2.3.4 */ - txgbe_e56_set_rxs_ufine_le_max(hw, speed); + txgbe_e56_set_rxs_ufine_le_max_40g(hw, speed); /* 2.3.4 RXS post CDR lock temperature tracking sequence */ - txgbe_temp_track_seq(hw, speed); + txgbe_temp_track_seq_40g(hw, speed); + + hw->link_valid = true; + + return 0; +} +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + txgbe_e56_config_rx_40G(hw, speed); + } else { + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + } return 0; } @@ -2001,6 +3054,151 @@ static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) * Completion of RXS powerdown can be confirmed by * observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST */ +static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + int i; + + for (i = 0; i < 4; i++) { + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + rdata = 0x0000; + addr = E56G__RXS0_ANA_OVRDEN_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + addr = E56G__PMD_RXS0_OVRDEN_0_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_3_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_DIG_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 2. Disable pattern checker */ + addr = E56G__RXS0_DFT_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_DFT_1, ber_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 3. Disable internal serial loopback mode */ + addr = E56G__RXS0_ANA_OVRDEN_3_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* 4. Enable bypass of clock gates in RXS - */ + addr = E56G__RXS0_RXS_CFG_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en) = 0x1FFF; + wr32_ephy(hw, addr, rdata); + } + + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + addr = E56G__PMD_BASER_PMD_CONTROL_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln1) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln2) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln3) = 0; + wr32_ephy(hw, addr, rdata); + + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + addr = E56G__PMD_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en) = 0x0; + wr32_ephy(hw, addr, rdata); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != 0x21) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + static int txgbe_e56_disable_rx(struct txgbe_hw *hw) { int status = 0; @@ -2133,8 +3331,13 @@ int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST * and confirm its value is POWERDN_ST */ - txgbe_e56_disable_rx(hw); - status = txgbe_e56_config_rx(hw, speed); + if (hw->mac.type == txgbe_mac_aml40) { + txgbe_e56_disable_rx40G(hw); + status = txgbe_e56_config_rx_40G(hw, speed); + } else { + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + } addr = E56PHY_INTR_0_ADDR; wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); @@ -2201,6 +3404,86 @@ int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) set_fields_e56(&value, 12, 12, 0); wr32_epcs(hw, SR_AN_CTRL, value); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0x3); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0x4); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_40g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0xf); + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { value = rd32_epcs(hw, SR_PCS_CTRL1); set_fields_e56(&value, 5, 2, 5); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0e3d7649d8..02c3305712 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2054,7 +2054,7 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); @@ -3206,7 +3206,7 @@ txgbe_dev_setup_link_thread_handler(void *param) struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) txgbe_dev_setup_link_alarm_handler_aml(hw); else txgbe_dev_setup_link_alarm_handler(dev); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (12 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang ` (7 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe.h | 2 + drivers/net/txgbe/base/txgbe_aml.c | 65 +- drivers/net/txgbe/base/txgbe_aml40.c | 43 +- drivers/net/txgbe/base/txgbe_e56.c | 22 +- drivers/net/txgbe/base/txgbe_e56.h | 2 + drivers/net/txgbe/base/txgbe_e56_bp.c | 2593 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 3 + drivers/net/txgbe/base/txgbe_hw.c | 6 + drivers/net/txgbe/base/txgbe_hw.h | 4 +- drivers/net/txgbe/base/txgbe_osdep.h | 4 + drivers/net/txgbe/base/txgbe_phy.c | 21 + drivers/net/txgbe/base/txgbe_phy.h | 22 + drivers/net/txgbe/base/txgbe_type.h | 25 +- drivers/net/txgbe/txgbe_ethdev.c | 109 +- drivers/net/txgbe/txgbe_ethdev.h | 2 +- 16 files changed, 2894 insertions(+), 30 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index 305c0291e3..a9a02577ce 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -13,4 +13,5 @@ base_sources = files( 'txgbe_phy.c', 'txgbe_vf.c', 'txgbe_e56.c', + 'txgbe_e56_bp.c', ) diff --git a/drivers/net/txgbe/base/txgbe.h b/drivers/net/txgbe/base/txgbe.h index 673a299860..27c3e3be38 100644 --- a/drivers/net/txgbe/base/txgbe.h +++ b/drivers/net/txgbe/base/txgbe.h @@ -13,5 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_vf.h" #include "txgbe_dcb.h" +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" #endif /* _TXGBE_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index 008b0245e5..a5b9d951ea 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -84,6 +85,13 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *speed = TXGBE_LINK_SPEED_UNKNOWN; } + if (txgbe_xpcs_an_enabled(hw)) { + if (!hw->an_done) { + *link_up = false; + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + } + return 0; } @@ -95,23 +103,41 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; + } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + hw->devarg.auto_neg = false; + *autoneg = false; + } else { + *autoneg = true; + } + *speed = hw->phy.fiber_suppport_speed; } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core0 || hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core1 || hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1) { + hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { *speed = TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; - } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { - *speed = TXGBE_LINK_SPEED_25GB_FULL; + } else if (hw->phy.media_type == txgbe_media_type_backplane) { + /* Backplane */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; + /* Backplane supports autonegotiation */ + *autoneg = hw->devarg.auto_neg; + } else if (hw->phy.media_type == txgbe_media_type_fiber) { + /* Fiber */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; } else { - /* SFP */ - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else - *speed = TXGBE_LINK_SPEED_10GB_FULL; - *autoneg = true; + /* Unknown */ + *speed = TXGBE_LINK_SPEED_UNKNOWN; + *autoneg = false; + PMD_DRV_LOG(DEBUG, "GET link capabilities failed"); + return TXGBE_ERR_LINK_SETUP; } return 0; @@ -193,7 +219,7 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) { DEBUGOUT("SFP not detected, skip setup mac link"); return 0; } @@ -216,6 +242,23 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return 0; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { DEBUGOUT("RX LOS"); diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 84c130704a..d350f18c4b 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -14,6 +14,7 @@ #include "txgbe_aml.h" #include "txgbe_aml40.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -98,7 +99,10 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = false; + *autoneg = true; + } else if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = true; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -115,8 +119,22 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) { - UNREFERENCED_PARAMETER(hw); - return txgbe_media_type_fiber_qsfp; + u8 device_type = hw->subsystem_device_id & 0xF0; + enum txgbe_media_type media_type; + + switch (device_type) { + case TXGBE_DEV_ID_KR_KX_KX4: + media_type = txgbe_media_type_backplane; + break; + case TXGBE_DEV_ID_SFP: + media_type = txgbe_media_type_fiber_qsfp; + break; + default: + media_type = txgbe_media_type_unknown; + break; + } + + return media_type; } s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, @@ -135,7 +153,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ @@ -148,6 +166,23 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return status; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index ebeae16e34..7ebd910823 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -49,7 +49,7 @@ int txgbe_e56_int_cmp(const void *a, const void *b) } s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) + bool *link_up) { u32 rdata = 0; u32 links_reg = 0; @@ -97,7 +97,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; pre2 = S25G_TX_FFE_CFG_DAC_PRE2; @@ -115,7 +116,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; pre2 = S40G_TX_FFE_CFG_PRE2; @@ -1504,7 +1506,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1539,7 +1541,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) if (((rdata >> (i * 8)) & 0x3f) == 0x21) break; if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1616,7 +1618,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1663,7 +1665,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) if (((rdata >> (i * 8)) & 0x3f) == 0x21) break; if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1932,7 +1934,7 @@ int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; } else { - DEBUGOUT("Error Speed\n"); + DEBUGOUT("Error Speed"); return 0; } @@ -3191,7 +3193,7 @@ static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) rdata = rd32_ephy(hw, addr); usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } @@ -3297,7 +3299,7 @@ static int txgbe_e56_disable_rx(struct txgbe_hw *hw) break; usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index eaa3ea5085..67ccdc8c7c 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1735,6 +1735,8 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up); s32 txgbe_e56_fec_set(struct txgbe_hw *hw); s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c new file mode 100644 index 0000000000..4928c888bb --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -0,0 +1,2593 @@ +#include "txgbe_e56.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" +#include "txgbe_e56_bp.h" +#include "txgbe.h" +#include "../txgbe_logs.h" + +static int +txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + u32 rdata, addr; + u32 ULTRAFINE_CODE[4] = {0}; + int lane_num = 0, lane_idx = 0; + u32 CMVAR_UFINE_MAX = 0; + + switch (speed) { + case 10: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + case 40: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 4; + break; + case 25: + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* ii get rx ana_bbcdr_ultrafine_i[14, 12] per lane */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE[lane_idx] = FIELD_GET_M(GENMASK(14, 12), rdata); + BP_LOG("ULTRAFINE_CODE[%d] = %d, CMVAR_UFINE_MAX: %x\n", + lane_idx, ULTRAFINE_CODE[lane_idx], CMVAR_UFINE_MAX); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE[lane_idx] > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE[lane_idx] -= 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 12, ULTRAFINE_CODE[lane_idx]); + wr32_ephy(hw, addr, rdata); + + /* ovrd_en_ana_bbcdr_ultrafine=1 override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + wr32_ephy(hw, addr, rdata | BIT(3)); + + /* Wait until 1milliseconds or greater */ + usec_delay(1000); + } + } + return 0; +} + +static int txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, + u32 speed) +{ + int OFFSET_CENTRE_RANGE_H[4] = {0}, OFFSET_CENTRE_RANGE_L[4] = {}, RANGE_FINAL[4] = {}; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int status = 0, lane_num = 0; + int T = 40, lane_id = 0; + u32 addr, rdata; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + switch (speed) { + case 10: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 1; + break; + case 40: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 4; + break; + case 25: + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* 2. Define software variable RX_COARSE_MID_TD */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 1 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_H[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_H[lane_id] = OFFSET_CENTRE_RANGE_H[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_H[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_H[lane_id]; + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 2 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0xf); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 3 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_L[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_L[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_L[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_L[lane_id]; + } + for (lane_id = 0; lane_id < lane_num; lane_id++) { + RANGE_FINAL[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] < + OFFSET_CENTRE_RANGE_H[lane_id] ? + CMVAR_RANGE_L : CMVAR_RANGE_H; + BP_LOG("lane_id:%d-RANGE_L:%x-RANGE_H:%x-RANGE_FINAL:%x\n", + lane_id, OFFSET_CENTRE_RANGE_L[lane_id], + OFFSET_CENTRE_RANGE_H[lane_id], RANGE_FINAL[lane_id]); + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 4 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, RANGE_FINAL[lane_id]); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x0); + wr32_ephy(hw, addr, rdata); + } + + /* Do SEQ::RX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + + return status; +} + +static int txgbe_e56_rxs_post_cdr_lock_temp_track_seq(struct txgbe_hw *hw, + u32 speed) +{ + int status = 0; + u32 rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH = 0; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX = 0; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX = 0; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH = 0; + int CMVAR_UFINE_MIN = 0; + int CMVAR_FINE_MIN = 0; + int CMVAR_UFINE_UMIN_WRAP = 0; + int CMVAR_COARSE_MIN = 0; + int CMVAR_UFINE_FMIN_WRAP = 0; + int CMVAR_FINE_FMIN_WRAP = 0; + + if (speed == 10) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == 25) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } + + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + BP_LOG("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature tracking occurs Error condition\n"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + BP_LOG("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature tracking occurs Error condition\n"); + } + } + + return status; +} + +static int txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u8 bp_link_mode) +{ + u32 rdata; + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (bp_link_mode == 40) { + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_adc_adapt_seq(struct txgbe_hw *hw, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + u32 rdata = 0, addr = 0; + int status = 0; + + int timer = 0, j = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait RXS0-3_OVRDVAL[1]::rxs0-3_rx0_cdr_rdy_o = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(12)), + 100, 2000, hw, 0x1544); + if (status) + BP_LOG("rxs%d_rx0_cdr_rdy_o = %x, %s.\n", + lane_idx, rdata, + status ? "FAILED" : "SUCCESS"); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* 4. Disable VGA and CTLE training so they don't interfere with ADC calibration */ + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 14, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 9, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_intl_cal_done_o bit17 = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(17)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_intl_cal_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_ofst_adapt_done_o bit26 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, + !(rdata & BIT(26)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_ofst_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_gain_adapt_done_o bit29 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, !(rdata & BIT(29)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_gain_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* 7. Perform ADC interleaver adaptation for 10ms or greater, + * and after that disable it + */ + /* a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(20); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + /* set ovrd_en_rxs0_rx0_adc_intl_adapt_en_i=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0); + wr32_ephy(hw, addr, rdata); + + /* 8. Now re-enable VGA and CTLE trainings, so that it continues + * to adapt tracking changes in temperature or voltage + * <1>Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + */ + /* set rxs0_rx0_vga_train_en_i=1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x1); + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* <2>wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 */ + /* set ovrd_en_rxs0_rx0_vga_train_done_o = 0 */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0x0); + wr32_ephy(hw, addr, rdata); + + /* Wait rxs0_rx0_vga_train_done_o bit8 = 0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(8)), + 100, 3000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_vga_train_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + if (bypass_ctle == 0) { + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0); + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + wr32_ephy(hw, addr, rdata); + } + + return status; +} + +static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, + u8 bp_link_mode, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + int status = 0; + u32 rdata, addr; + + switch (bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + } + if (bypass_ctle != 0) + status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); + + status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + + /* Wait an fsm_rx_sts 25G */ + BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); + + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x1b1b1b1b & GENMASK(8 * lane_num - 1, 0))), + 1000, 300, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("wait ctrl_fsm_rx0_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + return status; +} + +static int txgbe_e56_cms_cfg_for_temp_track_range(struct txgbe_hw *hw) +{ + int status = 0, T = 40; + u32 addr, rdata; + + status = txgbe_e56_get_temp(hw, &T); + if (T < 40) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + } else if (T > 70) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + } else { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_10_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + } + return status; +} + +static int txgbe_e56_bp_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_e56_bp_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 0x18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode) +{ + int status = 0; + u32 rdata = 0; + + u32 speed_select = 0; + u32 pcs_type_sel = 0; + u32 cns_en = 0; + u32 rsfec_en = 0; + u32 pma_type = 0; + u32 an0_rate_select = 0; + + switch (bp_link_mode) { + case 10: + bp_link_mode = 10; + speed_select = 0; /* 10 Gb/s */ + pcs_type_sel = 0; /* 10GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0xb; /* 10GBASE-KR PMA/PMD type */ + an0_rate_select = 2; /* 10G-KR */ + break; + case 40: + bp_link_mode = 40; + speed_select = 3; /* 40 Gb/s */ + pcs_type_sel = 4; /* 40GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0b0100001; /* 40GBASE-CR PMA/PMD type */ + an0_rate_select = 4; /* 40G-KR: 3 40G-CR: 4 */ + break; + case 25: + bp_link_mode = 25; + speed_select = 5; /* 25 Gb/s */ + pcs_type_sel = 7; /* 25GBASE-R PCS Type */ + cns_en = 1; /* CNS_EN */ + rsfec_en = 1; /* RS-FEC enable*/ + pma_type = 0b0111001; /* 25GBASE-KR PMA/PMD type */ + an0_rate_select = 9; /* 9/10/17 25GK/CR-S or 25GK/CR */ + break; + default: + BP_LOG("%s %d :Invalid bp_link_mode\n", __func__, __LINE__); + break; + } + + hw->curbp_link_mode = bp_link_mode; + /* To switch to the 40G mode Ethernet operation, complete the following steps:*/ + /* 1. Initiate the vendor-specific software reset by programming + * the VR_RST field (bit [15]) of the VR_PCS_DIG_CTRL1 register to 1. + */ + rdata = rd32_epcs(hw, 0x038000); + wr32_epcs(hw, 0x038000, rdata | BIT(15)); + + /* 2. Wait for the hardware to clear the value for the VR_RST + * field (bit [15]) of the VR_PCS_DIG_CTRL1 register. + */ + BP_LOG("Wait for the bit [15] (VR_RST) to get cleared.\n"); + status = kr_read_poll(rd32_ephy, rdata, + FIELD_GET_M(BIT(15), rdata) == 0, 100, + 2000, hw, 0x038000); + BP_LOG("Wait PHY VR_RST = %x, Wait VR_RST %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* 3. Write 4'b0011 to bits [5:2] of the SR_PCS_CTRL1 register. + * 10G: 0 25G: 5 40G: 3 + */ + rdata = rd32_epcs(hw, 0x030000); + set_fields_e56(&rdata, 5, 2, speed_select); + wr32_epcs(hw, 0x030000, rdata); + + /* 4. Write pcs mode sel to bits [3:0] of the SR_PCS_CTRL2 register. + * 10G: 0 25G: 4'b0111 40G: 4'b0100 + */ + rdata = rd32_epcs(hw, 0x030007); + set_fields_e56(&rdata, 3, 0, pcs_type_sel); + wr32_epcs(hw, 0x030007, rdata); + + /* 0 1 1 1 0 0 1 : 25GBASE-KR or 25GBASE-KR-S PMA/PMD type + * 0 1 1 1 0 0 0 : 25GBASE-CR or 25GBASE-CR-S PMA/PMD type + * 0 1 0 0 0 0 1 : 40GBASE-CR4 PMA/PMD type + * 0 1 0 0 0 0 0 : 40GBASE-KR4 PMA/PMD type + * 0 0 0 1 0 1 1 : 10GBASE-KR PMA/PMD type + */ + rdata = rd32_epcs(hw, 0x010007); + set_fields_e56(&rdata, 6, 0, pma_type); + wr32_epcs(hw, 0x010007, rdata); + + /* 5. Write only 25g en to Bits [1:0] of VR_PCS_DIG_CTRL3 register. */ + rdata = rd32_epcs(hw, 0x38003); + set_fields_e56(&rdata, 1, 0, cns_en); + wr32_epcs(hw, 0x38003, rdata); + + /* 6. Program PCS_AM_CNT field of VR_PCS_AM_CNT register to 'd16383 to + * configure the alignment marker interval. To speed-up simulation, + * program a smaller value to this field. + */ + if (bp_link_mode == 40) + wr32_epcs(hw, 0x38018, 16383); + + /* 7. Program bit [2] of SR_PMA_RS_FEC_CTRL register to 0 + * if previously 1 (as RS-FEC is supported in 25G Mode). + */ + + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, rsfec_en); + wr32_epcs(hw, 0x100c8, rdata); + + /* 8. To enable BASE-R FEC (if desired), set bit [0]. + * in SR_PMA_KR_FEC_CTRL register + */ + + /* 4. set phy an status to 0 */ + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, 0xe); + wr32_ephy(hw, 0x1434, rdata); + + /* 9. Program Enterprise 56G PHY regs through its own APB interface: + * a. Program PHY registers as mentioned in Table 6-6 on page 1197 to + * configure the PHY to 40G + * Mode. For fast-simulation mode, additionally program, + * the registers shown in the Table 6-7 on page 1199 + * b. Enable the PMD by setting pmd_en field in PMD_CFG[0] (0x1400) + * register + */ + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&rdata, 29, 29, 0x1); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&rdata, 30, 30, 0x1); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&rdata, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&rdata, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&rdata, 18, 8, 0x294); + set_fields_e56(&rdata, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&rdata, 30, 28, 0x7); + set_fields_e56(&rdata, 26, 24, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) + set_fields_e56(&rdata, 18, 16, 0x5); + else if (bp_link_mode == 25) + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 14, 12, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&rdata, 26, 24, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) { + set_fields_e56(&rdata, 18, 16, 0x5); + set_fields_e56(&rdata, 2, 0, 0x5); + } else if (bp_link_mode == 25) { + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 2, 0, 0x3); + } + wr32_ephy(hw, DATAPATH_CFG1, rdata); + + rdata = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&rdata, 4, 0, an0_rate_select); + wr32_ephy(hw, AN_CFG1, rdata); + + status = txgbe_e56_cms_cfg_for_temp_track_range(hw); + + if (bp_link_mode == 10) + txgbe_e56_bp_cfg_10g(hw); + else if (bp_link_mode == 25) + txgbe_e56_bp_cfg_25g(hw); + else if (bp_link_mode == 40) + txgbe_e56_cfg_40g(hw); + + return status; +} + +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode, u32 need_restart) +{ + int status = 0; + u32 rdata; + + UNREFERENCED_PARAMETER(bp_link_mode); + + hw->an_done = false; + if (hw->curbp_link_mode == 10 && !need_restart) + return 0; + BP_LOG("Setup to backplane mode ==========\n"); + + u32 backplane_mode = 0; + u32 fec_advertise = 0; + + hw->an_done = false; + /* pcs + phy rst */ + rdata = rd32(hw, 0x1000c); + if (hw->bus.lan_id == 1) + rdata |= BIT(16); + else + rdata |= BIT(19); + wr32(hw, 0x1000c, rdata); + msleep(20); + + /* clear interrupt */ + wr32_epcs(hw, 0x070000, 0); + wr32_epcs(hw, 0x030000, 0x8000); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + wr32_epcs(hw, 0x078002, 0x0000); + /* pcs case fec en to work around first */ + wr32_epcs(hw, 0x100ab, 1); + + if (txgbe_is_backplane(hw)) { + /* backplane 10G/25G/40G */ + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + /* default all speed */ + if ((hw->device_id & 0xFF) == 0x10) { + backplane_mode |= BIT(7); + fec_advertise |= TXGBE_10G_FEC_ABL; + } else if ((hw->device_id & 0xFF) == 0x25) { + backplane_mode |= BIT(14) | BIT(15); + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } else if ((hw->device_id & 0xFF) == 0x40) { + if (hw->phy.bp_capa == 0) + /* original configure: KR4 + CR4 */ + backplane_mode |= BIT(9) | BIT(8); + else if (hw->phy.bp_capa == 1) + /* only 40GBASE-KR4 */ + backplane_mode |= BIT(8); + else if (hw->phy.bp_capa == 2) + /* only 40GBASE-CR4 */ + backplane_mode |= BIT(9); + fec_advertise |= TXGBE_10G_FEC_ABL; + BP_LOG("Advertised abilities: %d\n", backplane_mode); + } + } else { + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) + == TXGBE_LINK_SPEED_10GB_FULL) { + backplane_mode |= 0x80; + fec_advertise |= TXGBE_10G_FEC_ABL; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) + == TXGBE_LINK_SPEED_25GB_FULL) { + backplane_mode |= 0xc000; + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) + == TXGBE_LINK_SPEED_40GB_FULL) { + backplane_mode |= BIT(9) | BIT(8); + fec_advertise |= TXGBE_10G_FEC_ABL; + } + } + + wr32_epcs(hw, 0x070010, 0x0001); + + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + wr32_epcs(hw, 0x070011, backplane_mode | 0x11); + + /* BASE-R FEC */ + rdata = rd32_epcs(hw, 0x70012); + wr32_epcs(hw, 0x70012, fec_advertise); + + wr32_epcs(hw, 0x070016, 0x0000); + wr32_epcs(hw, 0x070017, 0x0); + wr32_epcs(hw, 0x070018, 0x0); + + /* config timer */ + wr32_epcs(hw, 0x078004, 0x003c); + wr32_epcs(hw, 0x078005, CL74_KRTR_TRAINNING_TIMEOUT); + wr32_epcs(hw, 0x078006, 25); + wr32_epcs(hw, 0x078000, 0x0008 | BIT(2)); + + BP_LOG("1.2 Wait 10G KR phy/pcs mode init ....\n"); + status = txgbe_set_phy_link_mode(hw, 10); + BP_LOG("Wait 10g phy/pcs mode init = %x, %s.\n", rdata, + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status ? "FAILED" : "SUCCESS"); + + /* 5. CM_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, 0x3); /* pll en */ + set_fields_e56(&rdata, 19, 12, 0x0); /* tx disable */ + set_fields_e56(&rdata, 8, 8, 0x0); /* pmd mode */ + set_fields_e56(&rdata, 1, 1, 0x1); /* pmd en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 6, TX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 12, 0x1); /* tx en */ + wr32_ephy(hw, 0x1400, rdata); + + BP_LOG("1.3 Wait 10G PHY RXS....\n"); + status = txgbe_e56_rxs_osc_init_for_temp_track_range(hw, 10); + BP_LOG("Wait 10G PHY/RXS mode init = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* Wait an 10g fsm_rx_sts */ + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0x3f) == 0xb), 1000, + 200, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("Wait 10g fsm_rx_sts = %x, Wait rx_sts %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + BP_LOG("Setup the backplane mode========end ==\n"); + + return status; +} + +static void txgbe_e56_print_page_status(struct txgbe_hw *hw, + struct txgbe_backplane_ability *local_ability, + struct txgbe_backplane_ability *lp_ability) +{ + u32 rdata = 0; + + /* Read the local AN73 Base Page Ability Registers */ + BP_LOG("Read the local Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG1); + local_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70010 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG2); + BP_LOG("\tread 70011 data %0x\n", rdata); + local_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + /* amber-lite only support 10GKR - 25GKR/CR - 25GKR-S/CR-S */ + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + local_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + local_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + local_ability->fec_ability = rdata; + BP_LOG("\tread 70012 data %0x\n", rdata); + + /* Read the link partner AN73 Base Page Ability Registers */ + BP_LOG("Read the link partner Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL1); + lp_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70013 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL2); + lp_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + BP_LOG("\tread 70014 data %0x\n", rdata); + BP_LOG("\tKX : %x\tKX4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_1000BASE_KX) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_10GBASE_KX4) ? 1 : 0); + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + lp_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + lp_ability->fec_ability = rdata; + + hw->phy.fec_mode = 0; + if (rdata & TXGBE_25G_RS_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_RS_FEC_REQ; + if (rdata & TXGBE_25G_BASE_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_BASE_FEC_REQ; + if (rdata & TXGBE_10G_FEC_ABL) + hw->phy.fec_mode |= TXGBE_10G_FEC_ABL; + if (rdata & TXGBE_10G_FEC_REQ) + hw->phy.fec_mode |= TXGBE_10G_FEC_REQ; + BP_LOG("\tread 70015 data %0x\n", rdata); + + BP_LOG("\tread 70016 data %0x\n", rd32_epcs(hw, 0x70016)); + BP_LOG("\tread 70017 data %0x\n", rd32_epcs(hw, 0x70017)); + BP_LOG("\tread 70018 data %0x\n", rd32_epcs(hw, 0x70018)); + BP_LOG("\tread 70019 data %0x\n", rd32_epcs(hw, 0x70019)); + BP_LOG("\tread 7001a data %0x\n", rd32_epcs(hw, 0x7001a)); + BP_LOG("\tread 7001b data %0x\n", rd32_epcs(hw, 0x7001b)); +} + +static int chk_bkp_ability(struct txgbe_hw *hw, + struct txgbe_backplane_ability local_ability, + struct txgbe_backplane_ability lp_ability) +{ + unsigned int com_link_ability; + + BP_LOG("CheckBkpAn73Ability():\n"); + /* Check the common link ability and take action based on the result*/ + com_link_ability = local_ability.link_ability & + lp_ability.link_ability; + BP_LOG("comAbility= 0x%x, Ability= 0x%x, lpAbility= 0x%x\n", + com_link_ability, local_ability.link_ability, + lp_ability.link_ability); + + if (com_link_ability == 0) { + hw->bp_link_mode = 0; + BP_LOG("Do not support any compatible speed mode!\n"); + return -EINVAL; + } else if (com_link_ability & BIT(ABILITY_40GBASE_KR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_KR4].\n"); + hw->bp_link_mode = 40; + } else if (com_link_ability & BIT(ABILITY_40GBASE_CR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_CR4].\n"); + hw->bp_link_mode = 40; + } else if (com_link_ability & BIT(ABILITY_25GBASE_KRCR_S)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR_S].\n"); + hw->fec_mode = TXGBE_25G_RS_FEC_REQ; + hw->bp_link_mode = 25; + } else if (com_link_ability & BIT(ABILITY_25GBASE_KRCR)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR].\n"); + hw->bp_link_mode = 25; + } else if (com_link_ability & BIT(ABILITY_10GBASE_KR)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KR].\n"); + hw->bp_link_mode = 10; + } else if (com_link_ability & BIT(ABILITY_10GBASE_KX4)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KX4].\n"); + hw->bp_link_mode = 10; + } else if (com_link_ability & BIT(ABILITY_1000BASE_KX)) { + BP_LOG("Link mode is [ABILITY_1000BASE_KX].\n"); + hw->bp_link_mode = 1; + } else { + BP_LOG("No compatible link mode found!\n"); + return -EINVAL; + } + + return 0; +} + +static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +{ + struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; + u32 an_int, base_page = 0; + int count = 0; + + an_int = rd32_epcs(hw, 0x78002); + /* 500ms timeout */ + if (!(an_int & VR_AN_INTR_PG_RCV)) + return -EINVAL; + + for (count = 0; count < 500; count++) { + u32 fsm = rd32_epcs(hw, 0x78010); + u32 rdata = rd32_epcs(hw, 0x78002); + + BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + an_int = rdata; + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + if (an_int & VR_AN_INTR_PG_RCV) { + u32 addr; + + txgbe_e56_print_page_status(hw, &local_ability, &lp_ability); + addr = base_page == 0 ? 0x70013 : 0x70019; + rdata = rd32_epcs(hw, addr); + if (rdata & BIT(14)) { + if (rdata & BIT(15)) { + /* always set null message */ + wr32_epcs(hw, 0x70016, 0x2001); + BP_LOG("write 70016 0x%0x\n", + 0x2001); + } + base_page = 1; + } + } + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } + usec_delay(100); + } + +check_ability: + return chk_bkp_ability(hw, local_ability, lp_ability); +} + +static int txgbe_e56_cl72_trainning(struct txgbe_hw *hw) +{ + u32 bylinkmode = hw->bp_link_mode; + u8 bypass_ctle = hw->bypass_ctle; + int status = 0, temp_data = 0; + u32 lane_num = 0, lane_idx = 0; + u32 __rte_unused pmd_ctrl = 0, txffe = 0; + int ret = 0; + u32 rdata; + + u8 pll_en_cfg = 0; + u8 pmd_mode = 0; + + switch (bylinkmode) { + case 10: + bylinkmode = 10; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + case 40: + bylinkmode = 40; + lane_num = 4; + pll_en_cfg = 0; /* pll_en_cfg : single link to 0 */ + pmd_mode = 1; /* pmd mode : 1 - single link */ + break; + case 25: + bylinkmode = 25; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); + status = txgbe_set_phy_link_mode(hw, bylinkmode); + + /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1434, rdata); + + /* 14 and 15. kr training: set BASER_PMD_CONTROL[0, 7] for lane0-4 */ + rdata = rd32_ephy(hw, 0x1640); + set_fields_e56(&rdata, 7, 0, GENMASK(2 * lane_num - 1, 0)); + wr32_ephy(hw, 0x1640, rdata); + + /* 16. enable CMS and its internal PLL */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, pll_en_cfg); + set_fields_e56(&rdata, 19, 12, 0); /* tx/rx off */ + set_fields_e56(&rdata, 8, 8, pmd_mode); + set_fields_e56(&rdata, 1, 1, 0x1); /* pmd en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 17. tx enable PMD_CFG[0] */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 15, 12, GENMASK(lane_num - 1, 0)); /* tx en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 18 */ + /* 19. rxs calibration and adaotation sequeence */ + BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); + ret |= status; + /* 20 */ + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + status = txgbe_e56_get_temp(hw, &temp_data); + if (bylinkmode == 40) + status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); + else + status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + /* 21 */ + BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0xe) & GENMASK(lane_num, 1)) == + (0xe & GENMASK(lane_num, 1)), 100, + 10000, hw, 0x163c); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, status ? "FAILED" : "SUCCESS", + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + ret |= status; + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } + + /* 22 */ + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + + return ret; +} + +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw) +{ + int status = 0; + u32 rdata; + + BP_LOG("2.1 Wait page changed ....\n"); + status = txgbe_e56_exchange_page(hw); + if (status) { + BP_LOG("Exchange page failed\n"); + return status; + } + + BP_LOG("2.2 Wait page changed ..done..\n"); + wr32_epcs(hw, 0x100ab, 0); + if (AN_TRAINNING_MODE) { + rdata = rd32_epcs(hw, 0x70000); + BP_LOG("read 0x70000 data %0x\n", rdata); + wr32_epcs(hw, 0x70000, 0); + BP_LOG("write 0x70000 0x%0x\n", 0); + } + + rdata = rd32_epcs(hw, 0x78002); + BP_LOG("read 78002 data %0x and clear page int\n", rdata); + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + + /* dis phy tx/rx lane */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, 0x1400, rdata); + BP_LOG("Ephy Write A: 0x%x, D: 0x%x\n", 0x1400, rdata); + + /* wait rx/tx/cm powerdn_st */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + if (hw->phy.fec_mode & TXGBE_25G_RS_FEC_REQ) { + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, 1); + wr32_epcs(hw, 0x100c8, rdata); + BP_LOG("Advertised FEC modes : %s\n", "RS-FEC"); + hw->cur_fec_link = TXGBE_PHY_FEC_RS; + } else if (hw->phy.fec_mode & TXGBE_25G_BASE_FEC_REQ) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "25GBASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else if (hw->fec_mode & (TXGBE_10G_FEC_REQ)) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "BASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else { + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "NONE"); + hw->cur_fec_link = TXGBE_PHY_FEC_OFF; + } + + status = txgbe_e56_cl72_trainning(hw); + + rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, rdata); + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + return status; +} diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index c58c061ea1..3e08d68545 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -272,4 +272,7 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_10_ADDR (E56PHY_CMS_BASE_ADDR + 0xD8) #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode, u32 need_restart); +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0c6a74c562..6d76b4854c 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4071,6 +4071,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } +bool txgbe_is_backplane(struct txgbe_hw *hw) +{ + return hw->phy.get_media_type(hw) == txgbe_media_type_backplane ? + true : false; +} + bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index bc34d639eb..b44190bc34 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -118,6 +118,6 @@ s32 txgbe_reinit_fdir_tables(struct txgbe_hw *hw); bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw); s32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr); s32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr, u32 *data); -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up); +bool txgbe_is_backplane(struct txgbe_hw *hw); +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask); #endif /* _TXGBE_HW_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index f4282b3241..da069e94f6 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -162,6 +162,10 @@ static inline u64 REVERT_BIT_MASK64(u64 mask) ((mask & 0xFFFFFFFF00000000) >> 32); } +#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) +#define GENMASK(h, l) \ + (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + #define IOMEM #define BIT(nr) (1UL << (nr)) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index bf7260a295..f3e3491b30 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -2503,6 +2503,27 @@ void txgbe_set_phy_temp(struct txgbe_hw *hw) } } +int txgbe_is_dac_cable(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) + return true; + + return false; +} + +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) +{ + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) + return false; + + return hw->devarg.auto_neg ? true : false; +} + /** * txgbe_kr_handle - Handle the interrupt of auto-negotiation * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index c02be3cc34..3fe7a34409 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -105,6 +105,8 @@ #define VR_AN_INTR_CMPLT MS16(0, 0x1) #define VR_AN_INTR_LINK MS16(1, 0x1) #define VR_AN_INTR_PG_RCV MS16(2, 0x1) +#define TXGBE_E56_AN_TXDIS MS16(3, 0x1) +#define TXGBE_E56_AN_PG_RCV MS16(4, 0x1) #define VR_AN_KR_MODE_CL 0x078003 #define VR_AN_KR_MODE_CL_PDET MS16(0, 0x1) #define VR_XS_OR_PCS_MMD_DIGI_CTL1 0x038000 @@ -428,6 +430,24 @@ #define TXGBE_BP_M_NAUTO 0 #define TXGBE_BP_M_AUTO 1 +#define kr_read_poll(op, val, cond, sleep_us, \ + times, args...) \ +({ \ + unsigned long __sleep_us = (sleep_us); \ + u32 __times = (times); \ + u32 i; \ + int __cond = 0; \ + for (i = 0; i < __times; i++) { \ + (val) = op(args); \ + if (cond) { \ + __cond = 1; \ + break; \ + } \ + usleep(__sleep_us);\ + } \ + (__cond) ? 0 : -1; \ +}) + #ifndef CL72_KRTR_PRBS_MODE_EN #define CL72_KRTR_PRBS_MODE_EN 0xFFFF /* open kr prbs check */ #endif @@ -490,6 +510,8 @@ void txgbe_autoc_write(struct txgbe_hw *hw, u64 value); void txgbe_bp_mode_set(struct txgbe_hw *hw); void txgbe_set_phy_temp(struct txgbe_hw *hw); void txgbe_bp_down_event(struct txgbe_hw *hw); +int txgbe_is_dac_cable(struct txgbe_hw *hw); +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw); s32 txgbe_kr_handle(struct txgbe_hw *hw); #endif /* _TXGBE_PHY_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 7fb4bcc513..47629aa9e0 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -719,6 +719,7 @@ struct txgbe_phy_info { u32 addr; u32 id; enum txgbe_sfp_type sfp_type; + u32 fiber_suppport_speed; bool sfp_setup_needed; u32 revision; u32 media_type; @@ -740,6 +741,7 @@ struct txgbe_phy_info { u16 ffe_pre2; u16 ffe_post; u16 fec_mode; + u16 bp_capa; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -899,7 +901,28 @@ struct txgbe_hw { u32 cur_fec_link; int temperature; u32 bp_link_mode; -}; + bool dac_sfp; + bool bypass_ctle; + u32 curbp_link_mode; + bool an_done; + u32 fsm; + u64 bp_event_interval; +}; + +typedef enum { + ABILITY_1000BASE_KX, + ABILITY_10GBASE_KX4, + ABILITY_10GBASE_KR, + ABILITY_40GBASE_KR4, + ABILITY_40GBASE_CR4, + ABILITY_100GBASE_CR10, + ABILITY_100GBASE_KP4, + ABILITY_100GBASE_KR4, + ABILITY_100GBASE_CR4, + ABILITY_25GBASE_KRCR_S, + ABILITY_25GBASE_KRCR, + ABILITY_MAX, +} ability_filed_encding; struct txgbe_backplane_ability { u32 next_page; /* Next Page (bit0) */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 02c3305712..56987ae028 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2010,6 +2010,10 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_l2_tunnel_conf(dev); txgbe_filter_restore(dev); + hw->bp_event_interval = 100 * 1000; + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); + if (tm_conf->root && !tm_conf->committed) PMD_DRV_LOG(WARNING, "please call hierarchy_commit() " @@ -2054,8 +2058,10 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + } rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); @@ -2926,6 +2932,107 @@ txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) return NULL; } +void txgbe_dev_e56_check_bp_event(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + u32 an_int1 = 0, value = 0, fsm = 0; + u32 __rte_unused an_int = 0; + int ret = 0; + bool need_link_update = false; + + if (!hw) + return; + + if (!(txgbe_xpcs_an_enabled(hw))) + return; + + if (!hw->devarg.auto_neg) + return; + + /* only continue if link is down */ + if (dev->data->dev_link.link_status) + goto out; + + value = rd32_epcs(hw, VR_AN_INTR); + an_int = value; + if (value & 0xF) + hw->bp_event_interval = 100 * 1000; + + if (value & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + value &= ~VR_AN_INTR_CMPLT; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & VR_AN_INTR_LINK) { + value &= ~VR_AN_INTR_LINK; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & TXGBE_E56_AN_TXDIS) { + value &= ~TXGBE_E56_AN_TXDIS; + wr32_epcs(hw, VR_AN_INTR, value); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + goto an_status; + } + + if (value & VR_AN_INTR_PG_RCV) { + BP_LOG("%d Enter training\n", hw->port_id); + ret = handle_e56_bkp_an73_flow(hw); + if (!AN_TRAINNING_MODE) { + fsm = rd32_epcs(hw, 0x78010); + if (fsm & 0x8) + goto an_status; + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + BP_LOG("ALL SUCCEEDED\n"); + } + } else { + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + hw->an_done = true; + } + } + } + +an_status: + an_int1 = rd32_epcs(hw, 0x78002); + if (an_int1 & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + } + + BP_LOG("%d RLU:%x MLU:%x INT:%x-%x CTL:%x fsm:%x pmd_cfg0:%x an_done:%d\n", + hw->port_id, rd32_epcs(hw, 0x30001), rd32(hw, 0x14404), + an_int, an_int1, + rd32_epcs(hw, 0x70000), + rd32_epcs(hw, 0x78010), + rd32_ephy(hw, 0x1400), + hw->an_done); + + if (need_link_update) + txgbe_dev_link_update(dev, 0); + + if (dev->data->dev_link.link_status) + hw->bp_event_interval = 2000 * 1000; + +out: + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); +} + static void txgbe_dev_detect_sfp(void *param) { diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 1ec8e096cc..309db3bfe9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -747,5 +747,5 @@ void txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on); void txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, int mask); - +void txgbe_dev_e56_check_bp_event(void *param); #endif /* _TXGBE_ETHDEV_H_ */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 15/20] net/txgbe: fix FEC mode configuration on 25G NIC 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (13 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 16/20] net/txgbe: fix SFP module identification Zaiyu Wang ` (6 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The 25G NIC offers off, RS, Base-R, and auto FEC modes. When reconfiguring the PHY, the FEC mode must match on both sides; otherwise, the link cannot come up. The current driver fails to maintain this requirement, causing link instability. Add proper FEC mode handling during PHY reconfiguration to guarantee link establishment. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index a5b9d951ea..fbb09d144b 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -282,6 +282,14 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, !(hw->fec_mode & hw->cur_fec_link))) goto out; + if (speed == TXGBE_LINK_SPEED_25GB_FULL && + link_speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + + if (link_up) + goto out; + } + rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); rte_spinlock_unlock(&hw->phy_lock); @@ -360,7 +368,10 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* If we already have link at this speed, just jump out */ txgbe_e56_check_phy_link(hw, &link_speed, &link_up); - if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up) + hw->cur_fec_link = txgbe_phy_fec_get(hw); + + if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up && + hw->fec_mode & hw->cur_fec_link) goto out; /* Allow module to change analog characteristics (10G -> 25G) */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 16/20] net/txgbe: fix SFP module identification 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (14 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 17/20] net/txgbe: fix get module info operation Zaiyu Wang ` (5 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Some optical modules were not correctly recognized due to ambiguous classification in the original detection flow. Rework the module identification logic to cover all module types. Also narrow the I2C lock scope to avoid potential race conditions during module access. Fixes: ab191e6d9189 ("net/txgbe: support new SFP/QSFP modules") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 2 - drivers/net/txgbe/base/txgbe_phy.c | 339 ++++++++++------------------ drivers/net/txgbe/base/txgbe_phy.h | 18 +- drivers/net/txgbe/base/txgbe_type.h | 2 + 4 files changed, 132 insertions(+), 229 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 6d76b4854c..16fd9ba20d 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -2909,8 +2909,6 @@ s32 txgbe_init_ops_generic(struct txgbe_hw *hw) phy->read_i2c_eeprom = txgbe_read_i2c_eeprom; phy->write_i2c_eeprom = txgbe_write_i2c_eeprom; phy->identify_sfp = txgbe_identify_module; - phy->read_i2c_byte_unlocked = txgbe_read_i2c_byte_unlocked; - phy->write_i2c_byte_unlocked = txgbe_write_i2c_byte_unlocked; phy->check_overtemp = txgbe_check_overtemp; phy->reset = txgbe_reset_phy; phy->set_link_hostif = txgbe_hic_ephy_set_link; diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index f3e3491b30..ac06f9530a 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -830,6 +830,10 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) return TXGBE_ERR_SFP_NOT_PRESENT; } + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, &identifier); if (err != 0) { @@ -839,11 +843,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.id = 0; hw->phy.type = txgbe_phy_unknown; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_PRESENT; } if (identifier != TXGBE_SFF_IDENTIFIER_SFP) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -888,7 +894,42 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) * 11 SFP_1g_sx_CORE0 - chip-specific * 12 SFP_1g_sx_CORE1 - chip-specific */ - if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; + else + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->dac_sfp = true; + } + + if (comp_copper_len == TXGBE_SFF_COPPER_1M) + hw->bypass_ctle = true; + else + hw->bypass_ctle = false; + + if (comp_codes_25g == TXGBE_SFF_25GBASECR_91FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_74FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_NOFEC) { + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_25GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + } else { + hw->phy.fiber_suppport_speed |= + TXGBE_LINK_SPEED_10GB_FULL; + } + } else if (comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_12 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_12) { + hw->dac_sfp = false; + hw->phy.sfp_type = (hw->bus.lan_id == 0 + ? txgbe_sfp_type_25g_aoc_core0 + : txgbe_sfp_type_25g_aoc_core1); + } else if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + hw->dac_sfp = false; err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_CABLE_SPEC_COMP, &cable_spec); if (err != 0) @@ -1005,6 +1046,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) /* Allow any DA cable vendor */ if (cable_tech & (TXGBE_SFF_CABLE_DA_PASSIVE | TXGBE_SFF_CABLE_DA_ACTIVE)) { + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; } @@ -1017,6 +1059,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -1031,9 +1074,11 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { DEBUGOUT("SFP+ module not supported"); hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; } @@ -1046,28 +1091,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) { s32 err = TXGBE_ERR_PHY_ADDR_INVALID; - u32 vendor_oui = 0; - enum txgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; - u8 identifier = 0; - u8 comp_codes_1g = 0; - u8 comp_codes_10g = 0; - u8 oui_bytes[3] = {0, 0, 0}; - u16 enforce_sfp = 0; - u8 connector = 0; - u8 cable_length = 0; - u8 device_tech = 0; - bool active_cable = false; + u8 identifier = 0, transceiver_type = 0; u32 value; - if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { - hw->phy.sfp_type = txgbe_sfp_type_not_present; - err = TXGBE_ERR_SFP_NOT_PRESENT; - goto out; - } + /* config GPIO before read i2c */ + wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); if (hw->mac.type == txgbe_mac_aml40) { - /* config GPIO before read i2c */ - wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { hw->phy.sfp_type = txgbe_sfp_type_not_present; @@ -1075,175 +1105,68 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) } } - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, - &identifier); -ERR_I2C: - if (err != 0) { + if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { hw->phy.sfp_type = txgbe_sfp_type_not_present; - hw->phy.id = 0; - hw->phy.type = txgbe_phy_unknown; return TXGBE_ERR_SFP_NOT_PRESENT; } - if (identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; - } - hw->phy.id = identifier; + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_10GBE_COMP, - &comp_codes_10g); + err = hw->phy.read_i2c_sff8636(hw, 0, TXGBE_SFF_IDENTIFIER, + &identifier); if (err != 0) - goto ERR_I2C; + goto err_read_i2c_eeprom; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_1GBE_COMP, - &comp_codes_1g); - - if (err != 0) - goto ERR_I2C; + if (identifier != TXGBE_SFF_IDENTIFIER_QSFP && + identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { + PMD_INIT_LOG(ERR, "port[%d] QSFP module not supported, identifier = 0x%x", + hw->bus.lan_id, identifier); + hw->phy.type = txgbe_phy_sfp_unsupported; + err = TXGBE_ERR_SFP_NOT_SUPPORTED; + } else { + err = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_ETHERNET_COMP_OFFSET, + &transceiver_type); + if (err != 0) + goto err_read_i2c_eeprom; - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_PASSIVE_CABLE) { - hw->phy.type = txgbe_phy_qsfp_unknown_passive; - if (hw->mac.type == txgbe_mac_aml40) { + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core0; else hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core1; - } else { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; - } - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_SR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_LR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; - } else if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_srlr_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_srlr_core1; - } else { - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_ACTIVE_CABLE) - active_cable = true; - - if (!active_cable) { - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CONNECTOR, - &connector); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CABLE_LENGTH, - &cable_length); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_DEVICE_TECH, - &device_tech); - - if (connector == - TXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE && - cable_length > 0 && - ((device_tech >> 4) == - TXGBE_SFF_QSFP_TRANSMITTER_850NM_VCSEL)) - active_cable = true; + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } - if (active_cable) { - hw->phy.type = txgbe_phy_qsfp_unknown_active; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_SR4) { if (hw->bus.lan_id == 0) - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core0; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; else - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core1; - } else { - /* unsupported module type */ - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; } - } - - if (hw->phy.sfp_type != stored_sfp_type) - hw->phy.sfp_setup_needed = true; - - /* Determine if the QSFP+ PHY is dual speed or not. */ - hw->phy.multispeed_fiber = false; - if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) || - ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE))) - hw->phy.multispeed_fiber = true; - - /* Determine PHY vendor for optical modules */ - if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0, - &oui_bytes[0]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1, - &oui_bytes[1]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE2, - &oui_bytes[2]); - if (err != 0) - goto ERR_I2C; - - vendor_oui = - ((oui_bytes[0] << 24) | - (oui_bytes[1] << 16) | - (oui_bytes[2] << 8)); - - if (vendor_oui == TXGBE_SFF_VENDOR_OUI_INTEL) - hw->phy.type = txgbe_phy_qsfp_intel; - else - hw->phy.type = txgbe_phy_qsfp_unknown; - - hw->mac.get_device_caps(hw, &enforce_sfp); - if (!(enforce_sfp & TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) { - /* Make sure we're a supported PHY type */ - if (hw->phy.type == txgbe_phy_qsfp_intel) { - err = 0; - } else { - if (hw->allow_unsupported_sfp) { - DEBUGOUT("WARNING: Wangxun (R) Network Connections are quality tested using Wangxun (R) Ethernet Optics. " - "Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. " - "Wangxun Corporation is not responsible for any harm caused by using untested modules."); - err = 0; - } else { - DEBUGOUT("QSFP module not supported"); - hw->phy.type = - txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - } - } - } else { - err = 0; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_LR4) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } } -out: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; + +err_read_i2c_eeprom: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + hw->phy.id = 0; + hw->phy.type = txgbe_phy_unknown; + return TXGBE_ERR_SFP_NOT_PRESENT; } /** @@ -1278,6 +1201,26 @@ s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, sff8472_data); } +/** + * txgbe_read_i2c_sff8636 - Reads 8 bit word over I2C interface + * @hw: pointer to hardware structure + * @byte_offset: byte offset at address 0xA2 + * @eeprom_data: value read + * + * Performs byte read operation to SFP module's SFF-8472 data over I2C + **/ +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data) +{ + hw->phy.write_i2c_byte(hw, TXGBE_SFF_QSFP_PAGE_SELECT, + TXGBE_I2C_EEPROM_DEV_ADDR, + page); + + return hw->phy.read_i2c_byte(hw, byte_offset, + TXGBE_I2C_EEPROM_DEV_ADDR, + sff8636_data); +} + /** * txgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure @@ -1295,7 +1238,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte_unlocked - Reads 8 bit word over I2C + * txgbe_read_i2c_byte - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: address to read from @@ -1304,7 +1247,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, +s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { txgbe_i2c_start(hw, dev_addr); @@ -1334,30 +1277,7 @@ s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte - Reads 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to read - * @dev_addr: address to read from - * @data: value read - * - * Performs byte read operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_read_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - return err; -} - -/** - * txgbe_write_i2c_byte_unlocked - Writes 8 bit word over I2C + * txgbe_write_i2c_byte - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: address to write to @@ -1366,54 +1286,29 @@ s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) +s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data) { txgbe_i2c_start(hw, dev_addr); /* wait tx empty */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY, - TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) { + TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) return -TERR_TIMEOUT; - } - wr32(hw, TXGBE_I2CDATA, byte_offset | TXGBE_I2CDATA_STOP); + wr32(hw, TXGBE_I2CDATA, byte_offset); wr32(hw, TXGBE_I2CDATA, data | TXGBE_I2CDATA_WRITE); /* wait for write complete */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_RXFULL, - TXGBE_I2CICR_RXFULL, NULL, 100, 100)) { + TXGBE_I2CICR_RXFULL, NULL, 100, 100)) return -TERR_TIMEOUT; - } + txgbe_i2c_stop(hw); return 0; } -/** - * txgbe_write_i2c_byte - Writes 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to write - * @dev_addr: address to write to - * @data: value to write - * - * Performs byte write operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_write_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - - return err; -} - /** * txgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 3fe7a34409..4da4be0d5f 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -261,7 +261,9 @@ #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0 0xA5 #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1 0xA6 @@ -289,6 +291,9 @@ #define TXGBE_SFF_4x10GBASESR_CAP 0x11 #define TXGBE_SFF_40GBASEPSM4_PARALLEL 0x12 #define TXGBE_SFF_40GBASE_SWMD4_CAP 0x1f +#define TXGBE_SFF_COPPER_5M 0x5 +#define TXGBE_SFF_COPPER_3M 0x3 +#define TXGBE_SFF_COPPER_1M 0x1 #define TXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 #define TXGBE_SFF_25GAUI_C2M_AOC_BER_5 0x1 @@ -296,6 +301,11 @@ #define TXGBE_SFF_25GAUI_C2M_AOC_BER_12 0x18 #define TXGBE_SFF_25GAUI_C2M_ACC_BER_12 0x19 +#define TXGBE_ETHERNET_COMP_OFFSET 0x83 +#define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) +#define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) +#define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) + #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_1G 0x0 @@ -493,14 +503,12 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw); s32 txgbe_check_overtemp(struct txgbe_hw *hw); s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data); s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data); s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, - u8 *sff8472_data); + u8 *sff8472_data); +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data); s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 47629aa9e0..2e2d79e0e1 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -702,6 +702,8 @@ struct txgbe_phy_info { u8 dev_addr, u8 data); s32 (*read_i2c_sff8472)(struct txgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); + s32 (*read_i2c_sff8636)(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data); s32 (*read_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 (*write_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 17/20] net/txgbe: fix get module info operation 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (15 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 16/20] net/txgbe: fix SFP module identification Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 18/20] net/txgbe: fix get eeprom operation Zaiyu Wang ` (4 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.h | 6 +- drivers/net/txgbe/txgbe_ethdev.c | 116 ++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 4da4be0d5f..581f667bdc 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -257,11 +257,15 @@ #define TXGBE_SFF_CABLE_DA_PASSIVE 0x4 #define TXGBE_SFF_CABLE_DA_ACTIVE 0x8 #define TXGBE_SFF_CABLE_SPEC_COMP 0x3C +#define TXGBE_SFF_DDM_IMPLEMENTED 0x40 #define TXGBE_SFF_SFF_8472_SWAP 0x5C #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 -#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_SFF_REVISION_ADDR 0x01 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F + +#define TXGBE_MODULE_QSFP_MAX_LEN 640 #define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 56987ae028..bc651cfcfb 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5348,41 +5348,105 @@ txgbe_get_module_info(struct rte_eth_dev *dev, struct txgbe_hw *hw = TXGBE_DEV_HW(dev); uint32_t status; uint8_t sff8472_rev, addr_mode; + u8 identifier = 0; + u8 sff8636_rev = 0; bool page_swap = false; + u32 value; - /* Check whether we support SFF-8472 or not */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_COMP, - &sff8472_rev); - if (status != 0) - return -EIO; - - /* addressing mode is not supported */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_SWAP, - &addr_mode); - if (status != 0) - return -EIO; + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } - if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { - PMD_DRV_LOG(ERR, - "Address change required to access page 0xA2, " - "but not supported. Please report the module " - "type to the driver maintainers."); - page_swap = true; + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; } - if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap) { - /* We have a SFP, but it does not support SFF-8472 */ - modinfo->type = RTE_ETH_MODULE_SFF_8079; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; + + if (hw->mac.type == txgbe_mac_aml40) { + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_IDENTIFIER, + &identifier); } else { - /* We have a SFP which supports a revision of SFF-8472. */ - modinfo->type = RTE_ETH_MODULE_SFF_8472; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); } + if (status != 0) + goto ERROR_IO; + + switch (identifier) { + case TXGBE_SFF_IDENTIFIER_SFP: + /* Check whether we support SFF-8472 or not */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_COMP, + &sff8472_rev); + if (status != 0) + goto ERROR_IO; + + /* addressing mode is not supported */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_SWAP, + &addr_mode); + if (status != 0) + goto ERROR_IO; + + if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { + PMD_DRV_LOG(ERR, + "Address change required to access page 0xA2, " + "but not supported. Please report the module " + "type to the driver maintainers."); + page_swap = true; + } + + if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap || + !(addr_mode & TXGBE_SFF_DDM_IMPLEMENTED)) { + /* We have a SFP, but it does not support SFF-8472 */ + modinfo->type = RTE_ETH_MODULE_SFF_8079; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + } else { + /* We have a SFP which supports a revision of SFF-8472. */ + modinfo->type = RTE_ETH_MODULE_SFF_8472; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + } + break; + case TXGBE_SFF_IDENTIFIER_QSFP: + case TXGBE_SFF_IDENTIFIER_QSFP_PLUS: + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_SFF_REVISION_ADDR, + &sff8636_rev); + if (status != 0) + goto ERROR_IO; + /* Check revision compliance */ + if (sff8636_rev > 0x02) { + /* Module is SFF-8636 compliant */ + modinfo->type = RTE_ETH_MODULE_SFF_8636; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } else { + modinfo->type = RTE_ETH_MODULE_SFF_8436; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } + break; + default: + PMD_DRV_LOG(ERR, "SFF Module Type not recognized."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EINVAL; + } + + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } static int -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 18/20] net/txgbe: fix get eeprom operation 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (16 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 17/20] net/txgbe: fix get module info operation Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang ` (3 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 67 ++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bc651cfcfb..d6921704e8 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5458,23 +5458,76 @@ txgbe_get_module_eeprom(struct rte_eth_dev *dev, uint8_t databyte = 0xFF; uint8_t *data = info->data; uint32_t i = 0; + bool is_sfp = false; + u32 value; + u8 identifier = 0; + u16 offset; + u8 page = 0; + + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } + + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; + } if (info->length == 0) return -EINVAL; - for (i = info->offset; i < info->offset + info->length; i++) { - if (i < RTE_ETH_MODULE_SFF_8079_LEN) - status = hw->phy.read_i2c_eeprom(hw, i, &databyte); - else - status = hw->phy.read_i2c_sff8472(hw, i, &databyte); + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; - if (status != 0) - return -EIO; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); + if (status != 0) + goto ERROR_IO; + if (identifier == TXGBE_SFF_IDENTIFIER_SFP) + is_sfp = true; + + memset(data, 0, info->length); + + for (i = info->offset; i < info->offset + info->length; i++) { + if (is_sfp) { + if (i < RTE_ETH_MODULE_SFF_8079_LEN) + status = hw->phy.read_i2c_eeprom(hw, i, + &databyte); + else + status = hw->phy.read_i2c_sff8472(hw, i, + &databyte); + + if (status != 0) + goto ERROR_IO; + } else { + offset = i; + while (offset >= RTE_ETH_MODULE_SFF_8436_LEN) { + offset -= RTE_ETH_MODULE_SFF_8436_LEN / 2; + page++; + } + if (page == 0 || !(data[0x2] & 0x4)) { + status = hw->phy.read_i2c_sff8636(hw, page, offset, + &databyte); + if (status != 0) + goto ERROR_IO; + } + } data[i - info->offset] = databyte; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } bool -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 19/20] net/txgbe: fix to reset Tx write-back pointer 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (17 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 18/20] net/txgbe: fix get eeprom operation Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang ` (2 subsequent siblings) 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The write-back pointer was not reset when the Tx queue was reset. This leads to the wrong Tx desc free logic. Move the resetting of pointer into txq->ops->reset(txq). Fixes: 8ada71d0bb7f ("net/txgbe: add Tx head write-back mode for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 45 +++++++++++++---------- drivers/net/txgbe/txgbe_rxtx.h | 1 + drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 ++++ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 851cd122d8..ef53a868a6 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -2320,6 +2320,12 @@ txgbe_reset_tx_queue(struct txgbe_tx_queue *txq) txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); txq->tx_tail = 0; + /* Zero out headwb_mem memory */ + if (txq->headwb_mem) { + for (i = 0; i < txq->headwb_size; i++) + txq->headwb_mem[i] = 0; + } + /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition @@ -2419,7 +2425,7 @@ txgbe_get_tx_port_offloads(struct rte_eth_dev *dev) return tx_offload_capa; } -static int +static void txgbe_setup_headwb_resources(struct rte_eth_dev *dev, void *tx_queue, unsigned int socket_id) @@ -2427,33 +2433,33 @@ txgbe_setup_headwb_resources(struct rte_eth_dev *dev, struct txgbe_hw *hw = TXGBE_DEV_HW(dev); const struct rte_memzone *headwb; struct txgbe_tx_queue *txq = tx_queue; - u8 i, headwb_size = 0; + u8 headwb_size = 0; - if (hw->mac.type != txgbe_mac_aml && hw->mac.type != txgbe_mac_aml40) { - txq->headwb_mem = NULL; - return 0; - } + if (hw->mac.type != txgbe_mac_aml && hw->mac.type != txgbe_mac_aml40) + goto out; + + if (!hw->devarg.tx_headwb) + goto out; - headwb_size = hw->devarg.tx_headwb_size; + headwb_size = txq->headwb_size; headwb = rte_eth_dma_zone_reserve(dev, "tx_headwb_mem", txq->queue_id, sizeof(u32) * headwb_size, TXGBE_ALIGN, socket_id); if (headwb == NULL) { - DEBUGOUT("Fail to setup headwb resources: no mem"); - txgbe_tx_queue_release(txq); - return -ENOMEM; + PMD_DRV_LOG(INFO, + "Failed to allocate headwb memory for Tx queue %u, change to SP mode", + txq->queue_id); + goto out; } txq->headwb = headwb; txq->headwb_dma = TMZ_PADDR(headwb); txq->headwb_mem = (uint32_t *)TMZ_VADDR(headwb); + return; - /* Zero out headwb_mem memory */ - for (i = 0; i < headwb_size; i++) - txq->headwb_mem[i] = 0; - - return 0; +out: + txq->headwb_mem = NULL; } int __rte_cold @@ -2549,6 +2555,7 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, txq->offloads = offloads; txq->ops = &def_txq_ops; txq->tx_deferred_start = tx_conf->tx_deferred_start; + txq->headwb_size = hw->devarg.tx_headwb_size; #ifdef RTE_LIB_SECURITY txq->using_ipsec = !!(dev->data->dev_conf.txmode.offloads & RTE_ETH_TX_OFFLOAD_SECURITY); @@ -2584,8 +2591,7 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, /* set up scalar TX function as appropriate */ txgbe_set_tx_function(dev, txq); - if (hw->devarg.tx_headwb) - err = txgbe_setup_headwb_resources(dev, txq, socket_id); + txgbe_setup_headwb_resources(dev, txq, socket_id); txq->ops->reset(txq); txq->desc_error = 0; @@ -4762,15 +4768,14 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) wr32(hw, TXGBE_TXRP(txq->reg_idx), 0); wr32(hw, TXGBE_TXWP(txq->reg_idx), 0); - if ((hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) && - hw->devarg.tx_headwb) { + if (txq->headwb_mem) { uint32_t txdctl; wr32(hw, TXGBE_PX_TR_HEAD_ADDRL(txq->reg_idx), (uint32_t)(txq->headwb_dma & BIT_MASK32)); wr32(hw, TXGBE_PX_TR_HEAD_ADDRH(txq->reg_idx), (uint32_t)(txq->headwb_dma >> 32)); - if (hw->devarg.tx_headwb_size == 16) + if (txq->headwb_size == 16) txdctl = TXGBE_PX_TR_CFG_HEAD_WB | TXGBE_PX_TR_CFG_HEAD_WB_64BYTE; else diff --git a/drivers/net/txgbe/txgbe_rxtx.h b/drivers/net/txgbe/txgbe_rxtx.h index 02e2617cce..237bb64697 100644 --- a/drivers/net/txgbe/txgbe_rxtx.h +++ b/drivers/net/txgbe/txgbe_rxtx.h @@ -416,6 +416,7 @@ struct txgbe_tx_queue { uint64_t desc_error; bool resetting; const struct rte_memzone *headwb; + uint16_t headwb_size; uint64_t headwb_dma; volatile uint32_t *headwb_mem; }; diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h index edf3586b77..594886c5b1 100644 --- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h +++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h @@ -255,6 +255,13 @@ _txgbe_reset_tx_queue_vec(struct txgbe_tx_queue *txq) txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); txq->tx_tail = 0; + + /* Zero out headwb_mem memory */ + if (txq->headwb_mem) { + for (i = 0; i < txq->headwb_size; i++) + txq->headwb_mem[i] = 0; + } + /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v3 20/20] net/txgbe: fix to enable Tx desc check 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (18 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang @ 2026-05-09 11:28 ` Zaiyu Wang 2026-05-09 15:44 ` [PATCH v3 00/20] Wangxun Fixes Stephen Hemminger 2026-05-09 17:07 ` Stephen Hemminger 21 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-09 11:28 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Now lib security is enabled by default, and cannot be disabled if the driver is intended to be used. So Tdm_desc_chk is always unable to enable. Remove this restriction, and just enable the corresponding queue check. Fixes: 0eabdfcd4af4 ("net/txgbe: enable Tx descriptor error interrupt") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index ef53a868a6..8b3d5eec14 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -4768,6 +4768,12 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) wr32(hw, TXGBE_TXRP(txq->reg_idx), 0); wr32(hw, TXGBE_TXWP(txq->reg_idx), 0); +#ifdef RTE_LIBRTE_SECURITY + if (!(txq->using_ipsec)) +#endif + wr32m(hw, TXGBE_TDM_DESC_CHK(txq->reg_idx / 32), + BIT(txq->reg_idx % 32), BIT(txq->reg_idx % 32)); + if (txq->headwb_mem) { uint32_t txdctl; @@ -4785,11 +4791,6 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) } } -#ifndef RTE_LIB_SECURITY - for (i = 0; i < 4; i++) - wr32(hw, TXGBE_TDM_DESC_CHK(i), 0xFFFFFFFF); -#endif - /* Device configured with multiple TX queues. */ txgbe_dev_mq_tx_configure(dev); } -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* Re: [PATCH v3 00/20] Wangxun Fixes 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (19 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang @ 2026-05-09 15:44 ` Stephen Hemminger 2026-05-09 17:07 ` Stephen Hemminger 21 siblings, 0 replies; 92+ messages in thread From: Stephen Hemminger @ 2026-05-09 15:44 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Sat, 9 May 2026 19:28:02 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series fixes several issues found on Wangxun Emerald, Sapphire and > Amber-lite NICs, with a focus on link-related problems. > --- > v3: > - Addressed Stephen's comments > --- > v2: > - Fixed compilation error and code style issues > --- > > Zaiyu Wang (20): > net/txgbe: remove duplicate xstats counters > net/ngbe: remove duplicate xstats counters > net/ngbe: add missing CDR config for YT PHY > net/ngbe: fix VF promiscuous and allmulticast > net/txgbe: fix inaccuracy in TX rate limiting > net/txgbe: fix link status check condition > net/txgbe: fix Tx desc free logic > net/txgbe: fix link flow control registers for Amber-Lite > net/txgbe: fix link flow control config for Sapphire > net/txgbe: fix a mass of unknown interrupts > net/txgbe: fix traffic class priority configuration > net/txgbe: fix link stability for 25G NIC > net/txgbe: fix link stability for 40G NIC > net/txgbe: fix link stability for Amber-Lite backplane mode > net/txgbe: fix FEC mode configuration on 25G NIC > net/txgbe: fix SFP module identification > net/txgbe: fix get module info operation > net/txgbe: fix get eeprom operation > net/txgbe: fix to reset Tx write-back pointer > net/txgbe: fix to enable Tx desc check > > drivers/net/ngbe/base/ngbe_phy_yt.c | 3 + > drivers/net/ngbe/ngbe_ethdev.c | 5 - > drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +- > drivers/net/txgbe/base/meson.build | 2 + > drivers/net/txgbe/base/txgbe.h | 2 + > drivers/net/txgbe/base/txgbe_aml.c | 187 +- > drivers/net/txgbe/base/txgbe_aml.h | 6 +- > drivers/net/txgbe/base/txgbe_aml40.c | 113 +- > drivers/net/txgbe/base/txgbe_aml40.h | 6 +- > drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- > drivers/net/txgbe/base/txgbe_e56.c | 3774 +++++++++++++++++++++ > drivers/net/txgbe/base/txgbe_e56.h | 1744 ++++++++++ > drivers/net/txgbe/base/txgbe_e56_bp.c | 2593 ++++++++++++++ > drivers/net/txgbe/base/txgbe_e56_bp.h | 278 ++ > drivers/net/txgbe/base/txgbe_hw.c | 54 +- > drivers/net/txgbe/base/txgbe_hw.h | 4 +- > drivers/net/txgbe/base/txgbe_osdep.h | 4 + > drivers/net/txgbe/base/txgbe_phy.c | 360 +- > drivers/net/txgbe/base/txgbe_phy.h | 45 +- > drivers/net/txgbe/base/txgbe_regs.h | 11 +- > drivers/net/txgbe/base/txgbe_type.h | 43 +- > drivers/net/txgbe/txgbe_ethdev.c | 414 ++- > drivers/net/txgbe/txgbe_ethdev.h | 6 +- > drivers/net/txgbe/txgbe_rxtx.c | 102 +- > drivers/net/txgbe/txgbe_rxtx.h | 1 + > drivers/net/txgbe/txgbe_rxtx_vec_common.h | 14 +- > 26 files changed, 9350 insertions(+), 434 deletions(-) > create mode 100644 drivers/net/txgbe/base/txgbe_e56.c > create mode 100644 drivers/net/txgbe/base/txgbe_e56.h > create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c > create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h > Review will be delayed because of DPDK summit this week. ^ permalink raw reply [flat|nested] 92+ messages in thread
* Re: [PATCH v3 00/20] Wangxun Fixes 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang ` (20 preceding siblings ...) 2026-05-09 15:44 ` [PATCH v3 00/20] Wangxun Fixes Stephen Hemminger @ 2026-05-09 17:07 ` Stephen Hemminger 2026-05-11 10:28 ` Zaiyu Wang 21 siblings, 1 reply; 92+ messages in thread From: Stephen Hemminger @ 2026-05-09 17:07 UTC (permalink / raw) To: Zaiyu Wang; +Cc: dev On Sat, 9 May 2026 19:28:02 +0800 Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > This series fixes several issues found on Wangxun Emerald, Sapphire and > Amber-lite NICs, with a focus on link-related problems. > --- > v3: > - Addressed Stephen's comments > --- > v2: > - Fixed compilation error and code style issues > --- > > Zaiyu Wang (20): > net/txgbe: remove duplicate xstats counters > net/ngbe: remove duplicate xstats counters > net/ngbe: add missing CDR config for YT PHY > net/ngbe: fix VF promiscuous and allmulticast > net/txgbe: fix inaccuracy in TX rate limiting > net/txgbe: fix link status check condition > net/txgbe: fix Tx desc free logic > net/txgbe: fix link flow control registers for Amber-Lite > net/txgbe: fix link flow control config for Sapphire > net/txgbe: fix a mass of unknown interrupts > net/txgbe: fix traffic class priority configuration > net/txgbe: fix link stability for 25G NIC > net/txgbe: fix link stability for 40G NIC > net/txgbe: fix link stability for Amber-Lite backplane mode > net/txgbe: fix FEC mode configuration on 25G NIC > net/txgbe: fix SFP module identification > net/txgbe: fix get module info operation > net/txgbe: fix get eeprom operation > net/txgbe: fix to reset Tx write-back pointer > net/txgbe: fix to enable Tx desc check > > drivers/net/ngbe/base/ngbe_phy_yt.c | 3 + > drivers/net/ngbe/ngbe_ethdev.c | 5 - > drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +- > drivers/net/txgbe/base/meson.build | 2 + > drivers/net/txgbe/base/txgbe.h | 2 + > drivers/net/txgbe/base/txgbe_aml.c | 187 +- > drivers/net/txgbe/base/txgbe_aml.h | 6 +- > drivers/net/txgbe/base/txgbe_aml40.c | 113 +- > drivers/net/txgbe/base/txgbe_aml40.h | 6 +- > drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- > drivers/net/txgbe/base/txgbe_e56.c | 3774 +++++++++++++++++++++ > drivers/net/txgbe/base/txgbe_e56.h | 1744 ++++++++++ > drivers/net/txgbe/base/txgbe_e56_bp.c | 2593 ++++++++++++++ > drivers/net/txgbe/base/txgbe_e56_bp.h | 278 ++ > drivers/net/txgbe/base/txgbe_hw.c | 54 +- > drivers/net/txgbe/base/txgbe_hw.h | 4 +- > drivers/net/txgbe/base/txgbe_osdep.h | 4 + > drivers/net/txgbe/base/txgbe_phy.c | 360 +- > drivers/net/txgbe/base/txgbe_phy.h | 45 +- > drivers/net/txgbe/base/txgbe_regs.h | 11 +- > drivers/net/txgbe/base/txgbe_type.h | 43 +- > drivers/net/txgbe/txgbe_ethdev.c | 414 ++- > drivers/net/txgbe/txgbe_ethdev.h | 6 +- > drivers/net/txgbe/txgbe_rxtx.c | 102 +- > drivers/net/txgbe/txgbe_rxtx.h | 1 + > drivers/net/txgbe/txgbe_rxtx_vec_common.h | 14 +- > 26 files changed, 9350 insertions(+), 434 deletions(-) > create mode 100644 drivers/net/txgbe/base/txgbe_e56.c > create mode 100644 drivers/net/txgbe/base/txgbe_e56.h > create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c > create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h > New files missing SPDX headers must fix. ^ permalink raw reply [flat|nested] 92+ messages in thread
* RE: [PATCH v3 00/20] Wangxun Fixes 2026-05-09 17:07 ` Stephen Hemminger @ 2026-05-11 10:28 ` Zaiyu Wang 0 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:28 UTC (permalink / raw) To: 'Stephen Hemminger'; +Cc: dev > -----Original Message----- > From: Stephen Hemminger <stephen@networkplumber.org> > Sent: Sunday, May 10, 2026 1:07 AM > To: Zaiyu Wang <zaiyuwang@trustnetic.com>; Zaiyu Wang > <zaiyuwang@trustnetic.com> > Cc: dev@dpdk.org; dev@dpdk.org > Subject: Re: [PATCH v3 00/20] Wangxun Fixes > > On Sat, 9 May 2026 19:28:02 +0800 > Zaiyu Wang <zaiyuwang@trustnetic.com> wrote: > > > This series fixes several issues found on Wangxun Emerald, Sapphire > > and Amber-lite NICs, with a focus on link-related problems. > > --- > > v3: > > - Addressed Stephen's comments > > --- > > v2: > > - Fixed compilation error and code style issues > > --- > > > > Zaiyu Wang (20): > > net/txgbe: remove duplicate xstats counters > > net/ngbe: remove duplicate xstats counters > > net/ngbe: add missing CDR config for YT PHY > > net/ngbe: fix VF promiscuous and allmulticast > > net/txgbe: fix inaccuracy in TX rate limiting > > net/txgbe: fix link status check condition > > net/txgbe: fix Tx desc free logic > > net/txgbe: fix link flow control registers for Amber-Lite > > net/txgbe: fix link flow control config for Sapphire > > net/txgbe: fix a mass of unknown interrupts > > net/txgbe: fix traffic class priority configuration > > net/txgbe: fix link stability for 25G NIC > > net/txgbe: fix link stability for 40G NIC > > net/txgbe: fix link stability for Amber-Lite backplane mode > > net/txgbe: fix FEC mode configuration on 25G NIC > > net/txgbe: fix SFP module identification > > net/txgbe: fix get module info operation > > net/txgbe: fix get eeprom operation > > net/txgbe: fix to reset Tx write-back pointer > > net/txgbe: fix to enable Tx desc check > > > > drivers/net/ngbe/base/ngbe_phy_yt.c | 3 + > > drivers/net/ngbe/ngbe_ethdev.c | 5 - > > drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +- > > drivers/net/txgbe/base/meson.build | 2 + > > drivers/net/txgbe/base/txgbe.h | 2 + > > drivers/net/txgbe/base/txgbe_aml.c | 187 +- > > drivers/net/txgbe/base/txgbe_aml.h | 6 +- > > drivers/net/txgbe/base/txgbe_aml40.c | 113 +- > > drivers/net/txgbe/base/txgbe_aml40.h | 6 +- > > drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- > > drivers/net/txgbe/base/txgbe_e56.c | 3774 > +++++++++++++++++++++ > > drivers/net/txgbe/base/txgbe_e56.h | 1744 ++++++++++ > > drivers/net/txgbe/base/txgbe_e56_bp.c | 2593 ++++++++++++++ > > drivers/net/txgbe/base/txgbe_e56_bp.h | 278 ++ > > drivers/net/txgbe/base/txgbe_hw.c | 54 +- > > drivers/net/txgbe/base/txgbe_hw.h | 4 +- > > drivers/net/txgbe/base/txgbe_osdep.h | 4 + > > drivers/net/txgbe/base/txgbe_phy.c | 360 +- > > drivers/net/txgbe/base/txgbe_phy.h | 45 +- > > drivers/net/txgbe/base/txgbe_regs.h | 11 +- > > drivers/net/txgbe/base/txgbe_type.h | 43 +- > > drivers/net/txgbe/txgbe_ethdev.c | 414 ++- > > drivers/net/txgbe/txgbe_ethdev.h | 6 +- > > drivers/net/txgbe/txgbe_rxtx.c | 102 +- > > drivers/net/txgbe/txgbe_rxtx.h | 1 + > > drivers/net/txgbe/txgbe_rxtx_vec_common.h | 14 +- > > 26 files changed, 9350 insertions(+), 434 deletions(-) create mode > > 100644 drivers/net/txgbe/base/txgbe_e56.c > > create mode 100644 drivers/net/txgbe/base/txgbe_e56.h > > create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c > > create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h > > > > New files missing SPDX headers must fix. > Hi Stephen, Thanks for catching this. Apologies for the oversight. I've now gone through the relevant devtools checks and an updated patch set will be sent shortly. ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v4 00/20] Wangxun Fixes 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang ` (19 preceding siblings ...) 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang ` (19 more replies) 20 siblings, 20 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang This series fixes several issues found on Wangxun Emerald, Sapphire and Amber-lite NICs, with a focus on link-related problems. --- v4: - Fixed issues identified by devtools scripts --- v3: - Addressed Stephen's comments --- v2: - Fixed compilation error and code style issues --- Zaiyu Wang (20): net/txgbe: remove duplicate xstats counters net/ngbe: remove duplicate xstats counters net/ngbe: add missing CDR config for YT PHY net/ngbe: fix VF promiscuous and allmulticast net/txgbe: fix inaccuracy in Tx rate limiting net/txgbe: fix link status check condition net/txgbe: fix Tx desc free logic net/txgbe: fix link flow control registers for Amber-Lite net/txgbe: fix link flow control config for Sapphire net/txgbe: fix a mass of unknown interrupts net/txgbe: fix traffic class priority configuration net/txgbe: fix link stability for 25G NIC net/txgbe: fix link stability for 40G NIC net/txgbe: fix link stability for Amber-Lite backplane mode net/txgbe: fix FEC mode configuration on 25G NIC net/txgbe: fix SFP module identification net/txgbe: fix get module info operation net/txgbe: fix get EEPROM operation net/txgbe: fix to reset Tx write-back pointer net/txgbe: fix to enable Tx desc check drivers/net/ngbe/base/ngbe_phy_yt.c | 3 + drivers/net/ngbe/ngbe_ethdev.c | 5 - drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +- drivers/net/txgbe/base/meson.build | 2 + drivers/net/txgbe/base/txgbe.h | 2 + drivers/net/txgbe/base/txgbe_aml.c | 187 +- drivers/net/txgbe/base/txgbe_aml.h | 6 +- drivers/net/txgbe/base/txgbe_aml40.c | 113 +- drivers/net/txgbe/base/txgbe_aml40.h | 6 +- drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- drivers/net/txgbe/base/txgbe_e56.c | 3778 +++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56.h | 1748 ++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.c | 2597 ++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 282 ++ drivers/net/txgbe/base/txgbe_hw.c | 54 +- drivers/net/txgbe/base/txgbe_hw.h | 4 +- drivers/net/txgbe/base/txgbe_osdep.h | 4 + drivers/net/txgbe/base/txgbe_phy.c | 360 +- drivers/net/txgbe/base/txgbe_phy.h | 45 +- drivers/net/txgbe/base/txgbe_regs.h | 11 +- drivers/net/txgbe/base/txgbe_type.h | 43 +- drivers/net/txgbe/txgbe_ethdev.c | 414 ++- drivers/net/txgbe/txgbe_ethdev.h | 6 +- drivers/net/txgbe/txgbe_rxtx.c | 102 +- drivers/net/txgbe/txgbe_rxtx.h | 1 + drivers/net/txgbe/txgbe_rxtx_vec_common.h | 14 +- 26 files changed, 9366 insertions(+), 434 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56.c create mode 100644 drivers/net/txgbe/base/txgbe_e56.h create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h -- 2.21.0.windows.1 ^ permalink raw reply [flat|nested] 92+ messages in thread
* [PATCH v4 01/20] net/txgbe: remove duplicate xstats counters 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 02/20] net/ngbe: " Zaiyu Wang ` (18 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Fixes: 91fe49c87d76 ("net/txgbe: support device xstats") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 5d360f8305..779874aac9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -261,11 +261,6 @@ static const struct rte_txgbe_xstats_name_off rte_txgbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 02/20] net/ngbe: remove duplicate xstats counters 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang ` (17 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Remove four redundant counters (tx_xon_packets, rx_xon_packets, tx_xoff_packets and rx_xoff_packets) from xstats, as they were duplicates of tx_flow_control_xon_packets and others. Both sets were reading the same registers but being output twice under different names. After removing these entries, the flow control counters in DPDK now align with those in our Linux kernel driver. Fixes: 8b433d04adc9 ("net/ngbe: support device xstats") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev.c b/drivers/net/ngbe/ngbe_ethdev.c index 8b9d6371fb..6df53f3266 100644 --- a/drivers/net/ngbe/ngbe_ethdev.c +++ b/drivers/net/ngbe/ngbe_ethdev.c @@ -227,11 +227,6 @@ static const struct rte_ngbe_xstats_name_off rte_ngbe_stats_strings[] = { HW_XSTAT(tx_size_1024_to_max_packets), /* Flow Control */ - HW_XSTAT(tx_xon_packets), - HW_XSTAT(rx_xon_packets), - HW_XSTAT(tx_xoff_packets), - HW_XSTAT(rx_xoff_packets), - HW_XSTAT_NAME(tx_xon_packets, "tx_flow_control_xon_packets"), HW_XSTAT_NAME(rx_xon_packets, "rx_flow_control_xon_packets"), HW_XSTAT_NAME(tx_xoff_packets, "tx_flow_control_xoff_packets"), -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 03/20] net/ngbe: add missing CDR config for YT PHY 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 02/20] net/ngbe: " Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang ` (16 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu According to the PHY vendor, when YT8531S operates in UTP-to-Fiber or RGMII-to-Fiber mode with auto-negotiation disabled (Force mode), additional CDR (Clock Data Recovery) configuration is required to improve link connectivity. Without this config, link may be unstable or fail to establish. Fixes: f1268369403d ("net/ngbe: support autoneg on/off for external PHY SFI mode") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/base/ngbe_phy_yt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ngbe/base/ngbe_phy_yt.c b/drivers/net/ngbe/base/ngbe_phy_yt.c index d110fbc8b2..ab0778d246 100644 --- a/drivers/net/ngbe/base/ngbe_phy_yt.c +++ b/drivers/net/ngbe/base/ngbe_phy_yt.c @@ -264,6 +264,9 @@ s32 ngbe_setup_phy_link_yt(struct ngbe_hw *hw, u32 speed, value = YT_BCR_RESET | YT_BCR_ANE | YT_BCR_RESTART_AN | YT_BCR_DUPLEX | YT_BCR_SPEED_SELECT1; } else { + /* force mode need to config cdr */ + ngbe_write_phy_reg_sds_ext_yt(hw, 0x3, 0, 0x1434); + ngbe_write_phy_reg_sds_ext_yt(hw, 0xe, 0, 0x163); value = YT_BCR_RESET | YT_BCR_DUPLEX; if (speed & NGBE_LINK_SPEED_1GB_FULL) value |= YT_BCR_SPEED_SELECT1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 04/20] net/ngbe: fix VF promiscuous and allmulticast 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (2 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 05/20] net/txgbe: fix inaccuracy in Tx rate limiting Zaiyu Wang ` (15 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The configuration of allmulti and promiscuous modes conflicts together. For instance, if we enable promiscuous mode, then enable and disable allmulti, then the promiscuous mode is wrongly disabled. To resolve this, the following changes are made: - do nothing when we set/unset allmulti if promiscuous mode is on - restore the proper mode (none or allmulti) when we disable promiscuous mode Fixes: 7744e90805b5 ("net/ngbe: add promiscuous and allmulticast ops for VF device") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/ngbe/ngbe_ethdev_vf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/ngbe/ngbe_ethdev_vf.c b/drivers/net/ngbe/ngbe_ethdev_vf.c index 6406df40d0..81511fed8a 100644 --- a/drivers/net/ngbe/ngbe_ethdev_vf.c +++ b/drivers/net/ngbe/ngbe_ethdev_vf.c @@ -1196,9 +1196,13 @@ static int ngbevf_dev_promiscuous_disable(struct rte_eth_dev *dev) { struct ngbe_hw *hw = ngbe_dev_hw(dev); + int mode = NGBEVF_XCAST_MODE_NONE; int ret; - switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_NONE)) { + if (dev->data->all_multicast) + mode = NGBEVF_XCAST_MODE_ALLMULTI; + + switch (hw->mac.update_xcast_mode(hw, mode)) { case 0: ret = 0; break; @@ -1219,7 +1223,7 @@ ngbevf_dev_allmulticast_enable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; - if (dev->data->promiscuous == 1) + if (dev->data->promiscuous) return 0; switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_ALLMULTI)) { @@ -1243,6 +1247,9 @@ ngbevf_dev_allmulticast_disable(struct rte_eth_dev *dev) struct ngbe_hw *hw = ngbe_dev_hw(dev); int ret; + if (dev->data->promiscuous) + return 0; + switch (hw->mac.update_xcast_mode(hw, NGBEVF_XCAST_MODE_MULTI)) { case 0: ret = 0; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 05/20] net/txgbe: fix inaccuracy in Tx rate limiting 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (3 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 06/20] net/txgbe: fix link status check condition Zaiyu Wang ` (14 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Amber-lite NIC's TX rate limiting has large deviations for small packets. To address this, the following changes are made: 1. Set TDM_RL_ADJ (0x1820c) to 21B (includes 7B Ethernet preamble, 1B SFD, 1B EFD, and 12B IPG). 2) Remove the rate offset in the driver (e.g., 105 / 100, a rough compensation value from Linux kernel driver tests). After these changes, accuracy deviation for 64B packets is within ~5%, while large packets show lower deviation. Fixes: a309ab43acf3 ("net/txgbe: support Tx queue rate limiting for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_regs.h | 1 + drivers/net/txgbe/txgbe_ethdev.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 95c585a025..060757323a 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1670,6 +1670,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_TDM_FACTOR_INT_SHIFT 16 #define TXGBE_TDM_FACTOR_FRA_SHIFT 2 +#define TXGBE_TDM_RL_ADJ 0x1820C #define TXGBE_TDM_RL_VM_IDX 0x018218 #define TXGBE_TDM_RL_VM_CFG 0x01821C #define TXGBE_TDM_RL_CFG 0x018400 diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 779874aac9..414107d7a7 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -4314,7 +4314,6 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, u16 frac; link_speed = dev->data->dev_link.link_speed; - tx_rate = tx_rate * 105 / 100; /* Calculate the rate factor values to set */ factor_int = link_speed / tx_rate; frac = (link_speed % tx_rate) * 10000 / tx_rate; @@ -4324,6 +4323,7 @@ txgbe_set_queue_rate_limit(struct rte_eth_dev *dev, factor_fra = 0; } + wr32(hw, TXGBE_TDM_RL_ADJ, 21); wr32(hw, TXGBE_TDM_RL_QUEUE_IDX, queue_idx); wr32m(hw, TXGBE_TDM_RL_QUEUE_CFG, TXGBE_TDM_FACTOR_INT_MASK, factor_int << TXGBE_TDM_FACTOR_INT_SHIFT); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 06/20] net/txgbe: fix link status check condition 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (4 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 05/20] net/txgbe: fix inaccuracy in Tx rate limiting Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang ` (13 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original code incorrectly used 'if (link_up)' instead of 'if (*link_up)', causing the condition to always evaluate to true because the pointer itself is non-NULL. This led to incorrect speed assignment. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 2 +- drivers/net/txgbe/base/txgbe_aml40.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index b376eca5b5..de9a1b1c93 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -67,7 +67,7 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { switch (links_reg & TXGBE_CFG_PORT_ST_AML_LINK_MASK) { case TXGBE_CFG_PORT_ST_AML_LINK_25G: *speed = TXGBE_LINK_SPEED_25GB_FULL; diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 733bbac13a..eefd7119fd 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -68,7 +68,7 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } - if (link_up) { + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) *speed = TXGBE_LINK_SPEED_40GB_FULL; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 07/20] net/txgbe: fix Tx desc free logic 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (5 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 06/20] net/txgbe: fix link status check condition Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang ` (12 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu On some server environments, this driver caused TDM non-fatal errors or PCIe request errors during Tx operation In Amber-Lite NIC's Tx head write-back mode, the hardware periodically writes back a head index pointing to the next descriptor it is adout to process in Tx ring. All descriptors before the head are considered processed by hardware and can be safely freed by the driver. The root cause is that the driver can safely free a batch of descriptors only when the hardware's write-back head pointer has advanced beyond all descriptors in that batch, meaning they have all been processed by the hardware. If the driver frees a descriptor before the hardware has finished processing it, invalid memory access may occur, leading to the observed bug. To fix the issue, correct the boundary check in all three Tx cleanup functions, each of which was missing the proper condition to prevent freeing unprocessed descriptors. Fixes: 8ada71d0bb7f ("net/txgbe: add Tx head write-back mode for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 9 ++++++++- drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index e2cd9b8841..72a4965693 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -100,7 +100,9 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) @@ -652,6 +654,11 @@ txgbe_xmit_cleanup(struct txgbe_tx_queue *txq) /* we have caught up to head, no work left to do */ if (desc_to_clean_to == head) return -(1); + else if (desc_to_clean_to > head && head > last_desc_cleaned) + return -(1); + else if (last_desc_cleaned > desc_to_clean_to && + (head > last_desc_cleaned || head < desc_to_clean_to)) + return -(1); } else { if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) { PMD_TX_FREE_LOG(DEBUG, diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h index 00847d087b..edf3586b77 100644 --- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h +++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h @@ -94,8 +94,11 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq) txq->tx_next_dd - txq->tx_free_thresh; if (tx_last_dd >= txq->nb_tx_desc) tx_last_dd -= txq->nb_tx_desc; - volatile uint16_t head = (uint16_t)*txq->headwb_mem; - if (txq->tx_next_dd > head && head > tx_last_dd) + + volatile uint16_t head = (uint16_t)*txq->headwb_mem; + if (txq->tx_next_dd == head) + return 0; + else if (txq->tx_next_dd > head && head > tx_last_dd) return 0; else if (tx_last_dd > txq->tx_next_dd && (head > tx_last_dd || head < txq->tx_next_dd)) -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 08/20] net/txgbe: fix link flow control registers for Amber-Lite 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (6 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang ` (11 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The flow control counter registers on AML NICs differ from those on SP NICs. Update the register offsets accordingly to ensure the counters work correctly. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 7 ++++++ drivers/net/txgbe/base/txgbe_regs.h | 2 ++ drivers/net/txgbe/base/txgbe_type.h | 4 ++++ drivers/net/txgbe/txgbe_ethdev.c | 34 +++++++++++++++++++---------- 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0f3db3a1ad..0d3310e15c 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -394,6 +394,13 @@ s32 txgbe_clear_hw_cntrs(struct txgbe_hw *hw) rd32(hw, TXGBE_PBTXLNKXON); rd32(hw, TXGBE_PBTXLNKXOFF); + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + wr32(hw, TXGBE_PBRXLNKXON_AML, 0); + wr32(hw, TXGBE_PBRXLNKXOFF_AML, 0); + hw->last_stats.rx_xon_packets = 0; + hw->last_stats.rx_xoff_packets = 0; + } + /* DMA Stats */ rd32(hw, TXGBE_DMARXPKT); rd32(hw, TXGBE_DMATXPKT); diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 060757323a..de382601c9 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -1085,6 +1085,8 @@ enum txgbe_5tuple_protocol { #define TXGBE_PBRXDROP 0x019068 #define TXGBE_PBRXLNKXOFF 0x011988 #define TXGBE_PBRXLNKXON 0x011E0C +#define TXGBE_PBRXLNKXOFF_AML 0x011F80 +#define TXGBE_PBRXLNKXON_AML 0x011F84 #define TXGBE_PBRXUPXON(up) (0x011E30 + (up) * 4) #define TXGBE_PBRXUPXOFF(up) (0x011E10 + (up) * 4) diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index ede780321f..505f598fb7 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -876,6 +876,10 @@ struct txgbe_hw { u64 tx_qp_bytes; u64 rx_qp_mc_packets; } qp_last[TXGBE_MAX_QP]; + struct { + u64 rx_xon_packets; + u64 rx_xoff_packets; + } last_stats; rte_spinlock_t phy_lock; /*amlite: new SW-FW mbox */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 414107d7a7..3ae233f70a 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2264,16 +2264,18 @@ txgbe_dev_reset(struct rte_eth_dev *dev) return ret; } +#define TXGBE_UPDATE_COUNTER_32BIT_GENERIC(reg, last, count, reset) \ + do { \ + uint32_t current = rd32(hw, reg); \ + if ((current) < (last)) \ + current += 0x100000000ULL; \ + if (reset) \ + (last) = current; \ + (count) = (uint32_t)((current) - (last)); \ + } while (0) + #define UPDATE_QP_COUNTER_32bit(reg, last_counter, counter) \ - { \ - uint32_t current_counter = rd32(hw, reg); \ - if (current_counter < last_counter) \ - current_counter += 0x100000000LL; \ - if (!hw->offset_loaded) \ - last_counter = current_counter; \ - counter = current_counter - last_counter; \ - counter &= 0xFFFFFFFFLL; \ - } + TXGBE_UPDATE_COUNTER_32BIT_GENERIC(reg, last_counter, counter, !hw->offset_loaded) #define UPDATE_QP_COUNTER_36bit(reg_lsb, reg_msb, last_counter, counter) \ { \ @@ -2331,8 +2333,18 @@ txgbe_read_stats_registers(struct txgbe_hw *hw, hw_stats->up[i].rx_up_dropped += rd32(hw, TXGBE_PBRXMISS(i)); } - hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); - hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + TXGBE_UPDATE_COUNTER_32BIT_GENERIC(TXGBE_PBRXLNKXON_AML, + hw->last_stats.rx_xon_packets, + hw_stats->rx_xon_packets, !hw->offset_loaded); + TXGBE_UPDATE_COUNTER_32BIT_GENERIC(TXGBE_PBRXLNKXOFF_AML, + hw->last_stats.rx_xoff_packets, + hw_stats->rx_xoff_packets, !hw->offset_loaded); + } else { + hw_stats->rx_xon_packets += rd32(hw, TXGBE_PBRXLNKXON); + hw_stats->rx_xoff_packets += rd32(hw, TXGBE_PBRXLNKXOFF); + } hw_stats->tx_xon_packets += rd32(hw, TXGBE_PBTXLNKXON); hw_stats->tx_xoff_packets += rd32(hw, TXGBE_PBTXLNKXOFF); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 09/20] net/txgbe: fix link flow control config for Sapphire 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (7 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang ` (10 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit SP chips have a hardware bug preventing XON flow control support, so the driver disables it. Fixes: 69ce8c8a4ce3 ("net/txgbe: support flow control") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0d3310e15c..b1a1483dab 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -1037,8 +1037,10 @@ s32 txgbe_fc_enable(struct txgbe_hw *hw) for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { if ((hw->fc.current_mode & txgbe_fc_tx_pause) && hw->fc.high_water[i]) { - fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]) | - TXGBE_FCWTRLO_XON; + fcrtl = TXGBE_FCWTRLO_TH(hw->fc.low_water[i]); + /* SP doesn't support xon */ + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + fcrtl |= TXGBE_FCWTRLO_XON; fcrth = TXGBE_FCWTRHI_TH(hw->fc.high_water[i]) | TXGBE_FCWTRHI_XOFF; } else { -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 10/20] net/txgbe: fix a mass of unknown interrupts 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (8 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang ` (9 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit When RSC is enabled, Rx ring IVAR is set to configure ITR. It causes Rx ring interrupts report on the default msix_vector. Thus a mass of unknown interrupts occupy CPU. Fix the issue by setting ring IVAR only when the rxq interrupt is enabled. Fixes: be797cbf4582 ("net/txgbe: add Rx and Tx init") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 72a4965693..be279dc4ec 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -4354,6 +4354,8 @@ static int txgbe_set_rsc(struct rte_eth_dev *dev) { struct rte_eth_rxmode *rx_conf = &dev->data->dev_conf.rxmode; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = pci_dev->intr_handle; struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct rte_eth_dev_info dev_info = { 0 }; bool rsc_capable = false; @@ -4404,8 +4406,6 @@ txgbe_set_rsc(struct rte_eth_dev *dev) rd32(hw, TXGBE_RXCFG(rxq->reg_idx)); uint32_t psrtype = rd32(hw, TXGBE_POOLRSS(rxq->reg_idx)); - uint32_t eitr = - rd32(hw, TXGBE_ITR(rxq->reg_idx)); /* * txgbe PMD doesn't support header-split at the moment. @@ -4424,6 +4424,9 @@ txgbe_set_rsc(struct rte_eth_dev *dev) srrctl |= txgbe_get_rscctl_maxdesc(rxq->mb_pool); psrtype |= TXGBE_POOLRSS_L4HDR; + wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); + wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); + /* * RSC: Set ITR interval corresponding to 2K ints/s. * @@ -4437,19 +4440,20 @@ txgbe_set_rsc(struct rte_eth_dev *dev) * For a sparse streaming case this setting will yield * at most 500us latency for a single RSC aggregation. */ - eitr &= ~TXGBE_ITR_IVAL_MASK; - eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); - eitr |= TXGBE_ITR_WRDSA; + if (rte_intr_dp_is_en(intr_handle)) { + uint32_t eitr = rd32(hw, TXGBE_ITR(rxq->reg_idx)); - wr32(hw, TXGBE_RXCFG(rxq->reg_idx), srrctl); - wr32(hw, TXGBE_POOLRSS(rxq->reg_idx), psrtype); - wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); + eitr &= ~TXGBE_ITR_IVAL_MASK; + eitr |= TXGBE_ITR_IVAL_10G(TXGBE_QUEUE_ITR_INTERVAL_DEFAULT); + eitr |= TXGBE_ITR_WRDSA; + wr32(hw, TXGBE_ITR(rxq->reg_idx), eitr); - /* - * RSC requires the mapping of the queue to the - * interrupt vector. - */ - txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + /* + * RSC requires the mapping of the queue to the + * interrupt vector. + */ + txgbe_set_ivar_map(hw, 0, rxq->reg_idx, i); + } } dev->data->lro = 1; -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 11/20] net/txgbe: fix traffic class priority configuration 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (9 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang ` (8 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit After applying the following testpmd command, 802.1Q packets with specific priorities were not properly directed to the corresponding traffic classes: port config 0 dcb vt off 4 pfc off The old driver had two issues: 1. The hardware uses a 4-bit mapping register per traffic class for priority-to-TC mapping, but the driver incorrectly configured it as 3 bits. 2. The DCB TX configuration mistakenly wrote to the RX register. Fix both issues, ensuring that tc-prio mapping works as expected. Additionally, remove the stale and inconsistent TXGBE_DCBUP2TC_DEC macro as it has no callers. Fixes: 8bdc7882f376 ("net/txgbe: support DCB") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +- drivers/net/txgbe/base/txgbe_regs.h | 6 ++---- drivers/net/txgbe/txgbe_rxtx.c | 7 ++----- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_dcb_hw.c b/drivers/net/txgbe/base/txgbe_dcb_hw.c index 75c91a6b6a..79e1da447b 100644 --- a/drivers/net/txgbe/base/txgbe_dcb_hw.c +++ b/drivers/net/txgbe/base/txgbe_dcb_hw.c @@ -154,7 +154,7 @@ s32 txgbe_dcb_config_tx_data_arbiter_raptor(struct txgbe_hw *hw, u16 *refill, for (i = 0; i < TXGBE_DCB_UP_MAX; i++) reg |= TXGBE_DCBUP2TC_MAP(i, map[i]); - wr32(hw, TXGBE_PBRXUP2TC, reg); + wr32(hw, TXGBE_PBTXUP2TC, reg); /* Configure traffic class credits and priority */ for (i = 0; i < TXGBE_DCB_TC_MAX; i++) { diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index de382601c9..25aaf8ea68 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -503,10 +503,8 @@ #define TXGBE_PBRXCTL 0x019000 #define TXGBE_PBRXCTL_ST MS(0, 0x1) #define TXGBE_PBRXCTL_ENA MS(31, 0x1) -#define TXGBE_PBRXUP2TC 0x019008 #define TXGBE_PBTXUP2TC 0x01C800 -#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 3 * (tc), 0x7) -#define TXGBE_DCBUP2TC_DEC(tc, r) RS(r, 3 * (tc), 0x7) +#define TXGBE_DCBUP2TC_MAP(tc, v) LS(v, 4 * (tc), 0x7) #define TXGBE_PBRXSIZE(tc) (0x019020 + (tc) * 4) #define TXGBE_PBRXSIZE_KB(v) LS(v, 10, 0x3FF) @@ -1703,7 +1701,7 @@ enum txgbe_5tuple_protocol { #define TXGBE_RDM_PF_HIDE(_i) (0x12090 + ((_i) * 4)) #define TXGBE_RPUP2TC 0x019008 -#define TXGBE_RPUP2TC_UP_SHIFT 3 +#define TXGBE_RPUP2TC_UP_SHIFT 4 #define TXGBE_RPUP2TC_UP_MASK 0x7 #define TXGBE_RDM_DCACHE_CTL 0x0120A8 diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index be279dc4ec..851cd122d8 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -3385,11 +3385,8 @@ txgbe_vmdq_dcb_configure(struct rte_eth_dev *dev) queue_mapping = 0; for (i = 0; i < RTE_ETH_DCB_NUM_USER_PRIORITIES; i++) - /* - * mapping is done with 3 bits per priority, - * so shift by i*3 each time - */ - queue_mapping |= ((cfg->dcb_tc[i] & 0x07) << (i * 3)); + queue_mapping |= ((cfg->dcb_tc[i] & TXGBE_RPUP2TC_UP_MASK) << + (i * TXGBE_RPUP2TC_UP_SHIFT)); wr32(hw, TXGBE_RPUP2TC, queue_mapping); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 12/20] net/txgbe: fix link stability for 25G NIC 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (10 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang ` (7 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe_aml.c | 107 +- drivers/net/txgbe/base/txgbe_aml.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 2493 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56.h | 1746 +++++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 279 +++ drivers/net/txgbe/base/txgbe_hw.c | 35 +- drivers/net/txgbe/base/txgbe_phy.h | 1 - drivers/net/txgbe/base/txgbe_regs.h | 2 + drivers/net/txgbe/base/txgbe_type.h | 12 + drivers/net/txgbe/txgbe_ethdev.c | 83 +- drivers/net/txgbe/txgbe_ethdev.h | 4 + 12 files changed, 4711 insertions(+), 58 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56.c create mode 100644 drivers/net/txgbe/base/txgbe_e56.h create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.h diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index ac4a05005e..305c0291e3 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -12,4 +12,5 @@ base_sources = files( 'txgbe_mng.c', 'txgbe_phy.c', 'txgbe_vf.c', + 'txgbe_e56.c', ) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index de9a1b1c93..008b0245e5 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -12,6 +12,7 @@ #include "txgbe_mng.h" #include "txgbe_hw.h" #include "txgbe_aml.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -23,6 +24,7 @@ void txgbe_init_ops_aml(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml; + phy->setup_link_core = txgbe_setup_phy_link_aml; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml; @@ -175,16 +177,21 @@ void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed) } } -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; - u32 value = 0; + u32 value; + + *need_reset = false; if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { DEBUGOUT("SFP not detected, skip setup mac link"); @@ -197,33 +204,80 @@ s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, if (status) return status; + /* setup the highest link when no autoneg */ + if (!autoneg) { + if (speed & TXGBE_LINK_SPEED_25GB_FULL) + speed = TXGBE_LINK_SPEED_25GB_FULL; + else if (speed & TXGBE_LINK_SPEED_10GB_FULL) + speed = TXGBE_LINK_SPEED_10GB_FULL; + } + speed &= link_capabilities; if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - value = rd32(hw, TXGBE_GPIOEXT); - if (value & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | + TXGBE_SFP1_RX_LOS_LS)) { + DEBUGOUT("RX LOS"); return status; + } - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) { + DEBUGOUT("check phy link_up"); + break; + } + msleep(250); + } - if (link_up && speed == TXGBE_LINK_SPEED_25GB_FULL) + if (speed == TXGBE_LINK_SPEED_25GB_FULL) hw->cur_fec_link = txgbe_phy_fec_get(hw); if (link_speed == speed && link_up && - !(speed == TXGBE_LINK_SPEED_25GB_FULL && - !(hw->fec_mode & hw->cur_fec_link))) - return status; + !(speed == TXGBE_LINK_SPEED_25GB_FULL && + !(hw->fec_mode & hw->cur_fec_link))) + goto out; - if (speed & TXGBE_LINK_SPEED_25GB_FULL) - speed = 0x10; - else if (speed & TXGBE_LINK_SPEED_10GB_FULL) - speed = 0x08; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + + if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE) + goto out; - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) { + hw->link_valid = false; + link_up = false; + goto out; + } else { + hw->link_valid = true; + } + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + } else { + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + DEBUGOUT("MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + DEBUGOUT("MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + DEBUGOUT("Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -269,9 +323,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (10G -> 25G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, + bool need_reset; + + status = hw->phy.setup_link_core(hw, TXGBE_LINK_SPEED_25GB_FULL, - autoneg_wait_to_complete); + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -297,8 +354,12 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* Allow module to change analog characteristics (25G->10G) */ msec_delay(40); - status = hw->mac.setup_mac_link(hw, TXGBE_LINK_SPEED_10GB_FULL, - autoneg_wait_to_complete); + bool need_reset; + + status = hw->phy.setup_link_core(hw, + TXGBE_LINK_SPEED_10GB_FULL, + autoneg_wait_to_complete, + &need_reset); if (status != 0) return status; @@ -348,10 +409,8 @@ void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw) if (hw->phy.multispeed_fiber) { /* Set up dual speed SFP+ support */ mac->setup_link = txgbe_setup_mac_link_multispeed_fiber_aml; - mac->setup_mac_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } else { - mac->setup_link = txgbe_setup_mac_link_aml; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } } diff --git a/drivers/net/txgbe/base/txgbe_aml.h b/drivers/net/txgbe/base/txgbe_aml.h index e98c952787..bfb01b4968 100644 --- a/drivers/net/txgbe/base/txgbe_aml.h +++ b/drivers/net/txgbe/base/txgbe_aml.h @@ -16,7 +16,9 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml(struct txgbe_hw *hw); void txgbe_wait_for_link_up_aml(struct txgbe_hw *hw, u32 speed); -s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml(struct txgbe_hw *hw); #endif /* _TXGBE_AML_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c new file mode 100644 index 0000000000..e4ed1f95fc --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -0,0 +1,2493 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024-2026 Beijing WangXun Technology Co., Ltd. + */ + +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" +#include "../txgbe_logs.h" + +void +set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value) +{ + unsigned int i; + + /* Single bit field handling */ + if (bit_high == bit_low) { + if (set_value == 0) { + /* clear single bit */ + *src_data &= ~(1 << bit_low); + } else { + /* set single bit */ + *src_data |= (1 << bit_low); + } + } else { + /* first, clear the bit fields */ + for (i = bit_low; i <= bit_high; i++) { + /* clear single bit */ + *src_data &= ~(1 << i); + } + + /* second, or the bit fields with set value */ + *src_data |= (set_value << bit_low); + } +} + +/* + * compare function for qsort() + */ +static inline +int txgbe_e56_int_cmp(const void *a, const void *b) +{ + const int *num1 = (const int *)a; + const int *num2 = (const int *)b; + + if (*num1 < *num2) + return -1; + + else if (*num1 > *num2) + return 1; + + else + return 0; +} + +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up) +{ + u32 rdata = 0; + u32 links_reg = 0; + + /* must read it twice because the state may + * not be correct the first time you read it + */ + rdata = rd32_epcs(hw, 0x30001); + rdata = rd32_epcs(hw, 0x30001); + + if (rdata & TXGBE_E56_PHY_LINK_UP) + *link_up = true; + else + *link_up = false; + + if (!hw->link_valid) + *link_up = false; + + links_reg = rd32(hw, TXGBE_PORTSTAT); + if (*link_up) { + if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == + TXGBE_CFG_PORT_ST_AML_LINK_40G) + *speed = TXGBE_LINK_SPEED_40GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == + TXGBE_CFG_PORT_ST_AML_LINK_25G) + *speed = TXGBE_LINK_SPEED_25GB_FULL; + else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == + TXGBE_CFG_PORT_ST_AML_LINK_10G) + *speed = TXGBE_LINK_SPEED_10GB_FULL; + } else { + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + + return 0; +} + +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) +{ + u32 ffe_main = 0, pre1 = 0, pre2 = 0, post = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_MAIN; + pre1 = S25G_TX_FFE_CFG_PRE1; + pre2 = S25G_TX_FFE_CFG_PRE2; + post = S25G_TX_FFE_CFG_POST; + } + } + + if (hw->phy.ffe_set) { + ffe_main = hw->phy.ffe_main; + pre1 = hw->phy.ffe_pre; + pre2 = hw->phy.ffe_pre2; + post = hw->phy.ffe_post; + } + + DEBUGOUT("main = 0x%x, pre1 = 0x%x, pre2 = 0x%x, post = 0x%x", + ffe_main, pre1, pre2, post); + + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_1_ADDR, ffe_main); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_2_ADDR, pre1); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_3_ADDR, pre2); + wr32_ephy(hw, E56G__PMD_TX_FFE_CFG_4_ADDR, post); + + return 0; +} + +int +txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) +{ + int data_code, temp_data, temp_fraction; + u32 rdata; + u32 timer = 0; + + while (1) { + rdata = rd32(hw, 0x1033c); + if (((rdata >> 12) & 0x1) != 0) + break; + if (timer++ > PHYINIT_TIMEOUT) + return -1; + } + + data_code = rdata & 0xFFF; + temp_data = 419400 + 2205 * (data_code * 1000 / 4094 - 500); + + /* Change double Temperature to int */ + *temp = temp_data / 10000; + temp_fraction = temp_data - (*temp * 10000); + if (temp_fraction >= 5000) + *temp += 1; + + return 0; +} + +u32 +txgbe_e56_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + /* change 0x90 to 0x0 to fix 25G link up keep when cable unplugged */ + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S25G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S25G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S25G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S25G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +u32 +txgbe_e56_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_11, ana_test_adc_clkgen_i, 0x0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_test_adc_clkgen_i, + 0x0); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static inline int +txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int addr, rdata, timer; + int T = 40; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int OFFSET_CENTRE_RANGE_H, OFFSET_CENTRE_RANGE_L, RANGE_FINAL; + int i = 0; + int lane_num = 1; + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* + * 2. Define software variable RX_COARSE_MID_TD + * (RX Coarse Code mid value dependent upon temperature) + */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + } + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + lane_num = 4; + + /* 3. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_H */ + for (i = 0; i < lane_num; i++) { + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 4. Do SEQ::RX_ENABLE to enable RXS, and let it stop after oscillator calibration. + * This needs to be done by blocking the RX power-up fsm at the state following + * the oscillator calibration state. + * Follow below steps to do the same before SEQ::RX_ENABLE. + * a. ALIAS::PDIG::CTRL_FSM_RX_ST can be stopped at RX_SAMP_CAL_ST which is the + * state after RX_OSC_CAL_ST by configuring ALIAS::RXS::SAMP_CAL_DONE=0b0 + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + /* Do SEQ::RX_ENABLE to enable RXS */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* b. Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm its value is RX_SAMP_CAL_ST */ + rdata = 0; + timer = 0; + while ((rdata >> (i * 8) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (rdata & (0x100 << i)) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* 5/6.Define software variable as OFFSET_CENTRE_RANGE_H = ALIAS::RXS::COARSE */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_H > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_H = OFFSET_CENTRE_RANGE_H - RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_H = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_H; + + /* + * 7. Do SEQ::RX_DISABLE to disable RXS. + * Poll ALIAS::PDIG::CTRL_FSM_RX_ST and confirm. + */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) + break; + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 8. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, + * it is possible the timeout interrupt is set. + * Clear the same by clearing ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. + * Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + usec_delay(500); + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 9. Program ALIAS::RXS::RANGE_SEL = CMVAR::RANGE_L */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 10. Do SEQ::RX_ENABLE to enable RXS, + * and let it stop after oscillator calibration. + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, (0x1 << i)); + wr32_ephy(hw, addr, rdata); + + /* poll CTRL_FSM_RX_ST */ + timer = 0; + while (((rdata >> (i * 8)) & 0x3f) != 0x9) { + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x100) == 0x100) + break; + + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 11/12.Define software variable as OFFSET_CENTRE_RANGE_L = ALIAS::RXS::COARSE - + * RX_COARSE_MID_TD. Clear the INTR. + */ + rdata = 0; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_L > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_L = OFFSET_CENTRE_RANGE_L - RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_L = RX_COARSE_MID_TD - OFFSET_CENTRE_RANGE_L; + + /* + * 13. Perform below calculation in software. Goal is to pick range value + * which is closer to RX_COARSE_MID_TD. + */ + if (OFFSET_CENTRE_RANGE_L < OFFSET_CENTRE_RANGE_H) + RANGE_FINAL = CMVAR_RANGE_L; + else + RANGE_FINAL = CMVAR_RANGE_H; + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + + timer = 0; + while (1) { + usec_delay(500); + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (((rdata >> (i * 8)) & 0x3f) == 0x21) + break; + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + return -1; + } + } + + /* + * 15. Since RX power-up fsm is stopped in RX_SAMP_CAL_ST, + * it is possible the timeout interrupt is set. Clear the same by clearing + * ALIAS::PDIG::INTR_CTRL_FSM_RX_ERR. Also clear ALIAS::PDIG::INTR_RX_OSC_FREQ_ERR + * which could also be set. + */ + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(500); + wr32_ephy(hw, addr, rdata); + + usec_delay(500); + rdata = 0; + addr = E56PHY_INTR_0_ADDR; + rdata = rd32_ephy(hw, addr); + + /* 16. Program ALIAS::RXS::RANGE_SEL = RANGE_FINAL */ + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I, RANGE_FINAL); + wr32_ephy(hw, addr, rdata); + + /* + * 17. Program following before enabling RXS. Purpose is to disable power-up + * FSM control on ADC offset adaptation. + * Note: this step will be done in 2.3.3 RXS calibration and adaptation sequence + * 18. After this SEQ::RX_ENABLE can be done at any time. Note to ensure that + * ALIAS::RXS::RANGE_SEL = RANGE_FINAL configuration is retained. + * Rmove the OVRDEN on rxs0_rx0_samp_cal_done_o + */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDEN_0_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + } + + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0xf); + else + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x1); + wr32_ephy(hw, addr, rdata); + + return status; +} + +static inline +int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + + unsigned int CMVAR_UFINE_MAX = 0; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + else if (speed == TXGBE_LINK_SPEED_25GB_FULL) + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + + /* a. Assign software defined variables as below */ + /* ii. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE); + /* Set ovrd_en=1 to override ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i, + 1); + /* Wait until 1milliseconds or greater */ + msleep(10); + } + + return status; +} + +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) +{ + int status = 0, i, N, median; + unsigned int rdata; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + + /* Set ovrd_en=0 to read ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + + /* + * As status update from RXS hardware is asynchronous to read status + * of SECOND_ORDER, follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + /* set RXS_BBCDR_SECOND_ORDER_ST[i] = + * RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ + +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + int temperature; + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + PMD_DRV_LOG(ERR, "Error Speed"); + return 0; + } + + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; + + hw->temperature = temperature; + + /* + * Assign software defined variables as below + * a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER + */ + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + /* Set ovrd_en=1 to override ASIC value */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All two of above code updates should be written + * in a single register write + * Set ovrd_en=1 to override ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + /* + * Note: All three of above code updates should be written + * in a single register write + * Set ovrd_en=1 to override ASIC value + */ + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature " + "tracking occurs Error condition"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " + "temperature tracking occurs Error condition"); + } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static inline int +txgbe_e56_rxs_calib_adapt_seq(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypass_ctle = 1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) + bypass_ctle = 0; + + if (hw->mac.type == txgbe_mac_aml) { + msleep(350); + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { + if (rdata & TXGBE_SFP1_MOD_ABS_LS) + DEBUGOUT("E56phyRxsCalibAdaptSeq TXGBE_SFP1_MOD_ABS_LS"); + else if (rdata & TXGBE_SFP1_RX_LOS_LS) + DEBUGOUT("E56phyRxsCalibAdaptSeq TXGBE_SFP1_RX_LOS_LS"); + return TXGBE_ERR_PHY_INIT_NOT_DONE; + } + } + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I + , 0x1); + wr32_ephy(hw, addr, rdata); + + if (bypass_ctle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature + * tracking range here. RXS would be enabled at the end of this sequence. For the case + * when PAM4 KR training is not enabled (including PAM4 mode without KR training), + * wait until ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, + ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + EPHY_RREG(E56G__PMD_CTRL_FSM_RX_STAT_0); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + /* + * 4. Disable VGA and CTLE training so that they don't interfere with ADC calibration + * a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + /* + * 5. Perform ADC interleaver calibration + * a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE + */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O + , 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) & 1) + != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* + * 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (i = 0; i < 16; i++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_gain_adapt_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* + * 7. Perform ADC interleaver adaptation for 10ms or greater, and after that disable it + * a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_intl_adapt_en_i, 0); + + /* + * 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking + * changes in temperature or voltage + * <1> Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + * Set ALIAS::RXS::CTLE_TRAIN_EN = 0b1 + */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + /* + * <2> wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 + * wait for ALIAS::RXS::CTLE_TRAIN_DONE = 1 + */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_vga_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + if (bypass_ctle == 0) { + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o, 0); + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + return status; +} + +static inline u32 +txgbe_e56_cfg_temp(struct txgbe_hw *hw) +{ + u32 status; + u32 value; + int temp; + + status = txgbe_e56_get_temp(hw, &temp); + if (status) + temp = DEFAULT_TEMP; + + if (temp < DEFAULT_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else if (temp > HIGH_TEMP) { + value = rd32_ephy(hw, CMS_ANA_OVRDEN0); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN0, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL2); + set_fields_e56(&value, 20, 16, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL2, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 12, 12, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL7); + set_fields_e56(&value, 8, 4, 0x3); + wr32_ephy(hw, CMS_ANA_OVRDVAL7, value); + } else { + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 4, 4, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL4); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL4, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL5); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDEN1); + set_fields_e56(&value, 23, 23, 0x1); + wr32_ephy(hw, CMS_ANA_OVRDEN1, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL9); + set_fields_e56(&value, 24, 24, 0x1); + set_fields_e56(&value, 31, 29, 0x4); + wr32_ephy(hw, CMS_ANA_OVRDVAL9, value); + + value = rd32_ephy(hw, CMS_ANA_OVRDVAL10); + set_fields_e56(&value, 1, 0, 0x0); + wr32_ephy(hw, CMS_ANA_OVRDVAL10, value); + } + + return 0; +} + +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + + return 0; +} + +/* + * 2.2.10 SEQ::RX_DISABLE + * Use PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 to powerdown specific RXS lanes. + * Completion of RXS powerdown can be confirmed by + * observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST + */ +static int txgbe_e56_disable_rx(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i, 0); + + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + txgbe_e56_ephy_config(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o, 0); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_2); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_2); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_3); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_3); + + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_RREG(E56G__RXS0_DIG_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + EPHY_WREG(E56G__RXS0_DIG_OVRDEN_1); + + /* 2. Disable pattern checker */ + txgbe_e56_ephy_config(E56G__RXS0_DFT_1, ber_en, 0); + + /* 3. Disable internal serial loopback mode */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i, 0); + + /* 4. Enable bypass of clock gates in RXS */ + txgbe_e56_ephy_config(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en, 0x1FFF); + + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0, 0); + + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en, 0); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + while (1) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + if ((rdata & 0x3f) == 0x21) + break; + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) +{ + u32 addr; + u32 rdata; + int status = 0; + + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + + if (hw->mac.type == txgbe_mac_aml) { + rdata = rd32(hw, TXGBE_GPIOEXT); + if (rdata & (TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) + return TXGBE_ERR_TIMEOUT; + } + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, 0x0); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, 0x0); + + /* + * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST + * and confirm its value is POWERDN_ST + */ + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + + addr = E56PHY_INTR_0_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); + + addr = E56PHY_INTR_1_ADDR; + wr32_ephy(hw, addr, E56PHY_INTR_1_IDLE_EXIT1); + + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + hw->mac.enable_sec_tx_path(hw); + + return status; +} + +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) +{ + u32 value = 0; + u32 ppl_lock = false; + int status = 0; + u32 reset = 0; + + DEBUGOUT("port[%d] force set speed: 0x%x", hw->bus.lan_id, speed); + + if ((rd32(hw, TXGBE_EPHY_STAT) & TXGBE_EPHY_STAT_PPL_LOCK) == + TXGBE_EPHY_STAT_PPL_LOCK) { + ppl_lock = true; + wr32m(hw, TXGBE_MACTXCFG, TXGBE_MACTXCFG_TXE, + ~TXGBE_MACTXCFG_TXE); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + ~TXGBE_MACRXCFG_ENA); + + hw->mac.disable_sec_tx_path(hw); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.disable_tx_laser(hw); + + if (hw->bus.lan_id == 0) + reset = TXGBE_RST_EPHY_LAN_0; + + else + reset = TXGBE_RST_EPHY_LAN_1; + + wr32(hw, TXGBE_RST, + reset | rd32(hw, TXGBE_RST)); + txgbe_flush(hw); + usec_delay(10); + + /* XLGPCS REGS Start */ + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + value |= 0x8000; + wr32_epcs(hw, VR_PCS_DIG_CTRL1, value); + + usec_delay(1000); + value = rd32_epcs(hw, VR_PCS_DIG_CTRL1); + if ((value & 0x8000)) { + status = TXGBE_ERR_PHY_INIT_NOT_DONE; + hw->mac.enable_tx_laser(hw); + goto out; + } + + value = rd32_epcs(hw, SR_AN_CTRL); + set_fields_e56(&value, 12, 12, 0); + wr32_epcs(hw, SR_AN_CTRL, value); + + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 5); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 7); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0x39); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + /* Update to 0 for PIN CLKP/N: Enable the termination of the input buffer */ + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x3); + set_fields_e56(&value, 2, 0, 0x3); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x9); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_25g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (speed == TXGBE_LINK_SPEED_10GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_epcs(hw, SR_PMA_CTRL2); + set_fields_e56(&value, 6, 0, 0xb); + wr32_epcs(hw, SR_PMA_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_10g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0x1); /* TX_EN set */ + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + + if (hw->mac.type == txgbe_mac_aml) + hw->mac.enable_tx_laser(hw); + + status = txgbe_e56_config_rx(hw, speed); + + value = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&value, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, value); + + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + if (hw->fec_mode != TXGBE_PHY_FEC_AUTO) { + hw->cur_fec_link = hw->fec_mode; + txgbe_e56_fec_set(hw); + } + +out: + if (ppl_lock) { + hw->mac.enable_sec_tx_path(hw); + wr32m(hw, TXGBE_MACRXCFG, TXGBE_MACRXCFG_ENA, + TXGBE_MACRXCFG_ENA); + } + + return status; +} + +s32 txgbe_e56_fec_set(struct txgbe_hw *hw) +{ + u32 value; + + if (hw->cur_fec_link & TXGBE_PHY_FEC_RS) { + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + + /* enable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 1); + wr32_epcs(hw, 0x100c8, value); + } else if (hw->cur_fec_link & TXGBE_PHY_FEC_BASER) { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* enable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 1); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } else { + /* disable RS FEC */ + wr32_epcs(hw, 0x180a3, 0x7690); + wr32_epcs(hw, 0x180a4, 0x3347); + wr32_epcs(hw, 0x180a5, 0x896f); + wr32_epcs(hw, 0x180a6, 0xccb8); + wr32_epcs(hw, 0x38018, 0x3fff); + value = rd32_epcs(hw, 0x100c8); + set_fields_e56(&value, 2, 2, 0); + wr32_epcs(hw, 0x100c8, value); + + /* disable BASER FEC */ + value = rd32_epcs(hw, SR_PMA_KR_FEC_CTRL); + set_fields_e56(&value, 0, 0, 0); + wr32_epcs(hw, SR_PMA_KR_FEC_CTRL, value); + } + + return 0; +} + +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up) +{ + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + s32 i = 0, j = 0; + + do { + if (!(hw->fec_mode & BIT(j))) { + j += 1; + continue; + } + + hw->cur_fec_link = hw->fec_mode & BIT(j); + + /* + * If in fec auto mode, try another fec mode after no link in 1s + * for lr sfp, enable KR-FEC to link up with mellonax and intel + */ + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_fec_set(hw); + rte_spinlock_unlock(&hw->phy_lock); + + for (i = 0; i < 4; i++) { + msleep(250); + txgbe_e56_check_phy_link(hw, &link_speed, link_up); + if (*link_up) + return 0; + } + j += 1; + } while (j < 3); + + return 0; +} diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h new file mode 100644 index 0000000000..7509526263 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -0,0 +1,1746 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024-2026 Beijing WangXun Technology Co., Ltd. + */ + +#ifndef _TXGBE_E56_H_ +#define _TXGBE_E56_H_ + +#include "txgbe_type.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" + +#define EPHY_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_ephy(hw, REG##_ADDR); \ + } while (0) + +#define EPCS_RREG(REG) \ + do {\ + rdata = 0; \ + rdata = rd32_epcs(hw, REG##_ADDR); \ + } while (0) + +#define EPHY_WREG(REG) wr32_ephy(hw, REG##_ADDR, rdata) +#define EPCS_WREG(REG) wr32_epcs(hw, REG##_ADDR, rdata) + +#define txgbe_e56_ephy_config(reg, field, val) \ + do { \ + EPHY_RREG(reg); \ + EPHY_XFLD(reg, field) = (val); \ + EPHY_WREG(reg); \ + } while (0) + +#define txgbe_e56_epcs_config(reg, field, val) \ + do { \ + EPCS_RREG(reg); \ + EPCS_XFLD(reg, field) = (val); \ + EPCS_WREG(reg); \ + } while (0) + +/* + * LAN GPIO define for SFP+ module + * -- Fields + */ +#define SFP1_RS0 5, 5 +#define SFP1_RS1 4, 4 +#define SFP1_RX_LOS 3, 3 +#define SFP1_MOD_ABS 2, 2 +#define SFP1_TX_DISABLE 1, 1 +#define SFP1_TX_FAULT 0, 0 + +#define EPHY_XFLD(REG, FLD) (((REG *)&rdata)->FLD) +#define EPCS_XFLD(REG, FLD) (((REG *)&rdata)->FLD) + +typedef union { + struct { + u32 ana_refclk_buf_daisy_en_i : 1; + u32 ana_refclk_buf_pad_en_i : 1; + u32 ana_vddinoff_dcore_dig_o : 1; + u32 ana_lcpll_en_clkout_hf_left_top_i : 1; + u32 ana_lcpll_en_clkout_hf_right_top_i : 1; + u32 ana_lcpll_en_clkout_hf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_hf_right_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_left_top_i : 1; + u32 ana_lcpll_en_clkout_lf_right_top_i : 1; + u32 ana_lcpll_en_clkout_lf_left_bot_i : 1; + u32 ana_lcpll_en_clkout_lf_right_bot_i : 1; + u32 ana_bg_en_i : 1; + u32 ana_en_rescal_i : 1; + u32 ana_rescal_comp_o : 1; + u32 ana_en_ldo_core_i : 1; + u32 ana_lcpll_hf_en_bias_i : 1; + u32 ana_lcpll_hf_en_loop_i : 1; + u32 ana_lcpll_hf_en_cp_i : 1; + u32 ana_lcpll_hf_set_lpf_i : 1; + u32 ana_lcpll_hf_en_vco_i : 1; + u32 ana_lcpll_hf_vco_amp_status_o : 1; + u32 ana_lcpll_hf_en_odiv_i : 1; + u32 ana_lcpll_lf_en_bias_i : 1; + u32 ana_lcpll_lf_en_loop_i : 1; + u32 ana_lcpll_lf_en_cp_i : 1; + u32 ana_lcpll_lf_set_lpf_i : 1; + u32 ana_lcpll_lf_en_vco_i : 1; + u32 ana_lcpll_lf_vco_amp_status_o : 1; + u32 ana_lcpll_lf_en_odiv_i : 1; + u32 ana_lcpll_hf_refclk_select_i : 1; + u32 ana_lcpll_lf_refclk_select_i : 1; + u32 rsvd0 : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_0; + +/* AMLITE ETH PHY Registers */ +#define VR_PCS_DIG_CTRL1 0x38000 +#define SR_PCS_CTRL1 0x30000 +#define SR_PCS_CTRL2 0x30007 +#define SR_PMA_CTRL2 0x10007 +#define VR_PCS_DIG_CTRL3 0x38003 +#define VR_PMA_CTRL3 0x180a8 +#define VR_PMA_CTRL4 0x180a9 +#define SR_PMA_RS_FEC_CTRL 0x100c8 +#define CMS_ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN0 0xca4 +#define ANA_OVRDEN1 0xca8 +#define ANA_OVRDVAL0 0xcb0 +#define ANA_OVRDVAL5 0xcc4 +#define OSC_CAL_N_CDR4 0x14 +#define PLL0_CFG0 0xc10 +#define PLL0_CFG2 0xc18 +#define PLL0_DIV_CFG0 0xc1c +#define PLL1_CFG0 0xc48 +#define PLL1_CFG2 0xc50 +#define CMS_PIN_OVRDEN0 0xc8c +#define CMS_PIN_OVRDVAL0 0xc94 +#define DATAPATH_CFG0 0x142c +#define DATAPATH_CFG1 0x1430 +#define AN_CFG1 0x1438 +#define SPARE52 0x16fc +#define RXS_CFG0 0x000 +#define PMD_CFG0 0x1400 +#define SR_PCS_STS1 0x30001 +#define PMD_CTRL_FSM_TX_STAT0 0x14dc +#define CMS_ANA_OVRDEN0 0xca4 +#define CMS_ANA_OVRDEN1 0xca8 +#define CMS_ANA_OVRDVAL2 0xcb8 +#define CMS_ANA_OVRDVAL4 0xcc0 +#define CMS_ANA_OVRDVAL5 0xcc4 +#define CMS_ANA_OVRDVAL7 0xccc +#define CMS_ANA_OVRDVAL9 0xcd4 +#define CMS_ANA_OVRDVAL10 0xcd8 + +#define TXS_TXS_CFG1 0x804 +#define TXS_WKUP_CNT 0x808 +#define TXS_PIN_OVRDEN0 0x80c +#define TXS_PIN_OVRDVAL6 0x82c +#define TXS_ANA_OVRDVAL1 0x854 + +#define E56PHY_CMS_BASE_ADDR 0x0C00 + +#define E56PHY_CMS_PIN_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x8C) +#define E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I 12, 12 + +#define E56PHY_CMS_PIN_OVRDVAL_0_ADDR (E56PHY_CMS_BASE_ADDR + 0x94) +#define E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I 10, 10 + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) + +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I 29, 29 + +#define E56PHY_CMS_ANA_OVRDEN_1_ADDR (E56PHY_CMS_BASE_ADDR + 0xA8) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I 4, 4 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ADDR (E56PHY_CMS_BASE_ADDR + 0xB8) + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I 31, 28 + +#define E56PHY_CMS_ANA_OVRDVAL_4_ADDR (E56PHY_CMS_BASE_ADDR + 0xC0) + +#define E56PHY_TXS_BASE_ADDR 0x0800 +#define E56PHY_TXS1_BASE_ADDR 0x0900 +#define E56PHY_TXS2_BASE_ADDR 0x0A00 +#define E56PHY_TXS3_BASE_ADDR 0x0B00 +#define E56PHY_TXS_OFFSET 0x0100 + +#define E56PHY_PMD_RX_OFFSET 0x02C + +#define E56PHY_TXS_TXS_CFG_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x04) +#define E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256 7, 4 +#define E56PHY_TXS_WKUP_CNT_ADDR (E56PHY_TXS_BASE_ADDR + 0x08) +#define E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32 7, 0 +#define E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32 15, 8 + +#define E56PHY_TXS_PIN_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x0C) +#define E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I 28, 28 + +#define E56PHY_TXS_PIN_OVRDVAL_6_ADDR (E56PHY_TXS_BASE_ADDR + 0x2C) + +#define E56PHY_TXS_ANA_OVRDVAL_1_ADDR (E56PHY_TXS_BASE_ADDR + 0x54) +#define E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I 23, 8 + +#define E56PHY_TXS_ANA_OVRDEN_0_ADDR (E56PHY_TXS_BASE_ADDR + 0x44) +#define E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I 13, 13 + +#define E56PHY_RXS_BASE_ADDR 0x0000 +#define E56PHY_RXS1_BASE_ADDR 0x0200 +#define E56PHY_RXS2_BASE_ADDR 0x0400 +#define E56PHY_RXS3_BASE_ADDR 0x0600 +#define E56PHY_RXS_OFFSET 0x0200 + +#define E56PHY_RXS_RXS_CFG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x000) +#define E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL 1, 1 +#define E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN 17, 4 + +#define E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x008) +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1 15, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1_LSB 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1 31, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1_LSB 16 + +#define E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x014) +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT 18, 8 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1 21, 21 +#define E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1 27, 26 + +#define E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x018) +#define E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH 3, 2 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK 15, 12 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK 19, 16 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK 23, 20 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK 27, 24 +#define E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT 30, 28 + +#define E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x01C) +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK 3, 0 +#define E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK 7, 4 + +#define E56PHY_RXS_INTL_CONFIG_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x020) +#define E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1 31, 16 + +#define E56PHY_RXS_INTL_CONFIG_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x028) +#define E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1 1, 1 + +#define E56PHY_RXS_TXFFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x02C) +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH 18, 12 +#define E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH 26, 20 + +#define E56PHY_RXS_TXFFE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x030) +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x034) +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH 20, 12 + +#define E56PHY_RXS_TXFFE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x038) +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH 8, 0 +#define E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH 20, 12 +#define E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE 26, 21 + +#define E56PHY_RXS_VGA_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x04C) +#define E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET 18, 12 + +#define E56PHY_RXS_VGA_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x050) +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0 4, 0 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0 12, 8 +#define E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123 20, 16 +#define E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123 28, 24 + +#define E56PHY_RXS_CTLE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x054) +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0 24, 20 +#define E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123 31, 27 + +#define E56PHY_RXS_CTLE_TRAINING_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x058) +#define E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT 24, 0 + +#define E56PHY_RXS_CTLE_TRAINING_2_ADDR (E56PHY_RXS_BASE_ADDR + 0x05C) +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1 5, 0 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2 13, 8 +#define E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3 21, 16 + +#define E56PHY_RXS_CTLE_TRAINING_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x060) +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1 9, 8 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2 11, 10 +#define E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3 13, 12 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x064) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT 5, 4 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT 9, 8 +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8 31, 28 + +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x068) +#define E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG 31, 28 + +#define E56PHY_RXS_FFE_TRAINING_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x070) +#define E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN 23, 8 + +#define E56PHY_RXS_IDLE_DETECT_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x088) +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX 22, 16 +#define E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN 30, 24 + +#define E56PHY_RXS_ANA_OVRDEN_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x08C) +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_TRIM_RTERM_I 1, 1 +#define E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_BBCDR_OSC_RANGE_SEL_I 29, 29 + +#define E56PHY_RXS_ANA_OVRDEN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x090) +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I 0, 0 +#define E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I 9, 9 + +#define E56PHY_RXS_ANA_OVRDEN_3_ADDR (E56PHY_RXS_BASE_ADDR + 0x098) +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I 15, 15 +#define E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I 25, 25 + +#define E56PHY_RXS_ANA_OVRDEN_4_ADDR (E56PHY_RXS_BASE_ADDR + 0x09C) +#define E56PHY_RXS_ANA_OVRDVAL_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x0A0) +#define E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I 0, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_6_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B8) +#define E56PHY_RXS_ANA_OVRDVAL_14_ADDR (E56PHY_RXS_BASE_ADDR + 0x0D8) +#define E56PHY_RXS_ANA_OVRDVAL_15_ADDR (E56PHY_RXS_BASE_ADDR + 0x0DC) +#define E56PHY_RXS_ANA_OVRDVAL_17_ADDR (E56PHY_RXS_BASE_ADDR + 0x0E4) +#define E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I 18, 16 + +#define E56PHY_RXS_EYE_SCAN_1_ADDR (E56PHY_RXS_BASE_ADDR + 0x1A4) +#define E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER 31, 0 + +#define E56PHY_RXS_ANA_OVRDVAL_5_ADDR (E56PHY_RXS_BASE_ADDR + 0x0B4) +#define E56PHY_RXS_ANA_OVRDVAL_5_ANA_BBCDR_OSC_RANGE_SEL_I 1, 0 + +#define E56PHY_RXS_RINGO_0_ADDR (E56PHY_RXS_BASE_ADDR + 0x1FC) + +#define E56PHY_PMD_BASE_ADDR 0x1400 +#define E56PHY_PMD_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x000) +#define E56PHY_PMD_CFG_0_RX_EN_CFG 19, 16 + +#define E56PHY_PMD_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x00C) +#define E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K 31, 24 +#define E56PHY_PMD_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x010) +#define E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K 7, 0 +#define E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K 15, 8 +#define E56PHY_PMD_CFG_5_ADDR (E56PHY_PMD_BASE_ADDR + 0x014) +#define E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET 12, 12 +#define E56PHY_CTRL_FSM_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x040) +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_OFST_CAL_ERR 4, 4 +#define E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR 5, 5 +#define E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL 9, 8 +#define E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN 31, 24 + +#define E56PHY_CTRL_FSM_CFG_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x044) +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x048) +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_3_ADDR (E56PHY_PMD_BASE_ADDR + 0x04C) +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096 7, 0 + +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_4_ADDR (E56PHY_PMD_BASE_ADDR + 0x050) +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096 7, 0 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096 15, 8 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096 23, 16 +#define E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096 31, 24 + +#define E56PHY_CTRL_FSM_CFG_7_ADDR (E56PHY_PMD_BASE_ADDR + 0x05C) +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_8_ADDR (E56PHY_PMD_BASE_ADDR + 0x060) +#define E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_12_ADDR (E56PHY_PMD_BASE_ADDR + 0x070) +#define E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_13_ADDR (E56PHY_PMD_BASE_ADDR + 0x074) +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN 15, 0 +#define E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_14_ADDR (E56PHY_PMD_BASE_ADDR + 0x078) +#define E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_15_ADDR (E56PHY_PMD_BASE_ADDR + 0x07C) +#define E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_17_ADDR (E56PHY_PMD_BASE_ADDR + 0x084) +#define E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_18_ADDR (E56PHY_PMD_BASE_ADDR + 0x088) +#define E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN 15, 0 + +#define E56PHY_CTRL_FSM_CFG_29_ADDR (E56PHY_PMD_BASE_ADDR + 0x0B4) +#define E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN 31, 16 + +#define E56PHY_CTRL_FSM_CFG_33_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C4) +#define E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_CFG_34_ADDR (E56PHY_PMD_BASE_ADDR + 0x0C8) +#define E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL 15, 0 +#define E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL 31, 16 + +#define E56PHY_CTRL_FSM_RX_STAT_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x0FC) +#define E56PHY_RXS0_OVRDEN_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x130) +#define E56PHY_RXS0_OVRDEN_0_OVRD_EN_RXS0_RX0_SAMP_CAL_DONE_O 27, 27 + +#define E56PHY_RXS0_OVRDEN_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x134) +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I 14, 14 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I 16, 16 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CDR_EN_I 18, 18 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I 23, 23 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O 24, 24 +#define E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 24 + +#define E56PHY_RXS0_OVRDEN_2_ADDR (E56PHY_PMD_BASE_ADDR + 0x138) +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I 0, 0 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 3, 3 +#define E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I 6, 6 + +#define E56PHY_RXS0_OVRDVAL_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x140) +#define E56PHY_RXS0_OVRDVAL_0_RXS0_RX0_SAMP_CAL_DONE_O 22, 22 + +#define E56PHY_RXS0_OVRDVAL_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x144) +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I 7, 7 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I 9, 9 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CDR_EN_I 11, 11 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I 16, 16 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O 17, 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB 17 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I 25, 25 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I 28, 28 +#define E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I 31, 31 + +#define E56PHY_INTR_0_IDLE_ENTRY1 0x10000000 +#define E56PHY_INTR_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x1EC) +#define E56PHY_INTR_0_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E0) + +#define E56PHY_INTR_1_IDLE_EXIT1 0x1 +#define E56PHY_INTR_1_ADDR (E56PHY_PMD_BASE_ADDR + 0x1F0) +#define E56PHY_INTR_1_ENABLE_ADDR (E56PHY_PMD_BASE_ADDR + 0x1E4) + +#define E56PHY_KRT_TFSM_CFG_ADDR (E56PHY_PMD_BASE_ADDR + 0x2B8) +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K 7, 0 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K 15, 8 +#define E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K 23, 16 + +#define E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR (E56PHY_PMD_BASE_ADDR + 0x2BC) +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2 9, 8 +#define E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_3 13, 12 + +#define PHYINIT_TIMEOUT 1000 /* PHY initialization timeout value in 0.5ms unit */ + +#define E56G__BASEADDR 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_7; +#define E56G_CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G_CMS_ANA_OVRDEN_1; + +#define E56G_CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G_CMS_ANA_OVRDVAL_9; + +#define E56G_CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_vcofilt_byp_i : 1; + u32 ovrd_en_ana_bbcdr_coarse_i : 1; + u32 ovrd_en_ana_bbcdr_fine_i : 1; + u32 ovrd_en_ana_bbcdr_ultrafine_i : 1; + u32 ovrd_en_ana_en_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_divctrl_i : 1; + u32 ovrd_en_ana_bbcdr_int_cstm_i : 1; + u32 ovrd_en_ana_bbcdr_prop_step_i : 1; + u32 ovrd_en_ana_en_bbcdr_clk_i : 1; + u32 ovrd_en_ana_test_bbcdr_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ovrd_en_ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_rdout_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ovrd_en_ana_bbcdr_elv_cnt_pong_270_o : 1; + u32 ovrd_en_ana_en_bbcdr_samp_dac_i : 1; + u32 ovrd_en_ana_bbcdr_dac0_i : 1; + u32 ovrd_en_ana_bbcdr_dac90_i : 1; + u32 ovrd_en_ana_vga2_cload_in_cstm_i : 1; + u32 ovrd_en_ana_intlvr_cut_bw_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_1; + +#define E56G__RXS0_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0x90) + +typedef union { + struct { + u32 prediv0 : 16; + u32 target_cnt0 : 16; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_0; + +#define E56G_RXS0_OSC_CAL_N_CDR_0_ADDR (E56G__BASEADDR + 0x4) + +typedef union { + struct { + u32 osc_range_sel0 : 2; + u32 osc_range_sel1 : 2; + u32 osc_range_sel2 : 2; + u32 osc_range_sel3 : 2; + u32 vco_code_init : 11; + u32 calibrate_range_sel : 1; + u32 osc_current_boost_en0 : 1; + u32 osc_current_boost_en1 : 1; + u32 osc_current_boost_en2 : 1; + u32 osc_current_boost_en3 : 1; + u32 bbcdr_current_boost0 : 2; + u32 bbcdr_current_boost1 : 2; + u32 bbcdr_current_boost2 : 2; + u32 bbcdr_current_boost3 : 2; + }; + u32 reg; +} E56G_RXS0_OSC_CAL_N_CDR_4; + +#define E56G_RXS0_OSC_CAL_N_CDR_4_ADDR (E56G__BASEADDR + 0x14) + +typedef union { + struct { + u32 adc_intl2slice_delay0 : 16; + u32 adc_intl2slice_delay1 : 16; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_0; + +#define E56G_RXS0_INTL_CONFIG_0_ADDR (E56G__BASEADDR + 0x20) + +typedef union { + struct { + u32 interleaver_hbw_disable0 : 1; + u32 interleaver_hbw_disable1 : 1; + u32 interleaver_hbw_disable2 : 1; + u32 interleaver_hbw_disable3 : 1; + u32 rsvd0 : 28; + }; + u32 reg; +} E56G_RXS0_INTL_CONFIG_2; + +#define E56G_RXS0_INTL_CONFIG_2_ADDR (E56G__BASEADDR + 0x28) + +typedef union { + struct { + u32 ovrd_en_ana_bbcdr_dac180_i : 1; + u32 ovrd_en_ana_bbcdr_dac270_i : 1; + u32 ovrd_en_ana_bbcdr_en_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_clrz_samp_cal_cnt_i : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_0_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_90_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_180_o : 1; + u32 ovrd_en_ana_bbcdr_samp_cnt_270_o : 1; + u32 ovrd_en_ana_en_adcbuf1_i : 1; + u32 ovrd_en_ana_test_adcbuf1_i : 1; + u32 ovrd_en_ana_en_adc_clk4ui_i : 1; + u32 ovrd_en_ana_adc_clk_skew0_i : 1; + u32 ovrd_en_ana_adc_clk_skew90_i : 1; + u32 ovrd_en_ana_adc_clk_skew180_i : 1; + u32 ovrd_en_ana_adc_clk_skew270_i : 1; + u32 ovrd_en_ana_adc_update_skew_i : 1; + u32 ovrd_en_ana_en_adc_pi_i : 1; + u32 ovrd_en_ana_adc_pictrl_quad_i : 1; + u32 ovrd_en_ana_adc_pctrl_code_i : 1; + u32 ovrd_en_ana_adc_clkdiv_i : 1; + u32 ovrd_en_ana_test_adc_clkgen_i : 1; + u32 ovrd_en_ana_en_adc_i : 1; + u32 ovrd_en_ana_en_adc_vref_i : 1; + u32 ovrd_en_ana_vref_cnfg_i : 1; + u32 ovrd_en_ana_adc_data_cstm_o : 1; + u32 ovrd_en_ana_en_adccal_lpbk_i : 1; + u32 ovrd_en_ana_sel_adcoffset_cal_i : 1; + u32 ovrd_en_ana_sel_adcgain_cal_i : 1; + u32 ovrd_en_ana_adcgain_cal_swing_ctrl_i : 1; + u32 ovrd_en_ana_adc_gain_i : 1; + u32 ovrd_en_ana_vga_cload_out_cstm_i : 1; + u32 ovrd_en_ana_vga2_cload_out_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_2; + +#define E56G__RXS0_ANA_OVRDEN_2_ADDR (E56G__BASEADDR + 0x94) + +typedef union { + struct { + u32 ovrd_en_ana_adc_offset_i : 1; + u32 ovrd_en_ana_adc_slice_addr_i : 1; + u32 ovrd_en_ana_slice_wr_i : 1; + u32 ovrd_en_ana_test_adc_i : 1; + u32 ovrd_en_ana_test_adc_o : 1; + u32 ovrd_en_ana_spare_o : 8; + u32 ovrd_en_ana_sel_lpbk_i : 1; + u32 ovrd_en_ana_ana_debug_sel_i : 1; + u32 ovrd_en_ana_anabs_config_i : 1; + u32 ovrd_en_ana_en_anabs_i : 1; + u32 ovrd_en_ana_anabs_rxn_o : 1; + u32 ovrd_en_ana_anabs_rxp_o : 1; + u32 ovrd_en_ana_dser_clk_en_i : 1; + u32 ovrd_en_ana_dser_clk_config_i : 1; + u32 ovrd_en_ana_en_mmcdr_clk_obs_i : 1; + u32 ovrd_en_ana_skew_coarse0_fine1_i : 1; + u32 ovrd_en_ana_vddinoff_acore_dig_o : 1; + u32 ovrd_en_ana_vddinoff_dcore_dig_o : 1; + u32 ovrd_en_ana_vga2_boost_cstm_i : 1; + u32 ovrd_en_ana_adc_sel_vbgr_bias_i : 1; + u32 ovrd_en_ana_adc_nbuf_cnfg_i : 1; + u32 ovrd_en_ana_adc_pbuf_cnfg_i : 1; + u32 rsvd0 : 3; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_3; + +#define E56G__RXS0_ANA_OVRDEN_3_NUM 1 +#define E56G__RXS0_ANA_OVRDEN_3_ADDR (E56G__BASEADDR + 0x98) + +typedef union { + struct { + u32 pam4_ab_swap_en : 1; + u32 dser_data_sel : 1; + u32 signal_type : 1; + u32 precode_en : 1; + u32 train_clk_gate_bypass_en : 14; + u32 rsvd0 : 14; + }; + u32 reg; +} E56G__RXS0_RXS_CFG_0; + +#define E56G__RXS0_RXS_CFG_0_NUM 1 +#define E56G__RXS0_RXS_CFG_0_ADDR (E56G__BASEADDR + 0x0) + +typedef union { + struct { + u32 restart_training_ln0 : 1; + u32 training_enable_ln0 : 1; + u32 restart_training_ln1 : 1; + u32 training_enable_ln1 : 1; + u32 restart_training_ln2 : 1; + u32 training_enable_ln2 : 1; + u32 restart_training_ln3 : 1; + u32 training_enable_ln3 : 1; + u32 rsvd0 : 24; + }; + u32 reg; +} E56G__PMD_BASER_PMD_CONTROL; + +#define E56G__PMD_BASER_PMD_CONTROL_NUM 1 +#define E56G__PMD_BASER_PMD_CONTROL_ADDR (E56G__BASEADDR + 0x1640) + +typedef union { + struct { + u32 rx_to_tx_lpbk_en : 4; + u32 sel_wp_pmt_out : 4; + u32 sel_wp_pmt_clkout : 4; + u32 use_recent_marker_offset : 1; + u32 interrupt_debug_mode : 1; + u32 rsvd0 : 2; + u32 tx_ffe_coeff_update : 4; + u32 rsvd1 : 12; + }; + u32 reg; +} E56G__PMD_PMD_CFG_5; + +#define E56G__PMD_PMD_CFG_5_NUM 1 +#define E56G__PMD_PMD_CFG_5_ADDR (E56G__BASEADDR + 0x1414) + +typedef union { + struct { + u32 soft_reset : 1; + u32 pmd_en : 1; + u32 rsvd0 : 2; + u32 pll_refclk_sel : 2; + u32 rsvd1 : 2; + u32 pmd_mode : 1; + u32 rsvd2 : 3; + u32 tx_en_cfg : 4; + u32 rx_en_cfg : 4; + u32 pll_en_cfg : 2; + u32 rsvd3 : 2; + u32 pam4_precode_no_krt_en : 4; + u32 rsvd4 : 4; + }; + u32 reg; +} E56G__PMD_PMD_CFG_0; + +#define E56G__PMD_PMD_CFG_0_NUM 1 +#define E56G__PMD_PMD_CFG_0_ADDR (E56G__BASEADDR + 0x1400) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_rstn_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_divctrl_i : 1; + u32 ovrd_en_rxs0_rx0_bitclk_rate_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_width_i : 1; + u32 ovrd_en_rxs0_rx0_symdata_o : 1; + u32 ovrd_en_rxs0_rx0_precode_en_i : 1; + u32 ovrd_en_rxs0_rx0_signal_type_i : 1; + u32 ovrd_en_rxs0_rx0_sync_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_sync_o : 1; + u32 ovrd_en_rxs0_rx0_rate_select_i : 1; + u32 ovrd_en_rxs0_rx0_rterm_en_i : 1; + u32 ovrd_en_rxs0_rx0_bias_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_en_i : 1; + u32 ovrd_en_rxs0_rx0_ldo_rdy_i : 1; + u32 ovrd_en_rxs0_rx0_blwc_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_sel_i : 1; + u32 ovrd_en_rxs0_rx0_osc_en_i : 1; + u32 ovrd_en_rxs0_rx0_clkgencdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctlecdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_osc_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_osc_freq_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_samp_cal_err_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_cal_error_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_0; + +#define E56G__PMD_RXS0_OVRDEN_0_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_0_ADDR (E56G__BASEADDR + 0x1530) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_sparein_i : 8; + u32 ovrd_en_rxs0_rx0_spareout_o : 8; + u32 rsvd0 : 16; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_3; + +#define E56G__PMD_RXS0_OVRDEN_3_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_3_ADDR (E56G__BASEADDR + 0x153c) + +typedef union { + struct { + u32 vco_code_cont_adj_done_ovrd_en : 1; + u32 dfe_coeffl_ovrd_en : 1; + u32 dfe_coeffh_ovrd_en : 1; + u32 rsvd0 : 1; + u32 top_comp_th_ovrd_en : 1; + u32 mid_comp_th_ovrd_en : 1; + u32 bot_comp_th_ovrd_en : 1; + u32 rsvd1 : 1; + u32 level_target_ovrd_en : 4; + u32 ffe_coeff_c0to3_ovrd_en : 4; + u32 ffe_coeff_c4to7_ovrd_en : 4; + u32 ffe_coeff_c8to11_ovrd_en : 4; + u32 ffe_coeff_c12to15_ovrd_en : 4; + u32 ffe_coeff_update_ovrd_en : 1; + u32 rsvd2 : 3; + }; + u32 reg; +} E56G__RXS0_DIG_OVRDEN_1; + +#define E56G__RXS0_DIG_OVRDEN_1_NUM 1 +#define E56G__RXS0_DIG_OVRDEN_1_ADDR (E56G__BASEADDR + 0x160) + +typedef union { + struct { + u32 ber_en : 1; + u32 rsvd0 : 3; + u32 read_mode_en : 1; + u32 rsvd1 : 3; + u32 err_cnt_mode_all0_one1 : 1; + u32 rsvd2 : 3; + u32 init_lfsr_mode_continue0_restart1 : 1; + u32 rsvd3 : 3; + u32 pattern_sel : 4; + u32 rsvd4 : 12; + }; + u32 reg; +} E56G__RXS0_DFT_1; + +#define E56G__RXS0_DFT_1_NUM 1 +#define E56G__RXS0_DFT_1_ADDR (E56G__BASEADDR + 0xec) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_adapt_error_o : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_samp_th_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_efuse_bits_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_in_i : 1; + u32 ovrd_en_rxs0_rx0_wp_pmt_out_o : 1; + u32 rsvd0 : 15; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_2; + +#define E56G__PMD_RXS0_OVRDEN_2_ADDR (E56G__BASEADDR + 0x1538) + +typedef union { + struct { + u32 ana_bbcdr_osc_range_sel_i : 2; + u32 rsvd0 : 2; + u32 ana_bbcdr_coarse_i : 4; + u32 ana_bbcdr_fine_i : 3; + u32 rsvd1 : 1; + u32 ana_bbcdr_ultrafine_i : 3; + u32 rsvd2 : 1; + u32 ana_bbcdr_divctrl_i : 2; + u32 rsvd3 : 2; + u32 ana_bbcdr_int_cstm_i : 5; + u32 rsvd4 : 3; + u32 ana_bbcdr_prop_step_i : 4; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_5; + +#define E56G__RXS0_ANA_OVRDVAL_5_ADDR (E56G__BASEADDR + 0xb4) + +typedef union { + struct { + u32 ana_adc_pictrl_quad_i : 2; + u32 rsvd0 : 2; + u32 ana_adc_clkdiv_i : 2; + u32 rsvd1 : 2; + u32 ana_test_adc_clkgen_i : 4; + u32 ana_vref_cnfg_i : 4; + u32 ana_adcgain_cal_swing_ctrl_i : 4; + u32 ana_adc_gain_i : 4; + u32 ana_adc_offset_i : 4; + u32 ana_ana_debug_sel_i : 4; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_11; + +#define E56G__RXS3_ANA_OVRDVAL_11_ADDR (E56G__BASEADDR + 0x6cc) + +typedef union { + struct { + u32 rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 rxs0_rx0_fom_en_i : 1; + u32 rxs0_rx0_idle_detect_en_i : 1; + u32 rxs0_rx0_idle_o : 1; + u32 rxs0_rx0_txffe_train_en_i : 1; + u32 rxs0_rx0_txffe_train_enack_o : 1; + u32 rxs0_rx0_txffe_train_done_o : 1; + u32 rxs0_rx0_vga_train_en_i : 1; + u32 rxs0_rx0_vga_train_done_o : 1; + u32 rxs0_rx0_ctle_train_en_i : 1; + u32 rxs0_rx0_ctle_train_done_o : 1; + u32 rxs0_rx0_cdr_en_i : 1; + u32 rxs0_rx0_cdr_rdy_o : 1; + u32 rxs0_rx0_ffe_train_en_i : 1; + u32 rxs0_rx0_ffe_train_done_o : 1; + u32 rxs0_rx0_mmpd_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_en_i : 1; + u32 rxs0_rx0_adc_intl_cal_done_o : 1; + u32 rxs0_rx0_adc_intl_cal_error_o : 1; + u32 rxs0_rx0_dfe_train_en_i : 1; + u32 rxs0_rx0_dfe_train_done_o : 1; + u32 rxs0_rx0_vga_adapt_en_i : 1; + u32 rxs0_rx0_vga_adapt_done_o : 1; + u32 rxs0_rx0_ctle_adapt_en_i : 1; + u32 rxs0_rx0_ctle_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs0_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs0_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs0_rx0_adc_gain_adapt_en_i : 1; + u32 rxs0_rx0_adc_gain_adapt_done_o : 1; + u32 rxs0_rx0_adc_gain_adapt_error_o : 1; + u32 rxs0_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDVAL_1; +#define E56G__PMD_RXS0_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1544) + +typedef union { + struct { + u32 rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 rxs1_rx0_fom_en_i : 1; + u32 rxs1_rx0_idle_detect_en_i : 1; + u32 rxs1_rx0_idle_o : 1; + u32 rxs1_rx0_txffe_train_en_i : 1; + u32 rxs1_rx0_txffe_train_enack_o : 1; + u32 rxs1_rx0_txffe_train_done_o : 1; + u32 rxs1_rx0_vga_train_en_i : 1; + u32 rxs1_rx0_vga_train_done_o : 1; + u32 rxs1_rx0_ctle_train_en_i : 1; + u32 rxs1_rx0_ctle_train_done_o : 1; + u32 rxs1_rx0_cdr_en_i : 1; + u32 rxs1_rx0_cdr_rdy_o : 1; + u32 rxs1_rx0_ffe_train_en_i : 1; + u32 rxs1_rx0_ffe_train_done_o : 1; + u32 rxs1_rx0_mmpd_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_en_i : 1; + u32 rxs1_rx0_adc_intl_cal_done_o : 1; + u32 rxs1_rx0_adc_intl_cal_error_o : 1; + u32 rxs1_rx0_dfe_train_en_i : 1; + u32 rxs1_rx0_dfe_train_done_o : 1; + u32 rxs1_rx0_vga_adapt_en_i : 1; + u32 rxs1_rx0_vga_adapt_done_o : 1; + u32 rxs1_rx0_ctle_adapt_en_i : 1; + u32 rxs1_rx0_ctle_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs1_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs1_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs1_rx0_adc_gain_adapt_en_i : 1; + u32 rxs1_rx0_adc_gain_adapt_done_o : 1; + u32 rxs1_rx0_adc_gain_adapt_error_o : 1; + u32 rxs1_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDVAL_1; + +#define E56G__PMD_RXS1_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x1570) + +typedef union { + struct { + u32 rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 rxs2_rx0_fom_en_i : 1; + u32 rxs2_rx0_idle_detect_en_i : 1; + u32 rxs2_rx0_idle_o : 1; + u32 rxs2_rx0_txffe_train_en_i : 1; + u32 rxs2_rx0_txffe_train_enack_o : 1; + u32 rxs2_rx0_txffe_train_done_o : 1; + u32 rxs2_rx0_vga_train_en_i : 1; + u32 rxs2_rx0_vga_train_done_o : 1; + u32 rxs2_rx0_ctle_train_en_i : 1; + u32 rxs2_rx0_ctle_train_done_o : 1; + u32 rxs2_rx0_cdr_en_i : 1; + u32 rxs2_rx0_cdr_rdy_o : 1; + u32 rxs2_rx0_ffe_train_en_i : 1; + u32 rxs2_rx0_ffe_train_done_o : 1; + u32 rxs2_rx0_mmpd_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_en_i : 1; + u32 rxs2_rx0_adc_intl_cal_done_o : 1; + u32 rxs2_rx0_adc_intl_cal_error_o : 1; + u32 rxs2_rx0_dfe_train_en_i : 1; + u32 rxs2_rx0_dfe_train_done_o : 1; + u32 rxs2_rx0_vga_adapt_en_i : 1; + u32 rxs2_rx0_vga_adapt_done_o : 1; + u32 rxs2_rx0_ctle_adapt_en_i : 1; + u32 rxs2_rx0_ctle_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs2_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs2_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs2_rx0_adc_gain_adapt_en_i : 1; + u32 rxs2_rx0_adc_gain_adapt_done_o : 1; + u32 rxs2_rx0_adc_gain_adapt_error_o : 1; + u32 rxs2_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDVAL_1; + +#define E56G__PMD_RXS2_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x159c) + +typedef union { + struct { + u32 rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 rxs3_rx0_fom_en_i : 1; + u32 rxs3_rx0_idle_detect_en_i : 1; + u32 rxs3_rx0_idle_o : 1; + u32 rxs3_rx0_txffe_train_en_i : 1; + u32 rxs3_rx0_txffe_train_enack_o : 1; + u32 rxs3_rx0_txffe_train_done_o : 1; + u32 rxs3_rx0_vga_train_en_i : 1; + u32 rxs3_rx0_vga_train_done_o : 1; + u32 rxs3_rx0_ctle_train_en_i : 1; + u32 rxs3_rx0_ctle_train_done_o : 1; + u32 rxs3_rx0_cdr_en_i : 1; + u32 rxs3_rx0_cdr_rdy_o : 1; + u32 rxs3_rx0_ffe_train_en_i : 1; + u32 rxs3_rx0_ffe_train_done_o : 1; + u32 rxs3_rx0_mmpd_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_en_i : 1; + u32 rxs3_rx0_adc_intl_cal_done_o : 1; + u32 rxs3_rx0_adc_intl_cal_error_o : 1; + u32 rxs3_rx0_dfe_train_en_i : 1; + u32 rxs3_rx0_dfe_train_done_o : 1; + u32 rxs3_rx0_vga_adapt_en_i : 1; + u32 rxs3_rx0_vga_adapt_done_o : 1; + u32 rxs3_rx0_ctle_adapt_en_i : 1; + u32 rxs3_rx0_ctle_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_en_i : 1; + u32 rxs3_rx0_adc_ofst_adapt_done_o : 1; + u32 rxs3_rx0_adc_ofst_adapt_error_o : 1; + u32 rxs3_rx0_adc_gain_adapt_en_i : 1; + u32 rxs3_rx0_adc_gain_adapt_done_o : 1; + u32 rxs3_rx0_adc_gain_adapt_error_o : 1; + u32 rxs3_rx0_adc_intl_adapt_en_i : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDVAL_1; + +#define E56G__PMD_RXS3_OVRDVAL_1_ADDR (E56G__BASEADDR + 0x15c8) + +typedef union { + struct { + u32 ctrl_fsm_rx0_st : 6; + u32 rsvd0 : 2; + u32 ctrl_fsm_rx1_st : 6; + u32 rsvd1 : 2; + u32 ctrl_fsm_rx2_st : 6; + u32 rsvd2 : 2; + u32 ctrl_fsm_rx3_st : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_CTRL_FSM_RX_STAT_0; + +#define E56G__PMD_CTRL_FSM_RX_STAT_0_ADDR (E56G__BASEADDR + 0x14fc) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_0; +#define E56G__RXS0_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0xa0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_0; + +#define E56G__RXS1_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x2a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_0; + +#define E56G__RXS2_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x4a0) + +typedef union { + struct { + u32 ana_en_rterm_i : 1; + u32 ana_en_bias_i : 1; + u32 ana_en_ldo_i : 1; + u32 ana_rstn_i : 1; + u32 ana_en_blwc_i : 1; + u32 ana_en_acc_amp_i : 1; + u32 ana_en_acc_dac_i : 1; + u32 ana_en_afe_offset_cal_i : 1; + u32 ana_clk_offsetcal_i : 1; + u32 ana_acc_os_comp_o : 1; + u32 ana_en_ctle_i : 1; + u32 ana_ctle_bypass_i : 1; + u32 ana_en_ctlecdr_i : 1; + u32 ana_cdr_ctle_boost_i : 1; + u32 ana_en_vga_i : 1; + u32 ana_en_bbcdr_vco_i : 1; + u32 ana_bbcdr_vcofilt_byp_i : 1; + u32 ana_en_bbcdr_i : 1; + u32 ana_en_bbcdr_clk_i : 1; + u32 ana_bbcdr_en_elv_cnt_ping0_pong1_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_ping_i : 1; + u32 ana_bbcdr_clrz_elv_cnt_pong_i : 1; + u32 ana_bbcdr_clrz_cnt_sync_i : 1; + u32 ana_bbcdr_en_elv_cnt_rd_i : 1; + u32 ana_bbcdr_elv_cnt_ping_0_o : 1; + u32 ana_bbcdr_elv_cnt_ping_90_o : 1; + u32 ana_bbcdr_elv_cnt_ping_180_o : 1; + u32 ana_bbcdr_elv_cnt_ping_270_o : 1; + u32 ana_bbcdr_elv_cnt_pong_0_o : 1; + u32 ana_bbcdr_elv_cnt_pong_90_o : 1; + u32 ana_bbcdr_elv_cnt_pong_180_o : 1; + u32 ana_bbcdr_elv_cnt_pong_270_o : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_0; + +#define E56G__RXS3_ANA_OVRDVAL_0_ADDR (E56G__BASEADDR + 0x6a0) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDEN_0; + +#define E56G__RXS0_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x8c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDEN_0; + +#define E56G__RXS1_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x28c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDEN_0; + +#define E56G__RXS2_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x48c) + +typedef union { + struct { + u32 ovrd_en_ana_en_rterm_i : 1; + u32 ovrd_en_ana_trim_rterm_i : 1; + u32 ovrd_en_ana_en_bias_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_en_ldo_i : 1; + u32 ovrd_en_ana_test_ldo_i : 1; + u32 ovrd_en_ana_rstn_i : 1; + u32 ovrd_en_ana_en_blwc_i : 1; + u32 ovrd_en_ana_en_acc_amp_i : 1; + u32 ovrd_en_ana_en_acc_dac_i : 1; + u32 ovrd_en_ana_en_afe_offset_cal_i : 1; + u32 ovrd_en_ana_clk_offsetcal_i : 1; + u32 ovrd_en_ana_acc_os_code_i : 1; + u32 ovrd_en_ana_acc_os_comp_o : 1; + u32 ovrd_en_ana_test_acc_i : 1; + u32 ovrd_en_ana_en_ctle_i : 1; + u32 ovrd_en_ana_ctle_bypass_i : 1; + u32 ovrd_en_ana_ctle_cz_cstm_i : 1; + u32 ovrd_en_ana_ctle_cload_cstm_i : 1; + u32 ovrd_en_ana_test_ctle_i : 1; + u32 ovrd_en_ana_lfeq_ctrl_cstm_i : 1; + u32 ovrd_en_ana_en_ctlecdr_i : 1; + u32 ovrd_en_ana_cdr_ctle_boost_i : 1; + u32 ovrd_en_ana_test_ctlecdr_i : 1; + u32 ovrd_en_ana_en_vga_i : 1; + u32 ovrd_en_ana_vga_gain_cstm_i : 1; + u32 ovrd_en_ana_vga_cload_in_cstm_i : 1; + u32 ovrd_en_ana_test_vga_i : 1; + u32 ovrd_en_ana_en_bbcdr_vco_i : 1; + u32 ovrd_en_ana_bbcdr_osc_range_sel_i : 1; + u32 ovrd_en_ana_sel_vga_gain_byp_i : 1; + u32 ovrd_en_ana_vga2_gain_cstm_i : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDEN_0; + +#define E56G__RXS3_ANA_OVRDEN_0_NUM 1 +#define E56G__RXS3_ANA_OVRDEN_0_ADDR (E56G__BASEADDR + 0x68c) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS0_ANA_OVRDVAL_3; + +#define E56G__RXS0_ANA_OVRDVAL_3_NUM 1 +#define E56G__RXS0_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0xac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS1_ANA_OVRDVAL_3; + +#define E56G__RXS1_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x2ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS2_ANA_OVRDVAL_3; + +#define E56G__RXS2_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x4ac) + +typedef union { + struct { + u32 ana_ctle_cz_cstm_i : 5; + u32 rsvd0 : 3; + u32 ana_ctle_cload_cstm_i : 5; + u32 rsvd1 : 3; + u32 ana_test_ctle_i : 2; + u32 rsvd2 : 2; + u32 ana_lfeq_ctrl_cstm_i : 4; + u32 ana_test_ctlecdr_i : 2; + u32 rsvd3 : 2; + u32 ana_vga_cload_in_cstm_i : 3; + u32 rsvd4 : 1; + }; + u32 reg; +} E56G__RXS3_ANA_OVRDVAL_3; + +#define E56G__RXS3_ANA_OVRDVAL_3_ADDR (E56G__BASEADDR + 0x6ac) + +typedef union { + struct { + u32 ovrd_en_rxs0_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_fom_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs0_rx0_idle_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs0_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs0_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs0_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs0_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs0_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS0_OVRDEN_1; + +#define E56G__PMD_RXS0_OVRDEN_1_NUM 1 +#define E56G__PMD_RXS0_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1534) + +typedef union { + struct { + u32 ovrd_en_rxs1_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_fom_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs1_rx0_idle_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs1_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs1_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs1_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs1_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs1_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS1_OVRDEN_1; + +#define E56G__PMD_RXS1_OVRDEN_1_ADDR (E56G__BASEADDR + 0x1560) + +typedef union { + struct { + u32 ovrd_en_rxs2_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_fom_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs2_rx0_idle_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs2_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs2_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs2_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs2_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs2_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS2_OVRDEN_1; + +#define E56G__PMD_RXS2_OVRDEN_1_ADDR (E56G__BASEADDR + 0x158c) + +typedef union { + struct { + u32 ovrd_en_rxs3_rx0_adc_gain_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_gain_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_fe_ofst_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_fom_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_detect_en_i : 1; + u32 ovrd_en_rxs3_rx0_idle_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_rst_i : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_enack_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_txffe_coeff_change_o : 1; + u32 ovrd_en_rxs3_rx0_vga_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_cdr_en_i : 1; + u32 ovrd_en_rxs3_rx0_cdr_rdy_o : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_ffe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_mmpd_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_en_i : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_done_o : 1; + u32 ovrd_en_rxs3_rx0_adc_intl_cal_error_o : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_en_i : 1; + u32 ovrd_en_rxs3_rx0_dfe_train_done_o : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_vga_adapt_done_o : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_en_i : 1; + u32 ovrd_en_rxs3_rx0_ctle_adapt_done_o : 1; + }; + u32 reg; +} E56G__PMD_RXS3_OVRDEN_1; + +#define E56G__PMD_RXS3_OVRDEN_1_ADDR (E56G__BASEADDR + 0x15b8) + +#define E56G__RXS0_FOM_18__ADDR (E56G__BASEADDR + 0x1f8) +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB 11 +#define E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB 0 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB 23 +#define E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB 12 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB 25 +#define E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB 25 + +#define DEFAULT_TEMP 40 +#define HIGH_TEMP 70 + +#define E56PHY_RX_RDY_ST 0x1B + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 + +#define S25G_CMVAR_RANGE_H 0x1 +#define S25G_CMVAR_RANGE_L 0x0 +#define S25G_CMVAR_SEC_LOW_TH 0x1A +#define S25G_CMVAR_SEC_HIGH_TH 0x1D +#define S25G_CMVAR_UFINE_MAX 0x2 +#define S25G_CMVAR_FINE_MAX 0x7 +#define S25G_CMVAR_COARSE_MAX 0xF +#define S25G_CMVAR_UFINE_UMAX_WRAP 0x0 +#define S25G_CMVAR_UFINE_FMAX_WRAP 0x0 +#define S25G_CMVAR_FINE_FMAX_WRAP 0x2 +#define S25G_CMVAR_UFINE_MIN 0x0 +#define S25G_CMVAR_FINE_MIN 0x0 +#define S25G_CMVAR_COARSE_MIN 0x1 +#define S25G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S25G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S25G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_CMVAR_RANGE_H 0x3 +#define S10G_CMVAR_RANGE_L 0x2 +#define S10G_CMVAR_SEC_LOW_TH 0x1A +#define S10G_CMVAR_SEC_HIGH_TH 0x1D +#define S10G_CMVAR_UFINE_MAX 0x7 +#define S10G_CMVAR_FINE_MAX 0x7 +#define S10G_CMVAR_COARSE_MAX 0xF +#define S10G_CMVAR_UFINE_UMAX_WRAP 0x6 +#define S10G_CMVAR_UFINE_FMAX_WRAP 0x7 +#define S10G_CMVAR_FINE_FMAX_WRAP 0x1 +#define S10G_CMVAR_UFINE_MIN 0x0 +#define S10G_CMVAR_FINE_MIN 0x0 +#define S10G_CMVAR_COARSE_MIN 0x1 +#define S10G_CMVAR_UFINE_UMIN_WRAP 0x2 +#define S10G_CMVAR_UFINE_FMIN_WRAP 0x2 +#define S10G_CMVAR_FINE_FMIN_WRAP 0x5 + +#define S10G_TX_FFE_CFG_MAIN 0x2c2c2c2c +#define S10G_TX_FFE_CFG_PRE1 0x0 +#define S10G_TX_FFE_CFG_PRE2 0x0 +#define S10G_TX_FFE_CFG_POST 0x06060606 +#define S25G_TX_FFE_CFG_MAIN 0x31 +#define S25G_TX_FFE_CFG_PRE1 0x4 +#define S25G_TX_FFE_CFG_PRE2 0x1 +#define S25G_TX_FFE_CFG_POST 0x9 + +#define S25G_TX_FFE_CFG_DAC_MAIN 0x2a +#define S25G_TX_FFE_CFG_DAC_PRE1 0x03 +#define S25G_TX_FFE_CFG_DAC_PRE2 0x0 +#define S25G_TX_FFE_CFG_DAC_POST 0x11 + +#define S40G_TX_FFE_CFG_MAIN 0x2b2b2b2b +#define S40G_TX_FFE_CFG_PRE1 0x03030303 +#define S40G_TX_FFE_CFG_PRE2 0x0 +#define S40G_TX_FFE_CFG_POST 0x11111111 + +#define BYPASS_CTLE_TAG 0x0 + +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S10G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S10G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S10G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT1 0x1 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT2 0x0 +#define S25G_PHY_RX_CTLE_TAPWT_WEIGHT3 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP1 0x18 +#define S25G_PHY_RX_CTLE_TAP_FRACP2 0x0 +#define S25G_PHY_RX_CTLE_TAP_FRACP3 0x0 + +#define TXGBE_E56_PHY_LINK_UP 0x4 + +void set_fields_e56(unsigned int *src_data, unsigned int bit_high, + unsigned int bit_low, unsigned int set_value); +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane); +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE); +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw); +u32 txgbe_e56_cfg_10g(struct txgbe_hw *hw); +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed); +int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); +int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); +int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_fec_set(struct txgbe_hw *hw); +s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); +u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); + +#endif /* _TXGBE_E56_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h new file mode 100644 index 0000000000..97d5656cad --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024-2026 Beijing WangXun Technology Co., Ltd. + */ + +#ifndef _TXGBE_E56_BP_H_ +#define _TXGBE_E56_BP_H_ + +#define TXGBE_10G_FEC_REQ BIT(15) +#define TXGBE_10G_FEC_ABL BIT(14) +#define TXGBE_25G_BASE_FEC_REQ BIT(13) +#define TXGBE_25G_RS_FEC_REQ BIT(12) + +#ifndef __bf_shf +#define __bf_shf(x) (__builtin_ffsll(x) - 1) +#endif +/** + * FIELD_GET_M() - extract a bitfield element + * @_mask: shifted mask defining the field's length and position + * @_reg: value of entire bitfield + * + * FIELD_GET_M() extracts the field specified by @_mask from the + * bitfield passed in as @_reg by masking and shifting it down. + */ +#define FIELD_GET_M(_mask, _reg) \ + ({ \ + (typeof(_mask))(((_reg) & (_mask)) >> __bf_shf(_mask)); \ + }) + +typedef union { + struct { + u32 tx0_cursor_factor : 7; + u32 rsvd0 : 1; + u32 tx1_cursor_factor : 7; + u32 rsvd1 : 1; + u32 tx2_cursor_factor : 7; + u32 rsvd2 : 1; + u32 tx3_cursor_factor : 7; + u32 rsvd3 : 1; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_1; + +#define E56G__PMD_TX_FFE_CFG_1_NUM 1 +#define E56G__PMD_TX_FFE_CFG_1_ADDR (E56G__BASEADDR + 0x141c) +#define E56G__PMD_TX_FFE_CFG_1_PTR ((E56G__PMD_TX_FFE_CFG_1 *)(E56G__PMD_TX_FFE_CFG_1_ADDR)) +#define E56G__PMD_TX_FFE_CFG_1_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_1_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_1_READ_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_MSB 30 +#define E56G__PMD_TX_FFE_CFG_1_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_1_RESET_VALUE 0x3f3f3f3f + +typedef union { + struct { + u32 tx0_precursor1_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor1_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor1_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor1_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_2; + +#define E56G__PMD_TX_FFE_CFG_2_NUM 1 +#define E56G__PMD_TX_FFE_CFG_2_ADDR (E56G__BASEADDR + 0x1420) +#define E56G__PMD_TX_FFE_CFG_2_PTR ((E56G__PMD_TX_FFE_CFG_2 *)(E56G__PMD_TX_FFE_CFG_2_ADDR)) +#define E56G__PMD_TX_FFE_CFG_2_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_2_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_2_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_2_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_2_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_precursor2_factor : 6; + u32 rsvd0 : 2; + u32 tx1_precursor2_factor : 6; + u32 rsvd1 : 2; + u32 tx2_precursor2_factor : 6; + u32 rsvd2 : 2; + u32 tx3_precursor2_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_3; +#define E56G__PMD_TX_FFE_CFG_3_NUM 1 +#define E56G__PMD_TX_FFE_CFG_3_ADDR (E56G__BASEADDR + 0x1424) +#define E56G__PMD_TX_FFE_CFG_3_PTR ((E56G__PMD_TX_FFE_CFG_3 *)(E56G__PMD_TX_FFE_CFG_3_ADDR)) +#define E56G__PMD_TX_FFE_CFG_3_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_3_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_3_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_3_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_3_RESET_VALUE 0x0 + +typedef union { + struct { + u32 tx0_postcursor_factor : 6; + u32 rsvd0 : 2; + u32 tx1_postcursor_factor : 6; + u32 rsvd1 : 2; + u32 tx2_postcursor_factor : 6; + u32 rsvd2 : 2; + u32 tx3_postcursor_factor : 6; + u32 rsvd3 : 2; + }; + u32 reg; +} E56G__PMD_TX_FFE_CFG_4; +#define E56G__PMD_TX_FFE_CFG_4_NUM 1 +#define E56G__PMD_TX_FFE_CFG_4_ADDR (E56G__BASEADDR + 0x1428) +#define E56G__PMD_TX_FFE_CFG_4_PTR ((E56G__PMD_TX_FFE_CFG_4 *)(E56G__PMD_TX_FFE_CFG_4_ADDR)) +#define E56G__PMD_TX_FFE_CFG_4_STRIDE 4 +#define E56G__PMD_TX_FFE_CFG_4_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_ACC_SIZE 32 +#define E56G__PMD_TX_FFE_CFG_4_READ_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_READ_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_MSB 29 +#define E56G__PMD_TX_FFE_CFG_4_WRITE_LSB 0 +#define E56G__PMD_TX_FFE_CFG_4_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_vco_swing_ctrl_i : 4; + u32 ana_lcpll_lf_lpf_setcode_calib_i : 5; + u32 rsvd0 : 3; + u32 ana_lcpll_lf_vco_coarse_bin_i : 5; + u32 rsvd1 : 3; + u32 ana_lcpll_lf_vco_fine_therm_i : 8; + u32 ana_lcpll_lf_clkout_fb_ctrl_i : 2; + u32 rsvd2 : 2; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_7; +#define E56G__CMS_ANA_OVRDVAL_7_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_7_ADDR (E56G__BASEADDR + 0xccc) +#define E56G__CMS_ANA_OVRDVAL_7_PTR ((E56G__CMS_ANA_OVRDVAL_7 *)(E56G__CMS_ANA_OVRDVAL_7_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_7_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_7_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_7_READ_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_MSB 29 +#define E56G__CMS_ANA_OVRDVAL_7_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_7_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ovrd_en_ana_lcpll_hf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_hf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_hf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_hf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_lf_en_bias_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_loop_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_cp_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_base_i : 1; + u32 ovrd_en_ana_lcpll_lf_icp_fine_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_lpf_setcode_calib_i : 1; + u32 ovrd_en_ana_lcpll_lf_set_lpf_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_vco_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_coarse_bin_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_fine_therm_i : 1; + u32 ovrd_en_ana_lcpll_lf_vco_amp_status_o : 1; + u32 ovrd_en_ana_lcpll_lf_clkout_fb_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_clkdiv_ctrl_i : 1; + u32 ovrd_en_ana_lcpll_lf_en_odiv_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_in_i : 1; + u32 ovrd_en_ana_lcpll_lf_test_out_o : 1; + u32 ovrd_en_ana_lcpll_hf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_lf_refclk_select_i : 1; + u32 ovrd_en_ana_lcpll_hf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_lcpll_lf_clk_ref_sel_i : 1; + u32 ovrd_en_ana_test_bias_i : 1; + u32 ovrd_en_ana_test_slicer_i : 1; + u32 ovrd_en_ana_test_sampler_i : 1; + }; + u32 reg; +} E56G__CMS_ANA_OVRDEN_1; +#define E56G__CMS_ANA_OVRDEN_1_NUM 1 +#define E56G__CMS_ANA_OVRDEN_1_ADDR (E56G__BASEADDR + 0xca8) +#define E56G__CMS_ANA_OVRDEN_1_PTR ((E56G__CMS_ANA_OVRDEN_1 *)(E56G__CMS_ANA_OVRDEN_1_ADDR)) +#define E56G__CMS_ANA_OVRDEN_1_STRIDE 4 +#define E56G__CMS_ANA_OVRDEN_1_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDEN_1_READ_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_READ_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDEN_1_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDEN_1_RESET_VALUE 0x0 + +typedef union { + struct { + u32 ana_lcpll_lf_test_in_i : 32; + }; + u32 reg; +} E56G__CMS_ANA_OVRDVAL_9; +#define E56G__CMS_ANA_OVRDVAL_9_NUM 1 +#define E56G__CMS_ANA_OVRDVAL_9_ADDR (E56G__BASEADDR + 0xcd4) +#define E56G__CMS_ANA_OVRDVAL_9_PTR ((E56G__CMS_ANA_OVRDVAL_9 *)(E56G__CMS_ANA_OVRDVAL_9_ADDR)) +#define E56G__CMS_ANA_OVRDVAL_9_STRIDE 4 +#define E56G__CMS_ANA_OVRDVAL_9_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_ACC_SIZE 32 +#define E56G__CMS_ANA_OVRDVAL_9_READ_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_READ_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_MSB 31 +#define E56G__CMS_ANA_OVRDVAL_9_WRITE_LSB 0 +#define E56G__CMS_ANA_OVRDVAL_9_RESET_VALUE 0x0 + +#define SFP2_RS0 5 +#define SFP2_RS1 4 +#define SFP2_TX_DISABLE 1 +#define SFP2_TX_FAULT 0 +#define SFP2_RX_LOS_BIT 3 +#ifdef PHYINIT_TIMEOUT +#undef PHYINIT_TIMEOUT +#define PHYINIT_TIMEOUT 2000 +#endif + +#define E56PHY_CMS_ANA_OVRDEN_0_ADDR (E56PHY_CMS_BASE_ADDR + 0xA4) +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_DAISY_EN_I 0, 0 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I 1, 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_REFCLK_BUF_PAD_EN_I_LSB 1 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_VDDINOFF_DCORE_DIG_O 2, 2 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I 11, 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_EN_I_LSB 11 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I 12, 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_BG_TESTIN_I_LSB 12 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I 13, 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RESCAL_I_LSB 13 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O 14, 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_COMP_O_LSB 14 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I 15, 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_RESCAL_CODE_I_LSB 15 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I 16, 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_LDO_CORE_I_LSB 16 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I 17, 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_LDO_I_LSB 17 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I 18, 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_ANA_DEBUG_SEL_I_LSB 18 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I 19, 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_BIAS_I_LSB 19 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I 20, 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_LOOP_I_LSB 20 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I 21, 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_EN_CP_I_LSB 21 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I 22, 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_BASE_I_LSB 22 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I 23, 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_ICP_FINE_I_LSB 23 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I 24, 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_CTRL_I_LSB 24 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 25, 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I_LSB 25 +#define E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_SET_LPF_I 26, 26 + +#define E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I 20, 16 +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 12, 12 +#define E56PHY_CMS_ANA_OVRDVAL_7_ADDR (E56PHY_CMS_BASE_ADDR + 0xCC) +#define E56PHY_CMS_ANA_OVRDVAL_5_ADDR (E56PHY_CMS_BASE_ADDR + 0xC4) +#define E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I 23, 23 +#define E56PHY_CMS_ANA_OVRDVAL_9_ADDR (E56PHY_CMS_BASE_ADDR + 0xD4) +#define E56PHY_CMS_ANA_OVRDVAL_10_ADDR (E56PHY_CMS_BASE_ADDR + 0xD8) +#define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 + +#endif diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index b1a1483dab..0c6a74c562 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4071,37 +4071,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { - u32 rdata = 0; - u32 links_reg = 0; + u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); - /* must read it twice because the state may - * not be correct the first time you read it - */ - rdata = rd32_epcs(hw, 0x30001); - rdata = rd32_epcs(hw, 0x30001); - - if (rdata & TXGBE_AML_PHY_LINK_UP) - *link_up = true; - else - *link_up = false; - - links_reg = rd32(hw, TXGBE_PORTSTAT); - if (*link_up) { - if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == - TXGBE_CFG_PORT_ST_AML_LINK_40G) - *speed = TXGBE_LINK_SPEED_40GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_25G) == - TXGBE_CFG_PORT_ST_AML_LINK_25G) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_10G) == - TXGBE_CFG_PORT_ST_AML_LINK_10G) - *speed = TXGBE_LINK_SPEED_10GB_FULL; - } else { - *speed = TXGBE_LINK_SPEED_UNKNOWN; - } + if (gpio_ext & gpio_ext_mask) + return true; - return 0; + return false; } diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index f1849c8400..c02be3cc34 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -40,7 +40,6 @@ #define SR_PMA_KR_LD_CESTS_RR MS16(15, 0x1) #define SR_PMA_KR_FEC_CTRL 0x0100AB #define SR_PMA_KR_FEC_CTRL_EN MS16(0, 0x1) -#define SR_PMA_RS_FEC_CTRL 0x0100C8 #define SR_MII_MMD_CTL 0x1F0000 #define SR_MII_MMD_CTL_AN_EN 0x1000 #define SR_MII_MMD_CTL_RESTART_AN 0x0200 diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h index 25aaf8ea68..e2ba7acc4c 100644 --- a/drivers/net/txgbe/base/txgbe_regs.h +++ b/drivers/net/txgbe/base/txgbe_regs.h @@ -158,6 +158,8 @@ #define TXGBE_RST_SW MS(0, 0x1) #define TXGBE_RST_LAN(i) MS(((i) + 1), 0x1) #define TXGBE_RST_FW MS(3, 0x1) +#define TXGBE_RST_EPHY_LAN_1 MS(16, 0x1) +#define TXGBE_RST_EPHY_LAN_0 MS(19, 0x1) #define TXGBE_RST_MAC_LAN_1 MS(17, 0x1) #define TXGBE_RST_MAC_LAN_0 MS(20, 0x1) #define TXGBE_RST_ETH(i) MS(((i) + 29), 0x1) diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 505f598fb7..7fb4bcc513 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -64,6 +64,9 @@ #define TXGBE_AML_ALARM_THRE_MASK 0x1FFE0000U #define TXGBE_AML_DALARM_THRE_MASK 0x0001FFE0U +#define CL74_KRTR_TRAINNING_TIMEOUT 6000 /* 3000ms c74 trainning timeout */ +#define AN_TRAINNING_MODE 0 /* 0: not dis an 1: dis an */ + struct txgbe_thermal_diode_data { s16 temp; s16 alarm_thresh; @@ -690,6 +693,8 @@ struct txgbe_phy_info { s32 (*setup_link_speed)(struct txgbe_hw *hw, u32 speed, bool autoneg_wait_to_complete); s32 (*check_link)(struct txgbe_hw *hw, u32 *speed, bool *link_up); + s32 (*setup_link_core)(struct txgbe_hw *hw, u32 speed, + bool autoneg_wait_to_complete, bool *need_reset); s32 (*get_fw_version)(struct txgbe_hw *hw, u32 *fw_version); s32 (*read_i2c_byte)(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); @@ -732,7 +737,9 @@ struct txgbe_phy_info { u16 ffe_set; u16 ffe_main; u16 ffe_pre; + u16 ffe_pre2; u16 ffe_post; + u16 fec_mode; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -823,6 +830,7 @@ struct txgbe_devargs { struct txgbe_hw { void IOMEM *hw_addr; void *back; + void *dev_back; struct txgbe_mac_info mac; struct txgbe_addr_filter_info addr_ctrl; struct txgbe_fc_info fc; @@ -885,8 +893,12 @@ struct txgbe_hw { /*amlite: new SW-FW mbox */ u8 swfw_index; rte_atomic32_t swfw_busy; + bool link_valid; + bool reconfig_rx; u32 fec_mode; u32 cur_fec_link; + int temperature; + u32 bp_link_mode; }; struct txgbe_backplane_ability { diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 3ae233f70a..0e3d7649d8 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -592,6 +592,17 @@ txgbe_parse_devargs(struct rte_eth_dev *dev) fdir_conf->drop_queue = drop_queue; } +static void +txgbe_override_mac_ops(struct txgbe_hw *hw) +{ + struct txgbe_mac_info *mac = &hw->mac; + + if (hw->phy.multispeed_fiber) + mac->setup_mac_link = txgbe_setup_mac_link_aml; + else + mac->setup_link = txgbe_setup_mac_link_aml; +} + static int eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) { @@ -651,6 +662,7 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) /* Vendor and Device ID need to be set before init of shared code */ hw->back = pci_dev; + hw->dev_back = eth_dev; hw->port_id = eth_dev->data->port_id; hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; @@ -686,6 +698,9 @@ eth_txgbe_dev_init(struct rte_eth_dev *eth_dev, void *init_params __rte_unused) return -EIO; } + if (hw->mac.type == txgbe_mac_aml) + txgbe_override_mac_ops(hw); + /* Unlock any pending hardware semaphore */ txgbe_swfw_lock_reset(hw); @@ -2039,6 +2054,9 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); + if (hw->mac.type == txgbe_mac_aml) + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); txgbe_dev_wait_setup_link_complete(dev, 0); @@ -3093,6 +3111,65 @@ txgbe_tx_ring_recovery(struct rte_eth_dev *dev) } } +void +txgbe_dev_setup_link_alarm_handler_aml(void *param) +{ + struct txgbe_hw *hw = (struct txgbe_hw *)param; + struct rte_eth_dev *dev = (struct rte_eth_dev *)hw->dev_back; + struct txgbe_interrupt *intr = TXGBE_DEV_INTR(dev); + u32 speed; + bool autoneg = false; + u32 gssr = hw->phy.phy_semaphore_mask; + + if (!hw) + return; + + speed = hw->phy.autoneg_advertised; + if (!speed) + hw->mac.get_link_capabilities(hw, &speed, &autoneg); + + /* firmware is configuring phy now, delay host driver config action */ + if (hw->mac.acquire_swfw_sync(hw, gssr) != 0) { + rte_eal_alarm_set(1000 * 1000 * 2, + txgbe_dev_setup_link_alarm_handler_aml, hw); + PMD_DRV_LOG(DEBUG, "delay config ephy"); + return; + } + + hw->mac.setup_link(hw, speed, true); + + u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; + bool link_up = false; + + hw->mac.check_link(hw, &link_speed, &link_up, false); + if (link_up) { + PMD_DRV_LOG(DEBUG, "LINK UP IN HANDLER"); + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; + txgbe_dev_link_update_share(dev, 0); + } + + hw->mac.release_swfw_sync(hw, gssr); + + intr->flags &= ~TXGBE_FLAG_NEED_LINK_CONFIG; +} + +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete) +{ + bool need_reset = false; + s32 status = 0; + + status = hw->phy.setup_link_core(hw, speed, autoneg_wait_to_complete, &need_reset); + if (status) + return status; + + if (!hw->adapter_stopped && need_reset) + rte_eal_alarm_set(2000 * 1000, txgbe_dev_setup_link_alarm_handler_aml, hw); + + return status; +} + /* * If @timeout_ms was 0, it means that it will not return until link complete. * It returns 1 on complete, return 0 on timeout. @@ -3126,9 +3203,13 @@ txgbe_dev_setup_link_thread_handler(void *param) { struct rte_eth_dev *dev = (struct rte_eth_dev *)param; struct txgbe_adapter *ad = TXGBE_DEV_ADAPTER(dev); + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - txgbe_dev_setup_link_alarm_handler(dev); + if (hw->mac.type == txgbe_mac_aml) + txgbe_dev_setup_link_alarm_handler_aml(hw); + else + txgbe_dev_setup_link_alarm_handler(dev); rte_atomic_store_explicit(&ad->link_thread_running, 0, rte_memory_order_seq_cst); return 0; } diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 189fbac541..1ec8e096cc 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -733,6 +733,10 @@ int txgbe_dev_rss_reta_query(struct rte_eth_dev *dev, struct rte_eth_rss_reta_entry64 *reta_conf, uint16_t reta_size); void txgbe_dev_setup_link_alarm_handler(void *param); +void txgbe_dev_setup_link_alarm_handler_aml(void *param); +s32 txgbe_setup_mac_link_aml(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete); void txgbe_read_stats_registers(struct txgbe_hw *hw, struct txgbe_hw_stats *hw_stats); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 13/20] net/txgbe: fix link stability for 40G NIC 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (11 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang ` (6 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml40.c | 70 +- drivers/net/txgbe/base/txgbe_aml40.h | 6 +- drivers/net/txgbe/base/txgbe_e56.c | 1471 ++++++++++++++++++++++++-- drivers/net/txgbe/txgbe_ethdev.c | 4 +- 4 files changed, 1438 insertions(+), 113 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index eefd7119fd..84c130704a 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_aml40.h" +#include "txgbe_e56.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -24,6 +25,7 @@ void txgbe_init_ops_aml40(struct txgbe_hw *hw) /* PHY */ phy->get_media_type = txgbe_get_media_type_aml40; + phy->setup_link_core = txgbe_setup_phy_link_aml40; /* LINK */ mac->init_mac_link_ops = txgbe_init_mac_link_ops_aml40; @@ -52,6 +54,13 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, if (link_up_wait_to_complete) { for (i = 0; i < hw->mac.max_link_up_time; i++) { + if (!hw->link_valid) { + *link_up = false; + + msleep(100); + continue; + } + if (!(links_reg & TXGBE_PORTSTAT_UP)) { *link_up = false; } else { @@ -68,6 +77,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, u32 *speed, *link_up = false; } + if (!hw->link_valid) + *link_up = false; + if (*link_up) { if ((links_reg & TXGBE_CFG_PORT_ST_AML_LINK_40G) == TXGBE_CFG_PORT_ST_AML_LINK_40G) @@ -107,20 +119,24 @@ u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) return txgbe_media_type_fiber_qsfp; } -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, - u32 speed, - bool autoneg_wait_to_complete) +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset) { bool autoneg = false; s32 status = 0; + s32 ret_status = 0; u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN; bool link_up = false; + int i; u32 link_capabilities = TXGBE_LINK_SPEED_UNKNOWN; + u32 value; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { - DEBUGOUT("SFP not detected, skip setup mac link"); - return 0; - } + *need_reset = false; + + if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ status = hw->mac.get_link_capabilities(hw, @@ -132,18 +148,43 @@ s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; - status = hw->mac.check_link(hw, &link_speed, &link_up, - autoneg_wait_to_complete); + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + break; + msleep(250); + } if (link_speed == speed && link_up) - return status; + goto out; - if (speed & TXGBE_LINK_SPEED_40GB_FULL) - speed = 0x20; + rte_spinlock_lock(&hw->phy_lock); + ret_status = txgbe_set_link_to_amlite(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); - status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true); + if (ret_status == TXGBE_ERR_TIMEOUT) + hw->link_valid = false; + + for (i = 0; i < 4; i++) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up) + goto out; + msleep(250); + } - txgbe_wait_for_link_up_aml(hw, speed); +out: + if (link_up) { + value = rd32(hw, TXGBE_PORTSTAT); + if (!(value & TXGBE_PORTSTAT_UP)) { + DEBUGOUT("MAC link 0x14404: 0x%x", value); + *need_reset = true; + value = rd32(hw, 0x110b0); + DEBUGOUT("MAC intr status 0x110b0: 0x%x", value); + } + } else { + *need_reset = true; + DEBUGOUT("Link reconfiguration required. Reset scheduled in 2000ms."); + } return status; } @@ -159,6 +200,5 @@ void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw) mac->flap_tx_laser = txgbe_flap_tx_laser_multispeed_fiber; - mac->setup_link = txgbe_setup_mac_link_aml40; mac->set_rate_select_speed = txgbe_set_hard_rate_select_speed; } diff --git a/drivers/net/txgbe/base/txgbe_aml40.h b/drivers/net/txgbe/base/txgbe_aml40.h index f31360c899..d97654fbf8 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.h +++ b/drivers/net/txgbe/base/txgbe_aml40.h @@ -14,7 +14,9 @@ s32 txgbe_check_mac_link_aml40(struct txgbe_hw *hw, s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 *speed, bool *autoneg); u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw); -s32 txgbe_setup_mac_link_aml40(struct txgbe_hw *hw, u32 speed, - bool autoneg_wait_to_complete); +s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, + u32 speed, + bool autoneg_wait_to_complete, + bool *need_reset); void txgbe_init_mac_link_ops_aml40(struct txgbe_hw *hw); #endif /* _TXGBE_AML40_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index e4ed1f95fc..c6fb2627d4 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -102,11 +102,29 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; + pre1 = S25G_TX_FFE_CFG_DAC_PRE1; + pre2 = S25G_TX_FFE_CFG_DAC_PRE2; + post = S25G_TX_FFE_CFG_DAC_POST; + } else { ffe_main = S25G_TX_FFE_CFG_MAIN; pre1 = S25G_TX_FFE_CFG_PRE1; pre2 = S25G_TX_FFE_CFG_PRE2; post = S25G_TX_FFE_CFG_POST; } + } else if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + ffe_main = S10G_TX_FFE_CFG_MAIN; + pre1 = S10G_TX_FFE_CFG_PRE1; + pre2 = S10G_TX_FFE_CFG_PRE2; + post = S10G_TX_FFE_CFG_POST; + + if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + ffe_main = S40G_TX_FFE_CFG_MAIN; + pre1 = S40G_TX_FFE_CFG_PRE1; + pre2 = S40G_TX_FFE_CFG_PRE2; + post = S40G_TX_FFE_CFG_POST; + } } if (hw->phy.ffe_set) { @@ -154,6 +172,416 @@ txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp) return 0; } +u32 txgbe_e56_cfg_40g(struct txgbe_hw *hw) +{ + u32 addr; + u32 rdata = 0; + int i; + + /* CMS Config Master */ + addr = E56G_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + addr = E56G_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + /* TXS Config Master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_TXS_TXS_CFG_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_WKUP_CNT_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR + (E56PHY_TXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + /* Setting TX FFE */ + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_40GB_FULL); + + /* RXS Config master */ + for (i = 0; i < 4; i++) { + addr = E56PHY_RXS_RXS_CFG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, + S10G_PHY_RX_CTLE_TAP_FRACP1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, + S10G_PHY_RX_CTLE_TAP_FRACP2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, + S10G_PHY_RX_CTLE_TAP_FRACP3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT2); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, + S10G_PHY_RX_CTLE_TAPWT_WEIGHT3); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS3_ANA_OVRDVAL_11_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS3_ANA_OVRDVAL_11 *)&rdata)->ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ((E56G__RXS0_ANA_OVRDEN_2 *)&rdata)->ovrd_en_ana_test_adc_clkgen_i = 0x0; + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_EYE_SCAN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS_RINGO_0_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 4, 0x366); + wr32_ephy(hw, addr, rdata); + } + + /* PDIG Config master */ + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + u32 txgbe_e56_cfg_25g(struct txgbe_hw *hw) { @@ -1298,6 +1726,46 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) return status; } +static int txgbe_e56_set_rxs_ufine_le_max_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + unsigned int ULTRAFINE_CODE; + int i = 0; + unsigned int CMVAR_UFINE_MAX = 0; + u32 addr; + + for (i = 0; i < 4; i++) { + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + else if (speed == TXGBE_LINK_SPEED_25GB_FULL) + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + + /* a. Assign software defined variables as below */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE = ULTRAFINE_CODE - 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* Wait until 1milliseconds or greater */ + msleep(10); + } + } + return status; +} + static inline int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) { @@ -1332,38 +1800,269 @@ int txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) return status; } -int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) -{ - int status = 0, i, N, median; - unsigned int rdata; - int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; +int txgbe_e56_rx_rd_second_code_40g(struct txgbe_hw *hw, int *SECOND_CODE, int lane) +{ + int status = 0, i, N, median; + unsigned int rdata; + u32 addr; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + /* Set ovrd_en=0 to read ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* + * As status update from RXS hardware is asynchronous to read status of SECOND_ORDER, + * follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (lane * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +int txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE) +{ + int status = 0, i, N, median; + unsigned int rdata; + int array_size, RXS_BBCDR_SECOND_ORDER_ST[5]; + + + /* Set ovrd_en=0 to read ASIC value */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + + /* + * As status update from RXS hardware is asynchronous to read status + * of SECOND_ORDER, follow sequence mentioned below. + */ + N = 5; + for (i = 0; i < N; i = i + 1) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_int_cstm_i); + usec_delay(100); + } + + /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ + array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); + qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); + + median = ((N + 1) / 2) - 1; + *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; + + return status; +} + +/* + * 2.3.4 RXS post CDR lock temperature tracking sequence + * + * Below sequence must be run before the temperature drifts by >5degC + * after the CDR locks for the first time or after the ious time this + * sequence was run. It is recommended to call this sequence periodically + * (eg: once every 100ms) or trigger sequence if the temperature drifts + * by >=5degC. Temperature must be read from an on-die temperature sensor. + */ +int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) +{ + int status = 0; + unsigned int rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH; + int CMVAR_UFINE_MIN; + int CMVAR_FINE_MIN; + int CMVAR_UFINE_UMIN_WRAP; + int CMVAR_COARSE_MIN; + int CMVAR_UFINE_FMIN_WRAP; + int CMVAR_FINE_FMIN_WRAP; + int i; + u32 addr; + int temperature; + + for (i = 0; i < 4; i++) { + if (speed == TXGBE_LINK_SPEED_10GB_FULL || speed == TXGBE_LINK_SPEED_40GB_FULL) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } else { + DEBUGOUT("Error Speed\n"); + return 0; + } + status = txgbe_e56_get_temp(hw, &temperature); + if (status) + return 0; - /* Set ovrd_en=0 to read ASIC value */ - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_int_cstm_i, 0); + hw->temperature = temperature; - /* - * As status update from RXS hardware is asynchronous to read status - * of SECOND_ORDER, follow sequence mentioned below. - */ - N = 5; - for (i = 0; i < N; i = i + 1) { - /* set RXS_BBCDR_SECOND_ORDER_ST[i] = - * RXS::ANA_OVRDVAL[5]::ana_bbcdr_int_cstm_i[4:0] + /* Assign software defined variables as below */ + /* a. SECOND_CODE = ALIAS::RXS::SECOND_ORDER */ + status |= txgbe_e56_rx_rd_second_code_40g(hw, &SECOND_CODE, i); + + /* + * b. COARSE_CODE = ALIAS::RXS::COARSE + * c. FINE_CODE = ALIAS::RXS::FINE + * d. ULTRAFINE_CODE = ALIAS::RXS::ULTRAFINE */ - EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); - RXS_BBCDR_SECOND_ORDER_ST[i] = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, - ana_bbcdr_int_cstm_i); - usec_delay(100); + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + /* Set ovrd_en=1 to override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = FINE_CODE + 1; + wr32_ephy(hw, addr, rdata); + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_coarse_i) = COARSE_CODE + 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature " + "tracking occurs Error condition"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = ULTRAFINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = FINE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_coarse_i) = COARSE_CODE - 1; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (E56PHY_RXS_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, + ovrd_en_ana_bbcdr_ultrafine_i) = 1; + wr32_ephy(hw, addr, rdata); + } else { + DEBUGOUT("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature " + "tracking occurs Error condition"); + } + } } - - /* sort array RXS_BBCDR_SECOND_ORDER_ST[i] */ - array_size = ARRAY_SIZE(RXS_BBCDR_SECOND_ORDER_ST); - qsort(RXS_BBCDR_SECOND_ORDER_ST, array_size, sizeof(int), txgbe_e56_int_cmp); - - median = ((N + 1) / 2) - 1; - *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median]; - return status; } @@ -1538,78 +2237,410 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed) PMD_DRV_LOG(ERR, "ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) " "temperature tracking occurs Error condition"); } - } + } + + return status; +} + +static inline int +txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) +{ + unsigned int rdata; + + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + /* 1. Program the following RXS registers as mentioned below. */ + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + /* 2. Program the following PDIG registers as mentioned below. */ + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_calib_adapt_seq_40G(struct txgbe_hw *hw, u32 speed) +{ + int status = 0, i, j; + u32 addr, timer; + u32 rdata = 0x0; + u32 bypass_ctle = true; + + for (i = 0; i < 4; i++) { + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_2_OVRD_EN_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + } + + if (bypass_ctle == 1) + txgbe_e56_ctle_bypass_seq(hw, speed); + + /* + * 2. Follow sequence described in 2.3.2 RXS Osc Initialization for temperature tracking + * range here. RXS would be enabled at the end of this sequence. For the case when PAM4 KR + * training is not enabled (including PAM4 mode without KR training), wait until + * ALIAS::PDIG::CTRL_FSM_RX_ST would return RX_TRAIN_15_ST (RX_RDY_ST). + */ + txgbe_e56_rxs_osc_init_for_temp_track_range(hw, speed); + + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + timer = 0; + rdata = 0; + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != E56PHY_RX_RDY_ST || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != E56PHY_RX_RDY_ST) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) { + rdata = 0; + addr = E56PHY_PMD_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, 0x0); + wr32_ephy(hw, addr, rdata); + return TXGBE_ERR_TIMEOUT; + } + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + rdata = 0; + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_cdr_rdy_o) != 1) { + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + return TXGBE_ERR_TIMEOUT; + } + + for (i = 0; i < 4; i++) { + /* 4. Disable VGA and CTLE training so they don't interfere with ADC calibration */ + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_VGA_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_VGA_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_CTLE_TRAIN_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_CTLE_TRAIN_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = E56PHY_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDEN_1_OVRD_EN_RXS0_RX0_ADC_INTL_CAL_DONE_O, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (((rdata >> E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_CAL_DONE_O_LSB) + & 1) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(1000); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* + * 6. Perform ADC offset adaptation and ADC gain adaptation, repeat them a few + * times and after that keep it disabled. + */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + timer = 0; + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_ofst_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_OFST_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, + ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_adc_gain_adapt_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_GAIN_ADAPT_EN_I, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ - return status; -} -static inline int -txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u32 speed) -{ - unsigned int rdata; + /* + * 7. Perform ADC interleaver adaptation for 10ms or greater, + * and after that disable it + * a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 + */ + addr = E56PHY_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS0_OVRDVAL_1_RXS0_RX0_ADC_INTL_ADAPT_EN_I, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(10); - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + /* + * 8. Now re-enable VGA and CTLE trainings, so that it continues to adapt tracking + * changes in temperature or voltage + */ + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_en_i) = 1; + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_vga_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); - if (speed == TXGBE_LINK_SPEED_40GB_FULL) { - /* 1. Program the following RXS registers as mentioned below. */ - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + if (timer++ > PHYINIT_TIMEOUT) + break; + } - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); - txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + if (bypass_ctle == 0) { + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); - /* 2. Program the following PDIG registers as mentioned below. */ - EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; - EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + rdata = 0; + timer = 0; + addr = E56G__PMD_RXS0_OVRDVAL_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (E56PHY_PMD_RX_OFFSET * i); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + wr32_ephy(hw, addr, rdata); - EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); - EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; - EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; - EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); } - return 0; + return status; } static inline int @@ -1982,20 +3013,42 @@ txgbe_e56_cfg_temp(struct txgbe_hw *hw) return 0; } -static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +static int txgbe_e56_config_rx_40G(struct txgbe_hw *hw, u32 speed) { s32 status; - status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + status = txgbe_e56_rxs_calib_adapt_seq_40G(hw, speed); if (status) return status; /* Step 2 of 2.3.4 */ - txgbe_e56_set_rxs_ufine_le_max(hw, speed); + txgbe_e56_set_rxs_ufine_le_max_40g(hw, speed); /* 2.3.4 RXS post CDR lock temperature tracking sequence */ - txgbe_temp_track_seq(hw, speed); + txgbe_temp_track_seq_40g(hw, speed); + + hw->link_valid = true; + + return 0; +} +static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) +{ + s32 status; + + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + txgbe_e56_config_rx_40G(hw, speed); + } else { + status = txgbe_e56_rxs_calib_adapt_seq(hw, speed); + if (status) + return status; + + /* Step 2 of 2.3.4 */ + txgbe_e56_set_rxs_ufine_le_max(hw, speed); + + /* 2.3.4 RXS post CDR lock temperature tracking sequence */ + txgbe_temp_track_seq(hw, speed); + } return 0; } @@ -2005,6 +3058,151 @@ static int txgbe_e56_config_rx(struct txgbe_hw *hw, u32 speed) * Completion of RXS powerdown can be confirmed by * observing ALIAS::PDIG::CTRL_FSM_RX_ST = POWERDN_ST */ +static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) +{ + int status = 0; + unsigned int rdata, timer; + unsigned int addr, temp; + int i; + + for (i = 0; i < 4; i++) { + /* 1. Disable OVERRIDE on below aliases */ + /* a. ALIAS::RXS::RANGE_SEL */ + rdata = 0x0000; + addr = E56G__RXS0_ANA_OVRDEN_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_bbcdr_osc_range_sel_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* b. ALIAS::RXS::COARSE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 0; + /* c. ALIAS::RXS::FINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 0; + /* d. ALIAS::RXS::ULTRAFINE */ + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* e. ALIAS::RXS::SAMP_CAL_DONE */ + addr = E56G__PMD_RXS0_OVRDEN_0_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_0, ovrd_en_rxs0_rx0_samp_cal_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_2_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* f. ALIAS::RXS::ADC_OFST_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_ofst_adapt_en_i) = 0; + /* g. ALIAS::RXS::ADC_GAIN_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_gain_adapt_en_i) = 0; + /* j. ALIAS::RXS::ADC_INTL_ADAPT_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_2, ovrd_en_rxs0_rx0_adc_intl_adapt_en_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_1_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* h. ALIAS::RXS::ADC_INTL_CAL_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_en_i) = 0; + /* i. ALIAS::RXS::ADC_INTL_CAL_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_adc_intl_cal_done_o) = 0; + /* k. ALIAS::RXS::CDR_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_cdr_en_i) = 0; + /* l. ALIAS::RXS::VGA_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_vga_train_en_i) = 0; + /* m. ALIAS::RXS::CTLE_TRAIN_EN */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + /* p. ALIAS::RXS::RX_FETX_TRAIN_DONE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_done_o) = 0; + /* r. ALIAS::RXS::RX_TXFFE_COEFF_CHANGE */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_coeff_change_o) = 0; + /* s. ALIAS::RXS::RX_TXFFE_TRAIN_ENACK */ + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_txffe_train_enack_o) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__PMD_RXS0_OVRDEN_3_ADDR + (i * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + /* n. ALIAS::RXS::RX_FETX_MOD_TYPE */ + /* o. ALIAS::RXS::RX_FETX_MOD_TYPE_UPDATE */ + temp = EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_3, ovrd_en_rxs0_rx0_spareout_o) = temp & 0x8F; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_DIG_OVRDEN_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + /* q. ALIAS::RXS::SLICER_THRESHOLD_OVRD_EN */ + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, top_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, mid_comp_th_ovrd_en) = 0; + EPHY_XFLD(E56G__RXS0_DIG_OVRDEN_1, bot_comp_th_ovrd_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 2. Disable pattern checker */ + addr = E56G__RXS0_DFT_1_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_DFT_1, ber_en) = 0; + wr32_ephy(hw, addr, rdata); + + /* 3. Disable internal serial loopback mode */ + addr = E56G__RXS0_ANA_OVRDEN_3_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_3, ovrd_en_ana_sel_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + addr = E56G__RXS0_ANA_OVRDEN_2_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_2, ovrd_en_ana_en_adccal_lpbk_i) = 0; + wr32_ephy(hw, addr, rdata); + + /* 4. Enable bypass of clock gates in RXS - */ + addr = E56G__RXS0_RXS_CFG_0_ADDR + (i * E56PHY_RXS_OFFSET); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__RXS0_RXS_CFG_0, train_clk_gate_bypass_en) = 0x1FFF; + wr32_ephy(hw, addr, rdata); + } + + /* 5. Disable KR training mode */ + /* a. ALIAS::PDIG::KR_TRAINING_MODE = 0b0 */ + addr = E56G__PMD_BASER_PMD_CONTROL_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln0) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln1) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln2) = 0; + EPHY_XFLD(E56G__PMD_BASER_PMD_CONTROL, training_enable_ln3) = 0; + wr32_ephy(hw, addr, rdata); + + /* 6. Disable RX to TX parallel loopback */ + /* a. ALIAS::PDIG::RX_TO_TX_LPBK_EN = 0b0 */ + addr = E56G__PMD_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_PMD_CFG_5, rx_to_tx_lpbk_en) = 0x0; + wr32_ephy(hw, addr, rdata); + + /* + * The FSM to disable RXS is present in PDIG. The FSM disables the RXS when + * PDIG::PMD_CFG[0]::rx_en_cfg[<lane no.>] = 0b0 + */ + txgbe_e56_ephy_config(E56G__PMD_PMD_CFG_0, rx_en_cfg, 0); + + /* Wait RX FSM to be POWERDN_ST */ + timer = 0; + + while (EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx0_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx1_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx2_st) != 0x21 || + EPHY_XFLD(E56G__PMD_CTRL_FSM_RX_STAT_0, ctrl_fsm_rx3_st) != 0x21) { + rdata = 0; + addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; + rdata = rd32_ephy(hw, addr); + usec_delay(100); + if (timer++ > PHYINIT_TIMEOUT) { + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + break; + } + } + + return status; +} + static int txgbe_e56_disable_rx(struct txgbe_hw *hw) { int status = 0; @@ -2137,8 +3335,13 @@ int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed) * 14. Do SEQ::RX_DISABLE to disable RXS. Poll ALIAS::PDIG::CTRL_FSM_RX_ST * and confirm its value is POWERDN_ST */ - txgbe_e56_disable_rx(hw); - status = txgbe_e56_config_rx(hw, speed); + if (hw->mac.type == txgbe_mac_aml40) { + txgbe_e56_disable_rx40G(hw); + status = txgbe_e56_config_rx_40G(hw, speed); + } else { + txgbe_e56_disable_rx(hw); + status = txgbe_e56_config_rx(hw, speed); + } addr = E56PHY_INTR_0_ADDR; wr32_ephy(hw, addr, E56PHY_INTR_0_IDLE_ENTRY1); @@ -2205,6 +3408,86 @@ int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed) set_fields_e56(&value, 12, 12, 0); wr32_epcs(hw, SR_AN_CTRL, value); + if (speed == TXGBE_LINK_SPEED_40GB_FULL) { + value = rd32_epcs(hw, SR_PCS_CTRL1); + set_fields_e56(&value, 5, 2, 0x3); + wr32_epcs(hw, SR_PCS_CTRL1, value); + + value = rd32_epcs(hw, SR_PCS_CTRL2); + set_fields_e56(&value, 3, 0, 0x4); + wr32_epcs(hw, SR_PCS_CTRL2, value); + + value = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&value, 29, 29, 0x1); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, value); + + value = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&value, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, value); + + value = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, value); + + value = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&value, 30, 30, 0x1); + set_fields_e56(&value, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, value); + + value = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, value); + + value = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&value, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, value); + + value = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&value, 25, 24, 0x1); + set_fields_e56(&value, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, value); + + value = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&value, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, value); + + value = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&value, 18, 8, 0x294); + set_fields_e56(&value, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&value, 30, 28, 0x7); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 14, 12, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, value); + + value = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&value, 26, 24, 0x5); + set_fields_e56(&value, 10, 8, 0x5); + set_fields_e56(&value, 18, 16, 0x5); + set_fields_e56(&value, 2, 0, 0x5); + wr32_ephy(hw, DATAPATH_CFG1, value); + + value = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&value, 4, 0, 0x2); + wr32_ephy(hw, AN_CFG1, value); + + txgbe_e56_cfg_temp(hw); + txgbe_e56_cfg_40g(hw); + + value = rd32_ephy(hw, PMD_CFG0); + set_fields_e56(&value, 21, 20, 0x3); + set_fields_e56(&value, 19, 12, 0xf); + set_fields_e56(&value, 8, 8, 0x0); + set_fields_e56(&value, 1, 1, 0x1); + wr32_ephy(hw, PMD_CFG0, value); + } + if (speed == TXGBE_LINK_SPEED_25GB_FULL) { value = rd32_epcs(hw, SR_PCS_CTRL1); set_fields_e56(&value, 5, 2, 5); diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 0e3d7649d8..02c3305712 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2054,7 +2054,7 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); @@ -3206,7 +3206,7 @@ txgbe_dev_setup_link_thread_handler(void *param) struct txgbe_hw *hw = TXGBE_DEV_HW(dev); rte_thread_detach(rte_thread_self()); - if (hw->mac.type == txgbe_mac_aml) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) txgbe_dev_setup_link_alarm_handler_aml(hw); else txgbe_dev_setup_link_alarm_handler(dev); -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (12 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang ` (5 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The link was previously configured via firmware, but this approach resulted in unstable link behavior. To resolve the issue, re-add the PHY configuration flow directly into the driver. Fixes: ead3616f630d ("net/txgbe: support PHY configuration via SW-FW mailbox") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/meson.build | 1 + drivers/net/txgbe/base/txgbe.h | 2 + drivers/net/txgbe/base/txgbe_aml.c | 65 +- drivers/net/txgbe/base/txgbe_aml40.c | 43 +- drivers/net/txgbe/base/txgbe_e56.c | 22 +- drivers/net/txgbe/base/txgbe_e56.h | 2 + drivers/net/txgbe/base/txgbe_e56_bp.c | 2597 +++++++++++++++++++++++++ drivers/net/txgbe/base/txgbe_e56_bp.h | 3 + drivers/net/txgbe/base/txgbe_hw.c | 6 + drivers/net/txgbe/base/txgbe_hw.h | 4 +- drivers/net/txgbe/base/txgbe_osdep.h | 4 + drivers/net/txgbe/base/txgbe_phy.c | 21 + drivers/net/txgbe/base/txgbe_phy.h | 22 + drivers/net/txgbe/base/txgbe_type.h | 25 +- drivers/net/txgbe/txgbe_ethdev.c | 109 +- drivers/net/txgbe/txgbe_ethdev.h | 2 +- 16 files changed, 2898 insertions(+), 30 deletions(-) create mode 100644 drivers/net/txgbe/base/txgbe_e56_bp.c diff --git a/drivers/net/txgbe/base/meson.build b/drivers/net/txgbe/base/meson.build index 305c0291e3..a9a02577ce 100644 --- a/drivers/net/txgbe/base/meson.build +++ b/drivers/net/txgbe/base/meson.build @@ -13,4 +13,5 @@ base_sources = files( 'txgbe_phy.c', 'txgbe_vf.c', 'txgbe_e56.c', + 'txgbe_e56_bp.c', ) diff --git a/drivers/net/txgbe/base/txgbe.h b/drivers/net/txgbe/base/txgbe.h index 673a299860..27c3e3be38 100644 --- a/drivers/net/txgbe/base/txgbe.h +++ b/drivers/net/txgbe/base/txgbe.h @@ -13,5 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_vf.h" #include "txgbe_dcb.h" +#include "txgbe_e56.h" +#include "txgbe_e56_bp.h" #endif /* _TXGBE_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index 008b0245e5..a5b9d951ea 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -13,6 +13,7 @@ #include "txgbe_hw.h" #include "txgbe_aml.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml(struct txgbe_hw *hw) { @@ -84,6 +85,13 @@ s32 txgbe_check_mac_link_aml(struct txgbe_hw *hw, u32 *speed, *speed = TXGBE_LINK_SPEED_UNKNOWN; } + if (txgbe_xpcs_an_enabled(hw)) { + if (!hw->an_done) { + *link_up = false; + *speed = TXGBE_LINK_SPEED_UNKNOWN; + } + } + return 0; } @@ -95,23 +103,41 @@ s32 txgbe_get_link_capabilities_aml(struct txgbe_hw *hw, *speed = TXGBE_LINK_SPEED_10GB_FULL | TXGBE_LINK_SPEED_25GB_FULL; *autoneg = true; + } else if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + if (hw->phy.fiber_suppport_speed == + TXGBE_LINK_SPEED_10GB_FULL) { + hw->devarg.auto_neg = false; + *autoneg = false; + } else { + *autoneg = true; + } + *speed = hw->phy.fiber_suppport_speed; } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core0 || hw->phy.sfp_type == txgbe_sfp_type_25g_sr_core1 || hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1) { + hw->phy.sfp_type == txgbe_sfp_type_25g_lr_core1 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || + hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { *speed = TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; - } else if (hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core0 || - hw->phy.sfp_type == txgbe_sfp_type_25g_aoc_core1) { - *speed = TXGBE_LINK_SPEED_25GB_FULL; + } else if (hw->phy.media_type == txgbe_media_type_backplane) { + /* Backplane */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; + /* Backplane supports autonegotiation */ + *autoneg = hw->devarg.auto_neg; + } else if (hw->phy.media_type == txgbe_media_type_fiber) { + /* Fiber */ + *speed = TXGBE_LINK_SPEED_10GB_FULL | + TXGBE_LINK_SPEED_25GB_FULL; *autoneg = false; } else { - /* SFP */ - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) - *speed = TXGBE_LINK_SPEED_25GB_FULL; - else - *speed = TXGBE_LINK_SPEED_10GB_FULL; - *autoneg = true; + /* Unknown */ + *speed = TXGBE_LINK_SPEED_UNKNOWN; + *autoneg = false; + PMD_DRV_LOG(DEBUG, "GET link capabilities failed"); + return TXGBE_ERR_LINK_SETUP; } return 0; @@ -193,7 +219,7 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) { + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) { DEBUGOUT("SFP not detected, skip setup mac link"); return 0; } @@ -216,6 +242,23 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, speed, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return 0; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + if (txgbe_gpio_ext_check(hw, TXGBE_SFP1_MOD_ABS_LS | TXGBE_SFP1_RX_LOS_LS)) { DEBUGOUT("RX LOS"); diff --git a/drivers/net/txgbe/base/txgbe_aml40.c b/drivers/net/txgbe/base/txgbe_aml40.c index 84c130704a..d350f18c4b 100644 --- a/drivers/net/txgbe/base/txgbe_aml40.c +++ b/drivers/net/txgbe/base/txgbe_aml40.c @@ -14,6 +14,7 @@ #include "txgbe_aml.h" #include "txgbe_aml40.h" #include "txgbe_e56.h" +#include "txgbe_e56_bp.h" void txgbe_init_ops_aml40(struct txgbe_hw *hw) { @@ -98,7 +99,10 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { *speed = TXGBE_LINK_SPEED_40GB_FULL; - *autoneg = false; + *autoneg = true; + } else if (txgbe_is_backplane(hw)) { + *speed = TXGBE_LINK_SPEED_40GB_FULL; + *autoneg = true; } else { /* * Temporary workaround: set speed to 40G even if sfp not present @@ -115,8 +119,22 @@ s32 txgbe_get_link_capabilities_aml40(struct txgbe_hw *hw, u32 txgbe_get_media_type_aml40(struct txgbe_hw *hw) { - UNREFERENCED_PARAMETER(hw); - return txgbe_media_type_fiber_qsfp; + u8 device_type = hw->subsystem_device_id & 0xF0; + enum txgbe_media_type media_type; + + switch (device_type) { + case TXGBE_DEV_ID_KR_KX_KX4: + media_type = txgbe_media_type_backplane; + break; + case TXGBE_DEV_ID_SFP: + media_type = txgbe_media_type_fiber_qsfp; + break; + default: + media_type = txgbe_media_type_unknown; + break; + } + + return media_type; } s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, @@ -135,7 +153,7 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, *need_reset = false; - if (hw->phy.sfp_type == txgbe_sfp_type_not_present) + if (hw->phy.sfp_type == txgbe_sfp_type_not_present && !txgbe_is_backplane(hw)) hw->phy.identify_sfp(hw); /* Check to see if speed passed in is supported. */ @@ -148,6 +166,23 @@ s32 txgbe_setup_phy_link_aml40(struct txgbe_hw *hw, if (speed == TXGBE_LINK_SPEED_UNKNOWN) return TXGBE_ERR_LINK_SETUP; + if (txgbe_xpcs_an_enabled(hw)) { + txgbe_e56_check_phy_link(hw, &link_speed, &link_up); + if (link_up && hw->an_done && !autoneg_wait_to_complete) + return status; + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 40, autoneg_wait_to_complete); + rte_spinlock_unlock(&hw->phy_lock); + return status; + } + + if (txgbe_is_backplane(hw) || txgbe_is_dac_cable(hw) || + hw->phy.ffe_set) { + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_tx_ffe_cfg(hw, speed); + rte_spinlock_unlock(&hw->phy_lock); + } + for (i = 0; i < 4; i++) { txgbe_e56_check_phy_link(hw, &link_speed, &link_up); if (link_up) diff --git a/drivers/net/txgbe/base/txgbe_e56.c b/drivers/net/txgbe/base/txgbe_e56.c index c6fb2627d4..79f3a81348 100644 --- a/drivers/net/txgbe/base/txgbe_e56.c +++ b/drivers/net/txgbe/base/txgbe_e56.c @@ -53,7 +53,7 @@ int txgbe_e56_int_cmp(const void *a, const void *b) } s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up) + bool *link_up) { u32 rdata = 0; u32 links_reg = 0; @@ -101,7 +101,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; } else if (speed == TXGBE_LINK_SPEED_25GB_FULL) { if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || - hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S25G_TX_FFE_CFG_DAC_MAIN; pre1 = S25G_TX_FFE_CFG_DAC_PRE1; pre2 = S25G_TX_FFE_CFG_DAC_PRE2; @@ -119,7 +120,8 @@ u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed) post = S10G_TX_FFE_CFG_POST; if (hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || - hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) { + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1 || + txgbe_is_backplane(hw)) { ffe_main = S40G_TX_FFE_CFG_MAIN; pre1 = S40G_TX_FFE_CFG_PRE1; pre2 = S40G_TX_FFE_CFG_PRE2; @@ -1508,7 +1510,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1543,7 +1545,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) if (((rdata >> (i * 8)) & 0x3f) == 0x21) break; if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1620,7 +1622,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) addr = E56PHY_CTRL_FSM_RX_STAT_0_ADDR; rdata = rd32_ephy(hw, addr); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1667,7 +1669,7 @@ txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, u32 speed) if (((rdata >> (i * 8)) & 0x3f) == 0x21) break; if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; return -1; } @@ -1936,7 +1938,7 @@ int txgbe_temp_track_seq_40g(struct txgbe_hw *hw, u32 speed) CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; } else { - DEBUGOUT("Error Speed\n"); + DEBUGOUT("Error Speed"); return 0; } @@ -3195,7 +3197,7 @@ static int txgbe_e56_disable_rx40G(struct txgbe_hw *hw) rdata = rd32_ephy(hw, addr); usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } @@ -3301,7 +3303,7 @@ static int txgbe_e56_disable_rx(struct txgbe_hw *hw) break; usec_delay(100); if (timer++ > PHYINIT_TIMEOUT) { - DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!\n"); + DEBUGOUT("ERROR: Wait E56PHY_CTRL_FSM_RX_STAT_0_ADDR Timeout!"); break; } } diff --git a/drivers/net/txgbe/base/txgbe_e56.h b/drivers/net/txgbe/base/txgbe_e56.h index 7509526263..974af675ed 100644 --- a/drivers/net/txgbe/base/txgbe_e56.h +++ b/drivers/net/txgbe/base/txgbe_e56.h @@ -1739,6 +1739,8 @@ int txgbe_temp_track_seq(struct txgbe_hw *hw, u32 speed); int txgbe_e56_get_temp(struct txgbe_hw *hw, int *temp); int txgbe_set_link_to_amlite(struct txgbe_hw *hw, u32 speed); int txgbe_e56_reconfig_rx(struct txgbe_hw *hw, u32 speed); +s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, + bool *link_up); s32 txgbe_e56_fec_set(struct txgbe_hw *hw); s32 txgbe_e56_fec_polling(struct txgbe_hw *hw, bool *link_up); u32 txgbe_e56_tx_ffe_cfg(struct txgbe_hw *hw, u32 speed); diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.c b/drivers/net/txgbe/base/txgbe_e56_bp.c new file mode 100644 index 0000000000..0cb2bc0fd6 --- /dev/null +++ b/drivers/net/txgbe/base/txgbe_e56_bp.c @@ -0,0 +1,2597 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024-2026 Beijing WangXun Technology Co., Ltd. + */ + +#include "txgbe_e56.h" +#include "txgbe_hw.h" +#include "txgbe_osdep.h" +#include "txgbe_phy.h" +#include "txgbe_e56_bp.h" +#include "txgbe.h" +#include "../txgbe_logs.h" + +static int +txgbe_e56_set_rxs_ufine_le_max(struct txgbe_hw *hw, u32 speed) +{ + u32 rdata, addr; + u32 ULTRAFINE_CODE[4] = {0}; + int lane_num = 0, lane_idx = 0; + u32 CMVAR_UFINE_MAX = 0; + + switch (speed) { + case 10: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + case 40: + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + lane_num = 4; + break; + case 25: + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* ii get rx ana_bbcdr_ultrafine_i[14, 12] per lane */ + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + ULTRAFINE_CODE[lane_idx] = FIELD_GET_M(GENMASK(14, 12), rdata); + BP_LOG("ULTRAFINE_CODE[%d] = %d, CMVAR_UFINE_MAX: %x\n", + lane_idx, ULTRAFINE_CODE[lane_idx], CMVAR_UFINE_MAX); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* b. Perform the below logic sequence */ + while (ULTRAFINE_CODE[lane_idx] > CMVAR_UFINE_MAX) { + ULTRAFINE_CODE[lane_idx] -= 1; + addr = E56G__RXS0_ANA_OVRDVAL_5_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 12, ULTRAFINE_CODE[lane_idx]); + wr32_ephy(hw, addr, rdata); + + /* ovrd_en_ana_bbcdr_ultrafine=1 override ASIC value */ + addr = E56G__RXS0_ANA_OVRDEN_1_ADDR + + (E56PHY_RXS_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + wr32_ephy(hw, addr, rdata | BIT(3)); + + /* Wait until 1milliseconds or greater */ + usec_delay(1000); + } + } + return 0; +} + +static int txgbe_e56_rxs_osc_init_for_temp_track_range(struct txgbe_hw *hw, + u32 speed) +{ + int OFFSET_CENTRE_RANGE_H[4] = {0}, OFFSET_CENTRE_RANGE_L[4] = {}, RANGE_FINAL[4] = {}; + int RX_COARSE_MID_TD, CMVAR_RANGE_H = 0, CMVAR_RANGE_L = 0; + int status = 0, lane_num = 0; + int T = 40, lane_id = 0; + u32 addr, rdata; + + /* Set CMVAR_RANGE_H/L based on the link speed mode */ + switch (speed) { + case 10: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 1; + break; + case 40: + CMVAR_RANGE_H = S10G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S10G_CMVAR_RANGE_L; + lane_num = 4; + break; + case 25: + CMVAR_RANGE_H = S25G_CMVAR_RANGE_H; + CMVAR_RANGE_L = S25G_CMVAR_RANGE_L; + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + /* 1. Read the temperature T just before RXS is enabled. */ + txgbe_e56_get_temp(hw, &T); + + /* 2. Define software variable RX_COARSE_MID_TD */ + if (T < -5) + RX_COARSE_MID_TD = 10; + else if (T < 30) + RX_COARSE_MID_TD = 9; + else if (T < 65) + RX_COARSE_MID_TD = 8; + else if (T < 100) + RX_COARSE_MID_TD = 7; + else + RX_COARSE_MID_TD = 6; + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_H); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 1 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_H[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_H[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_H[lane_id] = OFFSET_CENTRE_RANGE_H[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_H[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_H[lane_id]; + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 2 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, CMVAR_RANGE_L); + wr32_ephy(hw, addr, rdata); + + addr = 0x08c + (0x200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 29, 29, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1540 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 22, 22, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x1); + wr32_ephy(hw, addr, rdata); + } + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0xf); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x09090909 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 3 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + OFFSET_CENTRE_RANGE_L[lane_id] = (rdata >> 4) & 0xf; + if (OFFSET_CENTRE_RANGE_L[lane_id] > RX_COARSE_MID_TD) + OFFSET_CENTRE_RANGE_L[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] - + RX_COARSE_MID_TD; + else + OFFSET_CENTRE_RANGE_L[lane_id] = RX_COARSE_MID_TD - + OFFSET_CENTRE_RANGE_L[lane_id]; + } + for (lane_id = 0; lane_id < lane_num; lane_id++) { + RANGE_FINAL[lane_id] = OFFSET_CENTRE_RANGE_L[lane_id] < + OFFSET_CENTRE_RANGE_H[lane_id] ? + CMVAR_RANGE_L : CMVAR_RANGE_H; + BP_LOG("lane_id:%d-RANGE_L:%x-RANGE_H:%x-RANGE_FINAL:%x\n", + lane_id, OFFSET_CENTRE_RANGE_L[lane_id], + OFFSET_CENTRE_RANGE_H[lane_id], RANGE_FINAL[lane_id]); + } + + /* 7. Do SEQ::RX_DISABLE to disable RXS. */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + wr32_ephy(hw, 0x1400, rdata); + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x21212121 & GENMASK(8 * lane_num - 1, 0))), + 100, 2000, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + if (status) + BP_LOG("Wait fsm_rx_sts 4 = %x : %d, Wait rx_sts %s.\n", + rdata, status, status ? "FAILED" : "SUCCESS"); + rdata = rd32_ephy(hw, 0x15ec); + wr32_ephy(hw, 0x15ec, rdata); + + for (lane_id = 0; lane_id < lane_num; lane_id++) { + addr = 0x0b4 + (0x0200 * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, RANGE_FINAL[lane_id]); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_id * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1530 + (0x02c * lane_id); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 27, 0x0); + wr32_ephy(hw, addr, rdata); + } + + /* Do SEQ::RX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, E56PHY_PMD_CFG_0_RX_EN_CFG, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1400, rdata); + + return status; +} + +static int txgbe_e56_rxs_post_cdr_lock_temp_track_seq(struct txgbe_hw *hw, + u32 speed) +{ + int status = 0; + u32 rdata; + int SECOND_CODE; + int COARSE_CODE; + int FINE_CODE; + int ULTRAFINE_CODE; + + int CMVAR_SEC_LOW_TH = 0; + int CMVAR_UFINE_MAX = 0; + int CMVAR_FINE_MAX = 0; + int CMVAR_UFINE_UMAX_WRAP = 0; + int CMVAR_COARSE_MAX = 0; + int CMVAR_UFINE_FMAX_WRAP = 0; + int CMVAR_FINE_FMAX_WRAP = 0; + int CMVAR_SEC_HIGH_TH = 0; + int CMVAR_UFINE_MIN = 0; + int CMVAR_FINE_MIN = 0; + int CMVAR_UFINE_UMIN_WRAP = 0; + int CMVAR_COARSE_MIN = 0; + int CMVAR_UFINE_FMIN_WRAP = 0; + int CMVAR_FINE_FMIN_WRAP = 0; + + if (speed == 10) { + CMVAR_SEC_LOW_TH = S10G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S10G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S10G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S10G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S10G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S10G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S10G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S10G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S10G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S10G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S10G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S10G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S10G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S10G_CMVAR_FINE_FMIN_WRAP; + } else if (speed == 25) { + CMVAR_SEC_LOW_TH = S25G_CMVAR_SEC_LOW_TH; + CMVAR_UFINE_MAX = S25G_CMVAR_UFINE_MAX; + CMVAR_FINE_MAX = S25G_CMVAR_FINE_MAX; + CMVAR_UFINE_UMAX_WRAP = S25G_CMVAR_UFINE_UMAX_WRAP; + CMVAR_COARSE_MAX = S25G_CMVAR_COARSE_MAX; + CMVAR_UFINE_FMAX_WRAP = S25G_CMVAR_UFINE_FMAX_WRAP; + CMVAR_FINE_FMAX_WRAP = S25G_CMVAR_FINE_FMAX_WRAP; + CMVAR_SEC_HIGH_TH = S25G_CMVAR_SEC_HIGH_TH; + CMVAR_UFINE_MIN = S25G_CMVAR_UFINE_MIN; + CMVAR_FINE_MIN = S25G_CMVAR_FINE_MIN; + CMVAR_UFINE_UMIN_WRAP = S25G_CMVAR_UFINE_UMIN_WRAP; + CMVAR_COARSE_MIN = S25G_CMVAR_COARSE_MIN; + CMVAR_UFINE_FMIN_WRAP = S25G_CMVAR_UFINE_FMIN_WRAP; + CMVAR_FINE_FMIN_WRAP = S25G_CMVAR_FINE_FMIN_WRAP; + } + + status |= txgbe_e56_rx_rd_second_code(hw, &SECOND_CODE); + + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + COARSE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i); + FINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i); + ULTRAFINE_CODE = EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i); + + if (SECOND_CODE <= CMVAR_SEC_LOW_TH) { + if (ULTRAFINE_CODE < CMVAR_UFINE_MAX) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE + 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE < CMVAR_FINE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE < CMVAR_COARSE_MAX) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMAX_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE + 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + BP_LOG("ERROR: (SECOND_CODE <= CMVAR_SEC_LOW_TH) temperature tracking occurs Error condition\n"); + } + } else if (SECOND_CODE >= CMVAR_SEC_HIGH_TH) { + if (ULTRAFINE_CODE > CMVAR_UFINE_MIN) { + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_ultrafine_i, + ULTRAFINE_CODE - 1); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (FINE_CODE > CMVAR_FINE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_UMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_fine_i) = FINE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else if (COARSE_CODE > CMVAR_COARSE_MIN) { + EPHY_RREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_ultrafine_i) = CMVAR_UFINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, + ana_bbcdr_fine_i) = CMVAR_FINE_FMIN_WRAP; + EPHY_XFLD(E56G__RXS0_ANA_OVRDVAL_5, ana_bbcdr_coarse_i) = COARSE_CODE - 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDVAL_5); + EPHY_RREG(E56G__RXS0_ANA_OVRDEN_1); + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_coarse_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_fine_i) = 1; + EPHY_XFLD(E56G__RXS0_ANA_OVRDEN_1, ovrd_en_ana_bbcdr_ultrafine_i) = 1; + EPHY_WREG(E56G__RXS0_ANA_OVRDEN_1); + } else { + BP_LOG("ERROR: (SECOND_CODE >= CMVAR_SEC_HIGH_TH) temperature tracking occurs Error condition\n"); + } + } + + return status; +} + +static int txgbe_e56_ctle_bypass_seq(struct txgbe_hw *hw, u8 bp_link_mode) +{ + u32 rdata; + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS0_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS0_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, ovrd_en_rxs0_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS0_OVRDEN_1); + + if (bp_link_mode == 40) { + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_0, ana_ctle_bypass_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_bypass_i, 1); + + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS1_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS2_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDVAL_3, ana_ctle_cz_cstm_i, 0); + txgbe_e56_ephy_config(E56G__RXS3_ANA_OVRDEN_0, ovrd_en_ana_ctle_cz_cstm_i, 1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS1_OVRDVAL_1, rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS2_OVRDVAL_1, rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDVAL_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDVAL_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_en_i) = 0; + EPHY_XFLD(E56G__PMD_RXS3_OVRDVAL_1, rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDVAL_1); + + EPHY_RREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS1_OVRDEN_1, ovrd_en_rxs1_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS1_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS2_OVRDEN_1, ovrd_en_rxs2_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS2_OVRDEN_1); + EPHY_RREG(E56G__PMD_RXS3_OVRDEN_1); + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_en_i) = 1; + EPHY_XFLD(E56G__PMD_RXS3_OVRDEN_1, ovrd_en_rxs3_rx0_ctle_train_done_o) = 1; + EPHY_WREG(E56G__PMD_RXS3_OVRDEN_1); + } + return 0; +} + +static int txgbe_e56_rxs_adc_adapt_seq(struct txgbe_hw *hw, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + u32 rdata = 0, addr = 0; + int status = 0; + + int timer = 0, j = 0; + + switch (hw->bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait RXS0-3_OVRDVAL[1]::rxs0-3_rx0_cdr_rdy_o = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(12)), + 100, 2000, hw, 0x1544); + if (status) + BP_LOG("rxs%d_rx0_cdr_rdy_o = %x, %s.\n", + lane_idx, rdata, + status ? "FAILED" : "SUCCESS"); + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + /* 4. Disable VGA and CTLE training so they don't interfere with ADC calibration */ + /* a. Set ALIAS::RXS::VGA_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 14, 14, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Set ALIAS::RXS::CTLE_TRAIN_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 9, 9, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + /* 5. Perform ADC interleaver calibration */ + /* a. Remove the OVERRIDE on ALIAS::RXS::ADC_INTL_CAL_DONE */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_intl_cal_done_o bit17 = 1 */ + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(17)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_intl_cal_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* 6. Perform ADC offset adaptation and ADC gain adaptation, + * repeat them a few times and after that keep it disabled. + */ + for (j = 0; j < 16; j++) { + /* a. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, addr, rdata); + + /* b. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_ofst_adapt_done_o bit26 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, + !(rdata & BIT(26)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_ofst_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* c. ALIAS::RXS::ADC_OFST_ADAPT_EN = 0b0 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + /* d. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b1 */ + rdata = 0x0000; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x1); + wr32_ephy(hw, addr, rdata); + + /* e. Wait for 1ms or greater */ + /* usec_delay(1000); */ + /* set ovrd_en_rxs0_rx0_adc_ofst_adapt_done_o bit1=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 1, 0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + /* Wait rxs0_rx0_adc_gain_adapt_done_o bit29 = 0 */ + status = kr_read_poll(rd32_ephy, rdata, !(rdata & BIT(29)), + 100, 2000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_adc_gain_adapt_done_o %d = %x, %s.\n", + j, rdata, status ? "FAILED" : "SUCCESS"); + + /* f. ALIAS::RXS::ADC_GAIN_ADAPT_EN = 0b0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + } + /* g. Repeat #a to #f total 16 times */ + + /* 7. Perform ADC interleaver adaptation for 10ms or greater, + * and after that disable it + */ + /* a. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x1); + wr32_ephy(hw, addr, rdata); + /* b. Wait for 10ms or greater */ + msleep(20); + + /* c. ALIAS::RXS::ADC_INTL_ADAPT_EN = 0b0 */ + /* set ovrd_en_rxs0_rx0_adc_intl_adapt_en_i=0 */ + addr = 0x1538 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0); + wr32_ephy(hw, addr, rdata); + + /* 8. Now re-enable VGA and CTLE trainings, so that it continues + * to adapt tracking changes in temperature or voltage + * <1>Set ALIAS::RXS::VGA_TRAIN_EN = 0b1 + */ + /* set rxs0_rx0_vga_train_en_i=1 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 7, 7, 0x1); + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, rxs0_rx0_ctle_train_en_i) = 1; + wr32_ephy(hw, addr, rdata); + + /* <2>wait for ALIAS::RXS::VGA_TRAIN_DONE = 1 */ + /* set ovrd_en_rxs0_rx0_vga_train_done_o = 0 */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0x0); + wr32_ephy(hw, addr, rdata); + + /* Wait rxs0_rx0_vga_train_done_o bit8 = 0 */ + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + status = kr_read_poll(rd32_ephy, rdata, (rdata & BIT(8)), + 100, 3000, hw, addr); + if (status) + BP_LOG("rxs0_rx0_vga_train_done_o = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + if (bypass_ctle == 0) { + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_done_o) = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0; + timer = 0; + addr = 0x1544 + (E56PHY_PMD_RX_OFFSET * lane_idx); + while (EPHY_XFLD(E56G__PMD_RXS0_OVRDVAL_1, + rxs0_rx0_ctle_train_done_o) != 1) { + rdata = rd32_ephy(hw, addr); + usec_delay(500); + + if (timer++ > PHYINIT_TIMEOUT) + break; + } + } + + /* a. Remove the OVERRIDE on ALIAS::RXS::VGA_TRAIN_EN */ + addr = 0x1534 + (E56PHY_PMD_RX_OFFSET * lane_idx); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 15, 15, 0); + /* b. Remove the OVERRIDE on ALIAS::RXS::CTLE_TRAIN_EN */ + if (bypass_ctle == 0) + EPHY_XFLD(E56G__PMD_RXS0_OVRDEN_1, + ovrd_en_rxs0_rx0_ctle_train_en_i) = 0; + wr32_ephy(hw, addr, rdata); + } + + return status; +} + +static int txgbe_e56_phy_rxs_calib_adapt_seq(struct txgbe_hw *hw, + u8 bp_link_mode, u32 bypass_ctle) +{ + int lane_num = 0, lane_idx = 0; + int status = 0; + u32 rdata, addr; + + switch (bp_link_mode) { + case 10: + lane_num = 1; + break; + case 40: + lane_num = 4; + break; + case 25: + lane_num = 1; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 25, 25, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 0, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 28, 28, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 3, 3, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 16, 16, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 23, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 17, 17, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1534 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, addr, rdata); + + addr = 0x1544 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 31, 31, 0x0); + wr32_ephy(hw, addr, rdata); + + addr = 0x1538 + (lane_idx * E56PHY_PMD_RX_OFFSET); + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 6, 6, 0x1); + wr32_ephy(hw, addr, rdata); + } + if (bypass_ctle != 0) + status |= txgbe_e56_ctle_bypass_seq(hw, bp_link_mode); + + status |= txgbe_e56_rxs_osc_init_for_temp_track_range(hw, bp_link_mode); + + /* Wait an fsm_rx_sts 25G */ + BP_LOG("Wait CTRL_FSM_RX_STAT[0]::ctrl_fsm_rx0_st to be ready ...\n"); + + status |= kr_read_poll(rd32_ephy, rdata, + (((rdata & 0x3f3f3f3f) & GENMASK(8 * lane_num - 1, 0)) + == (0x1b1b1b1b & GENMASK(8 * lane_num - 1, 0))), + 1000, 300, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("wait ctrl_fsm_rx0_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + return status; +} + +static int txgbe_e56_cms_cfg_for_temp_track_range(struct txgbe_hw *hw) +{ + int status = 0, T = 40; + u32 addr, rdata; + + status = txgbe_e56_get_temp(hw, &T); + if (T < 40) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + } else if (T > 70) { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x1); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I, 0x3); + wr32_ephy(hw, addr, rdata); + } else { + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_LF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 24, 24, 0x1); + set_fields_e56(&rdata, 31, 29, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_10_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 1, 0, 0x0); + wr32_ephy(hw, addr, rdata); + } + return status; +} + +static int txgbe_e56_bp_cfg_25g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDVAL_0_INT_PLL0_TX_SIGNAL_TYPE_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_PIN_OVRDEN_0_OVRD_EN_PLL0_TX_SIGNAL_TYPE_I, + 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDVAL_2_ANA_LCPLL_HF_VCO_SWING_CTRL_I, + 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, + E56PHY_CMS_ANA_OVRDEN_0_OVRD_EN_ANA_LCPLL_HF_VCO_SWING_CTRL_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDVAL_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CMS_ANA_OVRDEN_1_OVRD_EN_ANA_LCPLL_HF_TEST_IN_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 27, 24, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_25GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_PREDIV1, 0x700); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_1_TARGET_CNT1, 0x2418); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_RANGE_SEL1, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_VCO_CODE_INIT, 0x7fb); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_OSC_CURRENT_BOOST_EN1, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_4_BBCDR_CURRENT_BOOST1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xa); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_0_ADC_INTL2SLICE_DELAY1, 0x3333); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_INTL_CONFIG_2_INTERLEAVER_HBW_DISABLE1, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1f8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0xf0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__RXS0_FOM_18__ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFL_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFL_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFFH_HINT__MSB, + E56G__RXS0_FOM_18__DFE_COEFFH_HINT__LSB, 0x0); + set_fields_e56(&rdata, E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__MSB, + E56G__RXS0_FOM_18__DFE_COEFF_HINT_LOAD__LSB, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x0); + set_fields_e56(&rdata, 14, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_e56_bp_cfg_10g(struct txgbe_hw *hw) +{ + u32 addr, rdata; + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_7_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDVAL_7 *)&rdata)->ana_lcpll_lf_vco_swing_ctrl_i = 0xf; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_vco_swing_ctrl_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDVAL_9_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 23, 0, 0x260000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56G__CMS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G__CMS_ANA_OVRDEN_1 *)&rdata)->ovrd_en_ana_lcpll_lf_test_in_i = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_TXS_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_TXS_CFG_1_ADAPTATION_WAIT_CNT_X256, 0xf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_WKUP_CNT_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTLDO_WKUP_CNT_X32, 0xff); + set_fields_e56(&rdata, E56PHY_TXS_WKUP_CNTDCC_WKUP_CNT_X32, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 19, 16, 0x6); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_PIN_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_PIN_OVRDEN_0_OVRD_EN_TX0_EFUSE_BITS_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDVAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDVAL_1_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_TXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_TXS_ANA_OVRDEN_0_OVRD_EN_ANA_TEST_DAC_I, 0x1); + wr32_ephy(hw, addr, rdata); + + txgbe_e56_tx_ffe_cfg(hw, TXGBE_LINK_SPEED_10GB_FULL); + + rdata = 0x0000; + addr = E56PHY_RXS_RXS_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_DSER_DATA_SEL, 0x0); + set_fields_e56(&rdata, E56PHY_RXS_RXS_CFG_0_TRAIN_CLK_GATE_BYPASS_EN, 0x1fff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_1_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->prediv0 = 0xfa0; + ((E56G_RXS0_OSC_CAL_N_CDR_0 *)&rdata)->target_cnt0 = 0x203a; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_4_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_range_sel0 = 0x2; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->vco_code_init = 0x7ff; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->osc_current_boost_en0 = 0x1; + ((E56G_RXS0_OSC_CAL_N_CDR_4 *)&rdata)->bbcdr_current_boost0 = 0x0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_SDM_WIDTH, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_PROP_STEP_POSTLOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_POSTLOCK, + 0xc); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BB_CDR_GAIN_CTRL_PRELOCK, + 0xf); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_5_BBCDR_RDY_CNT, 0x3); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OSC_CAL_N_CDR_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_PRELOCK, 0x7); + set_fields_e56(&rdata, E56PHY_RXS_OSC_CAL_N_CDR_6_PI_GAIN_CTRL_POSTLOCK, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_0_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_0 *)&rdata)->adc_intl2slice_delay0 = 0x5555; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_INTL_CONFIG_2_ADDR; + rdata = rd32_ephy(hw, addr); + ((E56G_RXS0_INTL_CONFIG_2 *)&rdata)->interleaver_hbw_disable0 = 0x1; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_LTH, 0x56); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_0_ADC_DATA_PEAK_UTH, 0x6a); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_LTH, 0x1e8); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_1_C1_UTH, 0x78); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_LTH, 0x100); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_2_CM1_UTH, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_TXFFE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_LTH, 0x4); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_CM2_UTH, 0x37); + set_fields_e56(&rdata, E56PHY_RXS_TXFFE_TRAINING_3_TXFFE_TRAIN_MOD_TYPE, 0x38); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_0_VGA_TARGET, 0x34); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_VGA_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT0, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA1_CODE_INIT123, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_VGA_TRAINING_1_VGA2_CODE_INIT123, 0xa); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT0, 0x9); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_0_CTLE_CODE_INIT123, 0x9); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_1_LFEQ_LUT, 0x1ffffea); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P1, 0x18); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_2_ISI_TH_FRAC_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_CTLE_TRAINING_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P1, 1); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P2, 0); + set_fields_e56(&rdata, E56PHY_RXS_CTLE_TRAINING_3_TAP_WEIGHT_P3, 0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_SLICE_DATA_AVG_CNT, + 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_ADC_DATA_AVG_CNT, 0x3); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_0_FE_OFFSET_DAC_CLK_CNT_X8, + 0xc); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_OFFSET_N_GAIN_CAL_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_OFFSET_N_GAIN_CAL_1_SAMP_ADAPT_CFG, 0x5); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_FFE_TRAINING_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_FFE_TRAINING_0_FFE_TAP_EN, 0xf9ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_IDLE_DETECT_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0xa); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0x5); + wr32_ephy(hw, addr, rdata); + + addr = 0x6cc; + rdata = 0x8020000; + wr32_ephy(hw, addr, rdata); + addr = 0x94; + rdata = 0; + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_0_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_0_OVRD_EN_ANA_EN_RTERM_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_6_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 4, 0, 0x6); + set_fields_e56(&rdata, 14, 13, 0x2); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_BBCDR_VCOFILT_BYP_I, + 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_1_OVRD_EN_ANA_TEST_BBCDR_I, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 2, 0, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDVAL_17_ANA_VGA2_BOOST_CSTM_I, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_ANABS_CONFIG_I, 0x1); + set_fields_e56(&rdata, E56PHY_RXS_ANA_OVRDEN_3_OVRD_EN_ANA_VGA2_BOOST_CSTM_I, + 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDVAL_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_ANA_OVRDEN_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 13, 13, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_EYE_SCAN_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_RXS_EYE_SCAN_1_EYE_SCAN_REF_TIMER, 0x400); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_RXS_RINGO_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, 21, 12, 0x366); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_3_CTRL_FSM_TIMEOUT_X64K, 0x80); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_ON_PERIOD_X64K, 0x18); + set_fields_e56(&rdata, E56PHY_PMD_CFG_4_TRAIN_DC_PERIOD_X512K, 0x3e); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_PMD_CFG_5_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_PMD_CFG_5_USE_RECENT_MARKER_OFFSET, 0x1); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_CONT_ON_ADC_GAIN_CAL_ERR, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_DO_RX_ADC_OFST_CAL, 0x3); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_0_RX_ERR_ACTION_EN, 0x40); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_1_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST0_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST1_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST2_WAIT_CNT_X4096, 0xff); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_1_TRAIN_ST3_WAIT_CNT_X4096, 0xff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_2_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST4_WAIT_CNT_X4096, 0x1); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST5_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST6_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_2_TRAIN_ST7_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_3_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST8_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST9_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST10_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_3_TRAIN_ST11_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_4_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST12_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST13_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST14_WAIT_CNT_X4096, 0x4); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_4_TRAIN_ST15_WAIT_CNT_X4096, 0x4); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_7_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST4_EN, 0x4bf); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_7_TRAIN_ST5_EN, 0xc4bf); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_8_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_8_TRAIN_ST7_EN, 0x47ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_12_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_12_TRAIN_ST15_EN, 0x67ff); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_13_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST0_DONE_EN, 0x8001); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_13_TRAIN_ST1_DONE_EN, 0x8002); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_14_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_14_TRAIN_ST3_DONE_EN, 0x8008); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_15_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_15_TRAIN_ST4_DONE_EN, 0x8004); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_17_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_17_TRAIN_ST8_DONE_EN, 0x20c0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_18_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_18_TRAIN_ST10_DONE_EN, 0x0); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_29_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_29_TRAIN_ST15_DC_EN, 0x3f6d); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_33_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN0_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_33_TRAIN1_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_CTRL_FSM_CFG_34_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN2_RATE_SEL, 0x8000); + set_fields_e56(&rdata, E56PHY_CTRL_FSM_CFG_34_TRAIN3_RATE_SEL, 0x8000); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_KRT_TFSM_CFG_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X1000K, 0x49); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_MAX_WAIT_TIMER_X8000K, 0x37); + set_fields_e56(&rdata, E56PHY_KRT_TFSM_CFGKRT_TFSM_HOLDOFF_TIMER_X256K, 0x2f); + wr32_ephy(hw, addr, rdata); + + rdata = 0x0000; + addr = E56PHY_FETX_FFE_TRAIN_CFG_0_ADDR; + rdata = rd32_ephy(hw, addr); + set_fields_e56(&rdata, E56PHY_FETX_FFE_TRAIN_CFG_0_KRT_FETX_INIT_FFE_CFG_2, + 0x2); + wr32_ephy(hw, addr, rdata); + + return 0; +} + +static int txgbe_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode) +{ + int status = 0; + u32 rdata = 0; + + u32 speed_select = 0; + u32 pcs_type_sel = 0; + u32 cns_en = 0; + u32 rsfec_en = 0; + u32 pma_type = 0; + u32 an0_rate_select = 0; + + switch (bp_link_mode) { + case 10: + bp_link_mode = 10; + speed_select = 0; /* 10 Gb/s */ + pcs_type_sel = 0; /* 10GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0xb; /* 10GBASE-KR PMA/PMD type */ + an0_rate_select = 2; /* 10G-KR */ + break; + case 40: + bp_link_mode = 40; + speed_select = 3; /* 40 Gb/s */ + pcs_type_sel = 4; /* 40GBASE-R PCS Type */ + cns_en = 0; /* CNS_EN disable */ + rsfec_en = 0; /* RS-FEC disable */ + pma_type = 0b0100001; /* 40GBASE-CR PMA/PMD type */ + an0_rate_select = 4; /* 40G-KR: 3 40G-CR: 4 */ + break; + case 25: + bp_link_mode = 25; + speed_select = 5; /* 25 Gb/s */ + pcs_type_sel = 7; /* 25GBASE-R PCS Type */ + cns_en = 1; /* CNS_EN */ + rsfec_en = 1; /* RS-FEC enable*/ + pma_type = 0b0111001; /* 25GBASE-KR PMA/PMD type */ + an0_rate_select = 9; /* 9/10/17 25GK/CR-S or 25GK/CR */ + break; + default: + BP_LOG("%s %d :Invalid bp_link_mode\n", __func__, __LINE__); + break; + } + + hw->curbp_link_mode = bp_link_mode; + /* To switch to the 40G mode Ethernet operation, complete the following steps:*/ + /* 1. Initiate the vendor-specific software reset by programming + * the VR_RST field (bit [15]) of the VR_PCS_DIG_CTRL1 register to 1. + */ + rdata = rd32_epcs(hw, 0x038000); + wr32_epcs(hw, 0x038000, rdata | BIT(15)); + + /* 2. Wait for the hardware to clear the value for the VR_RST + * field (bit [15]) of the VR_PCS_DIG_CTRL1 register. + */ + BP_LOG("Wait for the bit [15] (VR_RST) to get cleared.\n"); + status = kr_read_poll(rd32_ephy, rdata, + FIELD_GET_M(BIT(15), rdata) == 0, 100, + 2000, hw, 0x038000); + BP_LOG("Wait PHY VR_RST = %x, Wait VR_RST %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + /* 3. Write 4'b0011 to bits [5:2] of the SR_PCS_CTRL1 register. + * 10G: 0 25G: 5 40G: 3 + */ + rdata = rd32_epcs(hw, 0x030000); + set_fields_e56(&rdata, 5, 2, speed_select); + wr32_epcs(hw, 0x030000, rdata); + + /* 4. Write pcs mode sel to bits [3:0] of the SR_PCS_CTRL2 register. + * 10G: 0 25G: 4'b0111 40G: 4'b0100 + */ + rdata = rd32_epcs(hw, 0x030007); + set_fields_e56(&rdata, 3, 0, pcs_type_sel); + wr32_epcs(hw, 0x030007, rdata); + + /* 0 1 1 1 0 0 1 : 25GBASE-KR or 25GBASE-KR-S PMA/PMD type + * 0 1 1 1 0 0 0 : 25GBASE-CR or 25GBASE-CR-S PMA/PMD type + * 0 1 0 0 0 0 1 : 40GBASE-CR4 PMA/PMD type + * 0 1 0 0 0 0 0 : 40GBASE-KR4 PMA/PMD type + * 0 0 0 1 0 1 1 : 10GBASE-KR PMA/PMD type + */ + rdata = rd32_epcs(hw, 0x010007); + set_fields_e56(&rdata, 6, 0, pma_type); + wr32_epcs(hw, 0x010007, rdata); + + /* 5. Write only 25g en to Bits [1:0] of VR_PCS_DIG_CTRL3 register. */ + rdata = rd32_epcs(hw, 0x38003); + set_fields_e56(&rdata, 1, 0, cns_en); + wr32_epcs(hw, 0x38003, rdata); + + /* 6. Program PCS_AM_CNT field of VR_PCS_AM_CNT register to 'd16383 to + * configure the alignment marker interval. To speed-up simulation, + * program a smaller value to this field. + */ + if (bp_link_mode == 40) + wr32_epcs(hw, 0x38018, 16383); + + /* 7. Program bit [2] of SR_PMA_RS_FEC_CTRL register to 0 + * if previously 1 (as RS-FEC is supported in 25G Mode). + */ + + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, rsfec_en); + wr32_epcs(hw, 0x100c8, rdata); + + /* 8. To enable BASE-R FEC (if desired), set bit [0]. + * in SR_PMA_KR_FEC_CTRL register + */ + + /* 4. set phy an status to 0 */ + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, 0xe); + wr32_ephy(hw, 0x1434, rdata); + + /* 9. Program Enterprise 56G PHY regs through its own APB interface: + * a. Program PHY registers as mentioned in Table 6-6 on page 1197 to + * configure the PHY to 40G + * Mode. For fast-simulation mode, additionally program, + * the registers shown in the Table 6-7 on page 1199 + * b. Enable the PMD by setting pmd_en field in PMD_CFG[0] (0x1400) + * register + */ + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL0); + set_fields_e56(&rdata, 29, 29, 0x1); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDVAL0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDVAL5); + set_fields_e56(&rdata, 24, 24, 0x1); + wr32_ephy(hw, ANA_OVRDVAL5, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN0); + set_fields_e56(&rdata, 1, 1, 0x1); + wr32_ephy(hw, ANA_OVRDEN0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, ANA_OVRDEN1); + set_fields_e56(&rdata, 30, 30, 0x1); + set_fields_e56(&rdata, 25, 25, 0x1); + wr32_ephy(hw, ANA_OVRDEN1, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL0_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_CFG2); + set_fields_e56(&rdata, 12, 8, 0x4); + wr32_ephy(hw, PLL0_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG0); + set_fields_e56(&rdata, 25, 24, 0x1); + set_fields_e56(&rdata, 17, 16, 0x3); + wr32_ephy(hw, PLL1_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL1_CFG2); + set_fields_e56(&rdata, 12, 8, 0x8); + wr32_ephy(hw, PLL1_CFG2, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, PLL0_DIV_CFG0); + set_fields_e56(&rdata, 18, 8, 0x294); + set_fields_e56(&rdata, 4, 0, 0x8); + wr32_ephy(hw, PLL0_DIV_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG0); + set_fields_e56(&rdata, 30, 28, 0x7); + set_fields_e56(&rdata, 26, 24, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) + set_fields_e56(&rdata, 18, 16, 0x5); + else if (bp_link_mode == 25) + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 14, 12, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + wr32_ephy(hw, DATAPATH_CFG0, rdata); + + rdata = 0x0000; + rdata = rd32_ephy(hw, DATAPATH_CFG1); + set_fields_e56(&rdata, 26, 24, 0x5); + set_fields_e56(&rdata, 10, 8, 0x5); + if (bp_link_mode == 10 || bp_link_mode == 40) { + set_fields_e56(&rdata, 18, 16, 0x5); + set_fields_e56(&rdata, 2, 0, 0x5); + } else if (bp_link_mode == 25) { + set_fields_e56(&rdata, 18, 16, 0x3); + set_fields_e56(&rdata, 2, 0, 0x3); + } + wr32_ephy(hw, DATAPATH_CFG1, rdata); + + rdata = rd32_ephy(hw, AN_CFG1); + set_fields_e56(&rdata, 4, 0, an0_rate_select); + wr32_ephy(hw, AN_CFG1, rdata); + + status = txgbe_e56_cms_cfg_for_temp_track_range(hw); + + if (bp_link_mode == 10) + txgbe_e56_bp_cfg_10g(hw); + else if (bp_link_mode == 25) + txgbe_e56_bp_cfg_25g(hw); + else if (bp_link_mode == 40) + txgbe_e56_cfg_40g(hw); + + return status; +} + +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode, u32 need_restart) +{ + int status = 0; + u32 rdata; + + UNREFERENCED_PARAMETER(bp_link_mode); + + hw->an_done = false; + if (hw->curbp_link_mode == 10 && !need_restart) + return 0; + BP_LOG("Setup to backplane mode ==========\n"); + + u32 backplane_mode = 0; + u32 fec_advertise = 0; + + hw->an_done = false; + /* pcs + phy rst */ + rdata = rd32(hw, 0x1000c); + if (hw->bus.lan_id == 1) + rdata |= BIT(16); + else + rdata |= BIT(19); + wr32(hw, 0x1000c, rdata); + msleep(20); + + /* clear interrupt */ + wr32_epcs(hw, 0x070000, 0); + wr32_epcs(hw, 0x030000, 0x8000); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + wr32_epcs(hw, 0x078002, 0x0000); + /* pcs case fec en to work around first */ + wr32_epcs(hw, 0x100ab, 1); + + if (txgbe_is_backplane(hw)) { + /* backplane 10G/25G/40G */ + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + /* default all speed */ + if ((hw->device_id & 0xFF) == 0x10) { + backplane_mode |= BIT(7); + fec_advertise |= TXGBE_10G_FEC_ABL; + } else if ((hw->device_id & 0xFF) == 0x25) { + backplane_mode |= BIT(14) | BIT(15); + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } else if ((hw->device_id & 0xFF) == 0x40) { + if (hw->phy.bp_capa == 0) + /* original configure: KR4 + CR4 */ + backplane_mode |= BIT(9) | BIT(8); + else if (hw->phy.bp_capa == 1) + /* only 40GBASE-KR4 */ + backplane_mode |= BIT(8); + else if (hw->phy.bp_capa == 2) + /* only 40GBASE-CR4 */ + backplane_mode |= BIT(9); + fec_advertise |= TXGBE_10G_FEC_ABL; + BP_LOG("Advertised abilities: %d\n", backplane_mode); + } + } else { + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_10GB_FULL) + == TXGBE_LINK_SPEED_10GB_FULL) { + backplane_mode |= 0x80; + fec_advertise |= TXGBE_10G_FEC_ABL; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_25GB_FULL) + == TXGBE_LINK_SPEED_25GB_FULL) { + backplane_mode |= 0xc000; + fec_advertise |= TXGBE_25G_RS_FEC_REQ | + TXGBE_25G_BASE_FEC_REQ; + } + + if ((hw->phy.fiber_suppport_speed & TXGBE_LINK_SPEED_40GB_FULL) + == TXGBE_LINK_SPEED_40GB_FULL) { + backplane_mode |= BIT(9) | BIT(8); + fec_advertise |= TXGBE_10G_FEC_ABL; + } + } + + wr32_epcs(hw, 0x070010, 0x0001); + + /* 10GKR:7-25KR:14/15-40GKR:8-40GCR:9 */ + wr32_epcs(hw, 0x070011, backplane_mode | 0x11); + + /* BASE-R FEC */ + rdata = rd32_epcs(hw, 0x70012); + wr32_epcs(hw, 0x70012, fec_advertise); + + wr32_epcs(hw, 0x070016, 0x0000); + wr32_epcs(hw, 0x070017, 0x0); + wr32_epcs(hw, 0x070018, 0x0); + + /* config timer */ + wr32_epcs(hw, 0x078004, 0x003c); + wr32_epcs(hw, 0x078005, CL74_KRTR_TRAINNING_TIMEOUT); + wr32_epcs(hw, 0x078006, 25); + wr32_epcs(hw, 0x078000, 0x0008 | BIT(2)); + + BP_LOG("1.2 Wait 10G KR phy/pcs mode init ....\n"); + status = txgbe_set_phy_link_mode(hw, 10); + BP_LOG("Wait 10g phy/pcs mode init = %x, %s.\n", rdata, + /* wait rx/tx/cm powerdn_st according pmd 50 2.0.5 */ + status ? "FAILED" : "SUCCESS"); + + /* 5. CM_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, 0x3); /* pll en */ + set_fields_e56(&rdata, 19, 12, 0x0); /* tx disable */ + set_fields_e56(&rdata, 8, 8, 0x0); /* pmd mode */ + set_fields_e56(&rdata, 1, 1, 0x1); /* pmd en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 6, TX_ENABLE */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 12, 0x1); /* tx en */ + wr32_ephy(hw, 0x1400, rdata); + + BP_LOG("1.3 Wait 10G PHY RXS....\n"); + status = txgbe_e56_rxs_osc_init_for_temp_track_range(hw, 10); + BP_LOG("Wait 10G PHY/RXS mode init = %x, %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + + /* Wait an 10g fsm_rx_sts */ + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0x3f) == 0xb), 1000, + 200, hw, + E56PHY_CTRL_FSM_RX_STAT_0_ADDR); + BP_LOG("Wait 10g fsm_rx_sts = %x, Wait rx_sts %s.\n", rdata, + status ? "FAILED" : "SUCCESS"); + rdata = rd32_epcs(hw, 0x070000); + set_fields_e56(&rdata, 12, 12, 0x1); + wr32_epcs(hw, 0x070000, rdata); + BP_LOG("Setup the backplane mode========end ==\n"); + + return status; +} + +static void txgbe_e56_print_page_status(struct txgbe_hw *hw, + struct txgbe_backplane_ability *local_ability, + struct txgbe_backplane_ability *lp_ability) +{ + u32 rdata = 0; + + /* Read the local AN73 Base Page Ability Registers */ + BP_LOG("Read the local Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG1); + local_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70010 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG2); + BP_LOG("\tread 70011 data %0x\n", rdata); + local_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + /* amber-lite only support 10GKR - 25GKR/CR - 25GKR-S/CR-S */ + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + local_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + local_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + local_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_ADV_REG3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + local_ability->fec_ability = rdata; + BP_LOG("\tread 70012 data %0x\n", rdata); + + /* Read the link partner AN73 Base Page Ability Registers */ + BP_LOG("Read the link partner Base Page Ability Registers\n"); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL1); + lp_ability->next_page = (rdata & BIT(15)) ? 1 : 0; + BP_LOG("\tread 70013 data %0x\n", rdata); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL2); + lp_ability->link_ability = (rdata >> 5) & GENMASK(10, 0); + BP_LOG("\tread 70014 data %0x\n", rdata); + BP_LOG("\tKX : %x\tKX4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_1000BASE_KX) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_10GBASE_KX4) ? 1 : 0); + BP_LOG("\t10GKR : %x\t25GKR-S/CR-S: %x\t25GKR/CR : %x\n", + lp_ability->link_ability & BIT(ABILITY_10GBASE_KR) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR_S) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_25GBASE_KRCR) ? 1 : 0); + BP_LOG("\t40GCR4 : %x\t40GKR4 : %x\n", + lp_ability->link_ability & BIT(ABILITY_40GBASE_CR4) ? 1 : 0, + lp_ability->link_ability & BIT(ABILITY_40GBASE_KR4) ? 1 : 0); + rdata = rd32_epcs(hw, SR_AN_MMD_LP_ABL3); + BP_LOG("\tF1:FEC Req\tF0:FEC Sup\tF3:25GFEC\tF2:25GRS\n"); + BP_LOG("\tF1: %d\t\tF0: %d\t\tF3: %d\t\tF2: %d\n", + ((rdata >> 15) & 0x01), ((rdata >> 14) & 0x01), + ((rdata >> 13) & 0x01), ((rdata >> 12) & 0x01)); + lp_ability->fec_ability = rdata; + + hw->phy.fec_mode = 0; + if (rdata & TXGBE_25G_RS_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_RS_FEC_REQ; + if (rdata & TXGBE_25G_BASE_FEC_REQ) + hw->phy.fec_mode |= TXGBE_25G_BASE_FEC_REQ; + if (rdata & TXGBE_10G_FEC_ABL) + hw->phy.fec_mode |= TXGBE_10G_FEC_ABL; + if (rdata & TXGBE_10G_FEC_REQ) + hw->phy.fec_mode |= TXGBE_10G_FEC_REQ; + BP_LOG("\tread 70015 data %0x\n", rdata); + + BP_LOG("\tread 70016 data %0x\n", rd32_epcs(hw, 0x70016)); + BP_LOG("\tread 70017 data %0x\n", rd32_epcs(hw, 0x70017)); + BP_LOG("\tread 70018 data %0x\n", rd32_epcs(hw, 0x70018)); + BP_LOG("\tread 70019 data %0x\n", rd32_epcs(hw, 0x70019)); + BP_LOG("\tread 7001a data %0x\n", rd32_epcs(hw, 0x7001a)); + BP_LOG("\tread 7001b data %0x\n", rd32_epcs(hw, 0x7001b)); +} + +static int chk_bkp_ability(struct txgbe_hw *hw, + struct txgbe_backplane_ability local_ability, + struct txgbe_backplane_ability lp_ability) +{ + unsigned int com_link_ability; + + BP_LOG("CheckBkpAn73Ability():\n"); + /* Check the common link ability and take action based on the result*/ + com_link_ability = local_ability.link_ability & + lp_ability.link_ability; + BP_LOG("comAbility= 0x%x, Ability= 0x%x, lpAbility= 0x%x\n", + com_link_ability, local_ability.link_ability, + lp_ability.link_ability); + + if (com_link_ability == 0) { + hw->bp_link_mode = 0; + BP_LOG("Do not support any compatible speed mode!\n"); + return -EINVAL; + } else if (com_link_ability & BIT(ABILITY_40GBASE_KR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_KR4].\n"); + hw->bp_link_mode = 40; + } else if (com_link_ability & BIT(ABILITY_40GBASE_CR4)) { + BP_LOG("Link mode is [ABILITY_40GBASE_CR4].\n"); + hw->bp_link_mode = 40; + } else if (com_link_ability & BIT(ABILITY_25GBASE_KRCR_S)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR_S].\n"); + hw->fec_mode = TXGBE_25G_RS_FEC_REQ; + hw->bp_link_mode = 25; + } else if (com_link_ability & BIT(ABILITY_25GBASE_KRCR)) { + BP_LOG("Link mode is [ABILITY_25GBASE_KRCR].\n"); + hw->bp_link_mode = 25; + } else if (com_link_ability & BIT(ABILITY_10GBASE_KR)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KR].\n"); + hw->bp_link_mode = 10; + } else if (com_link_ability & BIT(ABILITY_10GBASE_KX4)) { + BP_LOG("Link mode is [ABILITY_10GBASE_KX4].\n"); + hw->bp_link_mode = 10; + } else if (com_link_ability & BIT(ABILITY_1000BASE_KX)) { + BP_LOG("Link mode is [ABILITY_1000BASE_KX].\n"); + hw->bp_link_mode = 1; + } else { + BP_LOG("No compatible link mode found!\n"); + return -EINVAL; + } + + return 0; +} + +static int txgbe_e56_exchange_page(struct txgbe_hw *hw) +{ + struct txgbe_backplane_ability local_ability = {0}, lp_ability = {0}; + u32 an_int, base_page = 0; + int count = 0; + + an_int = rd32_epcs(hw, 0x78002); + /* 500ms timeout */ + if (!(an_int & VR_AN_INTR_PG_RCV)) + return -EINVAL; + + for (count = 0; count < 500; count++) { + u32 fsm = rd32_epcs(hw, 0x78010); + u32 rdata = rd32_epcs(hw, 0x78002); + + BP_LOG("-----count----- %d - fsm: %x\n", count, fsm); + BP_LOG("read 78002 data %0x and clear pacv\n", rdata); + an_int = rdata; + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + if (an_int & VR_AN_INTR_PG_RCV) { + u32 addr; + + txgbe_e56_print_page_status(hw, &local_ability, &lp_ability); + addr = base_page == 0 ? 0x70013 : 0x70019; + rdata = rd32_epcs(hw, addr); + if (rdata & BIT(14)) { + if (rdata & BIT(15)) { + /* always set null message */ + wr32_epcs(hw, 0x70016, 0x2001); + BP_LOG("write 70016 0x%0x\n", + 0x2001); + } + base_page = 1; + } + } + if ((fsm & 0x8) == 0x8) { + hw->fsm = 0x8; + goto check_ability; + } + usec_delay(100); + } + +check_ability: + return chk_bkp_ability(hw, local_ability, lp_ability); +} + +static int txgbe_e56_cl72_trainning(struct txgbe_hw *hw) +{ + u32 bylinkmode = hw->bp_link_mode; + u8 bypass_ctle = hw->bypass_ctle; + int status = 0, temp_data = 0; + u32 lane_num = 0, lane_idx = 0; + u32 __rte_unused pmd_ctrl = 0, txffe = 0; + int ret = 0; + u32 rdata; + + u8 pll_en_cfg = 0; + u8 pmd_mode = 0; + + switch (bylinkmode) { + case 10: + bylinkmode = 10; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + case 40: + bylinkmode = 40; + lane_num = 4; + pll_en_cfg = 0; /* pll_en_cfg : single link to 0 */ + pmd_mode = 1; /* pmd mode : 1 - single link */ + break; + case 25: + bylinkmode = 25; + lane_num = 1; + pll_en_cfg = 3; + pmd_mode = 0; + break; + default: + BP_LOG("%s %d :Invalid speed\n", __func__, __LINE__); + break; + } + + BP_LOG("2.3 Wait %dG KR phy mode init ....\n", bylinkmode); + status = txgbe_set_phy_link_mode(hw, bylinkmode); + + /* 13. set phy an status to 1 - AN_CFG[0]: 4-7 lane0-lane3 */ + rdata = rd32_ephy(hw, 0x1434); + set_fields_e56(&rdata, 7, 4, GENMASK(lane_num - 1, 0)); + wr32_ephy(hw, 0x1434, rdata); + + /* 14 and 15. kr training: set BASER_PMD_CONTROL[0, 7] for lane0-4 */ + rdata = rd32_ephy(hw, 0x1640); + set_fields_e56(&rdata, 7, 0, GENMASK(2 * lane_num - 1, 0)); + wr32_ephy(hw, 0x1640, rdata); + + /* 16. enable CMS and its internal PLL */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 21, 20, pll_en_cfg); + set_fields_e56(&rdata, 19, 12, 0); /* tx/rx off */ + set_fields_e56(&rdata, 8, 8, pmd_mode); + set_fields_e56(&rdata, 1, 1, 0x1); /* pmd en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 17. tx enable PMD_CFG[0] */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 15, 12, GENMASK(lane_num - 1, 0)); /* tx en */ + wr32_ephy(hw, 0x1400, rdata); + + /* 18 */ + /* 19. rxs calibration and adaotation sequeence */ + BP_LOG("2.4 Wait %dG RXS.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_phy_rxs_calib_adapt_seq(hw, bylinkmode, bypass_ctle); + ret |= status; + /* 20 */ + BP_LOG("2.5 Wait %dG phy calibration.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + txgbe_e56_set_rxs_ufine_le_max(hw, bylinkmode); + status = txgbe_e56_get_temp(hw, &temp_data); + if (bylinkmode == 40) + status = txgbe_temp_track_seq_40g(hw, TXGBE_LINK_SPEED_40GB_FULL); + else + status = txgbe_e56_rxs_post_cdr_lock_temp_track_seq(hw, bylinkmode); + /* 21 */ + BP_LOG("2.6 Wait %dG phy kr training check.... fsm: %x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = kr_read_poll(rd32_ephy, rdata, + ((rdata & 0xe) & GENMASK(lane_num, 1)) == + (0xe & GENMASK(lane_num, 1)), 100, + 10000, hw, 0x163c); + pmd_ctrl = rd32_ephy(hw, 0x1644); + BP_LOG("KR TRAINNING CHECK = %x, %s. pmd_ctrl:%lx-%lx-%lx-%lx\n", + rdata, status ? "FAILED" : "SUCCESS", + FIELD_GET_M(GENMASK(3, 0), pmd_ctrl), + FIELD_GET_M(GENMASK(7, 4), pmd_ctrl), + FIELD_GET_M(GENMASK(11, 8), pmd_ctrl), + FIELD_GET_M(GENMASK(15, 12), pmd_ctrl)); + ret |= status; + BP_LOG("before: %x-%x-%x-%x\n", + rd32_ephy(hw, 0x141c), rd32_ephy(hw, 0x1420), + rd32_ephy(hw, 0x1424), rd32_ephy(hw, 0x1428)); + + for (lane_idx = 0; lane_idx < lane_num; lane_idx++) { + txffe = rd32_ephy(hw, 0x828 + lane_idx * 0x100); + BP_LOG("after[%x]: %lx-%lx-%lx-%lx\n", lane_idx, + FIELD_GET_M(GENMASK(6, 0), txffe), + FIELD_GET_M(GENMASK(21, 16), txffe), + FIELD_GET_M(GENMASK(29, 24), txffe), + FIELD_GET_M(GENMASK(13, 8), txffe)); + } + + /* 22 */ + BP_LOG("2.7 Wait %dG phy Rx adc.... fsm:%x\n", + bylinkmode, rd32_epcs(hw, 0x78010)); + status = txgbe_e56_rxs_adc_adapt_seq(hw, bypass_ctle); + + return ret; +} + +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw) +{ + int status = 0; + u32 rdata; + + BP_LOG("2.1 Wait page changed ....\n"); + status = txgbe_e56_exchange_page(hw); + if (status) { + BP_LOG("Exchange page failed\n"); + return status; + } + + BP_LOG("2.2 Wait page changed ..done..\n"); + wr32_epcs(hw, 0x100ab, 0); + if (AN_TRAINNING_MODE) { + rdata = rd32_epcs(hw, 0x70000); + BP_LOG("read 0x70000 data %0x\n", rdata); + wr32_epcs(hw, 0x70000, 0); + BP_LOG("write 0x70000 0x%0x\n", 0); + } + + rdata = rd32_epcs(hw, 0x78002); + BP_LOG("read 78002 data %0x and clear page int\n", rdata); + set_fields_e56(&rdata, 2, 2, 0x0); + wr32_epcs(hw, 0x78002, rdata); + + /* dis phy tx/rx lane */ + rdata = rd32_ephy(hw, 0x1400); + set_fields_e56(&rdata, 19, 16, 0x0); + set_fields_e56(&rdata, 15, 12, 0x0); + set_fields_e56(&rdata, 1, 1, 0x0); + wr32_ephy(hw, 0x1400, rdata); + BP_LOG("Ephy Write A: 0x%x, D: 0x%x\n", 0x1400, rdata); + + /* wait rx/tx/cm powerdn_st */ + status = kr_read_poll(rd32_ephy, rdata, + (rdata & GENMASK(3, 0)) == 0x9, 100, + 2000, hw, 0x14d4); + BP_LOG("wait ctrl_fsm_cm_st = %x, %s.\n", + rdata, status ? "FAILED" : "SUCCESS"); + + if (hw->phy.fec_mode & TXGBE_25G_RS_FEC_REQ) { + wr32_epcs(hw, 0x180a3, 0x68c1); + wr32_epcs(hw, 0x180a4, 0x3321); + wr32_epcs(hw, 0x180a5, 0x973e); + wr32_epcs(hw, 0x180a6, 0xccde); + + wr32_epcs(hw, 0x38018, 1024); + rdata = rd32_epcs(hw, 0x100c8); + set_fields_e56(&rdata, 2, 2, 1); + wr32_epcs(hw, 0x100c8, rdata); + BP_LOG("Advertised FEC modes : %s\n", "RS-FEC"); + hw->cur_fec_link = TXGBE_PHY_FEC_RS; + } else if (hw->phy.fec_mode & TXGBE_25G_BASE_FEC_REQ) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "25GBASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else if (hw->fec_mode & (TXGBE_10G_FEC_REQ)) { + /* FEC: FC-FEC/BASE-R */ + wr32_epcs(hw, 0x100ab, BIT(0)); + BP_LOG("Epcs Write A: 0x%x, D: 0x%x\n", 0x100ab, 1); + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "BASE-R"); + hw->cur_fec_link = TXGBE_PHY_FEC_BASER; + } else { + PMD_DRV_LOG(INFO, "Advertised FEC modes : %s", "NONE"); + hw->cur_fec_link = TXGBE_PHY_FEC_OFF; + } + + status = txgbe_e56_cl72_trainning(hw); + + rdata = rd32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MAX, 0x28); + set_fields_e56(&rdata, E56PHY_RXS_IDLE_DETECT_1_IDLE_TH_ADC_PEAK_MIN, 0xa); + wr32_ephy(hw, E56PHY_RXS_IDLE_DETECT_1_ADDR, rdata); + wr32_ephy(hw, E56PHY_INTR_0_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + wr32_ephy(hw, E56PHY_INTR_0_ENABLE_ADDR, E56PHY_INTR_0_IDLE_ENTRY1); + wr32_ephy(hw, E56PHY_INTR_1_ENABLE_ADDR, E56PHY_INTR_1_IDLE_EXIT1); + + return status; +} diff --git a/drivers/net/txgbe/base/txgbe_e56_bp.h b/drivers/net/txgbe/base/txgbe_e56_bp.h index 97d5656cad..9329387334 100644 --- a/drivers/net/txgbe/base/txgbe_e56_bp.h +++ b/drivers/net/txgbe/base/txgbe_e56_bp.h @@ -276,4 +276,7 @@ typedef union { #define E56PHY_CMS_ANA_OVRDVAL_10_ADDR (E56PHY_CMS_BASE_ADDR + 0xD8) #define E56PHY_CMS_ANA_OVRDVAL_7_ANA_LCPLL_LF_LPF_SETCODE_CALIB_I 8, 4 +int txgbe_e56_set_phy_link_mode(struct txgbe_hw *hw, + u8 bp_link_mode, u32 need_restart); +int handle_e56_bkp_an73_flow(struct txgbe_hw *hw); #endif diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 0c6a74c562..6d76b4854c 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -4071,6 +4071,12 @@ s32 txgbe_reset_pipeline_raptor(struct txgbe_hw *hw) return err; } +bool txgbe_is_backplane(struct txgbe_hw *hw) +{ + return hw->phy.get_media_type(hw) == txgbe_media_type_backplane ? + true : false; +} + bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask) { u32 gpio_ext = rd32(hw, TXGBE_GPIOEXT); diff --git a/drivers/net/txgbe/base/txgbe_hw.h b/drivers/net/txgbe/base/txgbe_hw.h index bc34d639eb..b44190bc34 100644 --- a/drivers/net/txgbe/base/txgbe_hw.h +++ b/drivers/net/txgbe/base/txgbe_hw.h @@ -118,6 +118,6 @@ s32 txgbe_reinit_fdir_tables(struct txgbe_hw *hw); bool txgbe_verify_lesm_fw_enabled_raptor(struct txgbe_hw *hw); s32 txgbe_fmgr_cmd_op(struct txgbe_hw *hw, u32 cmd, u32 cmd_addr); s32 txgbe_flash_read_dword(struct txgbe_hw *hw, u32 addr, u32 *data); -s32 txgbe_e56_check_phy_link(struct txgbe_hw *hw, u32 *speed, - bool *link_up); +bool txgbe_is_backplane(struct txgbe_hw *hw); +bool txgbe_gpio_ext_check(struct txgbe_hw *hw, u8 gpio_ext_mask); #endif /* _TXGBE_HW_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_osdep.h b/drivers/net/txgbe/base/txgbe_osdep.h index f4282b3241..da069e94f6 100644 --- a/drivers/net/txgbe/base/txgbe_osdep.h +++ b/drivers/net/txgbe/base/txgbe_osdep.h @@ -162,6 +162,10 @@ static inline u64 REVERT_BIT_MASK64(u64 mask) ((mask & 0xFFFFFFFF00000000) >> 32); } +#define BITS_PER_LONG (__SIZEOF_LONG__ * 8) +#define GENMASK(h, l) \ + (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + #define IOMEM #define BIT(nr) (1UL << (nr)) diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index bf7260a295..f3e3491b30 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -2503,6 +2503,27 @@ void txgbe_set_phy_temp(struct txgbe_hw *hw) } } +int txgbe_is_dac_cable(struct txgbe_hw *hw) +{ + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_act_lmt_core1 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core0 || + hw->phy.sfp_type == txgbe_qsfp_type_40g_cu_core1) + return true; + + return false; +} + +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw) +{ + if (!(txgbe_is_dac_cable(hw) || txgbe_is_backplane(hw))) + return false; + + return hw->devarg.auto_neg ? true : false; +} + /** * txgbe_kr_handle - Handle the interrupt of auto-negotiation * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index c02be3cc34..3fe7a34409 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -105,6 +105,8 @@ #define VR_AN_INTR_CMPLT MS16(0, 0x1) #define VR_AN_INTR_LINK MS16(1, 0x1) #define VR_AN_INTR_PG_RCV MS16(2, 0x1) +#define TXGBE_E56_AN_TXDIS MS16(3, 0x1) +#define TXGBE_E56_AN_PG_RCV MS16(4, 0x1) #define VR_AN_KR_MODE_CL 0x078003 #define VR_AN_KR_MODE_CL_PDET MS16(0, 0x1) #define VR_XS_OR_PCS_MMD_DIGI_CTL1 0x038000 @@ -428,6 +430,24 @@ #define TXGBE_BP_M_NAUTO 0 #define TXGBE_BP_M_AUTO 1 +#define kr_read_poll(op, val, cond, sleep_us, \ + times, args...) \ +({ \ + unsigned long __sleep_us = (sleep_us); \ + u32 __times = (times); \ + u32 i; \ + int __cond = 0; \ + for (i = 0; i < __times; i++) { \ + (val) = op(args); \ + if (cond) { \ + __cond = 1; \ + break; \ + } \ + usleep(__sleep_us);\ + } \ + (__cond) ? 0 : -1; \ +}) + #ifndef CL72_KRTR_PRBS_MODE_EN #define CL72_KRTR_PRBS_MODE_EN 0xFFFF /* open kr prbs check */ #endif @@ -490,6 +510,8 @@ void txgbe_autoc_write(struct txgbe_hw *hw, u64 value); void txgbe_bp_mode_set(struct txgbe_hw *hw); void txgbe_set_phy_temp(struct txgbe_hw *hw); void txgbe_bp_down_event(struct txgbe_hw *hw); +int txgbe_is_dac_cable(struct txgbe_hw *hw); +int txgbe_xpcs_an_enabled(struct txgbe_hw *hw); s32 txgbe_kr_handle(struct txgbe_hw *hw); #endif /* _TXGBE_PHY_H_ */ diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 7fb4bcc513..47629aa9e0 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -719,6 +719,7 @@ struct txgbe_phy_info { u32 addr; u32 id; enum txgbe_sfp_type sfp_type; + u32 fiber_suppport_speed; bool sfp_setup_needed; u32 revision; u32 media_type; @@ -740,6 +741,7 @@ struct txgbe_phy_info { u16 ffe_pre2; u16 ffe_post; u16 fec_mode; + u16 bp_capa; }; #define TXGBE_DEVARG_BP_AUTO "auto_neg" @@ -899,7 +901,28 @@ struct txgbe_hw { u32 cur_fec_link; int temperature; u32 bp_link_mode; -}; + bool dac_sfp; + bool bypass_ctle; + u32 curbp_link_mode; + bool an_done; + u32 fsm; + u64 bp_event_interval; +}; + +typedef enum { + ABILITY_1000BASE_KX, + ABILITY_10GBASE_KX4, + ABILITY_10GBASE_KR, + ABILITY_40GBASE_KR4, + ABILITY_40GBASE_CR4, + ABILITY_100GBASE_CR10, + ABILITY_100GBASE_KP4, + ABILITY_100GBASE_KR4, + ABILITY_100GBASE_CR4, + ABILITY_25GBASE_KRCR_S, + ABILITY_25GBASE_KRCR, + ABILITY_MAX, +} ability_filed_encding; struct txgbe_backplane_ability { u32 next_page; /* Next Page (bit0) */ diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 02c3305712..56987ae028 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -2010,6 +2010,10 @@ txgbe_dev_start(struct rte_eth_dev *dev) txgbe_l2_tunnel_conf(dev); txgbe_filter_restore(dev); + hw->bp_event_interval = 100 * 1000; + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); + if (tm_conf->root && !tm_conf->committed) PMD_DRV_LOG(WARNING, "please call hierarchy_commit() " @@ -2054,8 +2058,10 @@ txgbe_dev_stop(struct rte_eth_dev *dev) PMD_INIT_FUNC_TRACE(); - if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) { + rte_eal_alarm_cancel(txgbe_dev_e56_check_bp_event, dev); rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler_aml, hw); + } rte_eal_alarm_cancel(txgbe_dev_detect_sfp, dev); rte_eal_alarm_cancel(txgbe_tx_queue_clear_error, dev); @@ -2926,6 +2932,107 @@ txgbe_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements) return NULL; } +void txgbe_dev_e56_check_bp_event(void *param) +{ + struct rte_eth_dev *dev = (struct rte_eth_dev *)param; + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + u32 an_int1 = 0, value = 0, fsm = 0; + u32 __rte_unused an_int = 0; + int ret = 0; + bool need_link_update = false; + + if (!hw) + return; + + if (!(txgbe_xpcs_an_enabled(hw))) + return; + + if (!hw->devarg.auto_neg) + return; + + /* only continue if link is down */ + if (dev->data->dev_link.link_status) + goto out; + + value = rd32_epcs(hw, VR_AN_INTR); + an_int = value; + if (value & 0xF) + hw->bp_event_interval = 100 * 1000; + + if (value & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + value &= ~VR_AN_INTR_CMPLT; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & VR_AN_INTR_LINK) { + value &= ~VR_AN_INTR_LINK; + wr32_epcs(hw, VR_AN_INTR, value); + } + + if (value & TXGBE_E56_AN_TXDIS) { + value &= ~TXGBE_E56_AN_TXDIS; + wr32_epcs(hw, VR_AN_INTR, value); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + goto an_status; + } + + if (value & VR_AN_INTR_PG_RCV) { + BP_LOG("%d Enter training\n", hw->port_id); + ret = handle_e56_bkp_an73_flow(hw); + if (!AN_TRAINNING_MODE) { + fsm = rd32_epcs(hw, 0x78010); + if (fsm & 0x8) + goto an_status; + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + BP_LOG("ALL SUCCEEDED\n"); + } + } else { + if (ret) { + BP_LOG("Training FAILED, do reset\n"); + rte_spinlock_lock(&hw->phy_lock); + txgbe_e56_set_phy_link_mode(hw, 10, hw->bypass_ctle); + rte_spinlock_unlock(&hw->phy_lock); + } else { + hw->an_done = true; + } + } + } + +an_status: + an_int1 = rd32_epcs(hw, 0x78002); + if (an_int1 & VR_AN_INTR_CMPLT) { + hw->an_done = true; + need_link_update = true; + } + + BP_LOG("%d RLU:%x MLU:%x INT:%x-%x CTL:%x fsm:%x pmd_cfg0:%x an_done:%d\n", + hw->port_id, rd32_epcs(hw, 0x30001), rd32(hw, 0x14404), + an_int, an_int1, + rd32_epcs(hw, 0x70000), + rd32_epcs(hw, 0x78010), + rd32_ephy(hw, 0x1400), + hw->an_done); + + if (need_link_update) + txgbe_dev_link_update(dev, 0); + + if (dev->data->dev_link.link_status) + hw->bp_event_interval = 2000 * 1000; + +out: + if (hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) + rte_eal_alarm_set(hw->bp_event_interval, txgbe_dev_e56_check_bp_event, dev); +} + static void txgbe_dev_detect_sfp(void *param) { diff --git a/drivers/net/txgbe/txgbe_ethdev.h b/drivers/net/txgbe/txgbe_ethdev.h index 1ec8e096cc..309db3bfe9 100644 --- a/drivers/net/txgbe/txgbe_ethdev.h +++ b/drivers/net/txgbe/txgbe_ethdev.h @@ -747,5 +747,5 @@ void txgbe_vlan_hw_strip_bitmap_set(struct rte_eth_dev *dev, uint16_t queue, bool on); void txgbe_config_vlan_strip_on_all_queues(struct rte_eth_dev *dev, int mask); - +void txgbe_dev_e56_check_bp_event(void *param); #endif /* _TXGBE_ETHDEV_H_ */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 15/20] net/txgbe: fix FEC mode configuration on 25G NIC 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (13 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 16/20] net/txgbe: fix SFP module identification Zaiyu Wang ` (4 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The 25G NIC offers off, RS, Base-R, and auto FEC modes. When reconfiguring the PHY, the FEC mode must match on both sides; otherwise, the link cannot come up. The current driver fails to maintain this requirement, causing link instability. Add proper FEC mode handling during PHY reconfiguration to guarantee link establishment. Fixes: fb6eb170dfa2 ("net/txgbe: add basic link configuration for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_aml.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/txgbe/base/txgbe_aml.c b/drivers/net/txgbe/base/txgbe_aml.c index a5b9d951ea..fbb09d144b 100644 --- a/drivers/net/txgbe/base/txgbe_aml.c +++ b/drivers/net/txgbe/base/txgbe_aml.c @@ -282,6 +282,14 @@ s32 txgbe_setup_phy_link_aml(struct txgbe_hw *hw, !(hw->fec_mode & hw->cur_fec_link))) goto out; + if (speed == TXGBE_LINK_SPEED_25GB_FULL && + link_speed == TXGBE_LINK_SPEED_25GB_FULL) { + txgbe_e56_fec_polling(hw, &link_up); + + if (link_up) + goto out; + } + rte_spinlock_lock(&hw->phy_lock); ret_status = txgbe_set_link_to_amlite(hw, speed); rte_spinlock_unlock(&hw->phy_lock); @@ -360,7 +368,10 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw, /* If we already have link at this speed, just jump out */ txgbe_e56_check_phy_link(hw, &link_speed, &link_up); - if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up) + hw->cur_fec_link = txgbe_phy_fec_get(hw); + + if (link_speed == TXGBE_LINK_SPEED_25GB_FULL && link_up && + hw->fec_mode & hw->cur_fec_link) goto out; /* Allow module to change analog characteristics (10G -> 25G) */ -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 16/20] net/txgbe: fix SFP module identification 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (14 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 17/20] net/txgbe: fix get module info operation Zaiyu Wang ` (3 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Some optical modules were not correctly recognized due to ambiguous classification in the original detection flow. Rework the module identification logic to cover all module types. Also narrow the I2C lock scope to avoid potential race conditions during module access. Fixes: ab191e6d9189 ("net/txgbe: support new SFP/QSFP modules") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_hw.c | 2 - drivers/net/txgbe/base/txgbe_phy.c | 339 ++++++++++------------------ drivers/net/txgbe/base/txgbe_phy.h | 18 +- drivers/net/txgbe/base/txgbe_type.h | 2 + 4 files changed, 132 insertions(+), 229 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_hw.c b/drivers/net/txgbe/base/txgbe_hw.c index 6d76b4854c..16fd9ba20d 100644 --- a/drivers/net/txgbe/base/txgbe_hw.c +++ b/drivers/net/txgbe/base/txgbe_hw.c @@ -2909,8 +2909,6 @@ s32 txgbe_init_ops_generic(struct txgbe_hw *hw) phy->read_i2c_eeprom = txgbe_read_i2c_eeprom; phy->write_i2c_eeprom = txgbe_write_i2c_eeprom; phy->identify_sfp = txgbe_identify_module; - phy->read_i2c_byte_unlocked = txgbe_read_i2c_byte_unlocked; - phy->write_i2c_byte_unlocked = txgbe_write_i2c_byte_unlocked; phy->check_overtemp = txgbe_check_overtemp; phy->reset = txgbe_reset_phy; phy->set_link_hostif = txgbe_hic_ephy_set_link; diff --git a/drivers/net/txgbe/base/txgbe_phy.c b/drivers/net/txgbe/base/txgbe_phy.c index f3e3491b30..ac06f9530a 100644 --- a/drivers/net/txgbe/base/txgbe_phy.c +++ b/drivers/net/txgbe/base/txgbe_phy.c @@ -830,6 +830,10 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) return TXGBE_ERR_SFP_NOT_PRESENT; } + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; + err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, &identifier); if (err != 0) { @@ -839,11 +843,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.id = 0; hw->phy.type = txgbe_phy_unknown; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_PRESENT; } if (identifier != TXGBE_SFF_IDENTIFIER_SFP) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -888,7 +894,42 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) * 11 SFP_1g_sx_CORE0 - chip-specific * 12 SFP_1g_sx_CORE1 - chip-specific */ - if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + if (cable_tech & TXGBE_SFF_CABLE_DA_PASSIVE) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; + else + hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; + + if (hw->phy.sfp_type == txgbe_sfp_type_da_cu_core0 || + hw->phy.sfp_type == txgbe_sfp_type_da_cu_core1) { + hw->dac_sfp = true; + } + + if (comp_copper_len == TXGBE_SFF_COPPER_1M) + hw->bypass_ctle = true; + else + hw->bypass_ctle = false; + + if (comp_codes_25g == TXGBE_SFF_25GBASECR_91FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_74FEC || + comp_codes_25g == TXGBE_SFF_25GBASECR_NOFEC) { + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_25GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; + } else { + hw->phy.fiber_suppport_speed |= + TXGBE_LINK_SPEED_10GB_FULL; + } + } else if (comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_5 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_AOC_BER_12 || + comp_codes_25g == TXGBE_SFF_25GAUI_C2M_ACC_BER_12) { + hw->dac_sfp = false; + hw->phy.sfp_type = (hw->bus.lan_id == 0 + ? txgbe_sfp_type_25g_aoc_core0 + : txgbe_sfp_type_25g_aoc_core1); + } else if (cable_tech & TXGBE_SFF_CABLE_DA_ACTIVE) { + hw->dac_sfp = false; err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_CABLE_SPEC_COMP, &cable_spec); if (err != 0) @@ -1005,6 +1046,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) /* Allow any DA cable vendor */ if (cable_tech & (TXGBE_SFF_CABLE_DA_PASSIVE | TXGBE_SFF_CABLE_DA_ACTIVE)) { + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; } @@ -1017,6 +1059,7 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core0 || hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } @@ -1031,9 +1074,11 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) hw->phy.sfp_type == txgbe_sfp_type_1g_sx_core1)) { DEBUGOUT("SFP+ module not supported"); hw->phy.type = txgbe_phy_sfp_unsupported; + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return TXGBE_ERR_SFP_NOT_SUPPORTED; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; } @@ -1046,28 +1091,13 @@ s32 txgbe_identify_sfp_module(struct txgbe_hw *hw) s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) { s32 err = TXGBE_ERR_PHY_ADDR_INVALID; - u32 vendor_oui = 0; - enum txgbe_sfp_type stored_sfp_type = hw->phy.sfp_type; - u8 identifier = 0; - u8 comp_codes_1g = 0; - u8 comp_codes_10g = 0; - u8 oui_bytes[3] = {0, 0, 0}; - u16 enforce_sfp = 0; - u8 connector = 0; - u8 cable_length = 0; - u8 device_tech = 0; - bool active_cable = false; + u8 identifier = 0, transceiver_type = 0; u32 value; - if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { - hw->phy.sfp_type = txgbe_sfp_type_not_present; - err = TXGBE_ERR_SFP_NOT_PRESENT; - goto out; - } + /* config GPIO before read i2c */ + wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); if (hw->mac.type == txgbe_mac_aml40) { - /* config GPIO before read i2c */ - wr32(hw, TXGBE_GPIODATA, TXGBE_GPIOBIT_1); value = rd32(hw, TXGBE_GPIOEXT); if (value & TXGBE_SFP1_MOD_PRST_LS) { hw->phy.sfp_type = txgbe_sfp_type_not_present; @@ -1075,175 +1105,68 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw) } } - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_IDENTIFIER, - &identifier); -ERR_I2C: - if (err != 0) { + if (hw->phy.media_type != txgbe_media_type_fiber_qsfp) { hw->phy.sfp_type = txgbe_sfp_type_not_present; - hw->phy.id = 0; - hw->phy.type = txgbe_phy_unknown; return TXGBE_ERR_SFP_NOT_PRESENT; } - if (identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; - } - hw->phy.id = identifier; + err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (err) + return -EBUSY; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_10GBE_COMP, - &comp_codes_10g); + err = hw->phy.read_i2c_sff8636(hw, 0, TXGBE_SFF_IDENTIFIER, + &identifier); if (err != 0) - goto ERR_I2C; + goto err_read_i2c_eeprom; - err = hw->phy.read_i2c_eeprom(hw, TXGBE_SFF_QSFP_1GBE_COMP, - &comp_codes_1g); - - if (err != 0) - goto ERR_I2C; + if (identifier != TXGBE_SFF_IDENTIFIER_QSFP && + identifier != TXGBE_SFF_IDENTIFIER_QSFP_PLUS) { + PMD_INIT_LOG(ERR, "port[%d] QSFP module not supported, identifier = 0x%x", + hw->bus.lan_id, identifier); + hw->phy.type = txgbe_phy_sfp_unsupported; + err = TXGBE_ERR_SFP_NOT_SUPPORTED; + } else { + err = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_ETHERNET_COMP_OFFSET, + &transceiver_type); + if (err != 0) + goto err_read_i2c_eeprom; - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_PASSIVE_CABLE) { - hw->phy.type = txgbe_phy_qsfp_unknown_passive; - if (hw->mac.type == txgbe_mac_aml40) { + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_CR4) { if (hw->bus.lan_id == 0) hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core0; else hw->phy.sfp_type = txgbe_qsfp_type_40g_cu_core1; - } else { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_da_cu_core1; - } - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_SR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; - } else if (comp_codes_10g & TXGBE_SFF_40GBASE_LR4) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; - else - hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; - } else if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - if (hw->bus.lan_id == 0) - hw->phy.sfp_type = txgbe_sfp_type_srlr_core0; - else - hw->phy.sfp_type = txgbe_sfp_type_srlr_core1; - } else { - if (comp_codes_10g & TXGBE_SFF_QSFP_DA_ACTIVE_CABLE) - active_cable = true; - - if (!active_cable) { - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CONNECTOR, - &connector); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_CABLE_LENGTH, - &cable_length); - - hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_DEVICE_TECH, - &device_tech); - - if (connector == - TXGBE_SFF_QSFP_CONNECTOR_NOT_SEPARABLE && - cable_length > 0 && - ((device_tech >> 4) == - TXGBE_SFF_QSFP_TRANSMITTER_850NM_VCSEL)) - active_cable = true; + hw->phy.fiber_suppport_speed = + TXGBE_LINK_SPEED_40GB_FULL | + TXGBE_LINK_SPEED_10GB_FULL; } - if (active_cable) { - hw->phy.type = txgbe_phy_qsfp_unknown_active; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_SR4) { if (hw->bus.lan_id == 0) - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core0; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core0; else - hw->phy.sfp_type = - txgbe_sfp_type_da_act_lmt_core1; - } else { - /* unsupported module type */ - hw->phy.type = txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - goto out; + hw->phy.sfp_type = txgbe_qsfp_type_40g_sr_core1; } - } - - if (hw->phy.sfp_type != stored_sfp_type) - hw->phy.sfp_setup_needed = true; - - /* Determine if the QSFP+ PHY is dual speed or not. */ - hw->phy.multispeed_fiber = false; - if (((comp_codes_1g & TXGBE_SFF_1GBASESX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASESR_CAPABLE)) || - ((comp_codes_1g & TXGBE_SFF_1GBASELX_CAPABLE) && - (comp_codes_10g & TXGBE_SFF_10GBASELR_CAPABLE))) - hw->phy.multispeed_fiber = true; - - /* Determine PHY vendor for optical modules */ - if (comp_codes_10g & (TXGBE_SFF_10GBASESR_CAPABLE | - TXGBE_SFF_10GBASELR_CAPABLE)) { - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0, - &oui_bytes[0]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1, - &oui_bytes[1]); - - if (err != 0) - goto ERR_I2C; - - err = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_QSFP_VENDOR_OUI_BYTE2, - &oui_bytes[2]); - if (err != 0) - goto ERR_I2C; - - vendor_oui = - ((oui_bytes[0] << 24) | - (oui_bytes[1] << 16) | - (oui_bytes[2] << 8)); - - if (vendor_oui == TXGBE_SFF_VENDOR_OUI_INTEL) - hw->phy.type = txgbe_phy_qsfp_intel; - else - hw->phy.type = txgbe_phy_qsfp_unknown; - - hw->mac.get_device_caps(hw, &enforce_sfp); - if (!(enforce_sfp & TXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) { - /* Make sure we're a supported PHY type */ - if (hw->phy.type == txgbe_phy_qsfp_intel) { - err = 0; - } else { - if (hw->allow_unsupported_sfp) { - DEBUGOUT("WARNING: Wangxun (R) Network Connections are quality tested using Wangxun (R) Ethernet Optics. " - "Using untested modules is not supported and may cause unstable operation or damage to the module or the adapter. " - "Wangxun Corporation is not responsible for any harm caused by using untested modules."); - err = 0; - } else { - DEBUGOUT("QSFP module not supported"); - hw->phy.type = - txgbe_phy_sfp_unsupported; - err = TXGBE_ERR_SFP_NOT_SUPPORTED; - } - } - } else { - err = 0; + if (transceiver_type & TXGBE_SFF_ETHERNET_40G_LR4) { + if (hw->bus.lan_id == 0) + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core0; + else + hw->phy.sfp_type = txgbe_qsfp_type_40g_lr_core1; } } -out: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return err; + +err_read_i2c_eeprom: + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + hw->phy.sfp_type = txgbe_sfp_type_not_present; + hw->phy.id = 0; + hw->phy.type = txgbe_phy_unknown; + return TXGBE_ERR_SFP_NOT_PRESENT; } /** @@ -1278,6 +1201,26 @@ s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, sff8472_data); } +/** + * txgbe_read_i2c_sff8636 - Reads 8 bit word over I2C interface + * @hw: pointer to hardware structure + * @byte_offset: byte offset at address 0xA2 + * @eeprom_data: value read + * + * Performs byte read operation to SFP module's SFF-8472 data over I2C + **/ +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data) +{ + hw->phy.write_i2c_byte(hw, TXGBE_SFF_QSFP_PAGE_SELECT, + TXGBE_I2C_EEPROM_DEV_ADDR, + page); + + return hw->phy.read_i2c_byte(hw, byte_offset, + TXGBE_I2C_EEPROM_DEV_ADDR, + sff8636_data); +} + /** * txgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface * @hw: pointer to hardware structure @@ -1295,7 +1238,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte_unlocked - Reads 8 bit word over I2C + * txgbe_read_i2c_byte - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read * @dev_addr: address to read from @@ -1304,7 +1247,7 @@ s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, * Performs byte read operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, +s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data) { txgbe_i2c_start(hw, dev_addr); @@ -1334,30 +1277,7 @@ s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, } /** - * txgbe_read_i2c_byte - Reads 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to read - * @dev_addr: address to read from - * @data: value read - * - * Performs byte read operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_read_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - return err; -} - -/** - * txgbe_write_i2c_byte_unlocked - Writes 8 bit word over I2C + * txgbe_write_i2c_byte - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write * @dev_addr: address to write to @@ -1366,54 +1286,29 @@ s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, * Performs byte write operation to SFP module's EEPROM over I2C interface at * a specified device address. **/ -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) +s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, + u8 dev_addr, u8 data) { txgbe_i2c_start(hw, dev_addr); /* wait tx empty */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_TXEMPTY, - TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) { + TXGBE_I2CICR_TXEMPTY, NULL, 100, 100)) return -TERR_TIMEOUT; - } - wr32(hw, TXGBE_I2CDATA, byte_offset | TXGBE_I2CDATA_STOP); + wr32(hw, TXGBE_I2CDATA, byte_offset); wr32(hw, TXGBE_I2CDATA, data | TXGBE_I2CDATA_WRITE); /* wait for write complete */ if (!po32m(hw, TXGBE_I2CICR, TXGBE_I2CICR_RXFULL, - TXGBE_I2CICR_RXFULL, NULL, 100, 100)) { + TXGBE_I2CICR_RXFULL, NULL, 100, 100)) return -TERR_TIMEOUT; - } + txgbe_i2c_stop(hw); return 0; } -/** - * txgbe_write_i2c_byte - Writes 8 bit word over I2C - * @hw: pointer to hardware structure - * @byte_offset: byte offset to write - * @dev_addr: address to write to - * @data: value to write - * - * Performs byte write operation to SFP module's EEPROM over I2C interface at - * a specified device address. - **/ -s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data) -{ - u32 swfw_mask = hw->phy.phy_semaphore_mask; - int err = 0; - - if (hw->mac.acquire_swfw_sync(hw, swfw_mask)) - return TXGBE_ERR_SWFW_SYNC; - err = txgbe_write_i2c_byte_unlocked(hw, byte_offset, dev_addr, data); - hw->mac.release_swfw_sync(hw, swfw_mask); - - return err; -} - /** * txgbe_i2c_start - Sets I2C start condition * @hw: pointer to hardware structure diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 3fe7a34409..4da4be0d5f 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -261,7 +261,9 @@ #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE0 0xA5 #define TXGBE_SFF_QSFP_VENDOR_OUI_BYTE1 0xA6 @@ -289,6 +291,9 @@ #define TXGBE_SFF_4x10GBASESR_CAP 0x11 #define TXGBE_SFF_40GBASEPSM4_PARALLEL 0x12 #define TXGBE_SFF_40GBASE_SWMD4_CAP 0x1f +#define TXGBE_SFF_COPPER_5M 0x5 +#define TXGBE_SFF_COPPER_3M 0x3 +#define TXGBE_SFF_COPPER_1M 0x1 #define TXGBE_SFF_DA_SPEC_ACTIVE_LIMITING 0x4 #define TXGBE_SFF_25GAUI_C2M_AOC_BER_5 0x1 @@ -296,6 +301,11 @@ #define TXGBE_SFF_25GAUI_C2M_AOC_BER_12 0x18 #define TXGBE_SFF_25GAUI_C2M_ACC_BER_12 0x19 +#define TXGBE_ETHERNET_COMP_OFFSET 0x83 +#define TXGBE_SFF_ETHERNET_40G_CR4 MS(3, 0x1) +#define TXGBE_SFF_ETHERNET_40G_SR4 MS(2, 0x1) +#define TXGBE_SFF_ETHERNET_40G_LR4 MS(1, 0x1) + #define TXGBE_SFF_SOFT_RS_SELECT_MASK 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_10G 0x8 #define TXGBE_SFF_SOFT_RS_SELECT_1G 0x0 @@ -493,14 +503,12 @@ s32 txgbe_identify_qsfp_module(struct txgbe_hw *hw); s32 txgbe_check_overtemp(struct txgbe_hw *hw); s32 txgbe_read_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 *data); -s32 txgbe_read_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 *data); s32 txgbe_write_i2c_byte(struct txgbe_hw *hw, u8 byte_offset, u8 dev_addr, u8 data); -s32 txgbe_write_i2c_byte_unlocked(struct txgbe_hw *hw, u8 byte_offset, - u8 dev_addr, u8 data); s32 txgbe_read_i2c_sff8472(struct txgbe_hw *hw, u8 byte_offset, - u8 *sff8472_data); + u8 *sff8472_data); +s32 txgbe_read_i2c_sff8636(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data); s32 txgbe_read_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 txgbe_write_i2c_eeprom(struct txgbe_hw *hw, u8 byte_offset, diff --git a/drivers/net/txgbe/base/txgbe_type.h b/drivers/net/txgbe/base/txgbe_type.h index 47629aa9e0..2e2d79e0e1 100644 --- a/drivers/net/txgbe/base/txgbe_type.h +++ b/drivers/net/txgbe/base/txgbe_type.h @@ -702,6 +702,8 @@ struct txgbe_phy_info { u8 dev_addr, u8 data); s32 (*read_i2c_sff8472)(struct txgbe_hw *hw, u8 byte_offset, u8 *sff8472_data); + s32 (*read_i2c_sff8636)(struct txgbe_hw *hw, u8 page, u8 byte_offset, + u8 *sff8636_data); s32 (*read_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, u8 *eeprom_data); s32 (*write_i2c_eeprom)(struct txgbe_hw *hw, u8 byte_offset, -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 17/20] net/txgbe: fix get module info operation 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (15 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 16/20] net/txgbe: fix SFP module identification Zaiyu Wang @ 2026-05-11 10:35 ` Zaiyu Wang 2026-05-11 10:36 ` [PATCH v4 18/20] net/txgbe: fix get EEPROM operation Zaiyu Wang ` (2 subsequent siblings) 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:35 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/base/txgbe_phy.h | 6 +- drivers/net/txgbe/txgbe_ethdev.c | 116 ++++++++++++++++++++++------- 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/drivers/net/txgbe/base/txgbe_phy.h b/drivers/net/txgbe/base/txgbe_phy.h index 4da4be0d5f..581f667bdc 100644 --- a/drivers/net/txgbe/base/txgbe_phy.h +++ b/drivers/net/txgbe/base/txgbe_phy.h @@ -257,11 +257,15 @@ #define TXGBE_SFF_CABLE_DA_PASSIVE 0x4 #define TXGBE_SFF_CABLE_DA_ACTIVE 0x8 #define TXGBE_SFF_CABLE_SPEC_COMP 0x3C +#define TXGBE_SFF_DDM_IMPLEMENTED 0x40 #define TXGBE_SFF_SFF_8472_SWAP 0x5C #define TXGBE_SFF_SFF_8472_COMP 0x5E #define TXGBE_SFF_SFF_8472_OSCB 0x6E #define TXGBE_SFF_SFF_8472_ESCB 0x76 -#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F +#define TXGBE_SFF_SFF_REVISION_ADDR 0x01 +#define TXGBE_SFF_QSFP_PAGE_SELECT 0x7F + +#define TXGBE_MODULE_QSFP_MAX_LEN 640 #define TXGBE_SFF_IDENTIFIER_QSFP 0x0C #define TXGBE_SFF_IDENTIFIER_QSFP_PLUS 0x0D diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index 56987ae028..bc651cfcfb 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5348,41 +5348,105 @@ txgbe_get_module_info(struct rte_eth_dev *dev, struct txgbe_hw *hw = TXGBE_DEV_HW(dev); uint32_t status; uint8_t sff8472_rev, addr_mode; + u8 identifier = 0; + u8 sff8636_rev = 0; bool page_swap = false; + u32 value; - /* Check whether we support SFF-8472 or not */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_COMP, - &sff8472_rev); - if (status != 0) - return -EIO; - - /* addressing mode is not supported */ - status = hw->phy.read_i2c_eeprom(hw, - TXGBE_SFF_SFF_8472_SWAP, - &addr_mode); - if (status != 0) - return -EIO; + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } - if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { - PMD_DRV_LOG(ERR, - "Address change required to access page 0xA2, " - "but not supported. Please report the module " - "type to the driver maintainers."); - page_swap = true; + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; } - if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap) { - /* We have a SFP, but it does not support SFF-8472 */ - modinfo->type = RTE_ETH_MODULE_SFF_8079; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; + + if (hw->mac.type == txgbe_mac_aml40) { + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_IDENTIFIER, + &identifier); } else { - /* We have a SFP which supports a revision of SFF-8472. */ - modinfo->type = RTE_ETH_MODULE_SFF_8472; - modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); } + if (status != 0) + goto ERROR_IO; + + switch (identifier) { + case TXGBE_SFF_IDENTIFIER_SFP: + /* Check whether we support SFF-8472 or not */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_COMP, + &sff8472_rev); + if (status != 0) + goto ERROR_IO; + + /* addressing mode is not supported */ + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_SFF_8472_SWAP, + &addr_mode); + if (status != 0) + goto ERROR_IO; + + if (addr_mode & TXGBE_SFF_ADDRESSING_MODE) { + PMD_DRV_LOG(ERR, + "Address change required to access page 0xA2, " + "but not supported. Please report the module " + "type to the driver maintainers."); + page_swap = true; + } + + if (sff8472_rev == TXGBE_SFF_SFF_8472_UNSUP || page_swap || + !(addr_mode & TXGBE_SFF_DDM_IMPLEMENTED)) { + /* We have a SFP, but it does not support SFF-8472 */ + modinfo->type = RTE_ETH_MODULE_SFF_8079; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN; + } else { + /* We have a SFP which supports a revision of SFF-8472. */ + modinfo->type = RTE_ETH_MODULE_SFF_8472; + modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN; + } + break; + case TXGBE_SFF_IDENTIFIER_QSFP: + case TXGBE_SFF_IDENTIFIER_QSFP_PLUS: + status = hw->phy.read_i2c_sff8636(hw, 0, + TXGBE_SFF_SFF_REVISION_ADDR, + &sff8636_rev); + if (status != 0) + goto ERROR_IO; + /* Check revision compliance */ + if (sff8636_rev > 0x02) { + /* Module is SFF-8636 compliant */ + modinfo->type = RTE_ETH_MODULE_SFF_8636; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } else { + modinfo->type = RTE_ETH_MODULE_SFF_8436; + modinfo->eeprom_len = TXGBE_MODULE_QSFP_MAX_LEN; + } + break; + default: + PMD_DRV_LOG(ERR, "SFF Module Type not recognized."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EINVAL; + } + + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } static int -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 18/20] net/txgbe: fix get EEPROM operation 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (16 preceding siblings ...) 2026-05-11 10:35 ` [PATCH v4 17/20] net/txgbe: fix get module info operation Zaiyu Wang @ 2026-05-11 10:36 ` Zaiyu Wang 2026-05-11 10:36 ` [PATCH v4 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang 2026-05-11 10:36 ` [PATCH v4 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:36 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The original I2C access flow in the module information retrieval process was flawed. Correct the implementation to properly fetch module info. Fixes: abf042d32b39 ("net/txgbe: add Amber-Lite 25G/40G NICs") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_ethdev.c | 67 ++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/drivers/net/txgbe/txgbe_ethdev.c b/drivers/net/txgbe/txgbe_ethdev.c index bc651cfcfb..d6921704e8 100644 --- a/drivers/net/txgbe/txgbe_ethdev.c +++ b/drivers/net/txgbe/txgbe_ethdev.c @@ -5458,23 +5458,76 @@ txgbe_get_module_eeprom(struct rte_eth_dev *dev, uint8_t databyte = 0xFF; uint8_t *data = info->data; uint32_t i = 0; + bool is_sfp = false; + u32 value; + u8 identifier = 0; + u16 offset; + u8 page = 0; + + if (hw->mac.type == txgbe_mac_aml40) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_PRST_LS) + return -EIO; + } + + if (hw->mac.type == txgbe_mac_aml) { + value = rd32(hw, TXGBE_GPIOEXT); + if (value & TXGBE_SFP1_MOD_ABS_LS) + return -EIO; + } if (info->length == 0) return -EINVAL; - for (i = info->offset; i < info->offset + info->length; i++) { - if (i < RTE_ETH_MODULE_SFF_8079_LEN) - status = hw->phy.read_i2c_eeprom(hw, i, &databyte); - else - status = hw->phy.read_i2c_sff8472(hw, i, &databyte); + status = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + if (status) + return -EBUSY; - if (status != 0) - return -EIO; + status = hw->phy.read_i2c_eeprom(hw, + TXGBE_SFF_IDENTIFIER, + &identifier); + if (status != 0) + goto ERROR_IO; + if (identifier == TXGBE_SFF_IDENTIFIER_SFP) + is_sfp = true; + + memset(data, 0, info->length); + + for (i = info->offset; i < info->offset + info->length; i++) { + if (is_sfp) { + if (i < RTE_ETH_MODULE_SFF_8079_LEN) + status = hw->phy.read_i2c_eeprom(hw, i, + &databyte); + else + status = hw->phy.read_i2c_sff8472(hw, i, + &databyte); + + if (status != 0) + goto ERROR_IO; + } else { + offset = i; + while (offset >= RTE_ETH_MODULE_SFF_8436_LEN) { + offset -= RTE_ETH_MODULE_SFF_8436_LEN / 2; + page++; + } + if (page == 0 || !(data[0x2] & 0x4)) { + status = hw->phy.read_i2c_sff8636(hw, page, offset, + &databyte); + if (status != 0) + goto ERROR_IO; + } + } data[i - info->offset] = databyte; } + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); return 0; + +ERROR_IO: + PMD_DRV_LOG(ERR, "I2C IO ERROR."); + hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWPHY); + return -EIO; } bool -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 19/20] net/txgbe: fix to reset Tx write-back pointer 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (17 preceding siblings ...) 2026-05-11 10:36 ` [PATCH v4 18/20] net/txgbe: fix get EEPROM operation Zaiyu Wang @ 2026-05-11 10:36 ` Zaiyu Wang 2026-05-11 10:36 ` [PATCH v4 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:36 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu The write-back pointer was not reset when the Tx queue was reset. This leads to the wrong Tx desc free logic. Move the resetting of pointer into txq->ops->reset(txq). Fixes: 8ada71d0bb7f ("net/txgbe: add Tx head write-back mode for Amber-Lite") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 45 +++++++++++++---------- drivers/net/txgbe/txgbe_rxtx.h | 1 + drivers/net/txgbe/txgbe_rxtx_vec_common.h | 7 ++++ 3 files changed, 33 insertions(+), 20 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index 851cd122d8..ef53a868a6 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -2320,6 +2320,12 @@ txgbe_reset_tx_queue(struct txgbe_tx_queue *txq) txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); txq->tx_tail = 0; + /* Zero out headwb_mem memory */ + if (txq->headwb_mem) { + for (i = 0; i < txq->headwb_size; i++) + txq->headwb_mem[i] = 0; + } + /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition @@ -2419,7 +2425,7 @@ txgbe_get_tx_port_offloads(struct rte_eth_dev *dev) return tx_offload_capa; } -static int +static void txgbe_setup_headwb_resources(struct rte_eth_dev *dev, void *tx_queue, unsigned int socket_id) @@ -2427,33 +2433,33 @@ txgbe_setup_headwb_resources(struct rte_eth_dev *dev, struct txgbe_hw *hw = TXGBE_DEV_HW(dev); const struct rte_memzone *headwb; struct txgbe_tx_queue *txq = tx_queue; - u8 i, headwb_size = 0; + u8 headwb_size = 0; - if (hw->mac.type != txgbe_mac_aml && hw->mac.type != txgbe_mac_aml40) { - txq->headwb_mem = NULL; - return 0; - } + if (hw->mac.type != txgbe_mac_aml && hw->mac.type != txgbe_mac_aml40) + goto out; + + if (!hw->devarg.tx_headwb) + goto out; - headwb_size = hw->devarg.tx_headwb_size; + headwb_size = txq->headwb_size; headwb = rte_eth_dma_zone_reserve(dev, "tx_headwb_mem", txq->queue_id, sizeof(u32) * headwb_size, TXGBE_ALIGN, socket_id); if (headwb == NULL) { - DEBUGOUT("Fail to setup headwb resources: no mem"); - txgbe_tx_queue_release(txq); - return -ENOMEM; + PMD_DRV_LOG(INFO, + "Failed to allocate headwb memory for Tx queue %u, change to SP mode", + txq->queue_id); + goto out; } txq->headwb = headwb; txq->headwb_dma = TMZ_PADDR(headwb); txq->headwb_mem = (uint32_t *)TMZ_VADDR(headwb); + return; - /* Zero out headwb_mem memory */ - for (i = 0; i < headwb_size; i++) - txq->headwb_mem[i] = 0; - - return 0; +out: + txq->headwb_mem = NULL; } int __rte_cold @@ -2549,6 +2555,7 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, txq->offloads = offloads; txq->ops = &def_txq_ops; txq->tx_deferred_start = tx_conf->tx_deferred_start; + txq->headwb_size = hw->devarg.tx_headwb_size; #ifdef RTE_LIB_SECURITY txq->using_ipsec = !!(dev->data->dev_conf.txmode.offloads & RTE_ETH_TX_OFFLOAD_SECURITY); @@ -2584,8 +2591,7 @@ txgbe_dev_tx_queue_setup(struct rte_eth_dev *dev, /* set up scalar TX function as appropriate */ txgbe_set_tx_function(dev, txq); - if (hw->devarg.tx_headwb) - err = txgbe_setup_headwb_resources(dev, txq, socket_id); + txgbe_setup_headwb_resources(dev, txq, socket_id); txq->ops->reset(txq); txq->desc_error = 0; @@ -4762,15 +4768,14 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) wr32(hw, TXGBE_TXRP(txq->reg_idx), 0); wr32(hw, TXGBE_TXWP(txq->reg_idx), 0); - if ((hw->mac.type == txgbe_mac_aml || hw->mac.type == txgbe_mac_aml40) && - hw->devarg.tx_headwb) { + if (txq->headwb_mem) { uint32_t txdctl; wr32(hw, TXGBE_PX_TR_HEAD_ADDRL(txq->reg_idx), (uint32_t)(txq->headwb_dma & BIT_MASK32)); wr32(hw, TXGBE_PX_TR_HEAD_ADDRH(txq->reg_idx), (uint32_t)(txq->headwb_dma >> 32)); - if (hw->devarg.tx_headwb_size == 16) + if (txq->headwb_size == 16) txdctl = TXGBE_PX_TR_CFG_HEAD_WB | TXGBE_PX_TR_CFG_HEAD_WB_64BYTE; else diff --git a/drivers/net/txgbe/txgbe_rxtx.h b/drivers/net/txgbe/txgbe_rxtx.h index 02e2617cce..237bb64697 100644 --- a/drivers/net/txgbe/txgbe_rxtx.h +++ b/drivers/net/txgbe/txgbe_rxtx.h @@ -416,6 +416,7 @@ struct txgbe_tx_queue { uint64_t desc_error; bool resetting; const struct rte_memzone *headwb; + uint16_t headwb_size; uint64_t headwb_dma; volatile uint32_t *headwb_mem; }; diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h index edf3586b77..594886c5b1 100644 --- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h +++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h @@ -255,6 +255,13 @@ _txgbe_reset_tx_queue_vec(struct txgbe_tx_queue *txq) txq->tx_next_dd = (uint16_t)(txq->tx_free_thresh - 1); txq->tx_tail = 0; + + /* Zero out headwb_mem memory */ + if (txq->headwb_mem) { + for (i = 0; i < txq->headwb_size; i++) + txq->headwb_mem[i] = 0; + } + /* * Always allow 1 descriptor to be un-allocated to avoid * a H/W race condition -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
* [PATCH v4 20/20] net/txgbe: fix to enable Tx desc check 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang ` (18 preceding siblings ...) 2026-05-11 10:36 ` [PATCH v4 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang @ 2026-05-11 10:36 ` Zaiyu Wang 19 siblings, 0 replies; 92+ messages in thread From: Zaiyu Wang @ 2026-05-11 10:36 UTC (permalink / raw) To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu Now lib security is enabled by default, and cannot be disabled if the driver is intended to be used. So Tdm_desc_chk is always unable to enable. Remove this restriction, and just enable the corresponding queue check. Fixes: 0eabdfcd4af4 ("net/txgbe: enable Tx descriptor error interrupt") Cc: stable@dpdk.org Signed-off-by: Zaiyu Wang <zaiyuwang@trustnetic.com> --- drivers/net/txgbe/txgbe_rxtx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c index ef53a868a6..8b3d5eec14 100644 --- a/drivers/net/txgbe/txgbe_rxtx.c +++ b/drivers/net/txgbe/txgbe_rxtx.c @@ -4768,6 +4768,12 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) wr32(hw, TXGBE_TXRP(txq->reg_idx), 0); wr32(hw, TXGBE_TXWP(txq->reg_idx), 0); +#ifdef RTE_LIBRTE_SECURITY + if (!(txq->using_ipsec)) +#endif + wr32m(hw, TXGBE_TDM_DESC_CHK(txq->reg_idx / 32), + BIT(txq->reg_idx % 32), BIT(txq->reg_idx % 32)); + if (txq->headwb_mem) { uint32_t txdctl; @@ -4785,11 +4791,6 @@ txgbe_dev_tx_init(struct rte_eth_dev *dev) } } -#ifndef RTE_LIB_SECURITY - for (i = 0; i < 4; i++) - wr32(hw, TXGBE_TDM_DESC_CHK(i), 0xFFFFFFFF); -#endif - /* Device configured with multiple TX queues. */ txgbe_dev_mq_tx_configure(dev); } -- 2.21.0.windows.1 ^ permalink raw reply related [flat|nested] 92+ messages in thread
end of thread, other threads:[~2026-05-11 10:38 UTC | newest] Thread overview: 92+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-23 3:40 [PATCH 00/18] Wangxun Fixes Zaiyu Wang 2026-04-23 3:40 ` [PATCH 01/18] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-04-23 3:40 ` [PATCH 02/18] net/ngbe: " Zaiyu Wang 2026-04-23 3:40 ` [PATCH 03/18] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang 2026-04-23 3:40 ` [PATCH 04/18] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang 2026-04-23 3:40 ` [PATCH 05/18] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang 2026-04-23 3:40 ` [PATCH 06/18] net/txgbe: fix link status check condition Zaiyu Wang 2026-04-23 3:40 ` [PATCH 07/18] net/txgbe: fix Tx desc free logic Zaiyu Wang 2026-04-23 3:40 ` [PATCH 08/18] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang 2026-04-23 7:54 ` Jiawen Wu 2026-04-23 3:40 ` [PATCH 09/18] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang 2026-04-23 3:40 ` [PATCH 10/18] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang 2026-04-23 3:40 ` [PATCH 11/18] net/txgbe: fix traffic class priority configuration Zaiyu Wang 2026-04-23 3:40 ` [PATCH 12/18] net/txgbe: fix link stability for 25G NIC Zaiyu Wang 2026-04-23 8:22 ` Jiawen Wu 2026-04-23 3:40 ` [PATCH 13/18] net/txgbe: fix link stability for 40G NIC Zaiyu Wang 2026-04-23 3:40 ` [PATCH 14/18] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang 2026-04-23 3:40 ` [PATCH 15/18] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang 2026-04-23 3:40 ` [PATCH 16/18] net/txgbe: fix SFP module identification Zaiyu Wang 2026-04-23 3:40 ` [PATCH 17/18] net/txgbe: fix get module info operation Zaiyu Wang 2026-04-23 3:40 ` [PATCH 18/18] net/txgbe: fix get eeprom operation Zaiyu Wang 2026-04-24 21:59 ` Stephen Hemminger 2026-04-29 10:24 ` [PATCH v2 00/20] Wangxun Fixes Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 02/20] net/ngbe: " Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang 2026-04-29 10:24 ` [PATCH v2 05/20] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 06/20] net/txgbe: fix link status check condition Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang 2026-04-29 15:10 ` Stephen Hemminger 2026-04-29 10:25 ` [PATCH v2 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang 2026-04-29 15:11 ` Stephen Hemminger 2026-05-09 11:06 ` Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang 2026-04-29 15:12 ` Stephen Hemminger 2026-04-29 10:25 ` [PATCH v2 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 16/20] net/txgbe: fix SFP module identification Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 17/20] net/txgbe: fix get module info operation Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 18/20] net/txgbe: fix get eeprom operation Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang 2026-04-29 10:25 ` [PATCH v2 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 00/20] Wangxun Fixes Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 02/20] net/ngbe: " Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 05/20] net/txgbe: fix inaccuracy in TX rate limiting Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 06/20] net/txgbe: fix link status check condition Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 16/20] net/txgbe: fix SFP module identification Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 17/20] net/txgbe: fix get module info operation Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 18/20] net/txgbe: fix get eeprom operation Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang 2026-05-09 11:28 ` [PATCH v3 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang 2026-05-09 15:44 ` [PATCH v3 00/20] Wangxun Fixes Stephen Hemminger 2026-05-09 17:07 ` Stephen Hemminger 2026-05-11 10:28 ` Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 " Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 01/20] net/txgbe: remove duplicate xstats counters Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 02/20] net/ngbe: " Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 03/20] net/ngbe: add missing CDR config for YT PHY Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 04/20] net/ngbe: fix VF promiscuous and allmulticast Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 05/20] net/txgbe: fix inaccuracy in Tx rate limiting Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 06/20] net/txgbe: fix link status check condition Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 07/20] net/txgbe: fix Tx desc free logic Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 08/20] net/txgbe: fix link flow control registers for Amber-Lite Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 09/20] net/txgbe: fix link flow control config for Sapphire Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 10/20] net/txgbe: fix a mass of unknown interrupts Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 11/20] net/txgbe: fix traffic class priority configuration Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 12/20] net/txgbe: fix link stability for 25G NIC Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 13/20] net/txgbe: fix link stability for 40G NIC Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 14/20] net/txgbe: fix link stability for Amber-Lite backplane mode Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 15/20] net/txgbe: fix FEC mode configuration on 25G NIC Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 16/20] net/txgbe: fix SFP module identification Zaiyu Wang 2026-05-11 10:35 ` [PATCH v4 17/20] net/txgbe: fix get module info operation Zaiyu Wang 2026-05-11 10:36 ` [PATCH v4 18/20] net/txgbe: fix get EEPROM operation Zaiyu Wang 2026-05-11 10:36 ` [PATCH v4 19/20] net/txgbe: fix to reset Tx write-back pointer Zaiyu Wang 2026-05-11 10:36 ` [PATCH v4 20/20] net/txgbe: fix to enable Tx desc check Zaiyu Wang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox