|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Clock Generation Circuit driver – Ethernet-switch (ESWCLK) path. More...
#include <stdint.h>#include "ra8_attributes.h"#include "ra8_cgc.h"#include "ra8_cgc_internal.h"#include "ra8_cgc_regs.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_hw_err.h"#include "ra8_log.h"#include "ra8_mstp.h"#include "ra8_register_protection.h"#include "ra8_system_regs.h"#include "ra8_time_constants.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_cgc_eswckdivcr_t : uint8_t { k_ra8_eswckdivcr_div1 = 0U , k_ra8_eswckdivcr_div2 = 1U , k_ra8_eswckdivcr_div4 = 2U , k_ra8_eswckdivcr_div8 = 3U , k_ra8_eswckdivcr_div16 = 4U , k_ra8_eswckdivcr_div32 = 5U , k_ra8_eswckdivcr_div64 = 6U } |
| enum | ra8_cgc_eswclk_const_t : uint32_t { k_ra8_cgc_eswclk_target_hz = 250000000UL , k_ra8_cgc_eswphyclk_target_hz = 500000000UL , k_ra8_cgc_eswclk_poll_limit = 200000U } |
| Constants used by the ESWCLK bring-up path. More... | |
Functions | |
| static ra8_err_t | internal_wait_cksrdy (volatile const uint8_t *ckcr_reg, uint8_t expected) |
| Spin-wait for a peripheral clock control register's CKSRDY bit to match expected. | |
| static ra8_err_t | internal_switch_eswcr_to_pll1p (volatile uint8_t *ckcr_reg, volatile uint8_t *divcr_reg, uint8_t div_code) |
| Switch one ESW-family peripheral clock to PLL1P with the given divider code. | |
| static ra8_err_t | internal_wait_pdctreswm_clear (uint8_t bit) |
| Wait for a PDCTRESWM status bit to clear within a bounded budget. | |
| static ra8_err_t | internal_eswclk_power_on_domain (void) |
| Power on the ESWM peripheral domain via PDCTRESWM. | |
| static ra8_err_t | internal_eswclk_program_cks (void) |
| Switch ESWCLK + ESWPHYCLK to PLL1P (250 MHz + 500 MHz). | |
| ra8_err_t | ra8_cgc_eswclk_init (void) |
| Bring up the Ethernet Switch Module (ESWM / RMAC) clock. | |
| ra8_err_t | ra8_cgc_eswclk_hz (uint32_t *out_hz) |
| Query the current ESWCLK (Ethernet Switch clock) frequency. | |
Variables | |
| static const char * | s_tag = "CGC" |
| static uint32_t | s_eswclk_hz = 0U |
| Live ESWCLK frequency, published by ra8_cgc_eswclk_init. | |
Clock Generation Circuit driver – Ethernet-switch (ESWCLK) path.
Split out of ra8_cgc.c. Powers on the ESWM peripheral domain and routes the Ethernet-switch clocks off PLL1P:
Drives the canonical FSP bsp_peripheral_clock_set SREQ/SRDY handshake on ESWCKCR then ESWPCKCR. HOCO must be running before the handshake (the SREQ -> SRDY synchronizer crosses into the CURRENT source domain, which is HOCO at reset); this file reuses priv_ra8_cgc_ensure_hoco_running_for_usb_ck defined in ra8_cgc_usb.c. Every protected-register write is wrapped in RA8_PROTECTED_WRITE so the PRCR re-lock always happens.
Definition in file ra8_cgc_eswclk.c.
| enum ra8_cgc_eswckdivcr_t : uint8_t |
Definition at line 45 of file ra8_cgc_eswclk.c.
| enum ra8_cgc_eswclk_const_t : uint32_t |
Constants used by the ESWCLK bring-up path.
ESWCKDIVCR.CKDIV is a 4-bit field. Code 0 = /1, code 1 = /2, ... code 6 = /64 (the FSP encoding table). 125 MHz = PLL1P (1 GHz) / 8; the matching code is k_ra8_eswckdivcr_div8 (= 3 in the standard FSP "log2 ratio" map).
| Enumerator | |
|---|---|
| k_ra8_cgc_eswclk_target_hz | ESWCLK = PLL1P / 4. |
| k_ra8_cgc_eswphyclk_target_hz | ESWPHYCLK = PLL1P / 2. |
| k_ra8_cgc_eswclk_poll_limit | CKSRDY spin budget. |
Definition at line 65 of file ra8_cgc_eswclk.c.
|
static |
Power on the ESWM peripheral domain via PDCTRESWM.
After power-on reset the ESWM domain is gated – every per-port RMAC / ETHA register read returns 0 and writes are silently dropped until PDCTRESWM.PDDE = 0. PRCR group 1 (LPC + battery backup) protects this register. Mirrors FSP r_layer3_switch_module_start.
| k_ra8_err_hw_timeout | PDCSF or PDPGSF stuck high after PDDE=0. |
Definition at line 233 of file ra8_cgc_eswclk.c.
References internal_wait_pdctreswm_clear(), k_ra8_ok, k_ra8_pdctr_bit_pdcsf, k_ra8_pdctr_bit_pdde, k_ra8_pdctr_bit_pdpgsf, k_ra8_prcr_unlock_lpm, RA8_INTERNAL, ra8_log_error, RA8_PROTECTED_WRITE, ra8_sys_pdctreswm(), and s_tag.
Referenced by ra8_cgc_eswclk_init().
|
static |
Switch ESWCLK + ESWPHYCLK to PLL1P (250 MHz + 500 MHz).
Drives the canonical FSP SREQ/SRDY handshake on ESWCKCR (CKSEL=PLL1P, CKDIV=/4 -> 250 MHz) then ESWPCKCR (CKSEL=PLL1P, CKDIV=/2 -> 500 MHz). Matches the EK-RA8D2 FSP example project ethernet_ek_ra8d2_ep.
| k_ra8_err_hw_timeout | CKSRDY transition stuck on either reg. |
Definition at line 280 of file ra8_cgc_eswclk.c.
References internal_switch_eswcr_to_pll1p(), k_ra8_eswckdivcr_div2, k_ra8_eswckdivcr_div4, k_ra8_ok, k_ra8_prcr_unlock_cgc, RA8_INTERNAL, ra8_log_error, RA8_PROTECTED_WRITE, ra8_sys_eswckcr(), ra8_sys_eswckdivcr(), ra8_sys_eswpckcr(), ra8_sys_eswpckdivcr(), and s_tag.
Referenced by ra8_cgc_eswclk_init().
|
static |
Switch one ESW-family peripheral clock to PLL1P with the given divider code.
Both ESWCKCR (ESWM core clock) and ESWPCKCR (Ethernet-PHY interface clock) share the same SREQ/SRDY handshake protocol – the canonical FSP bsp_peripheral_clock_set sequence. Factoring this helper keeps ra8_cgc_eswclk_init short and lets the same logic configure both clocks without duplicating six MMIO writes per peripheral.
| [in] | ckcr_reg | Pointer to the 8-bit CKCR (source-select) reg. |
| [in] | divcr_reg | Pointer to the 8-bit CKDIVCR (divider) reg. |
| [in] | div_code | Divider code from ra8_cgc_eswckdivcr_t. |
| k_ra8_ok | Clock switched. |
| k_ra8_err_hw_timeout | CKSRDY handshake exhausted spin budget. |
Definition at line 157 of file ra8_cgc_eswclk.c.
References internal_wait_cksrdy(), k_ra8_eswckcr_bit_srdy, k_ra8_eswckcr_bit_sreq, k_ra8_eswckcr_mask_sel, k_ra8_eswcksel_pll1p, k_ra8_ok, and RA8_INTERNAL.
Referenced by internal_eswclk_program_cks().
|
static |
Spin-wait for a peripheral clock control register's CKSRDY bit to match expected.
Both ESWCKCR and ESWPCKCR share the same CKSRDY layout (bit 7), so one helper drains the SREQ/SRDY handshake for both peripherals.
| [in] | ckcr_reg | Pointer to the 8-bit peripheral clock control reg (ESWCKCR or ESWPCKCR; both have an identical CKSRDY layout at bit k_ra8_eswckcr_bit_srdy). |
| [in] | expected | 0 or 1. |
| k_ra8_ok | CKSRDY observed at the expected level. |
| k_ra8_err_hw_timeout | Poll budget exhausted. |
Definition at line 113 of file ra8_cgc_eswclk.c.
References k_ra8_cgc_eswclk_poll_limit, k_ra8_eswckcr_bit_srdy, ra8_hw_wait_flag_clear8(), ra8_hw_wait_flag_set8(), and RA8_INTERNAL.
Referenced by internal_switch_eswcr_to_pll1p().
|
static |
Wait for a PDCTRESWM status bit to clear within a bounded budget.
Polls PDCTRESWM at the requested bit position until it reads 0 or the spin budget is exhausted. Used during the ESWM power-domain power-on sequence to confirm PDCSF / PDPGSF have settled.
| [in] | bit | Bit position (PDCSF or PDPGSF) to poll. |
| k_ra8_ok | Polled bit observed at 0. |
| k_ra8_err_hw_timeout | Poll budget exhausted with bit still 1. |
Definition at line 205 of file ra8_cgc_eswclk.c.
References k_ra8_cgc_eswclk_poll_limit, ra8_hw_wait_flag_clear8(), RA8_INTERNAL, and ra8_sys_pdctreswm().
Referenced by internal_eswclk_power_on_domain().
|
nodiscard |
Query the current ESWCLK (Ethernet Switch clock) frequency.
Computed from the most recent ra8_cgc_eswclk_init call. Returns 0 if the ESWCLK has not been configured. Used by ra8_rmac_init (callers fill ra8_rmac_config_t.eswclk_hz from this value) to compute the MPIC.PSMCS divider code.
| [out] | out_hz | On success, the live ESWCLK frequency in Hz. |
| k_ra8_ok | ESWCLK frequency written to *out_hz. |
| k_ra8_err_null_ptr | out_hz is nullptr. |
Definition at line 336 of file ra8_cgc_eswclk.c.
References k_ra8_err_null_ptr, k_ra8_ok, and s_eswclk_hz.
Referenced by gptp_arm(), priv_ra8_board_eth_eswm_bring_up(), and tsn_arm_time_base().
|
nodiscard |
Bring up the Ethernet Switch Module (ESWM / RMAC) clock.
On RA8D2 the RMAC PHY-station-management hardware (MPSM/MPIC) is fed by ESWCLK, a dedicated peripheral clock with its own source- select (ESWCKCR) and divider (ESWCKDIVCR) registers. After power-on reset ESWCKCR reads as 0 (ESWCKSEL = HOCO ~20 MHz) which is fine for MDC but the source-select handshake (CKSREQ -> CKSRDY) must still be exercised for the divider write to take effect. Symptom on a chip where this routine has not run: ra8_rmac_mdio_c22_read returns k_ra8_err_hw_timeout for every PHY address even though the wire is physically connected and the PHY is out of reset.
Sequence per FSP bsp_peripheral_clock_set and the HUM Ch 9 "Clock selection switching procedure":
This implementation picks PLL1P / 8 = 125 MHz as the ESWCLK source, matching what every FSP example for the EK-RA8D2 ships with. The resulting 125 MHz fans out to:
The same eswclk_hz value is what the caller passes via ra8_rmac_config_t::eswclk_hz so internal_calc_psmcs can compute the right MPIC.PSMCS divider code.
| k_ra8_ok | ESWCLK selected and running. |
| k_ra8_err_hw_timeout | CKSRDY handshake never completed. |
Definition at line 303 of file ra8_cgc_eswclk.c.
References internal_eswclk_power_on_domain(), internal_eswclk_program_cks(), k_ra8_cgc_eswclk_target_hz, k_ra8_mstp_ethphyclk, k_ra8_ok, priv_ra8_cgc_ensure_hoco_running_for_usb_ck(), ra8_log_error, ra8_log_info, ra8_mstp_enable(), s_eswclk_hz, and s_tag.
Referenced by ehb_run_once(), gptp_setup_or_halt(), priv_ra8_board_eth_eswm_bring_up(), and tsn_setup_or_halt().
|
static |
Live ESWCLK frequency, published by ra8_cgc_eswclk_init.
Set to k_ra8_cgc_eswclk_target_hz on a successful bring-up; remains 0 until then. Callers query the value via ra8_cgc_eswclk_hz so ra8_rmac_init can fill ra8_rmac_config_t.eswclk_hz without the application having to know the PLL configuration.
Definition at line 84 of file ra8_cgc_eswclk.c.
Referenced by ra8_cgc_eswclk_hz(), and ra8_cgc_eswclk_init().
|
static |
Definition at line 43 of file ra8_cgc_eswclk.c.