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

Ethernet Generic PTP Timer driver implementation. More...

#include "ra8_eth_gptp.h"
#include <stdint.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_ether_regs.h"
#include "ra8_log.h"
#include "ra8_mstp.h"
#include "ra8_mstp_regs.h"
Include dependency graph for ra8_eth_gptp.c:

Go to the source code of this file.

Enumerations

enum  gptp_field_t : uint32_t {
  k_gptp_subns_shift = 27UL ,
  k_gptp_round_half = 2UL ,
  k_gptp_mask_nsec = 0x3FFFFFFFUL ,
  k_gptp_mask_sec_u = 0x0000FFFFUL ,
  k_gptp_shift_sec_u = 32UL
}
 Bit widths, shifts and masks of the GPTP timer registers. More...

Functions

static volatile r_gptp_timer_regs_tinternal_timer (ra8_gptp_timer_idx_t timer)
 Point at one timer unit's register block.
static void internal_stop (ra8_gptp_timer_idx_t timer)
 Stop one timer unit without validating its index.
static void internal_stop_all (void)
 Stop every timer unit in the block.
static void internal_write_offset (ra8_gptp_timer_idx_t timer, uint64_t sec, uint32_t nsec)
 Write the 78-bit offset of one timer unit in the mandated order.
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_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_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.

Variables

static const char * s_tag = "ETHGPT"
 Log tag for this driver.
static bool s_gptp_configured = false
 True once ra8_eth_gptp_init has programmed the block.

Detailed Description

Ethernet Generic PTP Timer driver implementation.

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

Implements the timer surface of HUM Ch 35 "Ethernet Generic PTP Timer (GPTP)" p 1925-1964. Every register touched here appears in HUM Table 35.3 p 1926 and carries the citation of its own subsection, not the chapter-opening page.

Definition in file ra8_eth_gptp.c.

Enumeration Type Documentation

◆ gptp_field_t

enum gptp_field_t : uint32_t

Bit widths, shifts and masks of the GPTP timer registers.

PTPTIVCt.TIV is 5.27 fixed point (HUM 35.3.2.3 p 1928): the top five bits are whole nanoseconds and the low 27 are the sub-nanosecond part, so the sub-nanosecond scale is 2^27. The GPTP time is 78 bits with the nanosecond part in bits [29:0] and the seconds split 32 + 16 across the M and U registers (HUM 35.3.3.3 to 35.3.3.5 p 1931-1932).

Invariant
k_gptp_mask_nsec covers exactly 30 bits and k_gptp_mask_sec_u exactly 16.
Example:
const uint32_t nsec = reg->PTPGPTPTML & (uint32_t)k_gptp_mask_nsec;
@ k_gptp_mask_nsec
Mask for GPTPL / TOVL [29:0].
See also
ra8_eth_gptp_get_time
Enumerator
k_gptp_subns_shift 

5.27 fixed-point scale of TIV.

k_gptp_round_half 

Round-to-nearest divisor for TIV.

k_gptp_mask_nsec 

Mask for GPTPL / TOVL [29:0].

k_gptp_mask_sec_u 

Mask for GPTPU / TOVU [15:0].

k_gptp_shift_sec_u 

Seconds upper part starts at 2^32.

Definition at line 82 of file ra8_eth_gptp.c.

Function Documentation

◆ internal_stop()

void internal_stop ( ra8_gptp_timer_idx_t timer)
static

Stop one timer unit without validating its index.

Writes PTPTMDC.TDq, which clears PTPTMEC.TEq in hardware.

Parameters
[in]timerTimer index, already validated by the caller.
Precondition
timer is below k_ra8_gptp_timer_count.
The ESWM module-stop gate is released.
Postcondition
PTPTMEC.TE[timer] reads 0.
The unit's counters read 0.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 128 of file ra8_eth_gptp.c.

References r_gptp_regs_t::PTPTMDC, and ra8_gptp().

Referenced by internal_stop_all(), ra8_eth_gptp_deinit(), ra8_eth_gptp_init(), and ra8_eth_gptp_timer_disable().

◆ internal_stop_all()

void internal_stop_all ( void )
static

Stop every timer unit in the block.

Loops k_ra8_gptp_timer_count times over internal_stop.

