* Re: [RFC] devtools: add tool calling support to review-patch.py
From: Stephen Hemminger @ 2026-06-16 22:42 UTC (permalink / raw)
To: Aaron Conole; +Cc: dev, David Marchand
In-Reply-To: <20260609182652.1053422-1-aconole@redhat.com>
On Tue, 9 Jun 2026 14:26:47 -0400
Aaron Conole <aconole@redhat.com> wrote:
> Add an iterative tool-use loop to review-patch.py for the Anthropic
> and OpenAI providers. The reviewer can now look up additional context
> from the DPDK source tree when the patch alone is insufficient,
> rather than having to guess at surrounding code, API contracts, or
> function signatures.
>
> Tool calling is enabled by default with a limit of 10 rounds. Pass
> '--tool-rounds 0' to disable it and restore the previous single-shot
> behavior. The round limit prevents runaway cost on large patches
> that when reached will force the model to deliver a final judgement.
>
> Initial tool set:
> - grep Searches for regex across the file system with
> optional path restrictions and case-insensitive
> matches.
> - file_read Line range read of a specific path.
>
> Both tools are limited to the repository root to prevent path
> traversal. Path outputs are relative to the repo root.
>
> The system prompt is extended when tool calling is active to
> encourage the model to use tools only when genuinely needed,
> keeping unnecessary round trips and token costs under control
> and to a minimum.
>
> Internally, _common.py gains send_request_raw() (returning the
> raw response dict) so the tool-calling loops can inspect
> stop_reason / finish_reason before extracting text.
>
> Signed-off-by: Aaron Conole <aconole@redhat.com>
> ---
Well AI saw the security bypass here...
Error
=====
devtools/ai/review-patch.py: path containment check is bypassable
(_tool_grep and _tool_file_read)
repo_resolved = Path(repo_root).resolve()
search_path = (repo_resolved / rel_path).resolve()
if not str(search_path).startswith(str(repo_resolved)):
return "Error: path is outside the repository"
str.startswith() on the resolved path string is a prefix match, not a
path-component match. If repo_root resolves to /home/me/dpdk, then
/home/me/dpdk-private/secrets passes the check, since the string starts
with "/home/me/dpdk". The commit message states both tools are "limited
to the repository root to prevent path traversal" -- that property does
not hold for sibling directories sharing the name prefix. Same bug in
both tool helpers.
# is_relative_to (3.9+), raises nothing, no string games
if not search_path.is_relative_to(repo_resolved):
return "Error: path is outside the repository"
(Absolute rel_path and ../ escapes are already caught by resolve() +
this fix; only the prefix case is currently open.)
Warning
=======
devtools/ai/_common.py: unrelated reformatting mixed into a feature
patch. The docstring re-wrapping in print_token_summary(),
_extract_text(), _print_verbose_usage(), and the classify_review()
regex reflow in review-patch.py are cosmetic churn unrelated to tool
calling. Drop them or split into a separate cleanup; they inflate the
diff and obscure the actual change.
devtools/ai/review-patch.py: grep --include list excludes the files the
tool prompt points the model at. _tool_grep restricts to
*.[ch]/*.py/*.rst/*.ini, but TOOL_PROMPT_EXTENSION explicitly directs
the model to check ".ci/" scripts, meson.build, and MAINTAINERS. Those
are extensionless or shell, so grep silently returns "No matches found"
rather than surfacing the omission. Either widen the include set or
note the restriction in the tool description so the model doesn't draw
false conclusions from empty results.
Info
====
xai is OpenAI wire-compatible and already shares build_openai_request()
elsewhere, but tool calling is gated to provider == "openai" in
call_api() and the verbose banner. xai (and any future
OpenAI-compatible provider) falls back to single-shot with no notice.
Reusing call_api_with_tools_openai() for xai looks free.
send_request_raw() bypasses _extract_text(), which is where the
"error" in result check lived. The tool loops read stop_reason /
choices directly, so a provider error returned with HTTP 200 yields an
empty string and a misleading "clean" review instead of a hard failure.
Worth a guard on api_result.get("error") at the top of each loop body.
Default-on at 10 rounds is a behavior and cost change for every existing
caller, and grants repo-wide read to the model by default. Reasonable
for an RFC to propose, but worth calling out explicitly for the list --
some CI users may want opt-in rather than opt-out.
^ permalink raw reply
* Re: [PATCH v2] devtools: add Vertex AI to review scripts
From: Stephen Hemminger @ 2026-06-16 22:44 UTC (permalink / raw)
To: David Marchand; +Cc: dev, thomas, Aaron Conole
In-Reply-To: <20260602064406.1230601-1-david.marchand@redhat.com>
On Tue, 2 Jun 2026 08:44:06 +0200
David Marchand <david.marchand@redhat.com> wrote:
> OpenAI, xAI) can now use Vertex AI with Application Default Credentials.
>
> This requires a python dependency google-auth but it is left as
> optional.
>
> Key features:
> - Auto-detection of authentication method based on environment
> - Manual override via --auth flag (auto, direct, vertex)
> - Automatic model name translation for Vertex format
> - Support for both global and regional Vertex endpoints
> - Proper error handling for Vertex API responses
>
> Provider-specific implementations:
> - Anthropic: Uses /publishers/anthropic/models/{model}:rawPredict
> with model name format claude-sonnet-4-5@20250929
> - Google: Uses /publishers/google/models/{model}:generateContent
> - OpenAI/xAI: Use /endpoints/openapi/chat/completions
> with publisher prefix (e.g., openai/gpt-oss-120b-maas)
>
> Authentication detection logic:
> - Vertex: Requires google-auth library and ADC configured
> - Direct: Falls back to API key from environment variables
>
> Available models on Vertex AI:
> - Anthropic: All Claude models
> - Google: All Gemini models
> - OpenAI: gpt-oss-120b-maas, gpt-oss-20b-maas (open-weight only)
> - xAI: grok-4.20-*, grok-4.1-fast-* variants
>
> Signed-off-by: David Marchand <david.marchand@redhat.com>
> ---
I have no direct knowledge of Vertex pro/con.
AI review with better model had some insights.
On the whole the refactor is sound: moving "model" insertion into
_build_request_meta and threading an auth string instead of api_key is
consistent across _common.py, review-patch.py and review-doc.py, and the
build_*_request signature changes match their only callers. Two issues and
a couple of minor notes.
Warning: project-id resolution is split and the early error is unreachable-
proof in the wrong direction.
get_vertex_credentials() does:
credentials, project = google_auth_default()
...
if not project:
error("Could not detect GCP project. Set GOOGLE_CLOUD_PROJECT ...")
return credentials.token, project
but the caller then applies its own fallback:
access_token, project_id = get_vertex_credentials()
project_id = os.environ.get("GOOGLE_CLOUD_PROJECT") \
or os.environ.get("GCP_PROJECT") or project_id
If ADC resolves no project, get_vertex_credentials() calls error() and
exits before the GCP_PROJECT fallback can run. google.auth.default()
honors GOOGLE_CLOUD_PROJECT itself, but not GCP_PROJECT, so the
GCP_PROJECT branch here is dead in exactly the case it exists for, and
the error message tells the user to set a variable that wouldn't have
helped. Resolve the project in one place: drop the "if not project"
error from get_vertex_credentials() and check after the env fallback,
or move the env lookups into get_vertex_credentials().
Warning: several added lines exceed the 100-column limit.
_common.py: error("Could not detect GCP project...") 137 cols
_common.py: error("Vertex AI support requires...") 108 cols
_common.py: project_id = os.environ.get(...) or ... 102 cols
_common.py: vertex_base = f"https://aiplatform..." 104 cols
_common.py: vertex_base = f"https://{location}-..." 115 cols
pycodestyle/flake8 will flag all five; the project_id line is also
black-splittable so "black --check" fails on it. Wrap the f-strings and
split the message strings.
Info: detect_auth_method() catches bare Exception around
google_auth_default(). Acceptable for best-effort autodetection, but
narrowing it (or a "# noqa"/pylint disable with a reason) documents intent.
Info: the HTTPError path now does error_data[0].get('error', ...) after
unwrapping a list. If a Vertex error body is a list of non-dicts this
raises AttributeError outside the JSONDecodeError guard. Low risk, but a
type check would harden it.
Info: --auth is wired into review-patch.py and review-doc.py but
compare-patch-reviews.sh has no passthrough, so Vertex can't be selected
when comparing providers. May be intentional for this patch.
^ permalink raw reply
* Re: [PATCH v2] tools: AI review handle empty Error sections
From: Stephen Hemminger @ 2026-06-16 22:46 UTC (permalink / raw)
To: Matthew Gee; +Cc: dev, aconole, lylavoie
In-Reply-To: <20260612190807.1020863-1-mgee@iol.unh.edu>
On Fri, 12 Jun 2026 15:08:07 -0400
Matthew Gee <mgee@iol.unh.edu> wrote:
> Previous review-patch.py would detect and report and error or warning
> based off of the occurrence of the headers of the error and warning
> sections. This led to consistent false positives as often AI reviewers
> will create the header but put "none" or similar filler text within
> the following body.
>
> This patch updates the code in order to check if the AI review has a
> body with error or warnings to fix and not just filler text. This is
> done by querying multiple lines at once and adjusting the regex to
> filter out headers followed only by filler text or formatting in the
> review.
>
> These changes were tested against 10+ AI review outputs with several
> variations in formatting and filler text in order to catch a good
> variety of cases to make sure code reviews with actual errors or
> warnings are caught and not missed.
>
> Signed-off-by: Matthew Gee <mgee@iol.unh.edu>
> ---
AI saw some stuff which I missed.
Matthew,
The windowing (tee/islice/chain) is aligned correctly, but the new
matching has a few problems.
The bigger issue is that this only recognizes markdown '#' headers now.
The old scan matched an optional '#' prefix, '**' bold, and '<h1-3>' too.
rgx_should_match requires "#+\s", so plain-text "Errors:" / "**Errors**"
and HTML "<h2>Errors</h2>" no longer match. Default --format is text and
html is supported, so reviews in those formats classify clean (exit 0)
even when they report errors, which silently breaks the 2/3 exit codes
compare-patch-reviews.sh relies on. The '#'/'**'/'<h>' alternatives need
to stay.
The 3-line concatenation also reintroduces the false positive you're
trying to kill. curr+next+next_next are joined with no separator, so
## Errors
None
## Warnings
collapses to "## errorsnone## warnings"; the 'none...$' filler anchor
fails because the next header follows, and has_errors gets set. Any
output that doesn't blank-line-separate sections hits this.
And in the other direction, content more than two lines below a header
is missed: two blank lines between "## Errors" and the body leave
stripped == "## errors", the '$' branch matches, and a real finding is
suppressed. The heuristic ends up sensitive to exact line spacing both
ways.
Minor: iter[str] / iter[str | None] aren't valid generics (use the
already-imported Iterator); the vars are also re-annotated with
conflicting types and annotate the iterators rather than the loop
targets. mypy will reject these. Run black too - the new for/zip line
and the stripped assignment are over width.
Suggest keeping header matching in all three formats, then scanning past
blank lines to the first non-empty body line and suppressing only if
it's filler (none/n/a/empty). That decouples detection from spacing
instead of fixing it to a 3-line shape.
^ permalink raw reply
* DPDK next-net will closed for summer holidays in July
From: Stephen Hemminger @ 2026-06-16 22:50 UTC (permalink / raw)
To: dev
I will not be doing any active review, merging, or contributing
to DPDK from July 4th - July 21st. If your patch is in patchwork
will get back to it after holiday (on pause); just don't panic if
no review or merge happens.
^ permalink raw reply
* [PATCH] net/bnxt: avoid link flap on flow control set
From: Mohammad Shuab Siddique @ 2026-06-16 23:23 UTC (permalink / raw)
To: dev; +Cc: kishore.padmanabha, stable, Chenna Arnoori
From: Chenna Arnoori <chenna.arnoori@broadcom.com>
When OVS-DPDK reconciles port state, it calls flow_ctrl_get followed
by flow_ctrl_set if the returned configuration differs from its
database. The driver was reporting autoneg=1 whenever the firmware
had auto_pause set (including the AUTONEG_PAUSE bit 0x4), even
though no pause autoneg was actually requested. This mismatch
caused OVS to repeatedly call flow_ctrl_set, which triggered a
full link reconfig with PHY reset, flapping the link every time
any interface change occurred on the system.
Two problems were fixed. First, flow_ctrl_set was clearing all
autoneg bits instead of only the flow-control autoneg bit,
which also wiped the speed autoneg state. Second, the pause
set path was abandoning its own HWRM request and calling the
full link config function, which built a separate request
without the pause fields that set_pause_common would have
computed.
Port the kernel bnxt_en driver's approach: add a
set_link_common helper that merges link and speed fields into
an existing HWRM request, and rework set_pause to build a
single combined request with both pause and link fields when
a full reconfig is needed. When only pause changes without an
auto-to-force transition, a pause-only PHY config is sent
without a full link reprogram.
Fixes: 8aaf473bbed6 ("net/bnxt: add flow control operations")
Cc: stable@dpdk.org
Signed-off-by: Chenna Arnoori <chenna.arnoori@broadcom.com>
Signed-off-by: Mohammad Shuab Siddique <mohammad-shuab.siddique@broadcom.com>
---
drivers/net/bnxt/bnxt.h | 4 +
drivers/net/bnxt/bnxt_ethdev.c | 12 ++-
drivers/net/bnxt/bnxt_hwrm.c | 148 +++++++++++++++++++++++++++++++++
drivers/net/bnxt/bnxt_hwrm.h | 1 +
4 files changed, 163 insertions(+), 2 deletions(-)
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index 7515f0564f..066a6fd478 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -333,6 +333,10 @@ struct bnxt_link_info {
uint8_t active_lanes;
uint8_t option_flags;
uint16_t pmd_speed_lanes;
+ uint8_t autoneg;
+#define BNXT_AUTONEG_SPEED 1
+#define BNXT_AUTONEG_FLOW_CTRL 2
+ bool force_link_chng;
};
#define BNXT_COS_QUEUE_COUNT 8
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 1b8cf3a52a..23a6b193b7 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -2565,7 +2565,7 @@ static int bnxt_flow_ctrl_get_op(struct rte_eth_dev *dev,
return rc;
memset(fc_conf, 0, sizeof(*fc_conf));
- if (bp->link_info->auto_pause)
+ if (bp->link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
fc_conf->autoneg = 1;
switch (bp->link_info->pause) {
case 0:
@@ -2601,6 +2601,14 @@ static int bnxt_flow_ctrl_set_op(struct rte_eth_dev *dev,
return -ENOTSUP;
}
+ if (fc_conf->autoneg) {
+ bp->link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+ } else {
+ if (bp->link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)
+ bp->link_info->force_link_chng = true;
+ bp->link_info->autoneg &= ~BNXT_AUTONEG_FLOW_CTRL;
+ }
+
switch (fc_conf->mode) {
case RTE_ETH_FC_NONE:
bp->link_info->auto_pause = 0;
@@ -2642,7 +2650,7 @@ static int bnxt_flow_ctrl_set_op(struct rte_eth_dev *dev,
}
break;
}
- return bnxt_set_hwrm_link_config(bp, true);
+ return bnxt_hwrm_set_pause(bp);
}
/* Add UDP tunneling port */
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index 0c82935de9..e333b3d182 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -1876,6 +1876,21 @@ static int bnxt_hwrm_port_phy_qcfg(struct bnxt *bp,
link_info->auto_pause = resp->auto_pause;
link_info->force_pause = resp->force_pause;
link_info->auto_mode = resp->auto_mode;
+
+ if (link_info->auto_mode != HWRM_PORT_PHY_QCFG_OUTPUT_AUTO_MODE_NONE) {
+ link_info->autoneg = BNXT_AUTONEG_SPEED;
+ if (bp->hwrm_spec_code >= 0x10201) {
+ if (link_info->auto_pause &
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE)
+ link_info->autoneg |=
+ BNXT_AUTONEG_FLOW_CTRL;
+ } else {
+ link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
+ }
+ } else {
+ link_info->autoneg = 0;
+ }
+
link_info->phy_type = resp->phy_type;
link_info->media_type = resp->media_type;
@@ -4048,6 +4063,139 @@ static int bnxt_hwrm_port_phy_cfg_v2(struct bnxt *bp, struct bnxt_link_info *con
return rc;
}
+static void
+bnxt_hwrm_set_pause_common(struct bnxt *bp,
+ struct hwrm_port_phy_cfg_input *req)
+{
+ struct bnxt_link_info *link_info = bp->link_info;
+
+ if (link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) {
+ if (bp->hwrm_spec_code >= 0x10201)
+ req->auto_pause =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_AUTONEG_PAUSE;
+ if (link_info->auto_pause &
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX)
+ req->auto_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_RX;
+ if (link_info->auto_pause &
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX)
+ req->auto_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_PAUSE_TX;
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
+ } else {
+ if (link_info->force_pause &
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX)
+ req->force_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_RX;
+ if (link_info->force_pause &
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX)
+ req->force_pause |=
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAUSE_TX;
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_FORCE_PAUSE);
+ if (bp->hwrm_spec_code >= 0x10201) {
+ req->auto_pause = req->force_pause;
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_PAUSE);
+ }
+ }
+}
+
+static void
+bnxt_hwrm_set_link_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req)
+{
+ struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
+ uint16_t autoneg, speed;
+
+ autoneg = bnxt_check_eth_link_autoneg(dev_conf->link_speeds);
+
+ if (BNXT_CHIP_P5(bp) &&
+ dev_conf->link_speeds & RTE_ETH_LINK_SPEED_40G)
+ autoneg = 0;
+
+ if (autoneg == 1 && BNXT_CHIP_P5(bp) &&
+ bp->link_info->auto_mode == 0 &&
+ bp->link_info->force_pam4_link_speed ==
+ HWRM_PORT_PHY_CFG_INPUT_FORCE_PAM4_LINK_SPEED_200GB)
+ autoneg = 0;
+
+ speed = bnxt_parse_eth_link_speed(bp, dev_conf->link_speeds,
+ bp->link_info);
+ req->flags |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESET_PHY);
+
+ if (autoneg == 1 &&
+ (bp->link_info->support_auto_speeds ||
+ bp->link_info->support_pam4_auto_speeds)) {
+ uint16_t spd_mask;
+ uint32_t en;
+
+ req->flags |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_RESTART_AUTONEG);
+ spd_mask = bnxt_parse_eth_link_speed_mask(bp,
+ dev_conf->link_speeds);
+ req->auto_link_speed_mask = rte_cpu_to_le_16(spd_mask);
+ req->auto_link_pam4_speed_mask =
+ rte_cpu_to_le_16(bp->link_info->auto_pam4_link_speed_mask);
+ en = HWRM_PORT_PHY_CFG_IN_EN_AUTO_LINK_SPEED_MASK |
+ HWRM_PORT_PHY_CFG_IN_EN_AUTO_PAM4_LINK_SPD_MASK |
+ HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_MODE;
+ req->enables |= rte_cpu_to_le_32(en);
+ req->auto_mode =
+ HWRM_PORT_PHY_CFG_INPUT_AUTO_MODE_SPEED_MASK;
+ } else {
+ uint32_t en;
+
+ req->flags |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_FLAGS_FORCE);
+ if (speed) {
+ if (bp->link_info->link_signal_mode) {
+ req->force_pam4_link_speed =
+ rte_cpu_to_le_16(speed);
+ en = HWRM_PORT_PHY_CFG_IN_EN_FORCE_PAM4_LINK_SPEED;
+ req->enables |= rte_cpu_to_le_32(en);
+ } else {
+ req->force_link_speed =
+ rte_cpu_to_le_16(speed);
+ }
+ }
+ }
+ req->auto_duplex =
+ bnxt_parse_eth_link_duplex(dev_conf->link_speeds);
+ req->enables |=
+ rte_cpu_to_le_32(HWRM_PORT_PHY_CFG_INPUT_ENABLES_AUTO_DUPLEX);
+}
+
+int bnxt_hwrm_set_pause(struct bnxt *bp)
+{
+ struct hwrm_port_phy_cfg_input req = {0};
+ struct hwrm_port_phy_cfg_output *resp = bp->hwrm_cmd_resp_addr;
+ struct bnxt_link_info *link_info = bp->link_info;
+ int rc;
+
+ HWRM_PREP(&req, HWRM_PORT_PHY_CFG, BNXT_USE_CHIMP_MB);
+
+ bnxt_hwrm_set_pause_common(bp, &req);
+
+ if ((link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL) ||
+ link_info->force_link_chng)
+ bnxt_hwrm_set_link_common(bp, &req);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
+
+ HWRM_CHECK_RESULT();
+
+ if (!rc && !(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL)) {
+ link_info->pause = link_info->force_pause;
+ link_info->auto_pause = 0;
+ }
+ link_info->force_link_chng = false;
+
+ HWRM_UNLOCK();
+ return rc;
+}
+
static int bnxt_set_hwrm_link_config_v2(struct bnxt *bp, bool link_up)
{
struct rte_eth_conf *dev_conf = &bp->eth_dev->data->dev_conf;
diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h
index fc56223ab4..3034803023 100644
--- a/drivers/net/bnxt/bnxt_hwrm.h
+++ b/drivers/net/bnxt/bnxt_hwrm.h
@@ -261,6 +261,7 @@ void bnxt_free_hwrm_rx_ring(struct bnxt *bp, int queue_index);
int bnxt_alloc_hwrm_resources(struct bnxt *bp);
int bnxt_get_hwrm_link_config(struct bnxt *bp, struct rte_eth_link *link);
int bnxt_set_hwrm_link_config(struct bnxt *bp, bool link_up);
+int bnxt_hwrm_set_pause(struct bnxt *bp);
int bnxt_hwrm_func_qcfg(struct bnxt *bp, uint16_t *mtu);
int bnxt_hwrm_func_resc_qcaps(struct bnxt *bp);
int bnxt_hwrm_func_reserve_vf_resc(struct bnxt *bp, bool test);
--
2.47.3
^ permalink raw reply related
* [PATCH v5 0/6] net/gve: add hardware timestamping support
From: Mark Blasko @ 2026-06-17 0:07 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260613042300.3760470-1-blasko@google.com>
This patch series introduces support for GVE hardware timestamping
on DQO queues. To support concurrent access, a mutex lock is introduced
to protect admin queue operations. A mechanism is then added to
periodically synchronize the NIC clock via a dedicated control thread,
and support is introduced for the read_clock ethdev operation.
Finally, the RX datapath is updated to reconstruct full 64-bit
timestamps from the 32-bit values in DQO descriptors.
---
v5:
- Patch 4: Reword commit message to describe control thread implementation.
v4:
- Patch 4: Offload periodic NIC clock reads to a dedicated control thread.
- Patch 5: Correct mutex initialization and teardown ordering.
- Patch 6: Update GVE documentation to clarify queue format requirements.
v3:
- Patch 5:
- Add mutex lock to protect shared NIC timestamp memzone access.
- Fix missing read_clock assignment to DQO queue ops table
(accidental omission in v2).
v2:
- Patch 1: Dropped ROBUST mutex attribute.
- Patch 3: Added adminq timestamp counter reset to gve_adminq_alloc.
- Patch 4:
- Removed redundant void* casts.
- Handled alarm reschedule failures by marking timestamp stale.
- Added transient error logging on memzone allocation failure.
- Patch 5: Scoped read_clock ethdev operation strictly to DQO queues.
- Patch 6:
- Scoped timestamp offload capability advertisement strictly to
DQO queues.
- Predicated capability advertisement directly on memzone
allocation.
- Initialized mbuf_timestamp_offset to -1.
- Added blank line separating release notes.
---
Mark Blasko (6):
net/gve: add thread safety to admin queue
net/gve: add device option support for HW timestamps
net/gve: add AdminQ command for NIC timestamps
net/gve: add periodic NIC clock synchronization
net/gve: support read clock ethdev op
net/gve: reconstruct HW timestamps from DQO
.mailmap | 1 +
doc/guides/nics/features/gve.ini | 1 +
doc/guides/nics/gve.rst | 20 +++
doc/guides/rel_notes/release_26_07.rst | 4 +
drivers/net/gve/base/gve_adminq.c | 128 +++++++++++++---
drivers/net/gve/base/gve_adminq.h | 29 ++++
drivers/net/gve/base/gve_desc_dqo.h | 8 +-
drivers/net/gve/gve_ethdev.c | 194 +++++++++++++++++++++++--
drivers/net/gve/gve_ethdev.h | 43 ++++++
drivers/net/gve/gve_rx_dqo.c | 26 ++++
10 files changed, 424 insertions(+), 30 deletions(-)
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply
* [PATCH v5 1/6] net/gve: add thread safety to admin queue
From: Mark Blasko @ 2026-06-17 0:07 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260617000712.2195506-1-blasko@google.com>
Introduce a pthread_mutex to protect the admin queue operations.
Locking was added around gve_adminq_execute_cmd and the batch
queue creation/destruction functions.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v2:
- Dropped ROBUST mutex attribute.
---
.mailmap | 1 +
drivers/net/gve/base/gve_adminq.c | 67 +++++++++++++++++++++++++------
drivers/net/gve/gve_ethdev.h | 1 +
3 files changed, 56 insertions(+), 13 deletions(-)
diff --git a/.mailmap b/.mailmap
index e052b85213..1b10cfca35 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1016,6 +1016,7 @@ Mario Carrillo <mario.alfredo.c.arevalo@intel.com>
Mário Kuka <kuka@cesnet.cz>
Mariusz Drost <mariuszx.drost@intel.com>
Mark Asselstine <mark.asselstine@windriver.com>
+Mark Blasko <blasko@google.com>
Mark Bloch <mbloch@nvidia.com> <markb@mellanox.com>
Mark Gillott <mgillott@vyatta.att-mail.com>
Mark Kavanagh <mark.b.kavanagh@intel.com>
diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 9c5316fb00..743ab8e7ae 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -216,6 +216,7 @@ gve_process_device_options(struct gve_priv *priv,
int gve_adminq_alloc(struct gve_priv *priv)
{
+ pthread_mutexattr_t mutexattr;
uint8_t pci_rev_id;
priv->adminq = gve_alloc_dma_mem(&priv->adminq_dma_mem, PAGE_SIZE);
@@ -241,6 +242,11 @@ int gve_adminq_alloc(struct gve_priv *priv)
priv->adminq_get_ptype_map_cnt = 0;
priv->adminq_cfg_flow_rule_cnt = 0;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init(&priv->adminq_lock, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
+
/* Setup Admin queue with the device */
rte_pci_read_config(priv->pci_dev, &pci_rev_id, sizeof(pci_rev_id),
RTE_PCI_REVISION_ID);
@@ -304,6 +310,7 @@ void gve_adminq_free(struct gve_priv *priv)
return;
gve_adminq_release(priv);
gve_free_dma_mem(&priv->adminq_dma_mem);
+ pthread_mutex_destroy(&priv->adminq_lock);
gve_clear_admin_queue_ok(priv);
}
@@ -418,7 +425,10 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
(tail & priv->adminq_mask)) {
int err;
- /* Flush existing commands to make room. */
+ /* Flush existing commands to make room.
+ * Note: This kicks the doorbell for all staged commands.
+ * Any failure here means we failed after attempting to kick.
+ */
err = gve_adminq_kick_and_wait(priv);
if (err)
return err;
@@ -509,17 +519,24 @@ static int gve_adminq_execute_cmd(struct gve_priv *priv,
u32 tail, head;
int err;
+ pthread_mutex_lock(&priv->adminq_lock);
tail = ioread32be(&priv->reg_bar0->adminq_event_counter);
head = priv->adminq_prod_cnt;
- if (tail != head)
+ if (tail != head) {
/* This is not a valid path */
- return -EINVAL;
+ err = -EINVAL;
+ goto unlock_and_return;
+ }
err = gve_adminq_issue_cmd(priv, cmd_orig);
if (err)
- return err;
+ goto unlock_and_return;
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_execute_extended_cmd(struct gve_priv *priv, u32 opcode,
@@ -693,13 +710,19 @@ int gve_adminq_create_tx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_create_tx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_create_rx_queue(struct gve_priv *priv, u32 queue_index)
@@ -747,13 +770,19 @@ int gve_adminq_create_rx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_create_rx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_destroy_tx_queue(struct gve_priv *priv, u32 queue_index)
@@ -779,13 +808,19 @@ int gve_adminq_destroy_tx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_destroy_tx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_adminq_destroy_rx_queue(struct gve_priv *priv, u32 queue_index)
@@ -811,13 +846,19 @@ int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 num_queues)
int err;
u32 i;
+ pthread_mutex_lock(&priv->adminq_lock);
+
for (i = 0; i < num_queues; i++) {
err = gve_adminq_destroy_rx_queue(priv, i);
if (err)
- return err;
+ goto unlock_and_return;
}
- return gve_adminq_kick_and_wait(priv);
+ err = gve_adminq_kick_and_wait(priv);
+
+unlock_and_return:
+ pthread_mutex_unlock(&priv->adminq_lock);
+ return err;
}
static int gve_set_desc_cnt(struct gve_priv *priv,
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 0577f03974..524e48e723 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -339,6 +339,7 @@ struct gve_priv {
struct gve_tx_queue **txqs;
struct gve_rx_queue **rxqs;
+ pthread_mutex_t adminq_lock; /* Protects AdminQ command execution */
uint32_t stats_report_len;
const struct rte_memzone *stats_report_mem;
uint16_t stats_start_idx; /* start index of array of stats written by NIC */
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related
* [PATCH v5 2/6] net/gve: add device option support for HW timestamps
From: Mark Blasko @ 2026-06-17 0:07 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260617000712.2195506-1-blasko@google.com>
Introduce the necessary definitions and functions for the device
option flag (GVE_DEV_OPT_ID_NIC_TIMESTAMP) to detect hardware
timestamping support in the gvnic device.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
drivers/net/gve/base/gve_adminq.c | 41 ++++++++++++++++++++++++++-----
drivers/net/gve/base/gve_adminq.h | 9 +++++++
drivers/net/gve/gve_ethdev.h | 3 +++
3 files changed, 47 insertions(+), 6 deletions(-)
diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 743ab8e7ae..1ced1e442e 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -38,7 +38,8 @@ void gve_parse_device_option(struct gve_priv *priv,
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_flow_steering **dev_op_flow_steering,
struct gve_device_option_modify_ring **dev_op_modify_ring,
- struct gve_device_option_jumbo_frames **dev_op_jumbo_frames)
+ struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
+ struct gve_device_option_nic_timestamp **dev_op_nic_timestamp)
{
u32 req_feat_mask = be32_to_cpu(option->required_features_mask);
u16 option_length = be16_to_cpu(option->option_length);
@@ -168,6 +169,24 @@ void gve_parse_device_option(struct gve_priv *priv,
}
*dev_op_jumbo_frames = RTE_PTR_ADD(option, sizeof(*option));
break;
+ case GVE_DEV_OPT_ID_NIC_TIMESTAMP:
+ if (option_length < sizeof(**dev_op_nic_timestamp) ||
+ req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP) {
+ PMD_DRV_LOG(WARNING, GVE_DEVICE_OPTION_ERROR_FMT,
+ "Nic Timestamp",
+ (int)sizeof(**dev_op_nic_timestamp),
+ GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP,
+ option_length, req_feat_mask);
+ break;
+ }
+
+ if (option_length > sizeof(**dev_op_nic_timestamp)) {
+ PMD_DRV_LOG(WARNING,
+ GVE_DEVICE_OPTION_TOO_BIG_FMT,
+ "Nic Timestamp");
+ }
+ *dev_op_nic_timestamp = RTE_PTR_ADD(option, sizeof(*option));
+ break;
default:
/* If we don't recognize the option just continue
* without doing anything.
@@ -186,7 +205,8 @@ gve_process_device_options(struct gve_priv *priv,
struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_flow_steering **dev_op_flow_steering,
struct gve_device_option_modify_ring **dev_op_modify_ring,
- struct gve_device_option_jumbo_frames **dev_op_jumbo_frames)
+ struct gve_device_option_jumbo_frames **dev_op_jumbo_frames,
+ struct gve_device_option_nic_timestamp **dev_op_nic_timestamp)
{
const int num_options = be16_to_cpu(descriptor->num_device_options);
struct gve_device_option *dev_opt;
@@ -207,7 +227,8 @@ gve_process_device_options(struct gve_priv *priv,
gve_parse_device_option(priv, dev_opt,
dev_op_gqi_rda, dev_op_gqi_qpl,
dev_op_dqo_rda, dev_op_flow_steering,
- dev_op_modify_ring, dev_op_jumbo_frames);
+ dev_op_modify_ring, dev_op_jumbo_frames,
+ dev_op_nic_timestamp);
dev_opt = next_opt;
}
@@ -920,7 +941,8 @@ static void gve_enable_supported_features(struct gve_priv *priv,
u32 supported_features_mask,
const struct gve_device_option_flow_steering *dev_op_flow_steering,
const struct gve_device_option_modify_ring *dev_op_modify_ring,
- const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames)
+ const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames,
+ const struct gve_device_option_nic_timestamp *dev_op_nic_timestamp)
{
if (dev_op_flow_steering &&
(supported_features_mask & GVE_SUP_FLOW_STEERING_MASK) &&
@@ -947,6 +969,11 @@ static void gve_enable_supported_features(struct gve_priv *priv,
PMD_DRV_LOG(INFO, "JUMBO FRAMES device option enabled.");
priv->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
}
+ if (dev_op_nic_timestamp &&
+ (supported_features_mask & GVE_SUP_NIC_TIMESTAMP_MASK)) {
+ PMD_DRV_LOG(INFO, "NIC TIMESTAMP device option enabled.");
+ priv->nic_timestamp_supported = true;
+ }
}
int gve_adminq_describe_device(struct gve_priv *priv)
@@ -954,6 +981,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
struct gve_device_option_modify_ring *dev_op_modify_ring = NULL;
struct gve_device_option_flow_steering *dev_op_flow_steering = NULL;
+ struct gve_device_option_nic_timestamp *dev_op_nic_timestamp = NULL;
struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL;
struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL;
struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL;
@@ -983,7 +1011,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
&dev_op_gqi_qpl, &dev_op_dqo_rda,
&dev_op_flow_steering,
&dev_op_modify_ring,
- &dev_op_jumbo_frames);
+ &dev_op_jumbo_frames,
+ &dev_op_nic_timestamp);
if (err)
goto free_device_descriptor;
@@ -1038,7 +1067,7 @@ int gve_adminq_describe_device(struct gve_priv *priv)
gve_enable_supported_features(priv, supported_features_mask,
dev_op_flow_steering, dev_op_modify_ring,
- dev_op_jumbo_frames);
+ dev_op_jumbo_frames, dev_op_nic_timestamp);
free_device_descriptor:
gve_free_dma_mem(&descriptor_dma_mem);
diff --git a/drivers/net/gve/base/gve_adminq.h b/drivers/net/gve/base/gve_adminq.h
index d8e5e6a352..eaee5649f2 100644
--- a/drivers/net/gve/base/gve_adminq.h
+++ b/drivers/net/gve/base/gve_adminq.h
@@ -153,6 +153,12 @@ struct gve_device_option_jumbo_frames {
GVE_CHECK_STRUCT_LEN(8, gve_device_option_jumbo_frames);
+struct gve_device_option_nic_timestamp {
+ __be32 supported_features_mask;
+};
+
+GVE_CHECK_STRUCT_LEN(4, gve_device_option_nic_timestamp);
+
/* Terminology:
*
* RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA
@@ -169,6 +175,7 @@ enum gve_dev_opt_id {
GVE_DEV_OPT_ID_MODIFY_RING = 0x6,
GVE_DEV_OPT_ID_JUMBO_FRAMES = 0x8,
GVE_DEV_OPT_ID_FLOW_STEERING = 0xb,
+ GVE_DEV_OPT_ID_NIC_TIMESTAMP = 0xd,
};
enum gve_dev_opt_req_feat_mask {
@@ -179,12 +186,14 @@ enum gve_dev_opt_req_feat_mask {
GVE_DEV_OPT_REQ_FEAT_MASK_FLOW_STEERING = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES = 0x0,
+ GVE_DEV_OPT_REQ_FEAT_MASK_NIC_TIMESTAMP = 0x0,
};
enum gve_sup_feature_mask {
GVE_SUP_MODIFY_RING_MASK = 1 << 0,
GVE_SUP_JUMBO_FRAMES_MASK = 1 << 2,
GVE_SUP_FLOW_STEERING_MASK = 1 << 5,
+ GVE_SUP_NIC_TIMESTAMP_MASK = 1 << 8,
};
#define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 524e48e723..b9b4688367 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -355,6 +355,9 @@ struct gve_priv {
void *avail_flow_rule_bmp_mem; /* Backing memory for the bitmap */
pthread_mutex_t flow_rule_lock; /* Lock for bitmap and tailq access */
TAILQ_HEAD(, gve_flow) active_flows;
+
+ /* HW Timestamping Fields */
+ bool nic_timestamp_supported;
};
static inline bool
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related
* [PATCH v5 3/6] net/gve: add AdminQ command for NIC timestamps
From: Mark Blasko @ 2026-06-17 0:07 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260617000712.2195506-1-blasko@google.com>
Introduce the necessary definitions and functions for the
GVE_ADMINQ_REPORT_NIC_TIMESTAMP AdminQ command.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v2:
- Added adminq timestamp counter reset to gve_adminq_alloc.
---
drivers/net/gve/base/gve_adminq.c | 20 ++++++++++++++++++++
drivers/net/gve/base/gve_adminq.h | 20 ++++++++++++++++++++
drivers/net/gve/gve_ethdev.h | 1 +
3 files changed, 41 insertions(+)
diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 1ced1e442e..2b25c7f390 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -263,6 +263,8 @@ int gve_adminq_alloc(struct gve_priv *priv)
priv->adminq_get_ptype_map_cnt = 0;
priv->adminq_cfg_flow_rule_cnt = 0;
+ priv->adminq_report_nic_timestamp_cnt = 0;
+
pthread_mutexattr_init(&mutexattr);
pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&priv->adminq_lock, &mutexattr);
@@ -522,6 +524,10 @@ static int gve_adminq_issue_cmd(struct gve_priv *priv,
case GVE_ADMINQ_CONFIGURE_FLOW_RULE:
priv->adminq_cfg_flow_rule_cnt++;
break;
+ case GVE_ADMINQ_REPORT_NIC_TIMESTAMP:
+ priv->adminq_report_nic_timestamp_cnt++;
+ break;
+
default:
PMD_DRV_LOG(ERR, "unknown AQ command opcode %d", opcode);
}
@@ -636,6 +642,20 @@ int gve_adminq_reset_flow_rules(struct gve_priv *priv)
return gve_adminq_configure_flow_rule(priv, &flow_rule_cmd);
}
+int gve_adminq_report_nic_timestamp(struct gve_priv *priv, dma_addr_t nic_ts_report_addr)
+{
+ union gve_adminq_command cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = cpu_to_be32(GVE_ADMINQ_REPORT_NIC_TIMESTAMP);
+ cmd.report_nic_timestamp = (struct gve_adminq_report_nic_timestamp) {
+ .nic_ts_report_len = cpu_to_be64(sizeof(struct gve_nic_ts_report)),
+ .nic_timestamp_addr = cpu_to_be64(nic_ts_report_addr),
+ };
+
+ return gve_adminq_execute_cmd(priv, &cmd);
+}
+
/* The device specifies that the management vector can either be the first irq
* or the last irq. ntfy_blk_msix_base_idx indicates the first irq assigned to
* the ntfy blks. It if is 0 then the management vector is last, if it is 1 then
diff --git a/drivers/net/gve/base/gve_adminq.h b/drivers/net/gve/base/gve_adminq.h
index eaee5649f2..954be39fbf 100644
--- a/drivers/net/gve/base/gve_adminq.h
+++ b/drivers/net/gve/base/gve_adminq.h
@@ -26,6 +26,7 @@ enum gve_adminq_opcodes {
GVE_ADMINQ_REPORT_LINK_SPEED = 0xD,
GVE_ADMINQ_GET_PTYPE_MAP = 0xE,
GVE_ADMINQ_VERIFY_DRIVER_COMPATIBILITY = 0xF,
+ GVE_ADMINQ_REPORT_NIC_TIMESTAMP = 0x11,
/* For commands that are larger than 56 bytes */
GVE_ADMINQ_EXTENDED_COMMAND = 0xFF,
};
@@ -373,6 +374,23 @@ struct gve_stats_report {
GVE_CHECK_STRUCT_LEN(8, gve_stats_report);
+struct gve_adminq_report_nic_timestamp {
+ __be64 nic_ts_report_len;
+ __be64 nic_timestamp_addr;
+};
+
+GVE_CHECK_STRUCT_LEN(16, gve_adminq_report_nic_timestamp);
+
+struct gve_nic_ts_report {
+ __be64 nic_timestamp; /* NIC clock in nanoseconds */
+ __be64 pre_cycles; /* System cycle counter before NIC clock read */
+ __be64 post_cycles; /* System cycle counter after NIC clock read */
+ __be64 reserved3;
+ __be64 reserved4;
+};
+
+GVE_CHECK_STRUCT_LEN(40, gve_nic_ts_report);
+
/* Numbers of gve tx/rx stats in stats report. */
#define GVE_TX_STATS_REPORT_NUM 6
#define GVE_RX_STATS_REPORT_NUM 2
@@ -490,6 +508,7 @@ union gve_adminq_command {
struct gve_adminq_verify_driver_compatibility
verify_driver_compatibility;
struct gve_adminq_extended_command extended_command;
+ struct gve_adminq_report_nic_timestamp report_nic_timestamp;
};
};
u8 reserved[64];
@@ -537,5 +556,6 @@ int gve_adminq_add_flow_rule(struct gve_priv *priv,
struct gve_flow_rule_params *rule, u32 loc);
int gve_adminq_del_flow_rule(struct gve_priv *priv, u32 loc);
int gve_adminq_reset_flow_rules(struct gve_priv *priv);
+int gve_adminq_report_nic_timestamp(struct gve_priv *priv, dma_addr_t nic_ts_report_addr);
#endif /* _GVE_ADMINQ_H */
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index b9b4688367..b67f82c263 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -328,6 +328,7 @@ struct gve_priv {
uint32_t adminq_get_ptype_map_cnt;
uint32_t adminq_verify_driver_compatibility_cnt;
uint32_t adminq_cfg_flow_rule_cnt;
+ uint32_t adminq_report_nic_timestamp_cnt;
volatile uint32_t state_flags;
/* Gvnic device link speed from hypervisor. */
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related
* [PATCH v5 4/6] net/gve: add periodic NIC clock synchronization
From: Mark Blasko @ 2026-06-17 0:07 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260617000712.2195506-1-blasko@google.com>
Introduce a mechanism to periodically fetch the NIC hardware timestamp
using the GVE_ADMINQ_REPORT_NIC_TIMESTAMP AdminQ command. The
synchronization runs every 250ms via a dedicated background control thread
(gve_nic_ts_thread). The thread polls using an incremental sleep loop
checking a stop flag to ensure fast termination during driver teardown.
After 7 consecutive clock read failures, the timestamp is marked as stale,
indicating to the RX path that reconstructed timestamps may be unreliable.
Atomics exist because of the potential for async callers (introduced
here) and async callers (introduced later in the RX datapath) accessing
the cached state.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v5:
- Reword commit message body to accurately describe the dedicated control
thread polling mechanism instead of obsolete rte_alarm.
v4:
- Replace EAL alarm thread with a dedicated control thread to
prevent blocking shared EAL interrupt thread for up to 2s
on GVE AdminQ timeouts.
- Implement incremental sleep loop to support fast termination.
v2:
- Removed redundant void* casts.
- Handled alarm reschedule failures by marking timestamp stale.
- Added transient error logging on memzone allocation failure.
---
drivers/net/gve/gve_ethdev.c | 122 +++++++++++++++++++++++++++++++++++
drivers/net/gve/gve_ethdev.h | 12 ++++
2 files changed, 134 insertions(+)
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 476b2c311f..fa91575b3e 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -452,6 +452,94 @@ gve_dev_start(struct rte_eth_dev *dev)
return 0;
}
+static void
+gve_read_nic_clock(void *arg)
+{
+ struct gve_priv *priv = arg;
+ uint32_t fails;
+ uint64_t ts;
+ int err;
+
+ if (!priv || !priv->nic_ts_report_mz)
+ return;
+
+ memset(priv->nic_ts_report, 0, sizeof(struct gve_nic_ts_report));
+
+ err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
+ if (err == 0) {
+ ts = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
+ rte_atomic_store_explicit(&priv->last_read_nic_timestamp, ts,
+ rte_memory_order_relaxed);
+ PMD_DRV_LOG(DEBUG, "Fetched NIC Timestamp: %" PRIu64, ts);
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0,
+ rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 0,
+ rte_memory_order_release);
+ } else {
+ PMD_DRV_LOG(ERR, "Failed to read NIC clock, AQ err: %d", err);
+ fails = rte_atomic_fetch_add_explicit(&priv->nic_ts_read_fails, 1,
+ rte_memory_order_relaxed) + 1;
+ if (fails >= GVE_NIC_CLOCK_READ_MAX_FAILS) {
+ if (!rte_atomic_load_explicit(&priv->nic_ts_stale,
+ rte_memory_order_relaxed))
+ PMD_DRV_LOG(ERR,
+ "NIC timestamping marked as stale after %u consecutive failures",
+ GVE_NIC_CLOCK_READ_MAX_FAILS);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 1,
+ rte_memory_order_release);
+ }
+ }
+}
+
+static uint32_t
+gve_nic_ts_thread(void *arg)
+{
+ struct gve_priv *priv = arg;
+ unsigned int sleep_cnt;
+
+ while (!rte_atomic_load_explicit(&priv->nic_ts_thread_should_stop,
+ rte_memory_order_relaxed)) {
+ gve_read_nic_clock(priv);
+ for (sleep_cnt = 0; sleep_cnt < GVE_NIC_CLOCK_READ_PERIOD_MS / 10; sleep_cnt++) {
+ if (rte_atomic_load_explicit(&priv->nic_ts_thread_should_stop,
+ rte_memory_order_relaxed))
+ break;
+ rte_delay_us_sleep(10000);
+ }
+ }
+ return 0;
+}
+
+static int
+gve_alloc_nic_ts_report(struct gve_priv *priv)
+{
+ char z_name[RTE_MEMZONE_NAMESIZE];
+
+ snprintf(z_name, sizeof(z_name), "gve_%s_nic_ts_report",
+ priv->pci_dev->device.name);
+ priv->nic_ts_report_mz = rte_memzone_reserve_aligned(z_name,
+ sizeof(struct gve_nic_ts_report), rte_socket_id(),
+ RTE_MEMZONE_IOVA_CONTIG, PAGE_SIZE);
+
+ if (!priv->nic_ts_report_mz) {
+ PMD_DRV_LOG(ERR, "Failed to allocate memzone for NIC TS report");
+ return -ENOMEM;
+ }
+ priv->nic_ts_report = priv->nic_ts_report_mz->addr;
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0, rte_memory_order_relaxed);
+ return 0;
+}
+
+static void
+gve_free_nic_ts_report(struct gve_priv *priv)
+{
+ if (priv->nic_ts_report_mz) {
+ rte_memzone_free(priv->nic_ts_report_mz);
+ priv->nic_ts_report_mz = NULL;
+ priv->nic_ts_report = NULL;
+ }
+}
+
static int
gve_dev_stop(struct rte_eth_dev *dev)
{
@@ -586,6 +674,13 @@ gve_teardown_device_resources(struct gve_priv *priv)
err);
}
+ if (priv->nic_ts_report_mz) {
+ rte_atomic_store_explicit(&priv->nic_ts_thread_should_stop, 1,
+ rte_memory_order_relaxed);
+ rte_thread_join(priv->nic_ts_thread_id, NULL);
+ gve_free_nic_ts_report(priv);
+ }
+
gve_free_ptype_lut_dqo(priv);
gve_free_counter_array(priv);
gve_free_irq_db(priv);
@@ -1252,6 +1347,32 @@ pci_dev_msix_vec_count(struct rte_pci_device *pdev)
return 0;
}
+static void
+gve_setup_nic_timestamp(struct gve_priv *priv)
+{
+ int err;
+
+ if (!priv->nic_timestamp_supported)
+ return;
+
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0, rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 1, rte_memory_order_relaxed);
+ err = gve_alloc_nic_ts_report(priv);
+ if (err == 0) {
+ gve_read_nic_clock(priv);
+ rte_atomic_store_explicit(&priv->nic_ts_thread_should_stop, 0,
+ rte_memory_order_relaxed);
+ err = rte_thread_create_internal_control(&priv->nic_ts_thread_id, "gve-ts",
+ gve_nic_ts_thread, priv);
+ if (err != 0) {
+ PMD_DRV_LOG(ERR, "Failed to create NIC clock sync thread, err=%d", err);
+ gve_free_nic_ts_report(priv);
+ }
+ } else {
+ PMD_DRV_LOG(ERR, "Failed to allocate memory for NIC timestamping subsystem. Please reset device to retry.");
+ }
+}
+
static int
gve_setup_device_resources(struct gve_priv *priv)
{
@@ -1307,6 +1428,7 @@ gve_setup_device_resources(struct gve_priv *priv)
goto free_ptype_lut;
}
}
+ gve_setup_nic_timestamp(priv);
gve_set_device_resources_ok(priv);
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index b67f82c263..4dcbaa9971 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -12,6 +12,8 @@
#include <rte_pci.h>
#include <pthread.h>
#include <rte_bitmap.h>
+#include <rte_memzone.h>
+#include <rte_thread.h>
#include "base/gve.h"
@@ -39,6 +41,9 @@
#define GVE_RSS_HASH_KEY_SIZE 40
#define GVE_RSS_INDIR_SIZE 128
+#define GVE_NIC_CLOCK_READ_PERIOD_MS 250
+#define GVE_NIC_CLOCK_READ_MAX_FAILS 7
+
#define GVE_TX_CKSUM_OFFLOAD_MASK ( \
RTE_MBUF_F_TX_L4_MASK | \
RTE_MBUF_F_TX_TCP_SEG)
@@ -359,6 +364,13 @@ struct gve_priv {
/* HW Timestamping Fields */
bool nic_timestamp_supported;
+ const struct rte_memzone *nic_ts_report_mz;
+ struct gve_nic_ts_report *nic_ts_report;
+ RTE_ATOMIC(uint64_t) last_read_nic_timestamp;
+ RTE_ATOMIC(uint32_t) nic_ts_read_fails;
+ RTE_ATOMIC(uint8_t) nic_ts_stale;
+ rte_thread_t nic_ts_thread_id;
+ RTE_ATOMIC(uint8_t) nic_ts_thread_should_stop;
};
static inline bool
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related
* [PATCH v5 5/6] net/gve: support read clock ethdev op
From: Mark Blasko @ 2026-06-17 0:07 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260617000712.2195506-1-blasko@google.com>
Implement the read_clock operation in eth_dev_ops. The function calls
the AdminQ command to fetch the current NIC timestamp synchronously,
updates the cached timestamp used for reconstruction, and returns the
full 64-bit value.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v4:
- Fix mutex initialization order: initialize nic_ts_lock before
calling gve_init_priv() (which invokes early setup-time read).
- Fix mutex teardown order: destroy nic_ts_lock only after the
background sync thread has been joined and stopped.
v3:
- Add mutex lock to protect shared NIC timestamp memzone access.
- Fix missing read_clock assignment to DQO queue ops table
(accidental omission in v2).
v2:
- Scoped read_clock ethdev operation strictly to DQO queues.
---
drivers/net/gve/gve_ethdev.c | 57 +++++++++++++++++++++++++++++++-----
drivers/net/gve/gve_ethdev.h | 1 +
2 files changed, 50 insertions(+), 8 deletions(-)
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index fa91575b3e..111f66efa8 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -463,11 +463,13 @@ gve_read_nic_clock(void *arg)
if (!priv || !priv->nic_ts_report_mz)
return;
+ pthread_mutex_lock(&priv->nic_ts_lock);
memset(priv->nic_ts_report, 0, sizeof(struct gve_nic_ts_report));
err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
if (err == 0) {
ts = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
+ pthread_mutex_unlock(&priv->nic_ts_lock);
rte_atomic_store_explicit(&priv->last_read_nic_timestamp, ts,
rte_memory_order_relaxed);
PMD_DRV_LOG(DEBUG, "Fetched NIC Timestamp: %" PRIu64, ts);
@@ -476,6 +478,7 @@ gve_read_nic_clock(void *arg)
rte_atomic_store_explicit(&priv->nic_ts_stale, 0,
rte_memory_order_release);
} else {
+ pthread_mutex_unlock(&priv->nic_ts_lock);
PMD_DRV_LOG(ERR, "Failed to read NIC clock, AQ err: %d", err);
fails = rte_atomic_fetch_add_explicit(&priv->nic_ts_read_fails, 1,
rte_memory_order_relaxed) + 1;
@@ -705,12 +708,13 @@ gve_dev_close(struct rte_eth_dev *dev)
if (gve_get_flow_subsystem_ok(priv))
gve_teardown_flow_subsystem(priv);
- pthread_mutex_destroy(&priv->flow_rule_lock);
-
gve_free_queues(dev);
gve_teardown_device_resources(priv);
gve_adminq_free(priv);
+ pthread_mutex_destroy(&priv->flow_rule_lock);
+ pthread_mutex_destroy(&priv->nic_ts_lock);
+
dev->data->mac_addrs = NULL;
return err;
@@ -1278,6 +1282,38 @@ gve_flow_ops_get(struct rte_eth_dev *dev, const struct rte_flow_ops **ops)
return 0;
}
+static int
+gve_read_clock(struct rte_eth_dev *dev, uint64_t *clock)
+{
+ struct gve_priv *priv = dev->data->dev_private;
+ uint64_t ts;
+ int err;
+
+ if (!priv->nic_timestamp_supported)
+ return -EOPNOTSUPP;
+
+ if (!priv->nic_ts_report_mz)
+ return -EIO;
+
+ pthread_mutex_lock(&priv->nic_ts_lock);
+ err = gve_adminq_report_nic_timestamp(priv, priv->nic_ts_report_mz->iova);
+ if (err != 0) {
+ pthread_mutex_unlock(&priv->nic_ts_lock);
+ return err;
+ }
+
+ ts = be64_to_cpu(priv->nic_ts_report->nic_timestamp);
+ pthread_mutex_unlock(&priv->nic_ts_lock);
+ *clock = ts;
+
+ /* Update the cached value */
+ rte_atomic_store_explicit(&priv->last_read_nic_timestamp, ts, rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_read_fails, 0, rte_memory_order_relaxed);
+ rte_atomic_store_explicit(&priv->nic_ts_stale, 0, rte_memory_order_release);
+
+ return 0;
+}
+
static const struct eth_dev_ops gve_eth_dev_ops = {
.dev_configure = gve_dev_configure,
.dev_start = gve_dev_start,
@@ -1332,6 +1368,7 @@ static const struct eth_dev_ops gve_eth_dev_ops_dqo = {
.rss_hash_conf_get = gve_rss_hash_conf_get,
.reta_update = gve_rss_reta_update,
.reta_query = gve_rss_reta_query,
+ .read_clock = gve_read_clock,
};
static int
@@ -1640,9 +1677,18 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
priv->max_nb_txq = max_tx_queues;
priv->max_nb_rxq = max_rx_queues;
+ pthread_mutexattr_init(&mutexattr);
+ pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init(&priv->flow_rule_lock, &mutexattr);
+ pthread_mutex_init(&priv->nic_ts_lock, &mutexattr);
+ pthread_mutexattr_destroy(&mutexattr);
+
err = gve_init_priv(priv, false);
- if (err)
+ if (err) {
+ pthread_mutex_destroy(&priv->flow_rule_lock);
+ pthread_mutex_destroy(&priv->nic_ts_lock);
return err;
+ }
if (gve_is_gqi(priv)) {
eth_dev->dev_ops = &gve_eth_dev_ops;
@@ -1656,11 +1702,6 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
eth_dev->data->mac_addrs = &priv->dev_addr;
- pthread_mutexattr_init(&mutexattr);
- pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);
- pthread_mutex_init(&priv->flow_rule_lock, &mutexattr);
- pthread_mutexattr_destroy(&mutexattr);
-
return 0;
}
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 4dcbaa9971..1e80f3a906 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -366,6 +366,7 @@ struct gve_priv {
bool nic_timestamp_supported;
const struct rte_memzone *nic_ts_report_mz;
struct gve_nic_ts_report *nic_ts_report;
+ pthread_mutex_t nic_ts_lock;
RTE_ATOMIC(uint64_t) last_read_nic_timestamp;
RTE_ATOMIC(uint32_t) nic_ts_read_fails;
RTE_ATOMIC(uint8_t) nic_ts_stale;
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related
* [PATCH v5 6/6] net/gve: reconstruct HW timestamps from DQO
From: Mark Blasko @ 2026-06-17 0:07 UTC (permalink / raw)
To: stephen; +Cc: dev, joshwash, jtranoleary, blasko
In-Reply-To: <20260617000712.2195506-1-blasko@google.com>
A full 64-bit NIC timestamp is periodically synced via an AdminQ
command and cached in the driver. In the RX datapath, this cached
value is used as a base to expand the 32-bit hardware timestamp into
a full 64-bit value, which is then stored in the mbuf's dynamic
timestamp field.
Signed-off-by: Mark Blasko <blasko@google.com>
Reviewed-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v4:
- Clarify in GVE documentation that both read_clock ethdev op and
per-packet RX timestamp offloading require the DQO queue format.
v2:
- Scoped timestamp offload capability advertisement strictly
to DQO queues.
- Predicated capability advertisement directly on memzone
allocation.
- Initialized mbuf_timestamp_offset to -1.
- Added blank line separating release notes.
---
doc/guides/nics/features/gve.ini | 1 +
doc/guides/nics/gve.rst | 20 ++++++++++++++++++++
doc/guides/rel_notes/release_26_07.rst | 4 ++++
drivers/net/gve/base/gve_desc_dqo.h | 8 ++++++--
drivers/net/gve/gve_ethdev.c | 15 ++++++++++++++-
drivers/net/gve/gve_ethdev.h | 25 +++++++++++++++++++++++++
drivers/net/gve/gve_rx_dqo.c | 26 ++++++++++++++++++++++++++
7 files changed, 96 insertions(+), 3 deletions(-)
diff --git a/doc/guides/nics/features/gve.ini b/doc/guides/nics/features/gve.ini
index 89c97fd27a..117ad4fc65 100644
--- a/doc/guides/nics/features/gve.ini
+++ b/doc/guides/nics/features/gve.ini
@@ -13,6 +13,7 @@ RSS hash = Y
RSS key update = Y
RSS reta update = Y
L4 checksum offload = Y
+Timestamp offload = Y
Basic stats = Y
FreeBSD = Y
Linux = Y
diff --git a/doc/guides/nics/gve.rst b/doc/guides/nics/gve.rst
index be855b645d..b73375c5c9 100644
--- a/doc/guides/nics/gve.rst
+++ b/doc/guides/nics/gve.rst
@@ -72,6 +72,7 @@ Supported features of the GVE PMD are:
- Tx UDP/TCP/SCTP Checksum
- RSS hash configuration
- RSS redirection table query and update
+- Timestamp offload
Currently, only GQI_QPL and GQI_RDA queue format are supported in PMD.
Jumbo Frame is not supported in PMD for now.
@@ -132,6 +133,25 @@ Security Protocols
- Flow priorities are not supported (must be 0).
- Masking is limited to full matches i.e. ``0x00...0`` or ``0xFF...F``.
+Timestamp Offload
+^^^^^^^^^^^^^^^^^
+
+The driver supports hardware-based packet timestamping on supported
+devices via the standard ``RTE_ETH_RX_OFFLOAD_TIMESTAMP`` offload capability.
+Both the ethdev ``.read_clock`` operation and per-packet RX timestamp offloading
+require the DQO queue format.
+
+**Limitations**
+
+- If the driver fails to fetch the NIC hardware clock for 7 consecutive periods,
+ the cached timestamp is marked as stale,
+ and the reconstructed timestamps are no longer propagated to the mbuf.
+- The timestamp reconstruction is only accurate
+ if the time between a packet's reception
+ and the last hardware clock sync is less than approximately 2 seconds.
+ The driver's internal clock sync period is set to respect this limitation.
+
+
Device Reset
^^^^^^^^^^^^
diff --git a/doc/guides/rel_notes/release_26_07.rst b/doc/guides/rel_notes/release_26_07.rst
index 2e449d3ee8..73c9a36007 100644
--- a/doc/guides/rel_notes/release_26_07.rst
+++ b/doc/guides/rel_notes/release_26_07.rst
@@ -91,6 +91,10 @@ New Features
Added network driver for the LinkData network adapters.
+* **Updated Google GVE net driver.**
+
+ * Added hardware timestamping support on DQO queues.
+
* **Updated Intel iavf driver.**
* Added support for transmitting LLDP packets based on mbuf packet type.
diff --git a/drivers/net/gve/base/gve_desc_dqo.h b/drivers/net/gve/base/gve_desc_dqo.h
index 71d9d60bb9..c1534959c2 100644
--- a/drivers/net/gve/base/gve_desc_dqo.h
+++ b/drivers/net/gve/base/gve_desc_dqo.h
@@ -226,7 +226,8 @@ struct gve_rx_compl_desc_dqo {
u8 status_error1;
- __le16 reserved5;
+ u8 reserved5;
+ u8 ts_sub_nsecs_low;
__le16 buf_id; /* Buffer ID which was sent on the buffer queue. */
union {
@@ -237,9 +238,12 @@ struct gve_rx_compl_desc_dqo {
};
__le32 hash;
__le32 reserved6;
- __le64 reserved7;
+ __le32 reserved7;
+ __le32 ts; /* timestamp in nanosecs */
} __packed;
+#define GVE_DQO_RX_HWTSTAMP_VALID 0x1
+
GVE_CHECK_STRUCT_LEN(32, gve_rx_compl_desc_dqo);
/* Ringing the doorbell too often can hurt performance.
diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index 111f66efa8..0b02dcb3ad 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -214,6 +214,7 @@ static int
gve_dev_configure(struct rte_eth_dev *dev)
{
struct gve_priv *priv = dev->data->dev_private;
+ int err;
if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) {
dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
@@ -223,13 +224,22 @@ gve_dev_configure(struct rte_eth_dev *dev)
if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO)
priv->enable_rsc = 1;
+ if (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+ err = rte_mbuf_dyn_rx_timestamp_register(&priv->mbuf_timestamp_offset,
+ &priv->mbuf_timestamp_mask);
+ if (err < 0) {
+ PMD_DRV_LOG(ERR, "Failed to register dynamic timestamp field");
+ return err;
+ }
+ }
+
/* Reset RSS RETA in case number of queues changed. */
if (priv->rss_config.indir) {
struct gve_rss_config update_reta_config;
gve_init_rss_config_from_priv(priv, &update_reta_config);
gve_generate_rss_reta(dev, &update_reta_config);
- int err = gve_adminq_configure_rss(priv, &update_reta_config);
+ err = gve_adminq_configure_rss(priv, &update_reta_config);
if (err)
PMD_DRV_LOG(ERR,
"Could not reconfigure RSS redirection table.");
@@ -828,6 +838,8 @@ gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
dev_info->min_mtu = RTE_ETHER_MIN_MTU;
dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_RSS_HASH;
+ if (!gve_is_gqi(priv) && priv->nic_ts_report_mz)
+ dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TIMESTAMP;
dev_info->tx_offload_capa =
RTE_ETH_TX_OFFLOAD_MULTI_SEGS |
RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
@@ -1683,6 +1695,7 @@ gve_dev_init(struct rte_eth_dev *eth_dev)
pthread_mutex_init(&priv->nic_ts_lock, &mutexattr);
pthread_mutexattr_destroy(&mutexattr);
+ priv->mbuf_timestamp_offset = -1;
err = gve_init_priv(priv, false);
if (err) {
pthread_mutex_destroy(&priv->flow_rule_lock);
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 1e80f3a906..4a7e5ecdf3 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -261,6 +261,7 @@ struct gve_rx_queue {
struct rte_mbuf **refill_bufs;
uint8_t is_gqi_qpl;
+ bool timestamp_enabled;
};
struct gve_flow {
@@ -372,8 +373,32 @@ struct gve_priv {
RTE_ATOMIC(uint8_t) nic_ts_stale;
rte_thread_t nic_ts_thread_id;
RTE_ATOMIC(uint8_t) nic_ts_thread_should_stop;
+
+ int mbuf_timestamp_offset;
+ uint64_t mbuf_timestamp_mask;
};
+/* Expand the hardware timestamp to the full 64 bits of width.
+ *
+ * This algorithm works by using the passed hardware timestamp to generate a
+ * diff relative to the last read of the nic clock. This diff can be positive or
+ * negative, as it is possible that we have read the clock more recently than
+ * the hardware has received this packet. To detect this, we use the high bit of
+ * the diff, and assume that the read is more recent if the high bit is set. In
+ * this case we invert the process.
+ *
+ * Note that this means if the time delta between packet reception and the last
+ * clock read is greater than ~2 seconds, this will provide invalid results.
+ */
+static inline uint64_t
+gve_reconstruct_ts(uint64_t last_sync, uint32_t ts)
+{
+ uint32_t low = (uint32_t)last_sync;
+ int32_t diff = (int32_t)(ts - low);
+
+ return last_sync + diff;
+}
+
static inline bool
gve_is_gqi(struct gve_priv *priv)
{
diff --git a/drivers/net/gve/gve_rx_dqo.c b/drivers/net/gve/gve_rx_dqo.c
index 8035aee572..cc343f3fd8 100644
--- a/drivers/net/gve/gve_rx_dqo.c
+++ b/drivers/net/gve/gve_rx_dqo.c
@@ -160,6 +160,8 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
{
volatile struct gve_rx_compl_desc_dqo *rx_desc;
struct gve_rx_queue *rxq;
+ uint64_t last_sync = 0;
+ struct gve_priv *priv;
struct rte_mbuf *rxm;
uint16_t rx_buf_id;
uint16_t pkt_len;
@@ -171,6 +173,15 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
nb_rx = 0;
rxq = rx_queue;
rx_id = rxq->rx_tail;
+ priv = rxq->hw;
+
+ if (rxq->timestamp_enabled &&
+ !rte_atomic_load_explicit(&priv->nic_ts_stale,
+ rte_memory_order_acquire)) {
+ last_sync =
+ rte_atomic_load_explicit(&priv->last_read_nic_timestamp,
+ rte_memory_order_relaxed);
+ }
while (nb_rx < nb_pkts) {
rx_desc = &rxq->compl_ring[rx_id];
@@ -208,6 +219,16 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
gve_parse_csum_ol_flags(rxm, rx_desc);
rxm->hash.rss = rte_le_to_cpu_32(rx_desc->hash);
+ if (last_sync != 0 &&
+ (rx_desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID) &&
+ priv->mbuf_timestamp_offset >= 0) {
+ uint32_t ts = rte_le_to_cpu_32(rx_desc->ts);
+ uint64_t full_ts = gve_reconstruct_ts(last_sync, ts);
+
+ *RTE_MBUF_DYNFIELD(rxm, priv->mbuf_timestamp_offset, uint64_t *) = full_ts;
+ rxm->ol_flags |= priv->mbuf_timestamp_mask;
+ }
+
rx_pkts[nb_rx++] = rxm;
bytes += pkt_len;
}
@@ -320,6 +341,11 @@ gve_rx_queue_setup_dqo(struct rte_eth_dev *dev, uint16_t queue_id,
return -ENOMEM;
}
+ /* Setup hardware timestamping if enabled */
+ if ((conf->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) ||
+ (dev->data->dev_conf.rxmode.offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP))
+ rxq->timestamp_enabled = true;
+
/* check free_thresh here */
free_thresh = conf->rx_free_thresh ?
conf->rx_free_thresh : GVE_DEFAULT_RX_FREE_THRESH;
--
2.54.0.1189.g8c84645362-goog
^ permalink raw reply related
* RE: [PATCH v6 00/21] Wangxun Fixes
From: Zaiyu Wang @ 2026-06-17 1:38 UTC (permalink / raw)
To: 'Stephen Hemminger'; +Cc: dev
In-Reply-To: <20260616144218.3bb7ea85@phoenix.local>
> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Wednesday, June 17, 2026 5:42 AM
> To: Zaiyu Wang <zaiyuwang@trustnetic.com>; Zaiyu Wang <zaiyuwang@trustnetic.com>
> Cc: dev@dpdk.org; dev@dpdk.org
> Subject: Re: [PATCH v6 00/21] Wangxun Fixes
>
> On Tue, 16 Jun 2026 20:20:08 +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.
> > ---
> > v6:
> > - Fixed more issues identified by AI review
> > ---
> > v5:
> > - Fixed issues identified by AI review
> > ---
> > v4:
> > - Fixed issues identified by devtools scripts
> > ---
> > v3:
> > - Addressed Stephen's comments
> > ---
> > v2:
> > - Fixed compilation error and code style issues
> > ---
> >
> > Zaiyu Wang (21):
> > 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
> > net/txgbe: fix temperature track for AML NIC
> >
> > 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 | 185 +-
> > drivers/net/txgbe/base/txgbe_aml.h | 6 +-
> > drivers/net/txgbe/base/txgbe_aml40.c | 114 +-
> > drivers/net/txgbe/base/txgbe_aml40.h | 6 +-
> > drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +-
> > drivers/net/txgbe/base/txgbe_e56.c | 3773 +++++++++++++++++++++
> > drivers/net/txgbe/base/txgbe_e56.h | 1753 ++++++++++
> > 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 | 362 +-
> > drivers/net/txgbe/base/txgbe_phy.h | 46 +-
> > drivers/net/txgbe/base/txgbe_regs.h | 13 +-
> > drivers/net/txgbe/base/txgbe_type.h | 43 +-
> > drivers/net/txgbe/txgbe_ethdev.c | 472 ++-
> > drivers/net/txgbe/txgbe_ethdev.h | 7 +-
> > drivers/net/txgbe/txgbe_rxtx.c | 109 +-
> > drivers/net/txgbe/txgbe_rxtx.h | 36 +
> > drivers/net/txgbe/txgbe_rxtx_vec_common.h | 17 +-
> > 26 files changed, 9464 insertions(+), 444 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
> >
>
> AI review was mostly clean, do you want to change this one thing?
>
> Review of [PATCH v6 00/21] net/{txgbe,ngbe} fixes from Zaiyu Wang
>
> All findings from the v5 review are addressed:
>
> - 07/21: Tx desc free now loads the 32-bit headwb_mem atomically and
> casts to uint16_t at the use site, removing the type pun.
> - 14/21: kr_read_poll() switches from usleep() to usec_delay() to
> match the rest of the txgbe base layer.
> - 16/21: stray tab+space indent in txgbe_read_i2c_sff8636() is gone.
> - 17/21: stray tab+space indent in txgbe_get_module_info() is gone.
> TXGBE_SFF_DDM_IMPLEMENTED is now indented as a bit mask under the
> 8472_SWAP register definition, which reads correctly.
> - 18/21: page is reset to 0 inside each iteration of the for loop so
> it no longer accumulates across iterations. The flat-memory check
> is now driven by an explicit read of module byte 2 via
> read_i2c_sff8636() into a local is_flat_mem flag, instead of
> reading data[0x2] out of the caller's output buffer. databyte is
> cleared to 0 at the top of each loop body so the skipped-read
> branch can no longer leak the previous iteration's value.
> - 20/21: RTE_LIBRTE_SECURITY is corrected to RTE_LIB_SECURITY so the
> !txq->using_ipsec guard is actually preprocessed in.
>
> One small remaining comment on 18/21, not blocking.
>
> Patch 18/21 (net/txgbe: fix get EEPROM operation)
>
> Info: is_flat_mem has inverted semantics relative to its name, which is going to confuse
future
> maintainers. SFF-8636 byte 2 bit 2
> ("Flat_mem") is 1 for flat-memory modules and 0 for paged-memory modules (this is the
same
> convention ethtool uses). The new code treats the bit the opposite way:
>
> + bool is_flat_mem = true;
> ...
> + if (rdata & 0x4)
> + is_flat_mem = false;
> ...
> + if (page == 0 || is_flat_mem) {
> + status = hw->phy.read_i2c_sff8636(hw, page, ...);
>
> So when the module reports flat (bit set), is_flat_mem is set to false; when paged (bit
clear),
> is_flat_mem stays true. The condition 'page == 0 || is_flat_mem' reads only page 0 in
the flat
> case and any page in the paged case, which is the right behavior, but the variable ends
up meaning
> "paged memory is OK to read" rather than "module is flat". Suggest either:
>
> bool is_flat_mem = false;
> if (rdata & 0x4)
> is_flat_mem = true;
> ...
> if (page == 0 || !is_flat_mem) {
> ...
> }
>
> or renaming to allow_paged_reads (or similar) and keeping the existing default and
condition.
>
>
>
Hi Stephen,
Thanks for your time. I will fix the issue as you suggested in v7 and send it shortly.
^ permalink raw reply
* [PATCH v7 00/21] Wangxun Fixes
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang
In-Reply-To: <20260423034024.14404-1-zaiyuwang@trustnetic.com>
This series fixes several issues found on Wangxun Emerald, Sapphire and
Amber-lite NICs, with a focus on link-related problems.
---
v7:
- Fixed inverted semantics of is_flat_mem to match SFF8636
---
v6:
- Fixed more issues identified by AI review
---
v5:
- Fixed issues identified by AI review
---
v4:
- Fixed issues identified by devtools scripts
---
v3:
- Addressed Stephen's comments
---
v2:
- Fixed compilation error and code style issues
---
Zaiyu Wang (21):
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
net/txgbe: fix temperature track for AML NIC
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 | 185 +-
drivers/net/txgbe/base/txgbe_aml.h | 6 +-
drivers/net/txgbe/base/txgbe_aml40.c | 114 +-
drivers/net/txgbe/base/txgbe_aml40.h | 6 +-
drivers/net/txgbe/base/txgbe_dcb_hw.c | 2 +-
drivers/net/txgbe/base/txgbe_e56.c | 3773 +++++++++++++++++++++
drivers/net/txgbe/base/txgbe_e56.h | 1753 ++++++++++
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 | 362 +-
drivers/net/txgbe/base/txgbe_phy.h | 46 +-
drivers/net/txgbe/base/txgbe_regs.h | 13 +-
drivers/net/txgbe/base/txgbe_type.h | 43 +-
drivers/net/txgbe/txgbe_ethdev.c | 472 ++-
drivers/net/txgbe/txgbe_ethdev.h | 7 +-
drivers/net/txgbe/txgbe_rxtx.c | 109 +-
drivers/net/txgbe/txgbe_rxtx.h | 36 +
drivers/net/txgbe/txgbe_rxtx_vec_common.h | 17 +-
26 files changed, 9464 insertions(+), 444 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
* [PATCH v7 02/21] net/ngbe: remove duplicate xstats counters
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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
* [PATCH v7 03/21] net/ngbe: add missing CDR config for YT PHY
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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
* [PATCH v7 04/21] net/ngbe: fix VF promiscuous and allmulticast
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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
* [PATCH v7 01/21] net/txgbe: remove duplicate xstats counters
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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
* [PATCH v7 05/21] net/txgbe: fix inaccuracy in Tx rate limiting
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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 | 3 +++
drivers/net/txgbe/txgbe_ethdev.c | 2 +-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/txgbe/base/txgbe_regs.h b/drivers/net/txgbe/base/txgbe_regs.h
index 95c585a025..3d1bc88430 100644
--- a/drivers/net/txgbe/base/txgbe_regs.h
+++ b/drivers/net/txgbe/base/txgbe_regs.h
@@ -1670,6 +1670,9 @@ enum txgbe_5tuple_protocol {
#define TXGBE_TDM_FACTOR_INT_SHIFT 16
#define TXGBE_TDM_FACTOR_FRA_SHIFT 2
+#define TXGBE_TDM_RL_ADJ 0x1820C
+ /* Ethernet framing overhead: 7B Ethernet preamble + 1B SFD + 1B EFD + 12B IPG */
+#define TXGBE_FRAME_OVERHEAD 21
#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..099341b5ab 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, TXGBE_FRAME_OVERHEAD);
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
* [PATCH v7 06/21] net/txgbe: fix link status check condition
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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
* [PATCH v7 08/21] net/txgbe: fix link flow control registers for Amber-Lite
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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 3d1bc88430..22c46e3d56 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 099341b5ab..9b5a4b72e4 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
* [PATCH v7 07/21] net/txgbe: fix Tx desc free logic
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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 | 16 +++++------
drivers/net/txgbe/txgbe_rxtx.h | 35 +++++++++++++++++++++++
drivers/net/txgbe/txgbe_rxtx_vec_common.h | 10 +++----
3 files changed, 48 insertions(+), 13 deletions(-)
diff --git a/drivers/net/txgbe/txgbe_rxtx.c b/drivers/net/txgbe/txgbe_rxtx.c
index e2cd9b8841..d6efb3b8cc 100644
--- a/drivers/net/txgbe/txgbe_rxtx.c
+++ b/drivers/net/txgbe/txgbe_rxtx.c
@@ -98,12 +98,11 @@ txgbe_tx_free_bufs(struct txgbe_tx_queue *txq)
if (tx_last_dd >= txq->nb_tx_desc)
tx_last_dd -= txq->nb_tx_desc;
- volatile uint16_t head = (uint16_t)*txq->headwb_mem;
+ uint32_t h = rte_atomic_load_explicit(txq->headwb_mem,
+ rte_memory_order_acquire);
+ const uint16_t head = (uint16_t)h;
- 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))
+ if (!txgbe_tx_headwb_desc_done(head, tx_last_dd, txq->tx_next_dd))
return 0;
} else {
/* check DD bit on threshold descriptor */
@@ -645,12 +644,13 @@ txgbe_xmit_cleanup(struct txgbe_tx_queue *txq)
status = txr[desc_to_clean_to].dw3;
if (txq->headwb_mem) {
- u32 head = *txq->headwb_mem;
+ uint32_t h = rte_atomic_load_explicit(txq->headwb_mem,
+ rte_memory_order_acquire);
+ const uint16_t head = (uint16_t)h;
PMD_TX_FREE_LOG(DEBUG, "queue[%02d]: headwb_mem = %03d, desc_to_clean_to = %03d",
txq->reg_idx, head, desc_to_clean_to);
- /* we have caught up to head, no work left to do */
- if (desc_to_clean_to == head)
+ if (!txgbe_tx_headwb_desc_done(head, last_desc_cleaned, desc_to_clean_to))
return -(1);
} else {
if (!(status & rte_cpu_to_le_32(TXGBE_TXD_DD))) {
diff --git a/drivers/net/txgbe/txgbe_rxtx.h b/drivers/net/txgbe/txgbe_rxtx.h
index 02e2617cce..43c818cfbf 100644
--- a/drivers/net/txgbe/txgbe_rxtx.h
+++ b/drivers/net/txgbe/txgbe_rxtx.h
@@ -426,6 +426,41 @@ struct txgbe_txq_ops {
void (*reset)(struct txgbe_tx_queue *txq);
};
+/**
+ * Check whether Tx descriptors in the range (last, next] are done
+ * in Tx head write-back mode.
+ *
+ * In head write-back mode, the hardware periodically updates *headwb_mem
+ * with the index of the next descriptor it will process.
+ * All descriptors before the head are considered processed by hardware and can
+ * be safely freed. The descriptor pointed to by head itself is not yet processed.
+ *
+ * @param head
+ * Current hardware head index read from headwb_mem.
+ * @param last
+ * The highest-index descriptor cleaned in the previous round
+ * (exclusive: descriptors at or before this index are already freed).
+ * @param next
+ * The highest-index descriptor to be cleaned in this round
+ * (inclusive: this descriptor is the target of the current cleanup).
+ * @return
+ * true if all descriptors in the range (last, next] have been completed
+ * by hardware and can be freed, false otherwise.
+ */
+static inline bool
+txgbe_tx_headwb_desc_done(uint16_t head, uint16_t last, uint16_t next)
+{
+ if (next == head)
+ return false;
+ else if (next > head && head > last)
+ return false;
+ /* wrap case */
+ else if (last > next && (head > last || head < next))
+ return false;
+
+ return true;
+}
+
/* Takes an ethdev and a queue and sets up the tx function to be used based on
* the queue parameters. Used in tx_queue_setup by primary process and then
* in dev_init by secondary process when attaching to an existing ethdev.
diff --git a/drivers/net/txgbe/txgbe_rxtx_vec_common.h b/drivers/net/txgbe/txgbe_rxtx_vec_common.h
index 00847d087b..77d7ff785b 100644
--- a/drivers/net/txgbe/txgbe_rxtx_vec_common.h
+++ b/drivers/net/txgbe/txgbe_rxtx_vec_common.h
@@ -94,11 +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)
- return 0;
- else if (tx_last_dd > txq->tx_next_dd &&
- (head > tx_last_dd || head < txq->tx_next_dd))
+ uint32_t h = rte_atomic_load_explicit(txq->headwb_mem,
+ rte_memory_order_acquire);
+ const uint16_t head = (uint16_t)h;
+
+ if (!txgbe_tx_headwb_desc_done(head, tx_last_dd, txq->tx_next_dd))
return 0;
} else {
/* check DD bit on threshold descriptor */
--
2.21.0.windows.1
^ permalink raw reply related
* [PATCH v7 09/21] net/txgbe: fix link flow control config for Sapphire
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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..db45c5c0ef 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]);
+ /* Only AML 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
* [PATCH v7 12/21] net/txgbe: fix link stability for 25G NIC
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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 | 105 +-
drivers/net/txgbe/base/txgbe_aml.h | 6 +-
drivers/net/txgbe/base/txgbe_e56.c | 2488 +++++++++++++++++++++++++
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, 4703 insertions(+), 59 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..6388893bca 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);
- status = hw->phy.set_link_hostif(hw, (u8)speed, autoneg, true);
+ if (ret_status == TXGBE_ERR_PHY_INIT_NOT_DONE)
+ goto out;
- txgbe_wait_for_link_up_aml(hw, speed);
+ 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);
+ }
+ }
+
+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;
}
@@ -242,9 +296,9 @@ static s32 txgbe_setup_mac_link_multispeed_fiber_aml(struct txgbe_hw *hw,
{
u32 link_speed = TXGBE_LINK_SPEED_UNKNOWN;
u32 highest_link_speed = TXGBE_LINK_SPEED_UNKNOWN;
+ bool autoneg, need_reset, link_up = false;
s32 status = 0;
u32 speedcnt = 0;
- bool autoneg, link_up = false;
/* Mask off requested but non-supported speeds */
status = hw->mac.get_link_capabilities(hw, &link_speed, &autoneg);
@@ -269,9 +323,10 @@ 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,
+ 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 +352,10 @@ 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);
+ 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 +405,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..870f4135ed
--- /dev/null
+++ b/drivers/net/txgbe/base/txgbe_e56.c
@@ -0,0 +1,2488 @@
+/* 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 &= ~(1U << bit_low);
+ } else {
+ /* set single bit */
+ *src_data |= (1U << bit_low);
+ }
+ } else {
+ /* first, clear the bit fields */
+ for (i = bit_low; i <= bit_high; i++) {
+ /* clear single bit */
+ *src_data &= ~(1U << 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");
+ 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");
+ 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");
+ 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");
+ 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;
+}
+
+#define RXS_READ_COUNT 5
+
+void txgbe_e56_rx_rd_second_code(struct txgbe_hw *hw, int *SECOND_CODE)
+{
+ int i, median;
+ unsigned int rdata;
+ int RXS_BBCDR_SECOND_ORDER_ST[RXS_READ_COUNT];
+
+ /* 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.
+ */
+ for (i = 0; i < RXS_READ_COUNT; 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] */
+ qsort(RXS_BBCDR_SECOND_ORDER_ST, RXS_READ_COUNT, sizeof(int), txgbe_e56_int_cmp);
+
+ median = ((RXS_READ_COUNT + 1) / 2) - 1;
+ *SECOND_CODE = RXS_BBCDR_SECOND_ORDER_ST[median];
+
+ return;
+}
+
+/*
+ * 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
+ */
+ 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;
+ bool bypass_ctle = true;
+
+ 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).
+ */
+ status |= 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..96c95a414e
--- /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);
+void 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 db45c5c0ef..7b6937b9ca 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 4aa62919b4..3c4c696c00 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 9b5a4b72e4..b883a7b174 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
* [PATCH v7 10/21] net/txgbe: fix a mass of unknown interrupts
From: Zaiyu Wang @ 2026-06-17 3:33 UTC (permalink / raw)
To: dev; +Cc: Zaiyu Wang, stable, Jiawen Wu, Ferruh Yigit
In-Reply-To: <20260617033400.376-1-zaiyuwang@trustnetic.com>
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 d6efb3b8cc..2d0c4989d9 100644
--- a/drivers/net/txgbe/txgbe_rxtx.c
+++ b/drivers/net/txgbe/txgbe_rxtx.c
@@ -4347,6 +4347,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;
@@ -4397,8 +4399,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.
@@ -4417,6 +4417,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.
*
@@ -4430,19 +4433,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
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox