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

RMAC off-chip PHY driver. More...

#include "ra8_rmac_phy.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
#include "ra8_rmac_phy_internal.h"
Include dependency graph for ra8_rmac_phy.c:

Go to the source code of this file.

Data Structures

struct  ra8_rmac_phy_internal_t

Enumerations

enum  ra8_rmac_phy_reg_t : uint8_t {
  k_ra8_rmac_phy_reg_control = 0U ,
  k_ra8_rmac_phy_reg_status = 1U ,
  k_ra8_rmac_phy_reg_an_advert = 4U ,
  k_ra8_rmac_phy_reg_an_partner = 5U ,
  k_ra8_rmac_phy_reg_1000t_ctrl = 9U ,
  k_ra8_rmac_phy_reg_1000t_status = 10U ,
  k_ra8_rmac_phy_reset_poll_max = 32U
}
enum  ra8_rmac_phy_bits_t : uint16_t {
  k_ra8_rmac_phy_bmcr_reset = 0x8000U ,
  k_ra8_rmac_phy_bmcr_an_enable = 0x1000U ,
  k_ra8_rmac_phy_bmcr_an_restart = 0x0200U ,
  k_ra8_rmac_phy_bmsr_link_up = 0x0004U ,
  k_ra8_rmac_phy_bmsr_an_complete = 0x0020U ,
  k_ra8_rmac_phy_lpa_100full = 0x0100U ,
  k_ra8_rmac_phy_lpa_100half = 0x0080U ,
  k_ra8_rmac_phy_lpa_10full = 0x0040U ,
  k_ra8_rmac_phy_lpa_10half = 0x0020U ,
  k_ra8_rmac_phy_msr_1000full = 0x0800U ,
  k_ra8_rmac_phy_msr_1000half = 0x0400U
}

Functions

bool priv_ra8_rmac_phy_internal_speed_ok (ra8_err_t err, uint16_t reg_value, uint16_t mask)
 Pure speed-detected predicate – see header for full contract.
static ra8_err_t internal_open_validate (const ra8_rmac_phy_cfg_t *cfg)
 Validate an ra8_rmac_phy_cfg_t before it is latched by open.
static ra8_err_t internal_reset_and_wait (uint16_t poll_max)
 Issue BMCR.RESET to the PHY and poll until it self-clears.
static ra8_err_t internal_program_advertise (void)
 Program the auto-negotiation advertisement registers.
ra8_err_t ra8_rmac_phy_open (const ra8_rmac_phy_cfg_t *cfg)
 Open the RMAC PHY driver and bring the off-chip PHY out of reset.
ra8_err_t ra8_rmac_phy_close (void)
 Close the PHY driver and forget all cached state.
ra8_err_t ra8_rmac_phy_mdio_read (uint8_t reg_addr, uint16_t *out_data)
 Read a 16-bit Clause-22 PHY register.
ra8_err_t ra8_rmac_phy_mdio_write (uint8_t reg_addr, uint16_t data)
 Write a 16-bit Clause-22 PHY register.
ra8_err_t ra8_rmac_phy_auto_negotiate_start (void)
 Restart auto-negotiation by writing BMCR.
static void internal_resolve_speed (ra8_rmac_phy_link_t *out)
 Resolve the negotiated speed once the link is up and AN done.
ra8_err_t ra8_rmac_phy_link_status_get (ra8_rmac_phy_link_t *out)
 Read BMSR / 1000T-status / LPA and decode the link state.
ra8_err_t ra8_rmac_phy_lsi_get (ra8_rmac_phy_lsi_t *out)
 Return the LSI tag the caller passed to ra8_rmac_phy_open.

Variables

static const char * s_tag = "RMPHY"
static ra8_rmac_phy_internal_t s_state = {}

Detailed Description

RMAC off-chip PHY driver.

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

Companion driver to ra8_rmac.c. Same MDIO bus shape as ra8_ether_phy but tracks 1000BASE-T capabilities and a vendor LSI identifier (KSZ8041 / KSZ8091RNB / DP83620 / ICS1894 / GPY111 / VSC8541) so future quirks can fan out by lsi_type.

Definition in file ra8_rmac_phy.c.

Enumeration Type Documentation

◆ ra8_rmac_phy_bits_t

enum ra8_rmac_phy_bits_t : uint16_t
Enumerator
k_ra8_rmac_phy_bmcr_reset 

RA8 rmac PHY bmcr reset.

k_ra8_rmac_phy_bmcr_an_enable 

RA8 rmac PHY bmcr an enable.

k_ra8_rmac_phy_bmcr_an_restart 

RA8 rmac PHY bmcr an restart.

