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

Clock Generation Circuit driver – PLL2 + USB-FS / USB-HS clocks. 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_mstp_regs.h"
#include "ra8_register_protection.h"
#include "ra8_system_regs.h"
#include "ra8_time_constants.h"
Include dependency graph for ra8_cgc_usb.c:

Go to the source code of this file.

Enumerations

enum  ra8_usbfs_clock_local_t : uint32_t {
  k_ra8_usbfs_srdy_poll_limit = 200000U ,
  k_ra8_usbfs_div5_code = 6U ,
  k_ra8_usbfs_div8_code = 4U
}
 Local sentinels for the USBCKSRDY handshake and divider codes. More...
enum  ra8_usbfs_mstp_local_t : uint32_t { k_ra8_mstpb11_usbfs_mask = (uint32_t)(1UL << 11) }
 Local sentinels for the USBFS module-stop pre-step. More...
enum  ra8_pll2_local_t : uint16_t {
  k_ra8_pll2_max_quarters = 3U ,
  k_ra8_pll2_usbfs_mul = 80U ,
  k_ra8_pll2_usbfs_quarters = 0U
}
 Local constants for the PLL2 bring-up path. More...
enum  ra8_usbhs_clock_local_t : uint32_t {
  k_ra8_usbhs_srdy_poll_limit = 200000U ,
  k_ra8_usbhs_div4_code = 2U
}
 Local sentinels for the USB60CKCR SREQ/SRDY handshake. More...
enum  ra8_usbhs_mstp_local_t : uint32_t { k_ra8_mstpb12_usbhs_mask = (uint32_t)(1UL << 12) }
 Local sentinels for the USBHS module-stop pre-step. More...

Functions

static ra8_err_t internal_wait_usbcksrdy (uint8_t expected)
 Spin until USBCKCR.USBCKSRDY matches the expected value.
static ra8_err_t internal_pll2_program_protected (uint32_t pll2ccr, uint16_t pll2ccr2)
 PRCR-protected stop+program+restart body of ra8_cgc_pll2_enable.
ra8_err_t ra8_cgc_pll2_enable (uint8_t mul_int, uint8_t mul_quarters, ra8_plodiv_t p_div_code)
 Implementation of ra8_cgc_pll2_enable().
static ra8_err_t internal_usbckcr_switch_to_pll2p_div5 (void)
 PRCR-protected USBCKCR / USBCKDIVCR handshake body.
ra8_err_t ra8_cgc_usbfs_clock_enable (void)
 Bring up the 48 MHz USB-FS clock from PLL2P / 5.
static ra8_err_t internal_wait_usb60cksrdy (uint8_t expected)
 Spin until USB60CKCR.USB60CKSRDY matches the expected value.
static ra8_err_t internal_usb60ckcr_switch_to_pll2p_div4 (void)
 PRCR-protected USB60CKCR / USB60CKDIVCR handshake body.
ra8_err_t priv_ra8_cgc_ensure_hoco_running_for_usb_ck (void)
 Ensure HOCO is running so a USBCKCR/USB60CKCR/ESWCKCR SREQ->SRDY handshake can drain.
ra8_err_t ra8_cgc_usbhs_pll_enable (void)
 Bring up the USBHS PHY 60 MHz reference clock + module clock path.

Variables

static const char * s_tag = "CGC"
static volatile uint8_t s_usb60ckcr_probe = 0U
 Last value read back from R_SYSTEM->USB60CKCR at the end of internal_usb60ckcr_switch_to_pll2p_div4.
static volatile uint8_t s_pll2_status_probe = 0U
 Last value read back from R_SYSTEM->OSCSF at the end of internal_usb60ckcr_switch_to_pll2p_div4.

Detailed Description

Clock Generation Circuit driver – PLL2 + USB-FS / USB-HS clocks.