Precondition
The ESWM module-stop gate is released.
No consumer is mid-read of either unit.
Postcondition
PTPTMEC.TE reads 0 for every unit.
Every unit's counters read 0.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 146 of file ra8_eth_gptp.c.

References internal_stop(), and k_ra8_gptp_timer_count.

Referenced by ra8_eth_gptp_enter_stop().

◆ internal_timer()

volatile r_gptp_timer_regs_t * internal_timer ( ra8_gptp_timer_idx_t timer)
inlinestatic

Point at one timer unit's register block.

Resolves base + 0x0020 + 0x40 * timer through r_gptp_regs_t.

Parameters
[in]timerTimer index, already validated by the caller.
Returns
Volatile pointer to the timer's register block.
Return values
&ra8_gptp()->TIMER[timer]Always – timer is pre-validated by the caller, so the accessor has no failure path and never yields nullptr.
Precondition
timer is below k_ra8_gptp_timer_count.
ra8_eth_gptp_init has released the module-stop gate.
Postcondition
The returned pointer is never nullptr.
No register was read or written.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 108 of file ra8_eth_gptp.c.

References ra8_gptp(), and r_gptp_regs_t::TIMER.

Referenced by internal_write_offset(), ra8_eth_gptp_deinit(), ra8_eth_gptp_get_avtp_ns(), ra8_eth_gptp_get_increment(), ra8_eth_gptp_get_time(), ra8_eth_gptp_init(), and ra8_eth_gptp_set_increment().

◆ internal_write_offset()

void internal_write_offset ( ra8_gptp_timer_idx_t timer,
uint64_t sec,
uint32_t nsec )
static

Write the 78-bit offset of one timer unit in the mandated order.

PTPTOVCtU then PTPTOVCtM then PTPTOVCtL; the L write is what commits the offset (HUM 35.4.1.3.1 Figure 35.4 p 1944-1945).

Parameters
[in]timerTimer index, already validated by the caller.
[in]secSeconds part, already range-checked by the caller.
[in]nsecNanoseconds part, already range-checked by the caller.
Precondition
timer is below k_ra8_gptp_timer_count.
sec fits in 48 bits and nsec is below one second.
Postcondition
The three offset registers hold the requested value.
The unit's reported time reflects the new offset.
Note
Not thread-safe unless documented otherwise.
Since
0.1.0

Definition at line 171 of file ra8_eth_gptp.c.

References internal_timer(), k_gptp_mask_nsec, k_gptp_mask_sec_u, k_gptp_shift_sec_u, r_gptp_timer_regs_t::PTPTOVCL, r_gptp_timer_regs_t::PTPTOVCM, and r_gptp_timer_regs_t::PTPTOVCU.

Referenced by ra8_eth_gptp_deinit(), ra8_eth_gptp_init(), and ra8_eth_gptp_set_offset().

◆ ra8_eth_gptp_deinit()

ra8_err_t ra8_eth_gptp_deinit ( void )
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.

Returns
ra8_err_t Error code.
Return values
k_ra8_okTimers stopped and the gate re-asserted.
k_ra8_err_hw_timeoutThe module-stop assert did not settle.
k_ra8_err_invalid_stateThe ESWM module-stop refcount was already 0 (no matching ra8_eth_gptp_init).
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has run (otherwise the write faults).
No consumer is mid-read of the timer.
Postcondition
Both timer units are stopped with PTPTIVCt and the offset at 0.
The ESWM module-stop bit is set once this driver is the last holder of the shared, reference-counted ESWM gate – ra8_etha_init takes the same gate, so with ETHA up the clock stays on.
Note
Not thread-safe; caller must provide synchronisation.
See also
ra8_eth_gptp_init The matching bring-up call
Since
0.1.0

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.

◆ ra8_eth_gptp_enter_stop()

ra8_err_t ra8_eth_gptp_enter_stop ( void )
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.

Returns
ra8_err_t Error code.
Return values
k_ra8_okTimers stopped, gate asserted.
k_ra8_err_hw_timeoutThe module-stop assert did not settle.
k_ra8_err_invalid_stateThe ESWM module-stop refcount was already 0 (no matching ra8_eth_gptp_init).
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
No consumer is mid-read of either timer.
Postcondition
Both timer units are stopped, with their configuration retained.
The ESWM module-stop bit is set once this driver is the last holder of the shared, reference-counted ESWM gate – ra8_etha_init takes the same gate, so with ETHA up the clock stays on.
Note
Not thread-safe; caller must provide synchronisation.
See also
ra8_eth_gptp_exit_stop The matching resume call
Since
0.1.0

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.