k_ra8_rmac_phy_bmsr_link_up 

RA8 rmac PHY bmsr link up.

k_ra8_rmac_phy_bmsr_an_complete 

RA8 rmac PHY bmsr an complete.

k_ra8_rmac_phy_lpa_100full 

RA8 rmac PHY lpa 100full.

k_ra8_rmac_phy_lpa_100half 

RA8 rmac PHY lpa 100half.

k_ra8_rmac_phy_lpa_10full 

RA8 rmac PHY lpa 10full.

k_ra8_rmac_phy_lpa_10half 

RA8 rmac PHY lpa 10half.

k_ra8_rmac_phy_msr_1000full 

RA8 rmac PHY msr 1000full.

k_ra8_rmac_phy_msr_1000half 

RA8 rmac PHY msr 1000half.

Definition at line 61 of file ra8_rmac_phy.c.

◆ ra8_rmac_phy_reg_t

enum ra8_rmac_phy_reg_t : uint8_t
Enumerator
k_ra8_rmac_phy_reg_control 

RA8 rmac PHY register control.

k_ra8_rmac_phy_reg_status 

RA8 rmac PHY register status.

k_ra8_rmac_phy_reg_an_advert 

RA8 rmac PHY register an advert.

k_ra8_rmac_phy_reg_an_partner 

RA8 rmac PHY register an partner.

k_ra8_rmac_phy_reg_1000t_ctrl 

RA8 rmac PHY register 1000t control.

k_ra8_rmac_phy_reg_1000t_status 

RA8 rmac PHY register 1000t status.

k_ra8_rmac_phy_reset_poll_max 

RA8 rmac PHY reset poll maximum.

Definition at line 51 of file ra8_rmac_phy.c.

Function Documentation

◆ internal_open_validate()

ra8_err_t internal_open_validate ( const ra8_rmac_phy_cfg_t * cfg)
static

Validate an ra8_rmac_phy_cfg_t before it is latched by open.

Shared precondition gate for ra8_rmac_phy_open: rejects NULL configuration / IO callbacks, an out-of-range Clause-22 PHY address, and an unknown LSI family tag. Extracted so the open path stays within the NASA P10 Rule 4 statement cap.

Parameters
[in]cfgCaller-supplied configuration block (may be NULL).
Returns
ra8_err_t error code.
Return values
k_ra8_okConfiguration is well-formed.
k_ra8_err_null_ptrcfg or a required IO callback NULL.
k_ra8_err_invalid_argphy_address or lsi_type bad.
Precondition
None – this IS the argument validation.
k_ra8_rmac_phy_lsi_count bounds the LSI enum.
Postcondition
No state is mutated.
Return value depends only on cfg.
Note
Pure validation helper; safe from any context.
Since
0.1.0

Definition at line 112 of file ra8_rmac_phy.c.

References ra8_rmac_phy_cfg_t::io, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_rmac_phy_addr_max, k_ra8_rmac_phy_lsi_count, ra8_rmac_phy_cfg_t::lsi_type, ra8_rmac_phy_cfg_t::phy_address, RA8_CHECK_NULL_PTR, ra8_rmac_phy_io_t::read, s_tag, and ra8_rmac_phy_io_t::write.

Referenced by ra8_rmac_phy_open().

◆ internal_program_advertise()

ra8_err_t internal_program_advertise ( void )
static

Program the auto-negotiation advertisement registers.

Writes the cached local-advertise word into Clause-22 register 4 (AN_ADVERT) and – if non-zero – the gbit-advertise word into register 9 (1000BASE-T control). Skipping the second write keeps 10/100-only PHYs from rejecting an unsupported register access.

Returns
ra8_err_t error code propagated from the MDIO callback.
Return values
k_ra8_okAdvertisement programmed.
Precondition
Caller has populated s_state.local_advertise / gbit_advertise.
Driver still holds the opened-but-tentative state from open().
Postcondition
Advertised abilities reflect the cached configuration on success.
Driver state is unchanged on error.
Note
Not thread-safe; called only from open().
Since
0.1.0

Definition at line 192 of file ra8_rmac_phy.c.

References k_ra8_ok, k_ra8_rmac_phy_reg_1000t_ctrl, k_ra8_rmac_phy_reg_an_advert, and s_state.

Referenced by ra8_rmac_phy_open().

◆ internal_reset_and_wait()

ra8_err_t internal_reset_and_wait ( uint16_t poll_max)
static

Issue BMCR.RESET to the PHY and poll until it self-clears.