Split out of ra8_cgc.c. Brings up PLL2 (960 MHz VCO, PLL2P = 240 MHz on the EK-RA8D2 24 MHz crystal) and routes the two USB controller clocks off it:

  • USB-FS: USBCKCR sources PLL2P / 5 = 48.000 MHz (0 ppm vs the USB-FS 48 MHz +/- 0.25 % spec).
  • USB-HS: USB60CKCR sources PLL2P / 4 = 60.000 MHz, the named operating clock for the USBHS module (HUM Ch 37.3.3 "Supplying the Clock").

Every protected-register write is wrapped in RA8_PROTECTED_WRITE so the PRCR re-lock always happens, even on early-return paths. The bounded OSCSF poll helpers and the shared PLL-multiplier scale factor live in ra8_cgc_internal.h; priv_ra8_cgc_ensure_hoco_running_for_usb_ck is defined here and reused by ra8_cgc_eswclk.c.

Tag ring/world:
Ring 1 (HAL), World S (secure-callable). Same ring/world as the parent ra8_cgc.c.
Since
0.1.0

Definition in file ra8_cgc_usb.c.

Enumeration Type Documentation

◆ ra8_pll2_local_t

enum ra8_pll2_local_t : uint16_t

Local constants for the PLL2 bring-up path.

The EK-RA8D2 board fits a 24 MHz crystal (per the schematic and the existing PLL1 setup). For USB-FS we want a /5 divider downstream so PLL2P needs to be 240 MHz, which means a 960 MHz VCO (the silicon minimum). PL2IDIV = /2 -> 12 MHz pre-scale. PLL2MUL = 80 (integer) with PLL2MULNF = 0 (no quarter steps) -> 12 * 80 = 960 MHz. PL2ODIVP = /4 -> 240 MHz at PLL2P. USBCKDIVCR = /5 -> 48 MHz exactly.

Spec compliance: USBCKCR source 240 MHz * (1/5) = 48.000 MHz (0 ppm error vs the USB-FS spec target of 48 MHz +/- 2500 ppm = +/- 0.25 %). PASS.

Enumerator
k_ra8_pll2_max_quarters 

Max value of PLL2MULNF[7:6].

k_ra8_pll2_usbfs_mul 

Integer multiplier for PLL2 USBFS path.

k_ra8_pll2_usbfs_quarters 

Fractional quarter-steps (none).

Definition at line 144 of file ra8_cgc_usb.c.

◆ ra8_usbfs_clock_local_t

enum ra8_usbfs_clock_local_t : uint32_t

Local sentinels for the USBCKSRDY handshake and divider codes.

USBCKDIVCR uses a non-linear code-to-ratio map (FSP bsp_clocks.c): /1=0, /2=1, /3=5, /4=2, /5=6, /6=3, /8=4, /10=7, /16=8. We expose only the divisors this driver actually uses.

Enumerator
k_ra8_usbfs_srdy_poll_limit 

Iterations before timeout.

k_ra8_usbfs_div5_code 

USBCKDIVCR codepoint for /5.

k_ra8_usbfs_div8_code 

USBCKDIVCR codepoint for /8.

Definition at line 94 of file ra8_cgc_usb.c.

◆ ra8_usbfs_mstp_local_t

enum ra8_usbfs_mstp_local_t : uint32_t

Local sentinels for the USBFS module-stop pre-step.

HUM Ch 9 – the entire xCKCR / xCKDIVCR family ("Clock Selection Switching Procedure") requires the dependent module to be in the module-stop state (MSTP = 1) BEFORE asserting xCKSREQ when changing the divider from 1/n where n != 1. Since this routine programmes USBCKDIVCR from reset (1/1) to /5, that precondition applies. Pages 367 (ADCCKDIVCR), 370 (SPICKCR), 373 (GPTCKDIVCR), 378 (ETHPCKDIVCR), and 381 (ESWPCKCR) all give the same instruction. If the caller has already released MSTPB11 (USBFS) before us the SREQ -> SRDY handshake silently hangs – the symptom we observed on real silicon was USBCKCR == 0x40 (SREQ=1, SRDY=0) and the host never seeing the device. Force the module-stop bit back to 1 inside the PRCR window so the routine is robust to call ordering.