◆ ra8_eth_gptp_exit_stop()

ra8_err_t ra8_eth_gptp_exit_stop ( void )
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.

Returns
ra8_err_t Error code.
Return values
k_ra8_okGate released.
k_ra8_err_hw_timeoutThe module-stop release did not settle.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_enter_stop asserted the gate.
The ESWCLK is running and stable.
Postcondition
The GPTP register window is addressable again (the ESWM gate is reference-counted, so it may already have been released by another holder such as ra8_etha_init).
Both timer units remain stopped.
Note
Not thread-safe; caller must provide synchronisation.
See also
ra8_eth_gptp_enter_stop The matching suspend call
Since
0.1.0

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.

◆ ra8_eth_gptp_get_avtp_ns()

ra8_err_t ra8_eth_gptp_get_avtp_ns ( ra8_gptp_timer_idx_t timer,
uint64_t * out_ns )
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
[out]out_nsReceives the 64-bit nanosecond count. Must not be nullptr.
Returns
ra8_err_t Error code.
Return values
k_ra8_okCounter copied out.
k_ra8_err_null_ptrout_ns == nullptr.
k_ra8_err_invalid_argtimer out of range.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
out_ns points at writable storage.
Postcondition
*out_ns describes one latched instant.
No GPTP state was mutated beyond the U latch.
Note
Not re-entrant: a concurrent reader would steal the U latch.
See also
ra8_eth_gptp_get_time The 78-bit view of the same counter
Since
0.1.0

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.

◆ ra8_eth_gptp_get_increment()

ra8_err_t ra8_eth_gptp_get_increment ( ra8_gptp_timer_idx_t timer,
uint32_t * out_tiv )
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
[out]out_tivReceives PTPTIVCt.TIV. Must not be nullptr.
Returns
ra8_err_t Error code.
Return values
k_ra8_okIncrement copied out.
k_ra8_err_null_ptrout_tiv == nullptr.
k_ra8_err_invalid_argtimer out of range.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
out_tiv points at writable storage.
Postcondition
*out_tiv holds the live register value on success.
No GPTP state was mutated.
Note
Performs one MMIO read; safe from any context.
See also
ra8_eth_gptp_set_increment Write the value this reports
Since
0.1.0

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.

◆ ra8_eth_gptp_get_time()

ra8_err_t ra8_eth_gptp_get_time ( ra8_gptp_timer_idx_t timer,
uint64_t * out_sec,
uint32_t * out_nsec )
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
[out]out_secReceives the 48-bit seconds part. Must not be nullptr.
[out]out_nsecReceives the 30-bit nanoseconds part. Must not be nullptr.
Returns
ra8_err_t Error code.
Return values
k_ra8_okTime copied out.
k_ra8_err_null_ptrEither output pointer is nullptr.
k_ra8_err_invalid_argtimer out of range.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
Both output pointers address writable storage.
Postcondition
*out_sec and *out_nsec describe one latched instant.
No GPTP state was mutated beyond the M/U latch.
Note
Not re-entrant: a concurrent reader would steal the M/U latch.
Example:
uint64_t sec = 0U;
uint32_t nsec = 0U;
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.
@ k_ra8_gptp_timer_0
Timer unit 0 (registers at +0x0020).
See also
ra8_eth_gptp_set_offset Move the reported time
Since
0.1.0

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().

◆ ra8_eth_gptp_init()

ra8_err_t ra8_eth_gptp_init ( const ra8_eth_gptp_cfg_t * cfg)
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.