IEEE 802.3 Clause 22 6.3.5.2.5 requires BMCR bit 15 (RESET) to be write-only; the PHY clears it once internal state has been re-initialized. Polls up to poll_max MDIO reads before giving up.

Parameters
[in]poll_maxMaximum read iterations before timing out.
Returns
ra8_err_t error code.
Return values
k_ra8_okBMCR.RESET observed clear.
k_ra8_err_hw_timeoutBMCR.RESET still set after poll_max reads.
Precondition
s_state.io.read and s_state.io.write non-NULL.
s_state.phy_address is the open driver's PHY.
Postcondition
On success the PHY is back in its post-reset default state.
On error the PHY may be partway through reset; caller closes driver.
Note
Not thread-safe; called from open under IRQ-masked init.
Since
0.1.0

Definition at line 149 of file ra8_rmac_phy.c.

References k_ra8_err_hw_timeout, k_ra8_ok, k_ra8_rmac_phy_bmcr_reset, k_ra8_rmac_phy_reg_control, and s_state.

◆ internal_resolve_speed()

void internal_resolve_speed ( ra8_rmac_phy_link_t * out)
static

Resolve the negotiated speed once the link is up and AN done.

Consults the 1000BASE-T status register (MSR, Clause-22 register 10) first when gigabit was advertised, then falls back to the partner ability word (LPA, register 5) for the 10/100 speeds. out->speed keeps its k_ra8_rmac_phy_speed_no_link preset when neither register yields a resolvable speed.

Parameters
[in,out]outLink snapshot being populated by the caller; speed / partner_ability are written here.
Precondition
out is non-NULL with speed preset to no-link.
Driver is open and BMSR reported link-up + AN-complete.
Postcondition
out->speed holds the best resolved speed (or no-link).
out->partner_ability caches LPA when the LPA read succeeded.
Note
Not thread-safe; called only from link_status_get.
Since
0.1.0

Definition at line 442 of file ra8_rmac_phy.c.

References k_ra8_ok, k_ra8_rmac_phy_lpa_100full, k_ra8_rmac_phy_lpa_100half, k_ra8_rmac_phy_lpa_10full, k_ra8_rmac_phy_lpa_10half, k_ra8_rmac_phy_msr_1000full, k_ra8_rmac_phy_msr_1000half, k_ra8_rmac_phy_reg_1000t_status, k_ra8_rmac_phy_reg_an_partner, k_ra8_rmac_phy_speed_1000f, k_ra8_rmac_phy_speed_1000h, k_ra8_rmac_phy_speed_100f, k_ra8_rmac_phy_speed_100h, k_ra8_rmac_phy_speed_10f, k_ra8_rmac_phy_speed_10h, ra8_rmac_phy_link_t::partner_ability, priv_ra8_rmac_phy_internal_speed_ok(), s_state, and ra8_rmac_phy_link_t::speed.

Referenced by ra8_rmac_phy_link_status_get().

◆ priv_ra8_rmac_phy_internal_speed_ok()

bool priv_ra8_rmac_phy_internal_speed_ok ( ra8_err_t err,
uint16_t reg_value,
uint16_t mask )

Pure speed-detected predicate – see header for full contract.

Pure predicate: PHY register read OK AND mask bit set.

Promoted helper so the line-352/356 AND can be driven under MC/DC.

Parameters
[in]errResult of the prior MIIM read.
[in]reg_valueRegister value just read.
[in]maskSpeed-bit mask to test.
Returns
Boolean predicate.
Return values
trueSpeed bit set and read OK.
falseOtherwise.
Precondition
None.
None.
Postcondition
No state mutated.
Return depends solely on inputs.
Note
Pure; thread-safe.
Since
0.1.0

Definition at line 44 of file ra8_rmac_phy.c.

References k_ra8_ok.

Referenced by internal_resolve_speed().

◆ ra8_rmac_phy_auto_negotiate_start()

ra8_err_t ra8_rmac_phy_auto_negotiate_start ( void )
nodiscard

Restart auto-negotiation by writing BMCR.

Restart auto-negotiation on the PHY.

{ANE | ANR}.

Sets the AN-enable + AN-restart bits in the IEEE 802.3 Clause-22 BMCR (register 0). Useful after the link partner changes or after the local advertisement masks were updated.

Returns
ra8_err_t error code.
Return values
k_ra8_okRestart command issued.
k_ra8_err_not_initializedra8_rmac_phy_open not called.
Precondition
Driver previously opened.
Local + gigabit advertisement registers have been programmed.
Postcondition
BMCR.ANE and BMCR.ANR are set.
Auto-negotiation FSM restarts on the link.
Note
Not thread-safe.
Since
0.1.0

Definition at line 411 of file ra8_rmac_phy.c.