Enumerator
k_ra8_mstpb11_usbfs_mask 

MSTPCRB.MSTPB11 (USBFS0).

Definition at line 124 of file ra8_cgc_usb.c.

◆ ra8_usbhs_clock_local_t

enum ra8_usbhs_clock_local_t : uint32_t

Local sentinels for the USB60CKCR SREQ/SRDY handshake.

USB60CKCR shares the bit layout of USBCKCR (HUM Ch 9; CMSIS R7KA8D2KF_core0.hR_SYSTEM->USB60CKCR_b mirrors USBCKCR_b with USB60CKSEL[3:0], USB60CKSREQ@bit6, USB60CKSRDY@bit7). USB60CKDIVCR uses the same non-linear codepoint map as USBCKDIVCR (FSP bsp_clocks.c): /1=0, /2=1, /3=5, /4=2, /5=6, /6=3, /8=4, /10=7, /16=8. For the EK-RA8D2 USBHS PHY we land 60.000 MHz on USB60CLK from PLL2P (240 MHz) / 4 = 60.000 MHz, matching the HUM Ch 37.3.3 "Supplying the Clock" requirement: "A 60-MHz clock must be supplied ... USB60CLK is the operating clock for the USBHS module" (HUM p 2102, line 85433). The PHY then internally divides USB60CLK to derive its USBMCLK reference; the PHYSET CLKSEL[1:0] field selects the after-division frequency (12 / 20 / 24 / 48 MHz; HUM Ch 37.2.17 PHYSET, p 2080). The earlier "USB60CLK = 48 MHz, CLKSEL=48" configuration violated the named-rate contract on the register and made macOS issue ~43 USB resets without RHST ever advancing past 000 (chirp limbo). PLL2 is configured at 960 MHz VCO with PL2ODIVP=/4 -> PLL2P=240 MHz, the same setup the FS path uses (see ra8_cgc_usbfs_clock_enable).

Codepoint table from HUM Ch 9 USB60CKDIVCR (matches USBCKDIVCR): /1=0, /2=1, /3=5, /4=2, /5=6, /6=3, /8=4, /10=7, /16=8.

Enumerator
k_ra8_usbhs_srdy_poll_limit 

Iterations before timeout.

k_ra8_usbhs_div4_code 

USB60CKDIVCR codepoint /4.

Definition at line 451 of file ra8_cgc_usb.c.

◆ ra8_usbhs_mstp_local_t

enum ra8_usbhs_mstp_local_t : uint32_t

Local sentinels for the USBHS module-stop pre-step.

Mirrors the FS path's MSTPB11 pre-step. HUM Ch 9 "Clock Selection Switching Procedure" requires the dependent module to be in module- stop state (MSTP=1) BEFORE asserting SREQ when changing the divider from 1/n with n!=1. We programme USB60CKDIVCR from reset (1/1) to /4, so this precondition applies. If the caller has already released MSTPB12 (USBHS) the SREQ->SRDY handshake silently hangs.

Enumerator
k_ra8_mstpb12_usbhs_mask 

MSTPCRB.MSTPB12 (USBHS).

Definition at line 468 of file ra8_cgc_usb.c.

Function Documentation

◆ internal_pll2_program_protected()

ra8_err_t internal_pll2_program_protected ( uint32_t pll2ccr,
uint16_t pll2ccr2 )
static

PRCR-protected stop+program+restart body of ra8_cgc_pll2_enable.

See implementation; mirrors internal_cgc_init_protected.