Parameters
[in]cfgStatic configuration. Must not be nullptr; clk_hz must be greater than 31250000 (see ra8_eth_gptp_cfg_t).
Returns
ra8_err_t Error code.
Return values
k_ra8_okBlock powered, both timers programmed.
k_ra8_err_null_ptrcfg == nullptr.
k_ra8_err_invalid_argcfg->clk_hz == 0.
k_ra8_err_out_of_rangecfg->clk_hz too low for a 32-bit TIV.
k_ra8_err_hw_timeoutThe ESWM module-stop release did not settle.
Precondition
The ESWCLK is running and stable (HUM 11.2.8 note 6 p 447).
Single-threaded init context, or IRQs masked.
Postcondition
On success both timer units hold the derived PTPTIVCt.
On success both timer units are stopped and read time zero.
On success every other entry point in this driver is unlocked.
Note
Not thread-safe; caller must provide synchronisation.
Example:
const ra8_eth_gptp_cfg_t cfg = {.clk_hz = 125000000U};
(void)ra8_eth_gptp_init(&cfg);
ra8_err_t ra8_eth_gptp_init(const ra8_eth_gptp_cfg_t *cfg)
Power up the GPTP block and programme both timers' increment.
Static configuration for ra8_eth_gptp_init.
See also
ra8_eth_gptp_timer_enable Start a programmed timer
ra8_eth_gptp_deinit Reverse this call
Since
0.1.0

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().

◆ ra8_eth_gptp_ip_version()

ra8_err_t ra8_eth_gptp_ip_version ( uint32_t * out_version)
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.

Parameters
[out]out_versionReceives PTPIPV.IPV. Must not be nullptr.
Returns
ra8_err_t Error code.
Return values
k_ra8_okVersion word copied out.
k_ra8_err_null_ptrout_version == nullptr.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
out_version points at writable storage.
Postcondition
*out_version holds the register value on success.
No GPTP state was mutated (the register is read-only).
Note
Safe to call from any context; performs one MMIO read.
See also
ra8_eth_gptp_init Must run first
Since
0.1.0

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().

◆ ra8_eth_gptp_set_increment()

ra8_err_t ra8_eth_gptp_set_increment ( ra8_gptp_timer_idx_t timer,
uint32_t tiv )
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
[in]tivNanoseconds per clk in 5.27 fixed point.
Returns
ra8_err_t Error code.
Return values
k_ra8_okIncrement written.
k_ra8_err_invalid_argtimer out of range, or tiv == 0.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
tiv came from ra8_eth_gptp_tiv_from_hz or a servo around it.
Postcondition
PTPTIVCt holds tiv.
The counter rate changes from the next clk edge.
Note
Not thread-safe against another writer of the same timer.
See also
ra8_eth_gptp_get_increment Read the value back
Since
0.1.0

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.

◆ ra8_eth_gptp_set_offset()

ra8_err_t ra8_eth_gptp_set_offset ( ra8_gptp_timer_idx_t timer,
uint64_t sec,
uint32_t nsec )
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
[in]secSeconds part, at most k_ra8_gptp_sec_max.
[in]nsecNanoseconds part, at most k_ra8_gptp_nsec_max.
Returns
ra8_err_t Error code.
Return values
k_ra8_okOffset committed.
k_ra8_err_invalid_argtimer, sec or nsec out of range.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
The caller accepts a discontinuity in the reported time.
Postcondition
The three offset registers hold the requested value.
The next ra8_eth_gptp_get_time reflects the new offset.
Note
Not thread-safe; the three writes are not atomic against a reader.
Example:
(void)ra8_eth_gptp_set_offset(k_ra8_gptp_timer_0, 1000000000ULL, 0U);
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.
See also
ra8_eth_gptp_get_time Observe the effect
Since
0.1.0

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().

◆ ra8_eth_gptp_timer_disable()

ra8_err_t ra8_eth_gptp_timer_disable ( ra8_gptp_timer_idx_t timer)
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
Returns
ra8_err_t Error code.
Return values
k_ra8_okTimer disabled.
k_ra8_err_invalid_argtimer out of range.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
No consumer is mid-read of this unit.
Postcondition
PTPTMEC.TE[timer] reads 0.
The unit's counters read 0.
Note
Not thread-safe against ra8_eth_gptp_timer_enable.
See also
ra8_eth_gptp_timer_enable Start the unit again
Since
0.1.0

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.

◆ ra8_eth_gptp_timer_enable()

ra8_err_t ra8_eth_gptp_timer_enable ( ra8_gptp_timer_idx_t timer)
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
Returns
ra8_err_t Error code.
Return values
k_ra8_okTimer enabled.
k_ra8_err_invalid_argtimer out of range.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has programmed PTPTIVCt for this timer.
The ESWCLK is running.
Postcondition
PTPTMEC.TE[timer] reads 1.
The unit's free-running counter advances by TIV per clk.
Note
Not thread-safe against ra8_eth_gptp_timer_disable.
See also
ra8_eth_gptp_timer_disable Stop the unit again
Since
0.1.0

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().

