ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_eth_link.c File Reference

Ethernet PHY link-status poller + MAC speed/duplex resync. More...

#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_eth.h"
#include "ra8_eth_internal.h"
#include "ra8_etha.h"
#include "ra8_log.h"
#include "ra8_rmac.h"
#include "ra8_time.h"
Include dependency graph for ra8_eth_link.c:

Go to the source code of this file.

Enumerations

enum  ra8_eth_an_poll_t : uint32_t {
  k_ra8_eth_an_poll_period_ms = 50U ,
  k_ra8_eth_an_poll_max_iters = 80U
}
 Bound on the AUTONEG_COMPLETE poll loop. More...

Functions

static void internal_pick_negotiated_speed (uint16_t anlpar, uint16_t gbsr, ra8_rmac_lsc_t *out_speed, ra8_rmac_duplex_t *out_duplex)
 Compute the highest auto-negotiated speed + duplex from ANLPAR+GBSR.
static void internal_wait_for_autoneg (ra8_rmac_port_t port)
 Poll BMSR.AUTONEG_COMPLETE until it asserts or the budget runs out.
static ra8_err_t internal_query_negotiated_speed (ra8_rmac_port_t port, ra8_rmac_lsc_t *out_speed, ra8_rmac_duplex_t *out_duplex)
 Read ANLPAR + GBSR and pick the negotiated speed/duplex.
static ra8_err_t internal_program_mpic (ra8_rmac_port_t port, ra8_rmac_lsc_t speed, ra8_rmac_duplex_t duplex)
 Drop ETHA to CONFIG, write MPIC, return to OPERATION.
static ra8_err_t internal_resync_mac_speed (ra8_rmac_port_t port, uint16_t bmcr)
 Resync MPIC.LSC / MPIC.PIPP to match the PHY auto-neg result.
static ra8_err_t internal_phy_read_link (ra8_rmac_port_t port, ra8_eth_link_t *out_status, uint16_t *out_bmcr)
 Read PHY BMSR + BMCR over MDIO and populate out_status.
ra8_err_t ra8_eth_link_status (ra8_eth_link_t *out_status)
 Query the PHY link state via MIIM (RMAC MDIO Clause-22).

Variables

static const char * s_tag = "ETH"
 Logger tag used by every ra8_eth_* call.
volatile uint16_t g_ra8_eth_phy_bmsr_after_wait
 BMSR snapshot AFTER the auto-neg wait.
volatile uint16_t g_ra8_eth_anlpar
 Last-read ANLPAR (PHY reg 5) snapshot for bench debugging.
volatile uint16_t g_ra8_eth_gbsr
 Last-read GBSR (PHY reg 10) snapshot for bench debugging.
volatile uint32_t g_ra8_eth_resync_speed_lsc
 Speed-LSC value the resync chose.
volatile uint32_t g_ra8_eth_resync_duplex
 Duplex value the resync chose.

Detailed Description

Ethernet PHY link-status poller + MAC speed/duplex resync.

Tag
[Ring 3 / HAL] {World: NS}

Split out of ra8_eth.c to keep each translation unit under the per-file line-count cap. Holds the read-mostly half of the NIC API: ra8_eth_link_status plus the one-shot MAC speed/duplex resync that realigns the on-chip RMAC's MPIC.LSC / MPIC.PIPP with whatever the PHY auto-negotiated.