Parameters
[in]pll2ccrPre-computed PLL2CCR value.
[in]pll2ccr2Pre-computed PLL2CCR2 value.
Returns
ra8_err_t error code.
Return values
k_ra8_okPLL2 stopped, re-programmed, and re-locked.
k_ra8_err_hw_timeoutPLL2SF stop or lock wait exceeded.
Precondition
Caller is single-threaded init context; CPU not sourced from PLL2.
PLL2 was previously stopped (OSCSF.PLL2SF=0 expected on entry).
Postcondition
On k_ra8_ok PLL2 is locked at the new mul / divider.
PRCR re-locked unconditionally (RA8_PROTECTED_WRITE invariant).
Note
Not thread-safe.
Since
0.1.0

Definition at line 192 of file ra8_cgc_usb.c.

References k_ra8_ok, k_ra8_oscsf_bit_pll2sf, k_ra8_pll2cr_run, k_ra8_pll2cr_stop, k_ra8_prcr_unlock_cgc, priv_ra8_cgc_wait_oscsf_clear(), priv_ra8_cgc_wait_oscsf_set(), RA8_INTERNAL, ra8_log_error, RA8_PROTECTED_WRITE, ra8_sys_pll2ccr(), ra8_sys_pll2ccr2(), ra8_sys_pll2cr(), and s_tag.

Referenced by ra8_cgc_pll2_enable().

◆ internal_usb60ckcr_switch_to_pll2p_div4()

ra8_err_t internal_usb60ckcr_switch_to_pll2p_div4 ( void )
static

PRCR-protected USB60CKCR / USB60CKDIVCR handshake body.

Mirror of internal_usbckcr_switch_to_pll2p_div5 for the USBHS 60 MHz path: SREQ=1, wait SRDY=1, write USB60CKDIVCR=/4, write USB60CKCR=src|SREQ, write USB60CKCR=src, wait SRDY=0. HUM Ch 9 "Clock Generation Circuit", USB60CKCR description (USBHS 60 MHz source select). FSP bsp_clocks.c ::bsp_peripheral_clock_set is the canonical reference for the SREQ/SRDY ordering.

Returns
ra8_err_t error code.
Return values
k_ra8_okUSBHS 60 MHz clock running on PLL2P/4.
k_ra8_err_hw_timeoutSRDY=1 or SRDY=0 wait exceeded.
Precondition
PLL2 locked at 240 MHz on PLL2P.
MSTPCRB.MSTPB12 = 1 (USBHS module-stopped).
Postcondition
On k_ra8_ok USB60CKCR.USB60CKSEL = PLL2P, USB60CKDIVCR = /4.
PRCR re-locked (RA8_PROTECTED_WRITE always re-locks).
Note
Not thread-safe; init context only.
Since
0.1.0

Definition at line 517 of file ra8_cgc_usb.c.

References internal_wait_usb60cksrdy(), k_ra8_ok, k_ra8_prcr_unlock_cgc, k_ra8_usbckcr_bit_srdy, k_ra8_usbckcr_bit_sreq, k_ra8_usbckcr_mask_sel, k_ra8_usbcksel_pll2p, k_ra8_usbhs_div4_code, RA8_INTERNAL, ra8_log_error, RA8_PROTECTED_WRITE, ra8_sys_oscsf(), ra8_sys_usb60ckcr(), ra8_sys_usb60ckdivcr(), s_pll2_status_probe, s_tag, and s_usb60ckcr_probe.

Referenced by ra8_cgc_usbhs_pll_enable().

◆ internal_usbckcr_switch_to_pll2p_div5()

ra8_err_t internal_usbckcr_switch_to_pll2p_div5 ( void )
static

PRCR-protected USBCKCR / USBCKDIVCR handshake body.

Steps 3..7 of the HUM "Clock selection switching procedure" inside the CGC-PRCR window: SREQ=1, wait SRDY=1, write USBCKDIVCR, write USBCKCR=src|SREQ, write USBCKCR=src, wait SRDY=0.

