ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rmac_phy.c
Go to the documentation of this file.
1
17
18#include "ra8_rmac_phy.h"
19
20#include <stdint.h>
21
22#include "ra8_attributes.h"
23#include "ra8_check.h"
24#include "ra8_err.h"
25#include "ra8_log.h"
27
44bool priv_ra8_rmac_phy_internal_speed_ok(ra8_err_t err, uint16_t reg_value, uint16_t mask)
45{
46 return (err == k_ra8_ok) && ((reg_value & mask) != 0U);
47}
48
49static const char* s_tag = "RMPHY";
50
60
74
84
86
113{
114 RA8_CHECK_NULL_PTR(cfg, s_tag, "cfg must not be nullptr");
115 RA8_CHECK_NULL_PTR(cfg->io.read, s_tag, "io.read required");
116 RA8_CHECK_NULL_PTR(cfg->io.write, s_tag, "io.write required");
119 }
120 if ((uint8_t)cfg->lsi_type >= k_ra8_rmac_phy_lsi_count) {
122 }
123 return k_ra8_ok;
124}
125
149static ra8_err_t internal_reset_and_wait(uint16_t poll_max)
150{
151 ra8_err_t err = s_state.io.write(s_state.io.ctx,
152 s_state.phy_address,
155 if (err != k_ra8_ok) {
156 return err;
157 }
158 for (uint16_t i = 0U; i < poll_max; ++i) {
159 uint16_t reg = 0U;
160 err = s_state.io.read(s_state.io.ctx, s_state.phy_address, k_ra8_rmac_phy_reg_control, &reg);
161 if (err != k_ra8_ok) {
162 return err;
163 }
164 if ((reg & k_ra8_rmac_phy_bmcr_reset) == 0U) {
165 return k_ra8_ok;
166 }
167 }
169}
170
193{
194 ra8_err_t err = s_state.io.write(s_state.io.ctx,
195 s_state.phy_address,
197 s_state.local_advertise);
198 if (err != k_ra8_ok) {
199 return err;
200 }
201 if (s_state.gbit_advertise != 0U) {
202 err = s_state.io.write(s_state.io.ctx,
203 s_state.phy_address,
205 s_state.gbit_advertise);
206 if (err != k_ra8_ok) {
207 return err;
208 }
209 }
210 return k_ra8_ok;
211}
212
252{
253 const ra8_err_t varg = internal_open_validate(cfg);
254 if (varg != k_ra8_ok) {
255 return varg;
256 }
257 if (s_state.opened) {
258 return k_ra8_err_exists;
259 }
260 s_state.opened = true;
261 s_state.phy_address = cfg->phy_address;
262 s_state.lsi_type = cfg->lsi_type;
263 s_state.local_advertise = cfg->local_advertise;
264 s_state.gbit_advertise = cfg->gbit_advertise;
265 s_state.io = cfg->io;
266 s_state.last_bmsr = 0U;
267
268 const uint16_t poll_max =
270 ra8_err_t err = internal_reset_and_wait(poll_max);
271 if (err != k_ra8_ok) {
272 s_state.opened = false;
273 return err;
274 }
275
277 if (err != k_ra8_ok) {
278 s_state.opened = false;
279 return err;
280 }
281 ra8_log_info_val(s_tag, "rmac phy lsi", (uint32_t)cfg->lsi_type);
282 return k_ra8_ok;
283}
284
308{
309 if (!s_state.opened) {
311 }
312 s_state.opened = false;
313 return k_ra8_ok;
314}
315
342ra8_err_t ra8_rmac_phy_mdio_read(uint8_t reg_addr, uint16_t* out_data)
343{
344 RA8_CHECK_NULL_PTR(out_data, s_tag, "out_data must not be nullptr");
345 if (!s_state.opened) {
347 }
348 if (reg_addr > k_ra8_rmac_phy_reg_max) {
350 }
351 return s_state.io.read(s_state.io.ctx, s_state.phy_address, reg_addr, out_data);
352}
353
379ra8_err_t ra8_rmac_phy_mdio_write(uint8_t reg_addr, uint16_t data)
380{
381 if (!s_state.opened) {
383 }
384 if (reg_addr > k_ra8_rmac_phy_reg_max) {
386 }
387 return s_state.io.write(s_state.io.ctx, s_state.phy_address, reg_addr, data);
388}
389
412{
413 if (!s_state.opened) {
415 }
416 const uint16_t bmcr = (uint16_t)(k_ra8_rmac_phy_bmcr_an_enable | k_ra8_rmac_phy_bmcr_an_restart);
417 return s_state.io.write(s_state.io.ctx, s_state.phy_address, k_ra8_rmac_phy_reg_control, bmcr);
418}
419
443{
444 ra8_err_t err = k_ra8_ok;
445 /* 1000T status first; if no gbit, fall back to LPA. */
446 if (s_state.gbit_advertise != 0U) {
447 uint16_t msr = 0U;
448 err =
449 s_state.io.read(s_state.io.ctx, s_state.phy_address, k_ra8_rmac_phy_reg_1000t_status, &msr);
452 return;
453 }
456 return;
457 }
458 }
459 uint16_t lpa = 0U;
460 err = s_state.io.read(s_state.io.ctx, s_state.phy_address, k_ra8_rmac_phy_reg_an_partner, &lpa);
461 if (err == k_ra8_ok) {
462 out->partner_ability = lpa;
463 if ((lpa & k_ra8_rmac_phy_lpa_100full) != 0U) {
465 } else if ((lpa & k_ra8_rmac_phy_lpa_100half) != 0U) {
467 } else if ((lpa & k_ra8_rmac_phy_lpa_10full) != 0U) {
469 } else if ((lpa & k_ra8_rmac_phy_lpa_10half) != 0U) {
471 }
472 }
473}
474
501{
502 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
503 if (!s_state.opened) {
505 }
506 uint16_t bmsr = 0U;
507 ra8_err_t err =
508 s_state.io.read(s_state.io.ctx, s_state.phy_address, k_ra8_rmac_phy_reg_status, &bmsr);
509 if (err != k_ra8_ok) {
510 return err;
511 }
512 s_state.last_bmsr = bmsr;
513 out->bmsr = bmsr;
514 out->link_up = (uint8_t)(((bmsr & k_ra8_rmac_phy_bmsr_link_up) != 0U) ? 1U : 0U);
515 out->auto_neg_done = (uint8_t)(((bmsr & k_ra8_rmac_phy_bmsr_an_complete) != 0U) ? 1U : 0U);
517 out->partner_ability = 0U;
518
519 if ((out->link_up != 0U) && (out->auto_neg_done != 0U)) {
521 }
522 return k_ra8_ok;
523}
524
549{
550 RA8_CHECK_NULL_PTR(out, s_tag, "out must not be nullptr");
551 if (!s_state.opened) {
553 }
554 *out = s_state.lsi_type;
555 return k_ra8_ok;
556}
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_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_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_exists
Item already exists – cannot create again.
Definition ra8_err.h:216
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ 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
static ra8_err_t internal_reset_and_wait(void)
Issue BMCR.RESET to the PHY and poll until it self-clears.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info_val(tag, message, value)
RA8 log info val.
Definition ra8_log.h:366
static uint32_t s_state
@ k_ra8_rmac_phy_bmsr_link_up
BMSR bit 2.
@ k_ra8_rmac_phy_bmcr_an_enable
BMCR bit 12.
@ k_ra8_rmac_phy_bmcr_an_restart
BMCR bit 9.
@ k_ra8_rmac_phy_bmcr_reset
BMCR bit 15.
ra8_err_t ra8_rmac_phy_mdio_read(uint8_t reg_addr, uint16_t *out_data)
Read a 16-bit Clause-22 PHY register.
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_close(void)
Close the PHY driver and forget all cached state.
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.
static ra8_err_t internal_program_advertise(void)
Program the auto-negotiation advertisement registers.
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.
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_lsi_get(ra8_rmac_phy_lsi_t *out)
Return the LSI tag the caller passed to ra8_rmac_phy_open.
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.
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_rmac_phy_bits_t
@ k_ra8_rmac_phy_bmsr_an_complete
RA8 rmac PHY bmsr an complete.
@ k_ra8_rmac_phy_msr_1000full
RA8 rmac PHY msr 1000full.
@ k_ra8_rmac_phy_lpa_10full
RA8 rmac PHY lpa 10full.
@ 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_10half
RA8 rmac PHY lpa 10half.
@ k_ra8_rmac_phy_msr_1000half
RA8 rmac PHY msr 1000half.
ra8_rmac_phy_reg_t
@ k_ra8_rmac_phy_reg_status
RA8 rmac PHY register status.
@ k_ra8_rmac_phy_reset_poll_max
RA8 rmac PHY reset poll maximum.
@ k_ra8_rmac_phy_reg_an_advert
RA8 rmac PHY register an advert.
@ k_ra8_rmac_phy_reg_control
RA8 rmac PHY register control.
@ k_ra8_rmac_phy_reg_1000t_ctrl
RA8 rmac PHY register 1000t control.
@ k_ra8_rmac_phy_reg_an_partner
RA8 rmac PHY register an partner.
@ k_ra8_rmac_phy_reg_1000t_status
RA8 rmac PHY register 1000t status.
ra8_err_t ra8_rmac_phy_auto_negotiate_start(void)
Restart auto-negotiation by writing BMCR.
Reduced-MAC (RMAC) PHY driver – off-chip PHY for the GMAC-FPI.
@ k_ra8_rmac_phy_speed_no_link
RA8 rmac PHY speed no link.
@ k_ra8_rmac_phy_speed_100f
RA8 rmac PHY speed 100f.
@ k_ra8_rmac_phy_speed_10h
RA8 rmac PHY speed 10h.
@ k_ra8_rmac_phy_speed_1000f
RA8 rmac PHY speed 1000f.
@ k_ra8_rmac_phy_speed_10f
RA8 rmac PHY speed 10f.
@ k_ra8_rmac_phy_speed_100h
RA8 rmac PHY speed 100h.
@ k_ra8_rmac_phy_speed_1000h
RA8 rmac PHY speed 1000h.
@ k_ra8_rmac_phy_addr_max
RA8 rmac PHY address maximum.
@ k_ra8_rmac_phy_reg_max
RA8 rmac PHY register maximum.
ra8_rmac_phy_lsi_t
Supported PHY-LSI identifiers.
@ k_ra8_rmac_phy_lsi_count
RA8 rmac PHY lsi count.
Test-access surface for ra8_rmac_phy internal helpers (MC/DC).
Configuration descriptor.
uint16_t local_advertise
Clause-22 reg 4 advertised.
uint16_t reset_poll_max
Reset poll maximum.
ra8_rmac_phy_lsi_t lsi_type
Lsi type.
uint16_t gbit_advertise
Clause-22 reg 9 (1000T).
uint8_t phy_address
PHY address.
ra8_rmac_phy_io_t io
Io.
uint16_t local_advertise
Local advertise.
ra8_rmac_phy_io_t io
Io.
uint16_t gbit_advertise
Gbit advertise.
uint16_t last_bmsr
Last bmsr.
uint8_t phy_address
PHY address.
ra8_rmac_phy_lsi_t lsi_type
Lsi type.
Pluggable MDIO bus.
ra8_err_t(* write)(void *ctx, uint8_t phy_addr, uint8_t reg_addr, uint16_t data)
Write.
ra8_err_t(* read)(void *ctx, uint8_t phy_addr, uint8_t reg_addr, uint16_t *out_data)
Read.