The board layer programs MPIC for 1 Gbps at boot (the maximum the EK-RA8D2's PHY supports). When the link partner only offers 10/100 the PHY negotiates down, but MPIC stays at 1 Gbps and the RMAC drops every RGMII edge as out-of-spec framing. This TU reads the auto-neg result registers (ANLPAR + GBSR), picks the highest mutually-supported speed/duplex, and brackets the MPIC write with the ETHA DISABLE -> CONFIG -> {MPIC} -> DISABLE -> OPERATION transitions HUM Ch 33.4.1.2 requires.

The singleton NIC runtime state (s_eth_state) and the one-shot resync latch (g_eth_mac_speed_resynced) are defined in ra8_eth.c and shared via ra8_eth_internal.h.

Every register access carries a HUM Ch 33 citation.

Definition in file ra8_eth_link.c.

Enumeration Type Documentation

◆ ra8_eth_an_poll_t

enum ra8_eth_an_poll_t : uint32_t

Bound on the AUTONEG_COMPLETE poll loop.

Spec: auto-neg should complete within ~3 s of link-up. We poll BMSR.AN_COMPLETE for up to 4 s in 50 ms increments before giving up and falling back to whatever ANLPAR / GBSR happen to read (typically zero -> 10M HD).

Enumerator
k_ra8_eth_an_poll_period_ms 

RA8 Ethernet an poll period ms.

k_ra8_eth_an_poll_max_iters 

80 * 50 ms = 4 s ceiling.

Definition at line 159 of file ra8_eth_link.c.

Function Documentation

◆ internal_phy_read_link()

ra8_err_t internal_phy_read_link ( ra8_rmac_port_t port,
ra8_eth_link_t * out_status,
uint16_t * out_bmcr )
static

Read PHY BMSR + BMCR over MDIO and populate out_status.

Helper extracted from ra8_eth_link_status so the per-condition decoding (link_up, duplex, speed) stays under the NASA Rule 4 function-size threshold and clang-tidy readability-function-size threshold.

Parameters
[in]portRMAC port carrying the PHY.
[out]out_statusLink-state fields populated in place.
[out]out_bmcrBMCR value (caller uses it for the MAC speed-resync write).
Returns
ra8_err_t MDIO read outcome.
Return values
k_ra8_okBoth BMSR + BMCR fetched cleanly.
otherUnderlying MDIO error from the first failing read.
Precondition
out_status != nullptr.
out_bmcr != nullptr.
Postcondition
On success out_status->{bmsr, link_up, full_duplex, speed_mbps} are populated; out_bmcr holds the raw BMCR.
On error out_status / out_bmcr are unmodified.
Note
Not thread-safe; serialise PHY access with the rest of the ethernet bring-up.
Since
0.1.0

Definition at line 397 of file ra8_eth_link.c.

References ra8_eth_link_t::bmsr, ra8_eth_link_t::full_duplex, k_ra8_eth_phy_addr_default, k_ra8_eth_phy_bmcr_duplex, k_ra8_eth_phy_bmcr_speed100, k_ra8_eth_phy_bmsr_link_up, k_ra8_eth_phy_reg_bmcr, k_ra8_eth_phy_reg_bmsr, k_ra8_eth_phy_speed_10, k_ra8_eth_phy_speed_100, k_ra8_ok, ra8_eth_link_t::link_up, RA8_RETURN_ON_ERROR, ra8_rmac_mdio_c22_read(), s_tag, and ra8_eth_link_t::speed_mbps.

Referenced by ra8_eth_link_status().

◆ internal_pick_negotiated_speed()

void internal_pick_negotiated_speed ( uint16_t anlpar,
uint16_t gbsr,
ra8_rmac_lsc_t * out_speed,
ra8_rmac_duplex_t * out_duplex )
static

Compute the highest auto-negotiated speed + duplex from ANLPAR+GBSR.

Mirrors FSP r_rmac_phy.c::R_RMAC_PHY_LinkPartnerAbilityGet. Picks the highest priority intersection of our local PHY advertisement and the link partner's: 1000F > 100F > 100H > 10F > 10H. BMCR's speed bits are NOT the negotiated speed – they reflect what the host commanded the PHY to be (not what the auto-neg landed on).

Parameters
[in]anlparAuto-negotiation Link Partner Ability register.
[in]gbsr1000BASE-T Status register (link-partner-ability bits).
[out]out_speedReceives the LSC value for ra8_rmac_set_link.
[out]out_duplexReceives the duplex value.
Precondition
out_speed and out_duplex are non-null.
Auto-neg has completed (caller checked BMSR.AN_COMPLETE).
Postcondition
On return *out_speed reflects the highest mutual ability.
On return *out_duplex reflects matching duplex.
Note
Not thread-safe.
Since
0.1.0

Definition at line 116 of file ra8_eth_link.c.

References k_ra8_eth_phy_anlpar_100f, k_ra8_eth_phy_anlpar_100h, k_ra8_eth_phy_anlpar_10f, k_ra8_eth_phy_anlpar_10h, k_ra8_eth_phy_gbsr_1000f, k_ra8_eth_phy_gbsr_1000h, k_ra8_rmac_duplex_full, k_ra8_rmac_duplex_half, k_ra8_rmac_lsc_1000mbit, k_ra8_rmac_lsc_100mbit, and k_ra8_rmac_lsc_10mbit.

Referenced by internal_query_negotiated_speed().

◆ internal_program_mpic()

ra8_err_t internal_program_mpic ( ra8_rmac_port_t port,
ra8_rmac_lsc_t speed,
ra8_rmac_duplex_t duplex )
static

Drop ETHA to CONFIG, write MPIC, return to OPERATION.

Bracketed write per HUM Ch 33.4.1.2 – MPIC only sticks while ETHA is in CONFIG. Always returns ETHA to OPERATION even if the MPIC write itself failed, so the chip doesn't park in CONFIG.

Parameters
[in]portRMAC port whose MPIC needs updating.
[in]speedTarget LSC value.
[in]duplexTarget duplex value.
Returns
ra8_err_t error code.
Return values
k_ra8_okMPIC programmed.
k_ra8_err_hw_timeoutETHA mode transition timed out.
k_ra8_err_invalid_argra8_rmac_set_link rejected the args.
Precondition
Auto-neg result has been read.
port and speed/duplex are in range.
Postcondition
On k_ra8_ok ETHA is in OPERATION, MPIC reflects the args.
On error ETHA is restored to OPERATION before returning.
Note
Not thread-safe.
Since
0.1.0

Definition at line 288 of file ra8_eth_link.c.

References k_ra8_etha_opc_config, k_ra8_etha_opc_disable, k_ra8_etha_opc_operation, k_ra8_etha_port_0, k_ra8_etha_port_1, k_ra8_ok, k_ra8_rmac_lsc_1000mbit, k_ra8_rmac_pis_gmii, k_ra8_rmac_pis_mii, k_ra8_rmac_port_0, ra8_etha_set_mode(), and ra8_rmac_set_link().

Referenced by internal_resync_mac_speed().

◆ internal_query_negotiated_speed()

ra8_err_t internal_query_negotiated_speed ( ra8_rmac_port_t port,
ra8_rmac_lsc_t * out_speed,
ra8_rmac_duplex_t * out_duplex )
static

Read ANLPAR + GBSR and pick the negotiated speed/duplex.

Helper extracted from internal_resync_mac_speed so each function fits under the 60-line / 40-statement cap. Reads PHY registers 5 (ANLPAR) and 10 (GBSR), snapshots them into the bench-side debug vars, then calls internal_pick_negotiated_speed to compute the highest mutually-supported speed/duplex.

Parameters
[in]portRMAC port whose PHY to query.
[out]out_speedReceives the LSC value.
[out]out_duplexReceives the duplex value.
Returns
ra8_err_t MDIO read outcome (propagated from the first failing read).
Return values
k_ra8_okBoth registers fetched.
otherMDIO read failure.
Precondition
Auto-neg has had a chance to settle (call internal_wait_for_autoneg first).
out_speed / out_duplex are non-null.
Postcondition
On success the resync debug snapshots are updated.
On failure *out_speed / *out_duplex are unmodified.
Note
Not thread-safe.
Since
0.1.0

Definition at line 233 of file ra8_eth_link.c.

References g_ra8_eth_anlpar, g_ra8_eth_gbsr, g_ra8_eth_resync_duplex, g_ra8_eth_resync_speed_lsc, internal_pick_negotiated_speed(), k_ra8_eth_phy_addr_default, k_ra8_eth_phy_reg_anlpar, k_ra8_eth_phy_reg_gbsr, k_ra8_ok, and ra8_rmac_mdio_c22_read().

Referenced by internal_resync_mac_speed().

◆ internal_resync_mac_speed()

ra8_err_t internal_resync_mac_speed ( ra8_rmac_port_t port,
uint16_t bmcr )
static

Resync MPIC.LSC / MPIC.PIPP to match the PHY auto-neg result.

Top-level helper. Polls for AUTONEG_COMPLETE, reads ANLPAR / GBSR for the actual negotiated speed/duplex, then writes MPIC inside the ETHA CONFIG bracket. See internal_query_negotiated_speed and internal_program_mpic for the per-step details.

Parameters
[in]portRMAC port whose MPIC needs updating.
[in]bmcrUnused – kept for API stability with the old caller.
Returns
ra8_err_t error code.
Return values
k_ra8_okMPIC re-programmed.
k_ra8_err_invalid_argra8_rmac_set_link rejected an arg.
k_ra8_err_hw_timeoutAn ETHA mode transition or MDIO timed out.
Precondition
ra8_eth_open has succeeded (::s_eth_state.opened == 1).
g_eth_mac_speed_resynced is false on first call after open.
Postcondition
On success MPIC matches the PHY's negotiated speed/duplex.
On success g_eth_mac_speed_resynced is true.
Note
Not thread-safe; firmware drives this from a single thread.
Since
0.1.0

Definition at line 347 of file ra8_eth_link.c.

References g_eth_mac_speed_resynced, internal_program_mpic(), internal_query_negotiated_speed(), internal_wait_for_autoneg(), k_ra8_ok, k_ra8_rmac_duplex_half, k_ra8_rmac_lsc_10mbit, ra8_log_info, and s_tag.

Referenced by ra8_eth_link_status().

◆ internal_wait_for_autoneg()

void internal_wait_for_autoneg ( ra8_rmac_port_t port)
static

Poll BMSR.AUTONEG_COMPLETE until it asserts or the budget runs out.

BMSR.LINK_STATUS can fire before AN_COMPLETE, but ANLPAR / GBSR only latch the link-partner advertisement at AN_COMPLETE. Reading them too early returns 0. Polls every k_ra8_eth_an_poll_period_ms for up to k_ra8_eth_an_poll_max_iters iterations (~4 s ceiling).

Parameters
[in]portRMAC port whose PHY to poll.
Precondition
Caller is single-threaded.
PHY is enumerated at k_ra8_eth_phy_addr_default.
Postcondition
Returns once AN_COMPLETE is set or the budget is exhausted.
Side-effect free apart from the busy-wait loop.
Note
Not thread-safe.
Since
0.1.0

Definition at line 184 of file ra8_eth_link.c.

References g_ra8_eth_phy_bmsr_after_wait, k_ra8_eth_an_poll_max_iters, k_ra8_eth_an_poll_period_ms, k_ra8_eth_phy_addr_default, k_ra8_eth_phy_bmsr_an_done, k_ra8_eth_phy_reg_bmsr, k_ra8_ok, ra8_delay_ms(), and ra8_rmac_mdio_c22_read().

Referenced by internal_resync_mac_speed().

◆ ra8_eth_link_status()

ra8_err_t ra8_eth_link_status ( ra8_eth_link_t * out_status)
nodiscard

Query the PHY link state via MIIM (RMAC MDIO Clause-22).

Reads BMSR (PHY register 0x01) for link-status, then BMCR (0x00) to extract the configured speed and duplex. The PHY address is fixed at 0 (the EK-RA8D2 board's on-board PHY default).

Parameters
[out]out_statusDestination structure.
Returns
ra8_err_t Error code.
Return values
k_ra8_okLink snapshot returned.
k_ra8_err_null_ptrout_status is nullptr.
k_ra8_err_not_initializedra8_eth_open was not called first.
k_ra8_err_hw_timeoutMDIO transaction did not complete.
Precondition
Driver previously brought up via ra8_eth_open.
PHY MDC clock programmed by RMAC init (MPIC.PSMCS).
Postcondition
out_status->link_up reflects BMSR bit 2.
out_status->bmsr is the raw PHY register snapshot.
See also
ra8_eth_get_stats
Since
0.1.0

Definition at line 427 of file ra8_eth_link.c.

References g_eth_mac_speed_resynced, internal_phy_read_link(), internal_resync_mac_speed(), k_ra8_err_not_initialized, k_ra8_ok, ra8_eth_link_t::link_up, priv_ra8_eth_channel_to_port(), RA8_CHECK_NULL_PTR, RA8_RETURN_ON_ERROR, s_eth_state, and s_tag.

Referenced by internal_handle_get_status(), and ra8_eth_open().

Variable Documentation

◆ g_ra8_eth_anlpar

volatile uint16_t g_ra8_eth_anlpar

Last-read ANLPAR (PHY reg 5) snapshot for bench debugging.

Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0

Definition at line 66 of file ra8_eth_link.c.

Referenced by internal_query_negotiated_speed().

◆ g_ra8_eth_gbsr

volatile uint16_t g_ra8_eth_gbsr

Last-read GBSR (PHY reg 10) snapshot for bench debugging.

Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0

Definition at line 74 of file ra8_eth_link.c.

Referenced by internal_query_negotiated_speed().

◆ g_ra8_eth_phy_bmsr_after_wait

volatile uint16_t g_ra8_eth_phy_bmsr_after_wait

BMSR snapshot AFTER the auto-neg wait.

BMSR snapshot AFTER the internal_wait_for_autoneg poll.

Defined once in ra8_eth_link.c; referenced from ra8_eth.c via this declaration.

Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0
Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0

Definition at line 58 of file ra8_eth_link.c.

Referenced by internal_wait_for_autoneg().

◆ g_ra8_eth_resync_duplex

volatile uint32_t g_ra8_eth_resync_duplex

Duplex value the resync chose.

0=half, 1=full.

Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0

Definition at line 90 of file ra8_eth_link.c.

Referenced by internal_query_negotiated_speed().

◆ g_ra8_eth_resync_speed_lsc

volatile uint32_t g_ra8_eth_resync_speed_lsc

Speed-LSC value the resync chose.

0=10M, 1=100M, 2=1000M.

Note
Read externally by J-Link only; firmware never reads back.
Since
0.1.0

Definition at line 82 of file ra8_eth_link.c.

Referenced by internal_query_negotiated_speed().

◆ s_tag

const char* s_tag = "ETH"
static

Logger tag used by every ra8_eth_* call.

Definition at line 50 of file ra8_eth_link.c.