Returns
ra8_err_t error code.
Return values
k_ra8_okHandshake completed; USBCLK on PLL2P/5 = 48 MHz.
k_ra8_err_hw_timeoutSRDY=1 or SRDY=0 wait exceeded.
Precondition
PLL2 locked at 240 MHz on PLL2P.
MSTPCRB.MSTPB11 = 1 (USBFS module-stopped).
Postcondition
On k_ra8_ok USBCKCR.USBCKSEL = PLL2P, USBCKDIVCR = /5.
PRCR re-locked (RA8_PROTECTED_WRITE always re-locks).
Note
Not thread-safe; init context only.
Since
0.1.0

Definition at line 314 of file ra8_cgc_usb.c.

References internal_wait_usbcksrdy(), k_ra8_ok, k_ra8_prcr_unlock_cgc, k_ra8_usbckcr_bit_sreq, k_ra8_usbckcr_mask_sel, k_ra8_usbcksel_pll2p, k_ra8_usbfs_div5_code, RA8_INTERNAL, ra8_log_error, RA8_PROTECTED_WRITE, ra8_sys_usbckcr(), ra8_sys_usbckdivcr(), and s_tag.

Referenced by ra8_cgc_usbfs_clock_enable().

◆ internal_wait_usb60cksrdy()

ra8_err_t internal_wait_usb60cksrdy ( uint8_t expected)
static

Spin until USB60CKCR.USB60CKSRDY matches the expected value.

See implementation.

Parameters
[in]expectedExpected value for USB60CKSRDY (0 or 1).
Returns
Result code.
Return values
k_ra8_okUSB60CKSRDY reached the expected level.
k_ra8_err_hw_timeoutPolling exceeded the iteration cap.
Precondition
PRCR-CGC must be unlocked at call site.
Caller is in single-threaded init context.
Postcondition
No mutation; readback only.
Iteration count is bounded.
Note
Not thread-safe.
Since
0.1.0

Definition at line 486 of file ra8_cgc_usb.c.

References k_ra8_usbckcr_bit_srdy, k_ra8_usbhs_srdy_poll_limit, ra8_hw_wait_flag_clear8(), ra8_hw_wait_flag_set8(), RA8_INTERNAL, and ra8_sys_usb60ckcr().

Referenced by internal_usb60ckcr_switch_to_pll2p_div4().

◆ internal_wait_usbcksrdy()

ra8_err_t internal_wait_usbcksrdy ( uint8_t expected)
static

Spin until USBCKCR.USBCKSRDY matches the expected value.

See implementation.

Parameters
[in]expectedExpected value for USBCKSRDY (0 or 1).
Returns
Result code.
Return values
k_ra8_okUSBCKSRDY reached the expected level.
k_ra8_err_hw_timeoutPolling exceeded the iteration cap.
Precondition
PRCR-CGC must be unlocked at call site.
Caller is in single-threaded init context.
Postcondition
No mutation; readback only.
Iteration count is bounded.
Note
Not thread-safe.
Since
0.1.0

Definition at line 164 of file ra8_cgc_usb.c.

References k_ra8_usbckcr_bit_srdy, k_ra8_usbfs_srdy_poll_limit, ra8_hw_wait_flag_clear8(), ra8_hw_wait_flag_set8(), RA8_INTERNAL, and ra8_sys_usbckcr().

Referenced by internal_usbckcr_switch_to_pll2p_div5().

◆ priv_ra8_cgc_ensure_hoco_running_for_usb_ck()

ra8_err_t priv_ra8_cgc_ensure_hoco_running_for_usb_ck ( void )

Ensure HOCO is running so a USBCKCR/USB60CKCR/ESWCKCR SREQ->SRDY handshake can drain.

USBCKCR / USB60CKCR / ESWCKCR all share HOCO as their reset-default source. The SREQ -> SRDY synchronizer chain crosses from ICLK into the CURRENT clock source's domain (HOCO at boot). If HOCO is stopped (HCSTP = 1) the handshake never completes. ra8_cgc_init leaves HOCO stopped because it switches SCKSCR to PLL1, so this helper restarts HOCO under a PRCR-CGC unlock window (HOCOCR IS PRCR-protected; writes outside the window are silently dropped) and then waits OSCSF.HOCOSF outside the PRCR window (read-only). Defined in ra8_cgc_usb.c and reused by ra8_cgc_eswclk.c.