References k_ra8_err_not_initialized, k_ra8_rmac_phy_bmcr_an_enable, k_ra8_rmac_phy_bmcr_an_restart, k_ra8_rmac_phy_reg_control, and s_state.

◆ ra8_rmac_phy_close()

ra8_err_t ra8_rmac_phy_close ( void )
nodiscard

Close the PHY driver and forget all cached state.

Close the driver.

Marks the driver as closed so subsequent IO calls return k_ra8_err_not_initialized. The PHY itself is left in its current state (the caller may issue another reset via ra8_rmac_phy_open later).

Returns
ra8_err_t error code.
Return values
k_ra8_okDriver state cleared.
k_ra8_err_invalid_stateDriver was not open.
Precondition
IRQs masked or single-threaded shutdown context.
ra8_rmac_phy_open previously succeeded.
Postcondition
Driver state is marked closed.
Off-chip PHY register state is unchanged.
Note
Not thread-safe.
Since
0.1.0

Definition at line 307 of file ra8_rmac_phy.c.

References k_ra8_err_invalid_state, k_ra8_ok, and s_state.

◆ ra8_rmac_phy_link_status_get()

ra8_err_t ra8_rmac_phy_link_status_get ( ra8_rmac_phy_link_t * out)
nodiscard

Read BMSR / 1000T-status / LPA and decode the link state.

Read BMSR + partner ability and resolve speed/duplex.

Reads BMSR (IEEE 802.3 register 1), then – if AN is complete and the link is up – consults the gigabit controller/peripheral status (MSR, register 10) and the partner ability (LPA, register 5) to map the advertised speeds to ra8_rmac_phy_speed_t.

Parameters
[out]outReceives the decoded link snapshot.
Returns
ra8_err_t error code.
Return values
k_ra8_ok*out populated.
k_ra8_err_null_ptrout was NULL.
k_ra8_err_not_initializedDriver not open.
Precondition
out non-NULL.
Driver previously opened.
Postcondition
*out reflects the live PHY state.
s_state.last_bmsr caches the raw BMSR for diagnostics.
Note
Not thread-safe; pair with caller-side mutex if shared.
Since
0.1.0

Definition at line 500 of file ra8_rmac_phy.c.

References ra8_rmac_phy_link_t::auto_neg_done, ra8_rmac_phy_link_t::bmsr, internal_resolve_speed(), k_ra8_err_not_initialized, k_ra8_ok, k_ra8_rmac_phy_bmsr_an_complete, k_ra8_rmac_phy_bmsr_link_up, k_ra8_rmac_phy_reg_status, k_ra8_rmac_phy_speed_no_link, ra8_rmac_phy_link_t::link_up, ra8_rmac_phy_link_t::partner_ability, RA8_CHECK_NULL_PTR, s_state, s_tag, and ra8_rmac_phy_link_t::speed.

◆ ra8_rmac_phy_lsi_get()

ra8_err_t ra8_rmac_phy_lsi_get ( ra8_rmac_phy_lsi_t * out)
nodiscard

Return the LSI tag the caller passed to ra8_rmac_phy_open.

Get the currently-bound PHY-LSI identifier.

Echoes back the cached ra8_rmac_phy_lsi_t so higher-level stacks can branch on the on-board PHY model without re-querying MDIO.

Parameters
[out]outReceives the cached LSI tag.
Returns
ra8_err_t error code.
Return values
k_ra8_ok*out populated.
k_ra8_err_null_ptrout was NULL.
k_ra8_err_not_initializedDriver not open.
Precondition
out non-NULL.
Driver previously opened.
Postcondition
*out equals the value passed in cfg->lsi_type.
Driver state is unchanged.
Note
Read-only; safe under simple races.
Since
0.1.0

Definition at line 548 of file ra8_rmac_phy.c.

References k_ra8_err_not_initialized, k_ra8_ok, RA8_CHECK_NULL_PTR, s_state, and s_tag.

◆ ra8_rmac_phy_mdio_read()

ra8_err_t ra8_rmac_phy_mdio_read ( uint8_t reg_addr,
uint16_t * out_data )
nodiscard

Read a 16-bit Clause-22 PHY register.

Read a Clause-22 register on the off-chip PHY.

Forwards the read to the injected io.read callback so the caller controls the actual MDIO transport. reg_addr must be in 0..31 (Clause-22 5-bit register space).

