ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_eth_link.c
Go to the documentation of this file.
1
33
34#include <stdint.h>
35
36#include "ra8_attributes.h"
37#include "ra8_check.h"
38#include "ra8_err.h"
39#include "ra8_eth.h"
40#include "ra8_eth_internal.h"
41#include "ra8_etha.h"
42#include "ra8_log.h"
43#include "ra8_rmac.h"
44#include "ra8_time.h"
45
50static const char* s_tag = "ETH";
51
59
66volatile uint16_t g_ra8_eth_anlpar;
67
74volatile uint16_t g_ra8_eth_gbsr;
75
83
90volatile uint32_t g_ra8_eth_resync_duplex;
91
116static void internal_pick_negotiated_speed(uint16_t anlpar,
117 uint16_t gbsr,
118 ra8_rmac_lsc_t* out_speed,
119 ra8_rmac_duplex_t* out_duplex)
120{
121 /* Default: lowest tier. */
122 *out_speed = k_ra8_rmac_lsc_10mbit;
123 *out_duplex = k_ra8_rmac_duplex_half;
124 if ((anlpar & (uint16_t)k_ra8_eth_phy_anlpar_10h) != 0U) {
125 *out_speed = k_ra8_rmac_lsc_10mbit;
126 *out_duplex = k_ra8_rmac_duplex_half;
127 }
128 if ((anlpar & (uint16_t)k_ra8_eth_phy_anlpar_10f) != 0U) {
129 *out_speed = k_ra8_rmac_lsc_10mbit;
130 *out_duplex = k_ra8_rmac_duplex_full;
131 }
132 if ((anlpar & (uint16_t)k_ra8_eth_phy_anlpar_100h) != 0U) {
133 *out_speed = k_ra8_rmac_lsc_100mbit;
134 *out_duplex = k_ra8_rmac_duplex_half;
135 }
136 if ((anlpar & (uint16_t)k_ra8_eth_phy_anlpar_100f) != 0U) {
137 *out_speed = k_ra8_rmac_lsc_100mbit;
138 *out_duplex = k_ra8_rmac_duplex_full;
139 }
140 if ((gbsr & (uint16_t)k_ra8_eth_phy_gbsr_1000h) != 0U) {
141 *out_speed = k_ra8_rmac_lsc_1000mbit;
142 *out_duplex = k_ra8_rmac_duplex_half;
143 }
144 if ((gbsr & (uint16_t)k_ra8_eth_phy_gbsr_1000f) != 0U) {
145 *out_speed = k_ra8_rmac_lsc_1000mbit;
146 *out_duplex = k_ra8_rmac_duplex_full;
147 }
148}
149
163
185{
186 uint16_t bmsr = 0U;
187 for (uint32_t i = 0U; i < (uint32_t)k_ra8_eth_an_poll_max_iters; ++i) {
188 if (ra8_rmac_mdio_c22_read(port,
190 (uint8_t)k_ra8_eth_phy_reg_bmsr,
191 &bmsr) != k_ra8_ok) {
193 return;
194 }
195 if ((bmsr & (uint16_t)k_ra8_eth_phy_bmsr_an_done) != 0U) {
197 return;
198 }
200 }
202}
203
234 ra8_rmac_lsc_t* out_speed,
235 ra8_rmac_duplex_t* out_duplex)
236{
237 uint16_t anlpar = 0U;
238 /* HUM Ch 33.4.1.1 "MPSM : PHY Station Management Register" p 1707 */
239 const ra8_err_t anlpar_err = ra8_rmac_mdio_c22_read(port,
242 &anlpar);
243 if (anlpar_err != k_ra8_ok) {
244 return anlpar_err;
245 }
246 uint16_t gbsr = 0U;
247 const ra8_err_t gbsr_err = ra8_rmac_mdio_c22_read(port,
249 (uint8_t)k_ra8_eth_phy_reg_gbsr,
250 &gbsr);
251 if (gbsr_err != k_ra8_ok) {
252 return gbsr_err;
253 }
254 g_ra8_eth_anlpar = anlpar;
255 g_ra8_eth_gbsr = gbsr;
256 internal_pick_negotiated_speed(anlpar, gbsr, out_speed, out_duplex);
257 g_ra8_eth_resync_speed_lsc = (uint32_t)*out_speed;
258 g_ra8_eth_resync_duplex = (uint32_t)*out_duplex;
259 return k_ra8_ok;
260}
261
287static ra8_err_t
289{
290 const ra8_etha_port_t etha_port = (port == k_ra8_rmac_port_0)
294 if (err != k_ra8_ok) {
295 return err;
296 }
298 if (err != k_ra8_ok) {
299 return err;
300 }
301 /* HUM Table 29.11: MPIC.PIS tracks link speed, not the external
302 * RGMII-ness -- GMII for 1 Gbps, MII for 10/100 Mbps. The ESWM
303 * MIICR1.MIISEL field (programmed once by the board) is what
304 * actually selects external RGMII. */
306 if (speed == k_ra8_rmac_lsc_1000mbit) {
308 }
309 const ra8_err_t set_err = ra8_rmac_set_link(port, pis, speed, duplex);
310 const ra8_err_t dis_err = ra8_etha_set_mode(etha_port, k_ra8_etha_opc_disable);
311 const ra8_err_t op_err = ra8_etha_set_mode(etha_port, k_ra8_etha_opc_operation);
312 if (set_err != k_ra8_ok) {
313 return set_err;
314 }
315 if (dis_err != k_ra8_ok) {
316 return dis_err;
317 }
318 return op_err;
319}
320
348{
349 (void)bmcr;
353 const ra8_err_t q_err = internal_query_negotiated_speed(port, &speed, &duplex);
354 if (q_err != k_ra8_ok) {
355 return q_err;
356 }
357 const ra8_err_t mpic_err = internal_program_mpic(port, speed, duplex);
358 if (mpic_err != k_ra8_ok) {
359 return mpic_err;
360 }
362 ra8_log_info(s_tag, "link_status: MPIC resynced to PHY speed/duplex");
363 return k_ra8_ok;
364}
365
396static ra8_err_t
397internal_phy_read_link(ra8_rmac_port_t port, ra8_eth_link_t* out_status, uint16_t* out_bmcr)
398{
399 uint16_t bmsr = 0U;
400 /* HUM Ch 33.4.1.1 "MPSM : PHY Station Management Register" p 1707 */
401 const ra8_err_t bmsr_err = ra8_rmac_mdio_c22_read(port,
403 (uint8_t)k_ra8_eth_phy_reg_bmsr,
404 &bmsr);
405 RA8_RETURN_ON_ERROR(bmsr_err, s_tag, "link_status: bmsr read");
406
407 uint16_t bmcr = 0U;
408 /* HUM Ch 33.4.1.1 "MPSM : PHY Station Management Register" p 1707 */
409 const ra8_err_t bmcr_err = ra8_rmac_mdio_c22_read(port,
411 (uint8_t)k_ra8_eth_phy_reg_bmcr,
412 &bmcr);
413 RA8_RETURN_ON_ERROR(bmcr_err, s_tag, "link_status: bmcr read");
414
415 out_status->bmsr = bmsr;
416 out_status->link_up = ((bmsr & k_ra8_eth_phy_bmsr_link_up) != 0U) ? 1U : 0U;
417 out_status->full_duplex = ((bmcr & k_ra8_eth_phy_bmcr_duplex) != 0U) ? 1U : 0U;
418 if ((bmcr & k_ra8_eth_phy_bmcr_speed100) != 0U) {
420 } else {
422 }
423 *out_bmcr = bmcr;
424 return k_ra8_ok;
425}
426
428{
429 RA8_CHECK_NULL_PTR(out_status, s_tag, "link_status: out must not be nullptr");
430 if (s_eth_state.opened == 0U) {
432 }
433
435 uint16_t bmcr = 0U;
436 const ra8_err_t err = internal_phy_read_link(port, out_status, &bmcr);
437 RA8_RETURN_ON_ERROR(err, s_tag, "link_status: phy read");
438
439 /* HUM Ch 33.4.1.2 "MPIC : PHY Interfaces Configuration Register"
440 * p 1707: on first link-up after open, realign MPIC.LSC with the
441 * PHY's negotiated speed. Sequential ifs (no compound boolean
442 * operators) so each gate remains MC/DC-clean without a paired
443 * test vector matrix. */
444 if (out_status->link_up == 0U) {
445 return k_ra8_ok;
446 }
448 return k_ra8_ok;
449 }
450 return internal_resync_mac_speed(port, bmcr);
451}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_initialized
Module not initialized – _init() not yet called successfully.
Definition ra8_err.h:235
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
ra8_rmac_port_t priv_ra8_eth_channel_to_port(uint8_t channel)
Map a logical channel index to an RMAC port identifier.
Definition ra8_eth.c:347
ra8_eth_state_t s_eth_state
Singleton NIC runtime state.
Definition ra8_eth.c:277
bool g_eth_mac_speed_resynced
Latch – true once ra8_eth_link_status has re-programmed MPIC.LSC / MPIC.PIPP to match the PHY's negot...
Definition ra8_eth.c:294
Ethernet Switch Module (ESWM) + frame TX/RX driver.
Cross-TU shared surface for the ra8_eth driver split.
volatile uint16_t g_ra8_eth_phy_bmsr_after_wait
BMSR snapshot AFTER the auto-neg wait.
@ k_ra8_eth_phy_bmsr_link_up
BMSR.LINK_STATUS bit 2.
@ k_ra8_eth_phy_bmcr_duplex
BMCR.DUPLEX_MODE bit 8.
@ k_ra8_eth_phy_anlpar_10h
ANLPAR bit 5: 10BASE-T.
@ k_ra8_eth_phy_addr_default
EK-RA8D2 PHY MDC address.
@ k_ra8_eth_phy_gbsr_1000h
GBSR bit 10: 1000BASE-T HD.
@ k_ra8_eth_phy_speed_100
100 Mbps.
@ k_ra8_eth_phy_reg_anlpar
ANLPAR (10/100 link partner).
@ k_ra8_eth_phy_bmcr_speed100
BMCR.SPEED_SELECT bit 13.
@ k_ra8_eth_phy_reg_bmcr
BMCR (basic mode control).
@ k_ra8_eth_phy_gbsr_1000f
GBSR bit 11: 1000BASE-T FD.
@ k_ra8_eth_phy_reg_gbsr
GBSR (1G link-partner ability).
@ k_ra8_eth_phy_reg_bmsr
BMSR (basic mode status).
@ k_ra8_eth_phy_speed_10
10 Mbps.
@ k_ra8_eth_phy_anlpar_10f
ANLPAR bit 6: 10BASE-T FD.
@ k_ra8_eth_phy_anlpar_100f
ANLPAR bit 8: 100BASE-TX FD.
@ k_ra8_eth_phy_anlpar_100h
ANLPAR bit 7: 100BASE-TX.
@ k_ra8_eth_phy_bmsr_an_done
BMSR.AUTONEG_COMPLETE bit 5.
Per-port Ethernet Agent (ETHA) driver – HUM Ch 32 (p 1627-1702).
ra8_err_t ra8_etha_set_mode(ra8_etha_port_t port, ra8_etha_opc_t mode)
Issue an explicit EAMC mode-change command.
Definition ra8_etha.c:494
ra8_etha_port_t
ETHA port index (m = 0, 1).
@ k_ra8_etha_port_0
ETHA port 0 (base 0x403C_A000).
@ k_ra8_etha_port_1
ETHA port 1 (base 0x403C_C000).
@ k_ra8_etha_opc_operation
Enter OPERATION mode.
@ k_ra8_etha_opc_config
Enter CONFIG mode.
@ k_ra8_etha_opc_disable
Enter DISABLE mode.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
Per-port Ethernet MAC (RMAC) driver – HUM Ch 33.
ra8_err_t ra8_rmac_set_link(ra8_rmac_port_t port, ra8_rmac_pis_t iface, ra8_rmac_lsc_t speed, ra8_rmac_duplex_t duplex)
Configure the link layer (interface, speed, duplex) atomically.
Definition ra8_rmac.c:782
ra8_err_t ra8_rmac_mdio_c22_read(ra8_rmac_port_t port, uint8_t phy_addr, uint8_t reg_addr, uint16_t *out_value)
Trigger an MDIO Clause-22 register read on the off-chip PHY.
Definition ra8_rmac.c:811
ra8_rmac_pis_t
Physical interface selector for MPIC.PIS[2:0].
@ k_ra8_rmac_pis_mii
MII (000b) – internal xMII for 10/100 Mbps.
@ k_ra8_rmac_pis_gmii
GMII (010b) – internal xMII for 1 Gbps.
ra8_rmac_lsc_t
Link-speed selector for MPIC.LSC[5:3] (HUM Ch 33.4).
@ k_ra8_rmac_lsc_1000mbit
1 Gbit/s.
@ k_ra8_rmac_lsc_100mbit
100 Mbit/s.
@ k_ra8_rmac_lsc_10mbit
10 Mbit/s.
ra8_rmac_port_t
RMAC port index (m = 0, 1).
@ k_ra8_rmac_port_0
RMAC port 0 (base 0x403C_B000).
ra8_rmac_duplex_t
Duplex selection (programmed via MPIC.PIPP / MPIC.PIP).
@ k_ra8_rmac_duplex_full
Full duplex.
@ k_ra8_rmac_duplex_half
Half duplex.
SysTick-based tick counter, delay and timestamp helpers.
void ra8_delay_ms(uint32_t ms)
Busy-wait for at least ms milliseconds.
Definition ra8_time.c:129