Returns
ra8_err_t error code.
Return values
k_ra8_okHOCO running, OSCSF.HOCOSF asserted.
k_ra8_err_hw_timeoutHOCOSF never asserted.
Precondition
Caller is single-threaded init context.
PRCR is currently locked (helper takes its own window).
Postcondition
On k_ra8_ok HOCO is running.
PRCR is re-locked.
Note
Not thread-safe.
Since
0.1.0

Definition at line 564 of file ra8_cgc_usb.c.

References k_ra8_hococr_hcstp, k_ra8_oscsf_bit_hocosf, k_ra8_prcr_unlock_cgc, priv_ra8_cgc_wait_oscsf_set(), RA8_PROTECTED_WRITE, and ra8_sys_hococr().

Referenced by ra8_cgc_eswclk_init(), and ra8_cgc_usbhs_pll_enable().

◆ ra8_cgc_pll2_enable()

ra8_err_t ra8_cgc_pll2_enable ( uint8_t mul_int,
uint8_t mul_quarters,
ra8_plodiv_t p_div_code )
nodiscard

Implementation of ra8_cgc_pll2_enable().

Bring up PLL2 with caller-supplied multiplier and P divider.

Idempotent: if OSCSF.PLL2SF is already asserted on entry the function returns k_ra8_ok without touching PLL2CCR / PLL2CCR2 / PLL2CR. This lets the FS and HS USB bring-up paths (which both want the same 960 MHz VCO with PLL2P = /4 = 240 MHz) coexist on the same boot without re-programming a live PLL2 (HUM Ch 9 forbids writing PLL2CCR while PLL2 is running, and downstream consumers – including USBCKCR sourced from PLL2P after the FS path runs – would lose their clock during the re-program).

Stops PLL2 (with bounded poll on OSCSF.PLL2SF clear), programmes PLL2CCR + PLL2CCR2, then starts PLL2 (bounded poll on OSCSF.PLL2SF set). Input divider is hard-wired to /2 and source to main XTAL because that is the only configuration the EK-RA8D2 (24 MHz crystal) needs today; broaden the API once a second board lands.

Parameters
[in]mul_intInteger multiplier (1..255).
[in]mul_quartersQuarter-step fractional multiplier (0..3).
[in]p_div_codera8_plodiv_t code for the P output divider.
Returns
Result code.
Return values
k_ra8_okPLL2 locked.
k_ra8_err_invalid_argmul_int is 0 or mul_quarters > 3.
k_ra8_err_hw_timeoutPLL2SF stop or start handshake timed out.
Precondition
ra8_cgc_init has been called and main XTAL is stable.
Single-threaded init context; CPU not sourced from PLL2.
Postcondition
On k_ra8_ok: PLL2 is locked at the requested multiplier and output divider; PRCR is re-locked.
On any error path the PRCR window is closed by RA8_PROTECTED_WRITE.
Note
Not thread-safe.
Since
0.1.0

Definition at line 258 of file ra8_cgc_usb.c.

References internal_pll2_program_protected(), k_ra8_cgc_quarters_per_unit, k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_oscsf_bit_pll2sf, k_ra8_plidiv_div2, k_ra8_pll2_max_quarters, k_ra8_pll2ccr_mask_plidiv, k_ra8_pll2ccr_mask_quarters, k_ra8_pllccr2_shift_plodivp, k_ra8_pllccr2_shift_plodivq, k_ra8_pllccr2_shift_plodivr, k_ra8_pllccr_shift_plsrcsel, k_ra8_pllccr_shift_quarters, k_ra8_plodiv_div6, k_ra8_plsrcsel_main, ra8_log_info, ra8_log_info_val, ra8_sys_oscsf(), and s_tag.

Referenced by ra8_cgc_usbfs_clock_enable(), ra8_cgc_usbhs_pll_enable(), and ra8_nsc_cgc_pll2_enable().