Parameters
[in]reg_addrClause-22 register index 0..31.
[out]out_dataReceives the 16-bit register value.
Returns
ra8_err_t error code.
Return values
k_ra8_okRead completed.
k_ra8_err_null_ptrout_data was NULL.
k_ra8_err_not_initializedra8_rmac_phy_open not called.
k_ra8_err_invalid_argreg_addr > 31.
Precondition
out_data non-NULL.
Driver previously opened.
Postcondition
*out_data reflects the live PHY register value.
No PHY register has been written.
Note
Re-entrancy is governed by the injected IO callback.
Since
0.1.0

Definition at line 342 of file ra8_rmac_phy.c.

References k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_rmac_phy_reg_max, RA8_CHECK_NULL_PTR, s_state, and s_tag.

◆ ra8_rmac_phy_mdio_write()

ra8_err_t ra8_rmac_phy_mdio_write ( uint8_t reg_addr,
uint16_t data )
nodiscard

Write a 16-bit Clause-22 PHY register.

Write a Clause-22 register on the off-chip PHY.

Forwards the write to the injected io.write callback. The PHY may treat the write as set-and-forget or as a self-clearing strobe depending on the register (e.g. BMCR.RESET).

Parameters
[in]reg_addrClause-22 register index 0..31.
[in]dataValue to write.
Returns
ra8_err_t error code.
Return values
k_ra8_okWrite completed.
k_ra8_err_not_initializedra8_rmac_phy_open not called.
k_ra8_err_invalid_argreg_addr > 31.
Precondition
Driver previously opened.
Caller has serialised access to MDIO.
Postcondition
Selected PHY register reflects data per IEEE 802.3 Clause 22.
Driver state is unchanged.
Note
Re-entrancy is governed by the injected IO callback.
Since
0.1.0

Definition at line 379 of file ra8_rmac_phy.c.

References k_ra8_err_invalid_arg, k_ra8_err_not_initialized, k_ra8_rmac_phy_reg_max, and s_state.

◆ ra8_rmac_phy_open()

ra8_err_t ra8_rmac_phy_open ( const ra8_rmac_phy_cfg_t * cfg)
nodiscard

Open the RMAC PHY driver and bring the off-chip PHY out of reset.

Open the PHY and run a soft-reset sequence.

Validates the caller-supplied configuration, captures the MDIO IO seam (read/write function pointers) into module-private state, issues a soft reset over MDIO and polls BMCR.RESET to clear, then programs the advertised abilities into ANAR (and 1000BASE-T control where the LSI supports gigabit). Subsequent ra8_rmac_phy_* calls operate against the cached state; only one open instance is permitted at a time.

Algorithm:

  1. Null-pointer + range validation on cfg / cfg->io / phy_address.
  2. Copy cfg fields into the module-private s_state.
  3. internal_reset_and_wait() drives BMCR.RESET=1 and polls clear.
  4. internal_program_advertise() writes ANAR (and 1000T_CTRL if used).
Parameters
[in]cfgPHY configuration: IO seam, MDIO address (0..31), LSI family, advertised abilities, and reset poll budget. Must not be nullptr; cfg->io.read and cfg->io.write must be non-null.
Returns
ra8_err_t error code.
Return values
k_ra8_okPHY reset and advertise programmed.
k_ra8_err_invalid_argcfg/io pointers null, phy_address out of range, or unknown lsi_type.
k_ra8_err_existsDriver already opened; close first.
k_ra8_err_ioMDIO write to BMCR/ANAR failed.
k_ra8_err_timeoutBMCR.RESET did not clear within budget.
Precondition
Caller is in single-threaded init context with the MDIO bus idle.
RMAC controller MDIO is clocked (caller has enabled the MAC).
Postcondition
On k_ra8_ok the driver is in the opened state with cached config.
On failure the driver remains closed (s_state.opened == false).
Note
Not thread-safe; the module owns a single static state instance.
Since
0.1.0

Definition at line 251 of file ra8_rmac_phy.c.

References ra8_rmac_phy_cfg_t::gbit_advertise, internal_open_validate(), internal_program_advertise(), internal_reset_and_wait(), ra8_rmac_phy_cfg_t::io, k_ra8_err_exists, k_ra8_ok, k_ra8_rmac_phy_reset_poll_max, ra8_rmac_phy_cfg_t::local_advertise, ra8_rmac_phy_cfg_t::lsi_type, ra8_rmac_phy_cfg_t::phy_address, ra8_log_info_val, ra8_rmac_phy_cfg_t::reset_poll_max, s_state, and s_tag.

Variable Documentation

◆ s_state

ra8_rmac_phy_internal_t s_state = {}
static

Definition at line 85 of file ra8_rmac_phy.c.

◆ s_tag

const char* s_tag = "RMPHY"
static

Definition at line 49 of file ra8_rmac_phy.c.