◆ ra8_eth_gptp_timer_is_enabled()

ra8_err_t ra8_eth_gptp_timer_is_enabled ( ra8_gptp_timer_idx_t timer,
bool * out_enabled )
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.

Parameters
[in]timerTimer index, below k_ra8_gptp_timer_count.
[out]out_enabledReceives PTPTMEC.TE[timer]. Must not be nullptr.
Returns
ra8_err_t Error code.
Return values
k_ra8_okState copied out.
k_ra8_err_null_ptrout_enabled == nullptr.
k_ra8_err_invalid_argtimer out of range.
k_ra8_err_not_initializedra8_eth_gptp_init has not run.
Precondition
ra8_eth_gptp_init has released the module-stop gate.
out_enabled points at writable storage.
Postcondition
*out_enabled holds the live enable bit on success.
No GPTP state was mutated.
Note
Performs one MMIO read; safe from any context.
See also
ra8_eth_gptp_timer_enable Set the bit this reports
Since
0.1.0

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.

◆ ra8_eth_gptp_tiv_from_hz()

ra8_err_t ra8_eth_gptp_tiv_from_hz ( uint32_t clk_hz,
uint32_t * out_tiv )
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.

Parameters
[in]clk_hzclk frequency in Hz. Must be nonzero and above 31250000, below which TIV would not fit in 32 bits.
[out]out_tivReceives the computed increment. Must not be nullptr.
Returns
ra8_err_t Error code.
Return values
k_ra8_okIncrement computed.
k_ra8_err_null_ptrout_tiv == nullptr.
k_ra8_err_invalid_argclk_hz == 0.
k_ra8_err_out_of_rangeComputed TIV exceeds 32 bits.
Precondition
out_tiv points at writable storage.
clk_hz describes the live ESWCLK, not a nominal figure.
Postcondition
*out_tiv is unmodified unless k_ra8_ok is returned.
No hardware register was read or written.
Note
Pure and re-entrant.
Example:
uint32_t tiv = 0U;
(void)ra8_eth_gptp_tiv_from_hz(125000000U, &tiv); // tiv == 0x40000000
ra8_err_t ra8_eth_gptp_tiv_from_hz(uint32_t clk_hz, uint32_t *out_tiv)
Derive PTPTIVCt.TIV from a clk frequency.
See also
ra8_eth_gptp_set_increment Apply the value to a timer
Since
0.1.0

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().

Variable Documentation

◆ s_gptp_configured

bool s_gptp_configured = false
static

True once ra8_eth_gptp_init has programmed the block.

Every other entry point documents "``ra8_eth_gptp_init`` has released the module-stop gate" as a precondition, and violating it is not a benign mistake: the GPTP window is inside the ESWM domain, so a read or write with MSTPC30 still asserted takes a bus fault. This flag turns that prose precondition into an enforced one. It stays true across ra8_eth_gptp_enter_stop / ra8_eth_gptp_exit_stop, because a module stop is a clock gate rather than a reset and PTPTIVCt plus the 78-bit offset survive it; only ra8_eth_gptp_deinit clears it.

Note
Not thread-safe; single-threaded init context assumed.
Warning
Do not modify outside ra8_eth_gptp_init / ra8_eth_gptp_deinit.
Since
0.1.0

Definition at line 59 of file ra8_eth_gptp.c.

Referenced by ra8_eth_gptp_deinit(), ra8_eth_gptp_enter_stop(), ra8_eth_gptp_exit_stop(), ra8_eth_gptp_get_avtp_ns(), ra8_eth_gptp_get_increment(), ra8_eth_gptp_get_time(), ra8_eth_gptp_init(), ra8_eth_gptp_ip_version(), ra8_eth_gptp_set_increment(), ra8_eth_gptp_set_offset(), ra8_eth_gptp_timer_disable(), ra8_eth_gptp_timer_enable(), and ra8_eth_gptp_timer_is_enabled().

◆ s_tag

const char* s_tag = "ETHGPT"
static

Log tag for this driver.

Passed to every ra8_log_* and RA8_CHECK_* call below.

Note
Read-only after load; never reassigned.
Warning
Do not modify: the HIL log scrapers key on this exact string.
Since
0.1.0

Definition at line 39 of file ra8_eth_gptp.c.