◆ ra8_cgc_usbfs_clock_enable()

ra8_err_t ra8_cgc_usbfs_clock_enable ( void )
nodiscard

Bring up the 48 MHz USB-FS clock from PLL2P / 5.

Bring up the USB-FS module clock (USBCKCR / USBCKDIVCR).

  1. Enable PLL2 at 960 MHz VCO with PLL2P = /4 = 240 MHz.
  2. Force MSTPB11 = 1 (USBFS module-stop) before reprogramming USBCKDIVCR per HUM Ch 9 "Clock selection switching procedure".
  3. Run the SREQ / SRDY handshake to swap USBCKCR.SEL to PLL2P and USBCKDIVCR to /5, landing 48.000 MHz on USBCLK (0 ppm vs the USB-FS 48 MHz +/- 0.25 % spec).
Returns
ra8_err_t error code.
Return values
k_ra8_okUSB-FS clock running at exactly 48 MHz.
k_ra8_err_hw_init_failedPLL2 enable failed; see log.
k_ra8_err_hw_timeoutUSBCKCR SREQ/SRDY handshake timed out.
Precondition
Caller is single-threaded init context.
PLL1 / SCKSCR have already been programmed by ra8_cgc_init.
Postcondition
On k_ra8_ok PLL2 is locked, MSTPB11 is set, USBCKCR sources PLL2P / 5 = 48 MHz, and PRCR is re-locked.
On error the USB-FS clock is left in a quiesced state.
Note
Not thread-safe; init context only.
Since
0.1.0

Definition at line 364 of file ra8_cgc_usb.c.

References internal_usbckcr_switch_to_pll2p_div5(), k_ra8_hococr_hcstp, k_ra8_mstpb11_usbfs_mask, k_ra8_ok, k_ra8_oscsf_bit_hocosf, k_ra8_pll2_usbfs_mul, k_ra8_pll2_usbfs_quarters, k_ra8_plodiv_div4, k_ra8_prcr_unlock_cgc, r_mstp_regs_t::MSTPCRB, priv_ra8_cgc_wait_oscsf_set(), ra8_cgc_pll2_enable(), ra8_log_error, ra8_log_error_val, ra8_log_info, ra8_mstp(), RA8_PROTECTED_WRITE, ra8_sys_hococr(), and s_tag.

Referenced by blc_setup_or_halt(), cdc_setup_or_halt(), dfu_setup_or_halt(), fileops_setup_or_halt(), hid_setup_or_halt(), main(), microsd_setup_or_halt(), mlun_setup_or_halt(), ospirw_setup_or_halt(), ra8_nsc_cgc_usbfs_clock_enable(), sdmsc_setup_or_halt(), selftest_setup_or_halt(), and wlun_setup_or_halt().

◆ ra8_cgc_usbhs_pll_enable()

ra8_err_t ra8_cgc_usbhs_pll_enable ( void )
nodiscard

Bring up the USBHS PHY 60 MHz reference clock + module clock path.

Bring up the USBHS PHY reference clock + module clock.

The USBHS PHY's internal 480 MHz CDR PLL requires a stable 12 MHz reference, derived inside the PHY from a /5 division of the 60 MHz USB60CLK. This routine programmes USB60CKCR / USB60CKDIVCR (HUM Ch 9 "Clock Generation Circuit") so USB60CLK = PLL2P / 4 = 60.000 MHz exactly (PLL2P = 240 MHz from the same configuration the FS path uses, see ra8_cgc_usbfs_clock_enable). Mirrors the canonical FSP bsp_clocks.c bsp_peripheral_clock_set SREQ/SRDY ordering.

