|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Ethernet Generic PTP Timer (GPTP) driver – HUM Ch 35. More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_eth_gptp_cfg_t |
| Static configuration for ra8_eth_gptp_init. More... | |
Enumerations | |
| enum | ra8_eth_gptp_limit_t : uint32_t { k_ra8_gptp_ns_per_sec = 1000000000UL , k_ra8_gptp_nsec_max = 999999999UL } |
| Field limits taken from the HUM register descriptions. More... | |
| enum | ra8_eth_gptp_sec_limit_t : uint64_t { k_ra8_gptp_sec_max = 0xFFFFFFFFFFFFULL } |
| Upper bound of the GPTP seconds field. More... | |
Functions | |
| ra8_err_t | ra8_eth_gptp_init (const ra8_eth_gptp_cfg_t *cfg) |
| Power up the GPTP block and programme both timers' increment. | |
| ra8_err_t | ra8_eth_gptp_deinit (void) |
| Stop both timers, clear their configuration and gate the block off. | |
| ra8_err_t | ra8_eth_gptp_ip_version (uint32_t *out_version) |
| Read the read-only PTPIPV IP-version word. | |
| ra8_err_t | ra8_eth_gptp_tiv_from_hz (uint32_t clk_hz, uint32_t *out_tiv) |
| Derive PTPTIVCt.TIV from a clk frequency. | |
| ra8_err_t | ra8_eth_gptp_timer_enable (ra8_gptp_timer_idx_t timer) |
| Start one timer unit (PTPTMEC.TEq). | |
| ra8_err_t | ra8_eth_gptp_timer_disable (ra8_gptp_timer_idx_t timer) |
| Stop one timer unit (PTPTMDC.TDq). | |
| ra8_err_t | ra8_eth_gptp_timer_is_enabled (ra8_gptp_timer_idx_t timer, bool *out_enabled) |
| Report whether one timer unit is enabled. | |
| ra8_err_t | ra8_eth_gptp_set_increment (ra8_gptp_timer_idx_t timer, uint32_t tiv) |
| Write one timer unit's increment register PTPTIVCt. | |
| ra8_err_t | ra8_eth_gptp_get_increment (ra8_gptp_timer_idx_t timer, uint32_t *out_tiv) |
| Read one timer unit's increment register PTPTIVCt. | |
| ra8_err_t | ra8_eth_gptp_set_offset (ra8_gptp_timer_idx_t timer, uint64_t sec, uint32_t nsec) |
| Load one timer unit's additive 78-bit offset. | |
| ra8_err_t | ra8_eth_gptp_get_time (ra8_gptp_timer_idx_t timer, uint64_t *out_sec, uint32_t *out_nsec) |
| Read one timer unit's 78-bit GPTP time. | |
| ra8_err_t | ra8_eth_gptp_get_avtp_ns (ra8_gptp_timer_idx_t timer, uint64_t *out_ns) |
| Read one timer unit's 64-bit AVTP nanosecond counter. | |
| ra8_err_t | ra8_eth_gptp_enter_stop (void) |
| Stop both timers and assert the ESWM module-stop gate. | |
| ra8_err_t | ra8_eth_gptp_exit_stop (void) |
| Release the ESWM module-stop gate again. | |
Ethernet Generic PTP Timer (GPTP) driver – HUM Ch 35.
Drives the RA8D2 GPTP block described by HUM Ch 35 "Ethernet Generic PTP Timer (GPTP)" p 1925-1964. That block is a timer, and this driver exposes exactly what the timer does:
The media-clock capture / recovery, cyclic-compare and pulse-output-timer parts of the same register window need the MEDIA_IN / MEDIA_OUT / CYCLIC_COMP pins, which the EK-RA8D2 board layer does not route, so this driver does not address them.
Definition in file ra8_eth_gptp.h.
| enum ra8_eth_gptp_limit_t : uint32_t |
Field limits taken from the HUM register descriptions.
PTPTOVCtL.TOVL accepts only 0x0000_0000..0x3B9A_C9FF (HUM 35.3.2.4 p 1929), i.e. a nanosecond value strictly below one second, and PTPTIVCt.TIV is a 5.27 fixed-point nanoseconds-per-clk value (HUM 35.3.2.3 p 1928).
| Enumerator | |
|---|---|
| k_ra8_gptp_ns_per_sec | Nanoseconds in one second. |
| k_ra8_gptp_nsec_max | Largest legal PTPTOVCtL.TOVL. |
Definition at line 73 of file ra8_eth_gptp.h.
| enum ra8_eth_gptp_sec_limit_t : uint64_t |
Upper bound of the GPTP seconds field.
The GPTP time is 78 bits with the second part in GPTP[t][77:30] (HUM 35.1 Table 35.1 p 1925), so seconds are 48 bits wide: {PTPTOVCtU.TOVU[15:0], PTPTOVCtM.TOVM[31:0]}.
| Enumerator | |
|---|---|
| k_ra8_gptp_sec_max | Largest 48-bit seconds value. |
Definition at line 96 of file ra8_eth_gptp.h.
|
nodiscard |
Stop both timers, clear their configuration and gate the block off.
The full teardown: writes both PTPTMDC.TD bits, restores the reset value of PTPTIVCt and of the 78-bit offset for both units, then re-asserts the ESWM module stop. Use ra8_eth_gptp_enter_stop instead when the configuration should survive the power transition.
| k_ra8_ok | Timers stopped and the gate re-asserted. |
| k_ra8_err_hw_timeout | The module-stop assert did not settle. |
| k_ra8_err_invalid_state | The ESWM module-stop refcount was already 0 (no matching ra8_eth_gptp_init). |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 227 of file ra8_eth_gptp.c.
References internal_stop(), internal_timer(), internal_write_offset(), k_ra8_gptp_timer_count, k_ra8_mstp_eswm, r_gptp_timer_regs_t::PTPTIVC, ra8_mstp_disable(), RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Stop both timers and assert the ESWM module-stop gate.
The low-power entry path. Unlike ra8_eth_gptp_deinit this leaves PTPTIVCt and the 78-bit offset intact – a module stop is a clock gate, not a reset – so ra8_eth_gptp_exit_stop followed by ra8_eth_gptp_timer_enable resumes on the same configuration.
| k_ra8_ok | Timers stopped, gate asserted. |
| k_ra8_err_hw_timeout | The module-stop assert did not settle. |
| k_ra8_err_invalid_state | The ESWM module-stop refcount was already 0 (no matching ra8_eth_gptp_init). |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 372 of file ra8_eth_gptp.c.
References internal_stop_all(), k_ra8_mstp_eswm, ra8_mstp_disable(), RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Release the ESWM module-stop gate again.
Leaves both timers stopped and their configuration as ra8_eth_gptp_enter_stop left it; call ra8_eth_gptp_timer_enable to resume counting.
| k_ra8_ok | Gate released. |
| k_ra8_err_hw_timeout | The module-stop release did not settle. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 379 of file ra8_eth_gptp.c.
References k_ra8_mstp_eswm, ra8_mstp_enable(), RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Read one timer unit's 64-bit AVTP nanosecond counter.
Reads PTPAVTPTMtL first, which latches PTPAVTPTMtU (HUM 35.4.1.3.3 Figure 35.6 p 1945-1946). The AVTP view is the same clock as ra8_eth_gptp_get_time flattened to nanoseconds modulo 2^64 (HUM 35.5.1.2 p 1952) and is what an AVB talker stamps into presentation times.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| [out] | out_ns | Receives the 64-bit nanosecond count. Must not be nullptr. |
| k_ra8_ok | Counter copied out. |
| k_ra8_err_null_ptr | out_ns == nullptr. |
| k_ra8_err_invalid_arg | timer out of range. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 354 of file ra8_eth_gptp.c.
References internal_timer(), k_gptp_shift_sec_u, k_ra8_err_invalid_arg, k_ra8_gptp_timer_count, k_ra8_ok, r_gptp_timer_regs_t::PTPAVTPTML, r_gptp_timer_regs_t::PTPAVTPTMU, RA8_CHECK_NULL_PTR, RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Read one timer unit's increment register PTPTIVCt.
Reads back whatever ra8_eth_gptp_set_increment last wrote, or the value ra8_eth_gptp_init derived from clk_hz, in the 5.27 fixed-point encoding of HUM 35.3.2.3 p 1928. A software servo reads its current correction through this call before computing the next one.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| [out] | out_tiv | Receives PTPTIVCt.TIV. Must not be nullptr. |
| k_ra8_ok | Increment copied out. |
| k_ra8_err_null_ptr | out_tiv == nullptr. |
| k_ra8_err_invalid_arg | timer out of range. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 302 of file ra8_eth_gptp.c.
References internal_timer(), k_ra8_err_invalid_arg, k_ra8_gptp_timer_count, k_ra8_ok, r_gptp_timer_regs_t::PTPTIVC, RA8_CHECK_NULL_PTR, RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Read one timer unit's 78-bit GPTP time.
Reads PTPGPTPTMtL first: that read latches PTPGPTPTMtM and PTPGPTPTMtU, so the following two reads belong to the same instant (HUM 35.4.1.3.4 Figure 35.7 p 1946). While the unit is disabled every field reads 0 (HUM 35.3.2.1 p 1927), so a stopped timer is reported as time zero rather than as an error.
*out_nsec is masked to the register's 30 bits, which is wider than the one-second range the counter should ever hold. A value at or above 1e9 is therefore passed through rather than rejected: on a healthy block it cannot occur, and on a faulted one the caller is better served seeing the raw reading than a synthesised error.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| [out] | out_sec | Receives the 48-bit seconds part. Must not be nullptr. |
| [out] | out_nsec | Receives the 30-bit nanoseconds part. Must not be nullptr. |
| k_ra8_ok | Time copied out. |
| k_ra8_err_null_ptr | Either output pointer is nullptr. |
| k_ra8_err_invalid_arg | timer out of range. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 331 of file ra8_eth_gptp.c.
References internal_timer(), k_gptp_mask_nsec, k_gptp_mask_sec_u, k_gptp_shift_sec_u, k_ra8_err_invalid_arg, k_ra8_gptp_timer_count, k_ra8_ok, r_gptp_timer_regs_t::PTPGPTPTML, r_gptp_timer_regs_t::PTPGPTPTMM, r_gptp_timer_regs_t::PTPGPTPTMU, RA8_CHECK_NULL_PTR, RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
Referenced by gptp_measure(), and tsn_check_time_base().
|
nodiscard |
Power up the GPTP block and programme both timers' increment.
Releases the ESWM module-stop gate (the GPTP window is inside the Layer-3 Ethernet Switch domain, MSTPC30), then for each of the two timer units: stops it via PTPTMDC, writes the derived PTPTIVCt and clears the 78-bit offset. Timers are left stopped; call ra8_eth_gptp_timer_enable to start counting.
| [in] | cfg | Static configuration. Must not be nullptr; clk_hz must be greater than 31250000 (see ra8_eth_gptp_cfg_t). |
| k_ra8_ok | Block powered, both timers programmed. |
| k_ra8_err_null_ptr | cfg == nullptr. |
| k_ra8_err_invalid_arg | cfg->clk_hz == 0. |
| k_ra8_err_out_of_range | cfg->clk_hz too low for a 32-bit TIV. |
| k_ra8_err_hw_timeout | The ESWM module-stop release did not settle. |
Definition at line 202 of file ra8_eth_gptp.c.
References ra8_eth_gptp_cfg_t::clk_hz, internal_stop(), internal_timer(), internal_write_offset(), k_ra8_gptp_timer_count, k_ra8_mstp_eswm, k_ra8_ok, r_gptp_timer_regs_t::PTPTIVC, RA8_CHECK_NULL_PTR, ra8_eth_gptp_tiv_from_hz(), ra8_log_info, ra8_mstp_enable(), RA8_RETURN_ON_ERROR, s_gptp_configured, and s_tag.
Referenced by gptp_arm(), and tsn_arm_time_base().
|
nodiscard |
Read the read-only PTPIPV IP-version word.
PTPIPV (HUM 35.3.1.1 p 1927) is the only register in the GPTP window with a nonzero reset value, so a nonzero read is positive evidence that the aperture really is the GPTP block rather than a reserved region echoing back writes.
| [out] | out_version | Receives PTPIPV.IPV. Must not be nullptr. |
| k_ra8_ok | Version word copied out. |
| k_ra8_err_null_ptr | out_version == nullptr. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 242 of file ra8_eth_gptp.c.
References k_ra8_ok, r_gptp_regs_t::PTPIPV, RA8_CHECK_NULL_PTR, ra8_gptp(), RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
Referenced by gptp_probe_presence().
|
nodiscard |
Write one timer unit's increment register PTPTIVCt.
PTPTIVCt is writable at any time (HUM Table 35.4 p 1946-1947), which is how a software servo applies a frequency correction: nudging TIV away from ra8_eth_gptp_tiv_from_hz makes the counter run fast or slow.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| [in] | tiv | Nanoseconds per clk in 5.27 fixed point. |
| k_ra8_ok | Increment written. |
| k_ra8_err_invalid_arg | timer out of range, or tiv == 0. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 287 of file ra8_eth_gptp.c.
References internal_timer(), k_ra8_err_invalid_arg, k_ra8_gptp_timer_count, k_ra8_ok, r_gptp_timer_regs_t::PTPTIVC, RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Load one timer unit's additive 78-bit offset.
Writes PTPTOVCtU, then PTPTOVCtM, then PTPTOVCtL – the order is load-bearing, because writing the L register is what commits the whole offset to the timer (HUM 35.4.1.3.1 Figure 35.4 p 1944-1945). The reported time is offset + free-running counter (HUM 35.5.1.1 p 1951), so this is the coarse "step" half of a software clock servo.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| [in] | sec | Seconds part, at most k_ra8_gptp_sec_max. |
| [in] | nsec | Nanoseconds part, at most k_ra8_gptp_nsec_max. |
| k_ra8_ok | Offset committed. |
| k_ra8_err_invalid_arg | timer, sec or nsec out of range. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 315 of file ra8_eth_gptp.c.
References internal_write_offset(), k_ra8_err_invalid_arg, k_ra8_gptp_nsec_max, k_ra8_gptp_sec_max, k_ra8_gptp_timer_count, k_ra8_ok, RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
Referenced by gptp_arm().
|
nodiscard |
Stop one timer unit (PTPTMDC.TDq).
Per HUM 35.3.2.1 p 1927 a disabled unit's counters are fixed at 0, so a stop is also a clear.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| k_ra8_ok | Timer disabled. |
| k_ra8_err_invalid_arg | timer out of range. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 264 of file ra8_eth_gptp.c.
References internal_stop(), k_ra8_err_invalid_arg, k_ra8_gptp_timer_count, k_ra8_ok, RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Start one timer unit (PTPTMEC.TEq).
Writes 1 to PTPTMEC.TEq (HUM 35.3.2.1 p 1927). The register is write-1-to-set, so the sibling unit's enable bit is untouched. Counting resumes from the next clk edge at the unit's current PTPTIVCt, on top of whatever 78-bit offset ra8_eth_gptp_set_offset last committed.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| k_ra8_ok | Timer enabled. |
| k_ra8_err_invalid_arg | timer out of range. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 252 of file ra8_eth_gptp.c.
References k_ra8_err_invalid_arg, k_ra8_gptp_timer_count, k_ra8_ok, r_gptp_regs_t::PTPTMEC, ra8_gptp(), RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
Referenced by gptp_arm(), and tsn_arm_time_base().
|
nodiscard |
Report whether one timer unit is enabled.
Reads PTPTMEC once and extracts bit timer (HUM 35.3.2.1 p 1927). PTPTMDC is write-only and reads as 0, so PTPTMEC is the single authority on whether a unit is running: a unit stopped through PTPTMDC reads back 0 here.
| [in] | timer | Timer index, below k_ra8_gptp_timer_count. |
| [out] | out_enabled | Receives PTPTMEC.TE[timer]. Must not be nullptr. |
| k_ra8_ok | State copied out. |
| k_ra8_err_null_ptr | out_enabled == nullptr. |
| k_ra8_err_invalid_arg | timer out of range. |
| k_ra8_err_not_initialized | ra8_eth_gptp_init has not run. |
Definition at line 274 of file ra8_eth_gptp.c.
References k_ra8_err_invalid_arg, k_ra8_gptp_timer_count, k_ra8_ok, r_gptp_regs_t::PTPTMEC, RA8_CHECK_NULL_PTR, ra8_gptp(), RA8_VALIDATE_INIT, s_gptp_configured, and s_tag.
|
nodiscard |
Derive PTPTIVCt.TIV from a clk frequency.
TIV is the nanoseconds-per-clk increment in 5.27 fixed point: TIV[31:27] is the whole-nanosecond part and TIV[26:0] the sub-nanosecond part (HUM 35.3.2.3 p 1928), so TIV = round(1e9 * 2^27 / clk_hz). The HUM's worked examples (0xA000_0000 / 0x5000_0000 / 0x2800_0000 / 0x2000_0000 for 50 / 100 / 200 / 250 MHz) fall out of that expression exactly.
This is a pure function – it touches no hardware – so an application can sanity-check its clock tree before powering the block on.
| [in] | clk_hz | clk frequency in Hz. Must be nonzero and above 31250000, below which TIV would not fit in 32 bits. |
| [out] | out_tiv | Receives the computed increment. Must not be nullptr. |
| k_ra8_ok | Increment computed. |
| k_ra8_err_null_ptr | out_tiv == nullptr. |
| k_ra8_err_invalid_arg | clk_hz == 0. |
| k_ra8_err_out_of_range | Computed TIV exceeds 32 bits. |
Definition at line 185 of file ra8_eth_gptp.c.
References k_gptp_round_half, k_gptp_subns_shift, k_ra8_err_invalid_arg, k_ra8_err_out_of_range, k_ra8_gptp_ns_per_sec, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by ra8_eth_gptp_init().