Sequence:

  1. Wait OSCSF.MOSCSF (main XTAL stable).
  2. Enable PLL2 at 240 MHz on PLL2P.
  3. Force MSTPCRB.MSTPB12 = 1 (USBHS module-stop) before changing USB60CKDIVCR off 1/1, per HUM "Clock selection switching procedure".
  4. Ensure HOCO is running (USB60CKCR's reset-default source) so the SREQ -> SRDY synchronizer chain can drain.
  5. SREQ/SRDY handshake on USB60CKCR/USB60CKDIVCR, landing USB60CLK = PLL2P / 4 = 60 MHz exactly.
Returns
ra8_err_t error code.
Return values
k_ra8_okUSBHS 60 MHz clock running on PLL2P/4.
k_ra8_err_hw_timeoutMain XTAL, HOCO, or USB60CKSRDY handshake timed out.
k_ra8_err_invalid_argPLL2 mul/quarters out of range (propagated from ra8_cgc_pll2_enable).
Precondition
ra8_cgc_init has been called.
Caller is single-threaded init context; CPU not on PLL2.
Postcondition
On k_ra8_ok: PLL2 locked at 240 MHz on PLL2P, MSTPB12 = 1, USB60CKCR.USB60CKSEL = PLL2P, USB60CKDIVCR = /4.
PRCR is re-locked.
Note
Not thread-safe; init context only.
See also
ra8_cgc_usbfs_clock_enable
ra8_cgc_pll2_enable
Since
0.1.0

Definition at line 624 of file ra8_cgc_usb.c.

References internal_usb60ckcr_switch_to_pll2p_div4(), k_ra8_mstpb12_usbhs_mask, k_ra8_ok, k_ra8_oscsf_bit_moscsf, k_ra8_pll2_usbfs_mul, k_ra8_pll2_usbfs_quarters, k_ra8_plodiv_div4, r_mstp_regs_t::MSTPCRB, priv_ra8_cgc_ensure_hoco_running_for_usb_ck(), priv_ra8_cgc_wait_oscsf_set(), ra8_cgc_pll2_enable(), ra8_log_error, ra8_log_error_val, ra8_log_info, ra8_mstp(), and s_tag.

Referenced by cdc_setup_or_halt(), dfu_setup_or_halt(), fileops_setup_or_halt(), hid_setup_or_halt(), internal_usbhs_clock_and_mstp(), main(), microsd_setup_or_halt(), mlun_setup_or_halt(), ospirw_setup_or_halt(), selftest_setup_or_halt(), and wlun_setup_or_halt().

Variable Documentation

◆ s_pll2_status_probe

volatile uint8_t s_pll2_status_probe = 0U
static

Last value read back from R_SYSTEM->OSCSF at the end of internal_usb60ckcr_switch_to_pll2p_div4.

Bit 6 (PLL2SF) must be 1 for the USB60CKCR clock-switch handshake to make forward progress. JLink-readable witness used in tandem with s_usb60ckcr_probe to disambiguate "PLL2 never locked" from "SREQ/SRDY ordering wrong".

Resolve the runtime address from the per-app .map file.

Note
Diagnostic-only; never read by production code paths.
Since
0.1.0

Definition at line 83 of file ra8_cgc_usb.c.

Referenced by internal_usb60ckcr_switch_to_pll2p_div4().

◆ s_tag

const char* s_tag = "CGC"
static

Definition at line 46 of file ra8_cgc_usb.c.

◆ s_usb60ckcr_probe

volatile uint8_t s_usb60ckcr_probe = 0U
static

Last value read back from R_SYSTEM->USB60CKCR at the end of internal_usb60ckcr_switch_to_pll2p_div4.

JLink-readable witness for the USBHS 60 MHz clock-source SREQ/SRDY handshake. After a successful handshake we expect: USB60CKCR = 0x06 (USB60CKSEL=PLL2P, USB60CKSREQ=0, USB60CKSRDY=0). On timeout the value captured here pins down which step of the handshake stalled.

Resolve the runtime address from the per-app .map file.

Note
Diagnostic-only; never read by production code paths.
Since
0.1.0

Definition at line 65 of file ra8_cgc_usb.c.

Referenced by internal_usb60ckcr_switch_to_pll2p_div4().