ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_mipi_phy.c
Go to the documentation of this file.
1
40
41#include "ra8_mipi_phy.h"
42
43#include <stdint.h>
44
45#include "ra8_attributes.h"
46#include "ra8_check.h"
47#include "ra8_err.h"
48#include "ra8_log.h"
50#include "ra8_mipi_phy_regs.h"
51#include "ra8_mstp_regs.h"
52
57static const char* s_tag = "MIPI_PHY";
58
76
92typedef enum : uint8_t {
95
105
115
116/* =============================================================================
117 * Driver state (module-private)
118 * =============================================================================
119 */
120
126
131static void* s_mipi_phy_ctx;
132
137static uint32_t s_last_sfr;
138
144
150
156
162
163/* =============================================================================
164 * Helpers (file-local)
165 * =============================================================================
166 */
167
187{
188 /* HUM Ch 64.4.2 "Module-Stop Function Setting", p 3838 */
189 volatile uint32_t* mstpc = &ra8_mstp()->MSTPCRC;
190 *mstpc = *mstpc & ~((uint32_t)1U << (uint32_t)k_ra8_mipi_phy_mstpc_bit);
191}
192
193/* Spin until ``(reg & mask) == mask`` or the budget runs out -- see surrounding code and HUM citations. */
195static ra8_err_t internal_mipi_phy_wait_set(volatile const uint32_t* reg, uint32_t mask)
196{
197 for (uint32_t i = 0U; i < (uint32_t)k_ra8_mipi_phy_spin_budget; ++i) {
198 if ((*reg & mask) == mask) {
199 return k_ra8_ok;
200 }
201 }
203}
204
205/* Pack a validated PLL config into the DPHYPLFCR register layout -- see surrounding code and HUM citations. */
208{
209 uint32_t v = 0U;
210 v |= ((uint32_t)pll->idiv & k_ra8_mipi_phy_plfcr_mask_idiv)
212 v |= ((uint32_t)pll->nfmul & k_ra8_mipi_phy_plfcr_mask_nfmul)
214 v |= ((uint32_t)pll->pmul & k_ra8_mipi_phy_plfcr_mask_pmul)
216 v |= ((uint32_t)pll->nmul_int & k_ra8_mipi_phy_plfcr_mask_nmul)
218 return v;
219}
220
246
249{
250 /* HUM Ch 64.2.8 "DPHYTIM1 : D-PHY Timing Control Register 1", p 3827 */
253
254 /* HUM Ch 64.2.9 "DPHYTIM2 : D-PHY Timing Control Register 2", p 3828 */
256 (((uint32_t)t->tclkmiss & k_ra8_mipi_phy_tim_byte_mask)
257 << (uint32_t)k_ra8_mipi_phy_tim_shift_b2) |
258 (((uint32_t)t->tclksett & k_ra8_mipi_phy_tim_byte_mask)
259 << (uint32_t)k_ra8_mipi_phy_tim_shift_b1) |
260 (((uint32_t)t->tclkprep & k_ra8_mipi_phy_tim_byte_mask)
261 << (uint32_t)k_ra8_mipi_phy_tim_shift_b0);
262
263 /* HUM Ch 64.2.10 "DPHYTIM3 : D-PHY Timing Control Register 3", p 3828 */
265 (((uint32_t)t->thssett & k_ra8_mipi_phy_tim_byte_mask)
266 << (uint32_t)k_ra8_mipi_phy_tim_shift_b1) |
267 (((uint32_t)t->thsprep & k_ra8_mipi_phy_tim_byte_mask)
268 << (uint32_t)k_ra8_mipi_phy_tim_shift_b0);
269
270 /* HUM Ch 64.2.11 "DPHYTIM4 : D-PHY Timing Control Register 4", p 3829 */
272 (((uint32_t)t->tclktrl & k_ra8_mipi_phy_tim_byte_mask)
273 << (uint32_t)k_ra8_mipi_phy_tim_shift_b3) |
274 (((uint32_t)t->tclkpost & k_ra8_mipi_phy_tim_byte_mask)
275 << (uint32_t)k_ra8_mipi_phy_tim_shift_b2) |
276 (((uint32_t)t->tclkpre & k_ra8_mipi_phy_tim_byte_mask)
277 << (uint32_t)k_ra8_mipi_phy_tim_shift_b1) |
278 (((uint32_t)t->tclkzero & k_ra8_mipi_phy_tim_byte_mask)
279 << (uint32_t)k_ra8_mipi_phy_tim_shift_b0);
280
281 /* HUM Ch 64.2.12 "DPHYTIM5 : D-PHY Timing Control Register 5", p 3830 */
283 (((uint32_t)t->thsexit & k_ra8_mipi_phy_tim_byte_mask)
284 << (uint32_t)k_ra8_mipi_phy_tim_shift_b2) |
285 (((uint32_t)t->thstrl & k_ra8_mipi_phy_tim_byte_mask)
286 << (uint32_t)k_ra8_mipi_phy_tim_shift_b1) |
287 (((uint32_t)t->thszero & k_ra8_mipi_phy_tim_byte_mask)
288 << (uint32_t)k_ra8_mipi_phy_tim_shift_b0);
289
290 /* HUM Ch 64.2.13 "DPHYTIM6 : D-PHY Timing Control Register 6", p 3831 */
292}
293
294/* =============================================================================
295 * Public API
296 * =============================================================================
297 */
298
320{
321 if (cfg == nullptr || cfg->p_timing == nullptr) {
322 return k_ra8_err_null_ptr;
323 }
324 if ((cfg->pclka_mhz < (uint8_t)k_ra8_mipi_phy_pclka_min_mhz) ||
325 (cfg->pclka_mhz > (uint8_t)k_ra8_mipi_phy_pclka_max_mhz)) {
327 }
328 if (cfg->escdiv > (uint8_t)k_ra8_mipi_phy_escdiv_max) {
330 }
333 return ((cfg->lane_count == k_ra8_mipi_phy_lane_count_3) ||
337 }
340 }
341 return k_ra8_ok;
342}
343
379
407
431
433{
435 RA8_RETURN_ON_ERROR(v_err, s_tag, "init: bad cfg");
436
437 /* Steps 1-5 -- HUM Ch 64.4.2 / 64.2.14 / 64.2.1 / 64.2.5 / 64.2.6 */
438 const ra8_err_t pwr_err = internal_mipi_phy_init_power_up(cfg);
439 RA8_RETURN_ON_ERROR(pwr_err, s_tag, "init: LDO did not stabilise");
440
442 /* Steps 6-9 -- HUM Ch 64.2.2/64.2.4/64.2.3/64.2.6 p 3823-3826 */
443 const ra8_err_t m_err = internal_mipi_phy_init_host(cfg);
444 RA8_RETURN_ON_ERROR(m_err, s_tag, "init: PLL did not lock");
445 } else {
446 /* CSI device mode: the PHY is a receiver, so the host-side PLL
447 * controls (PLFCR / ESCCR / PLOCR) are unused by this block. Make
448 * sure they hold their reset value (0) regardless of any prior
449 * host-mode state -- HUM Ch 64.2.2/64.2.3/64.2.4 p 3823-3825. */
453 }
454
455 /* Step 10 -- HUM Ch 64.2.8 "DPHYTIM1 : D-PHY Timing Control Register 1", p 3827 */
457
458 /* Step 11 -- HUM Ch 64.2.7 "DPHYOCR : D-PHY Operation Control Register", p 3827 */
460
462
463 ra8_log_info(s_tag, "mipi_phy_init done");
464 return k_ra8_ok;
465}
466
468{
469 /* Step 1 -- HUM Ch 64.2.7 "DPHYOCR : D-PHY Operation Control Register", p 3827 */
471
472 /* Step 2 -- HUM Ch 64.2.3 "DPHYPLOCR : D-PHY PLL Operation Control Register", p 3824 */
474
475 /* Step 3 -- HUM Ch 64.2.5 "DPHYPWRCR : D-PHY Power Supplying Control Register", p 3826 */
477
478 ra8_log_info(s_tag, "mipi_phy_deinit done");
479 return k_ra8_ok;
480}
481
483{
484 /* HUM Ch 64.2.7 "DPHYOCR : D-PHY Operation Control Register", p 3827 */
486 /* HUM Ch 64.2.3 "DPHYPLOCR : D-PHY PLL Operation Control Register", p 3824 */
488 /* HUM Ch 64.2.5 "DPHYPWRCR : D-PHY Power Supplying Control Register", p 3826 */
490 /* HUM Ch 64.2.2 "DPHYPLFCR : D-PHY PLL Frequency Control Register", p 3823 */
492 /* HUM Ch 64.2.4 "DPHYESCCR : D-PHY Escape Mode Clock Control Register", p 3825 */
494 /* HUM Ch 64.2.1 "DPHYREFCR : D-PHY Reference Clock Setting Register", p 3822 */
496 /* HUM Ch 64.2.14 "DPHYMDC : D-PHY Mode Control Register", p 3836 */
498 /* HUM Ch 64.2.8 "DPHYTIM1 : D-PHY Timing Control Register 1", p 3827 */
500 /* HUM Ch 64.2.9 "DPHYTIM2 : D-PHY Timing Control Register 2", p 3828 */
502 /* HUM Ch 64.2.10 "DPHYTIM3 : D-PHY Timing Control Register 3", p 3828 */
504 /* HUM Ch 64.2.11 "DPHYTIM4 : D-PHY Timing Control Register 4", p 3829 */
506 /* HUM Ch 64.2.12 "DPHYTIM5 : D-PHY Timing Control Register 5", p 3830 */
508 /* HUM Ch 64.2.13 "DPHYTIM6 : D-PHY Timing Control Register 6", p 3831 */
510 s_last_sfr = 0U;
511 return k_ra8_ok;
512}
513
515{
516 RA8_CHECK_NULL_PTR(cfg, s_tag, "recover: cfg must not be nullptr");
517 const ra8_err_t r_err = ra8_mipi_phy_reset();
518 /* GCOVR_EXCL_BR_START -- HW PHY/PLL ready */
519 RA8_RETURN_ON_ERROR(r_err, s_tag, "recover: reset failed");
520 /* GCOVR_EXCL_BR_STOP */
521 return ra8_mipi_phy_init(cfg);
522}
523
525{
526 RA8_CHECK_NULL_PTR(out_mask, s_tag, "out_mask must not be nullptr");
527
528 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
530 return k_ra8_ok;
531}
532
534{
535 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
537}
538
540{
541 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
543}
544
546{
547 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
550}
551
558
561{
562 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
563 const uint32_t sfr = *ra8_mipi_phy_reg32(k_ra8_mipi_phy_off_sfr);
564 const uint32_t prev = s_last_sfr;
565 s_last_sfr = sfr;
567 void* const ctx = s_mipi_phy_ctx;
568
569 if (fn == nullptr) {
570 return;
571 }
572
573 const uint32_t pwr_now = sfr & k_ra8_mipi_phy_sfr_pwrsf;
574 const uint32_t pwr_prev = prev & k_ra8_mipi_phy_sfr_pwrsf;
575 const uint32_t pll_now = sfr & k_ra8_mipi_phy_sfr_pllsf;
576 const uint32_t pll_prev = prev & k_ra8_mipi_phy_sfr_pllsf;
577
578 /* Emit at most one event per dispatch -- power edges take priority
579 * over PLL edges, with status_chg as the fallback when nothing
580 * transitioned. Multiple emits per call would over-count callers
581 * that key off the cb count. */
582 if ((pwr_now != 0U) && (pwr_prev == 0U)) {
583 fn(ctx, k_ra8_mipi_phy_event_ldo_ready, sfr);
584 } else if ((pwr_now == 0U) && (pwr_prev != 0U)) {
585 fn(ctx, k_ra8_mipi_phy_event_ldo_lost, sfr);
586 } else if ((pll_now != 0U) && (pll_prev == 0U)) {
588 } else if ((pll_now == 0U) && (pll_prev != 0U)) {
589 fn(ctx, k_ra8_mipi_phy_event_pll_lost, sfr);
590 } else {
592 }
593}
594
596{
597 /* HUM Ch 64.4.1 "Power Gating Control or Software Standby Mode", p 3837 */
598 return ra8_mipi_phy_deinit();
599}
600
602{
603 /* HUM Ch 64.4.1 "Power Gating Control or Software Standby Mode", p 3837 */
604 return ra8_mipi_phy_init(cfg);
605}
606
608{
609 /* HUM Ch 64.2.5 "DPHYPWRCR : D-PHY Power Supplying Control Register", p 3826 */
611 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
614}
615
617{
618 /* HUM Ch 64.2.5 "DPHYPWRCR : D-PHY Power Supplying Control Register", p 3826 */
620 return k_ra8_ok;
621}
622
624{
625 /* HUM Ch 64.2.3 "DPHYPLOCR : D-PHY PLL Operation Control Register", p 3824 */
627 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
630}
631
633{
634 /* HUM Ch 64.2.3 "DPHYPLOCR : D-PHY PLL Operation Control Register", p 3824 */
636 return k_ra8_ok;
637}
638
640{
641 RA8_CHECK_NULL_PTR(pll, s_tag, "pll must not be nullptr");
642 const ra8_err_t v_err = internal_mipi_phy_validate_pll(pll);
643 RA8_RETURN_ON_ERROR(v_err, s_tag, "set_lane_speed: pll out of range");
644
645 /* HUM Ch 64.2.2 "DPHYPLFCR : D-PHY PLL Frequency Control Register", p 3824 */
646 /* ("DPHYPLFCR must be set while D-PHY PLL operation is stopped".) */
648
649 /* HUM Ch 64.2.2 "DPHYPLFCR : D-PHY PLL Frequency Control Register", p 3823 */
651
652 /* HUM Ch 64.2.3 "DPHYPLOCR : D-PHY PLL Operation Control Register", p 3824 */
654
655 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
658}
659
661{
664 }
665 /* HUM Ch 64.2.7 "DPHYOCR : D-PHY Operation Control Register", p 3827 */
667 /* HUM Ch 64.2.14 "DPHYMDC : D-PHY Mode Control Register", p 3836 */
670 return k_ra8_ok;
671}
672
674{
675 if ((count == k_ra8_mipi_phy_lane_count_3) || (count == k_ra8_mipi_phy_lane_count_4)) {
676 /* HUM Ch 64.1 "Overview" p 3822 */
678 }
679 if ((count != k_ra8_mipi_phy_lane_count_1) && (count != k_ra8_mipi_phy_lane_count_2)) {
681 }
682 s_lane_count = count;
683 /* When the count drops to 1, force lane 1 off so callers don't see
684 * a stale "enabled" answer for an inactive lane. */
685 if (count == k_ra8_mipi_phy_lane_count_1) {
686 s_lane_enable_mask &= (uint8_t)~((uint8_t)1U << k_ra8_mipi_phy_lane_bit_d1);
687 } else {
688 s_lane_enable_mask |= (uint8_t)((uint8_t)1U << k_ra8_mipi_phy_lane_bit_d1);
689 }
690 return k_ra8_ok;
691}
692
697
699{
700 if ((lane == k_ra8_mipi_phy_lane_d2) || (lane == k_ra8_mipi_phy_lane_d3)) {
701 /* HUM Ch 64.1 "Overview" p 3822 */
703 }
704 uint8_t bit = 0U;
705 switch (lane) {
708 break;
711 break;
714 /* Cannot enable lane 1 when lane_count = 1. */
715 if (enable && (s_lane_count == k_ra8_mipi_phy_lane_count_1)) {
717 }
718 break;
719 default:
721 }
722 if (enable) {
723 s_lane_enable_mask |= (uint8_t)((uint8_t)1U << bit);
724 } else {
725 s_lane_enable_mask &= (uint8_t)~((uint8_t)1U << bit);
726 }
727 return k_ra8_ok;
728}
729
731{
732 uint8_t bit = 0U;
733 switch (lane) {
736 break;
739 break;
742 break;
743 default:
744 return false;
745 }
746 return (s_lane_enable_mask & (uint8_t)((uint8_t)1U << bit)) != 0U;
747}
748
757
762
764{
767 }
768 s_eotp = eotp;
769 return k_ra8_ok;
770}
771
776
778{
779 /* HUM Ch 64.2.1 "DPHYREFCR : D-PHY Reference Clock Setting Register", p 3822
780 * RFREQ encodes (MHz - 1); see ``k_ra8_mipi_phy_refcr_rfreq_bias``. FSP
781 * r_mipi_phy.c uses the same -1 encoding. */
782 if ((mhz < (uint8_t)k_ra8_mipi_phy_pclka_min_mhz) ||
783 (mhz > (uint8_t)k_ra8_mipi_phy_pclka_max_mhz)) {
785 }
788 return k_ra8_ok;
789}
790
792{
793 /* HUM Ch 64.2.4 "DPHYESCCR : D-PHY Escape Mode Clock Control Register", p 3825 */
794 if (escdiv > (uint8_t)k_ra8_mipi_phy_escdiv_max) {
796 }
797 /* HUM Ch 64.2.4 "DPHYESCCR : D-PHY Escape Mode Clock Control Register" p 3825 */
800 (uint32_t)escdiv & k_ra8_mipi_phy_esccr_escdiv_mask;
801 /* HUM Ch 64.2.3 "DPHYPLOCR : D-PHY PLL Operation Control Register", p 3824 */
803 /* HUM Ch 64.2.6 "DPHYSFR : D-PHY Status Flag Register", p 3826 */
806}
807
809{
810 RA8_CHECK_NULL_PTR(pll, s_tag, "validate_pll_band: pll must not be nullptr");
811 if ((mosc_mhz < k_ra8_mipi_phy_mosc_min_mhz) || (mosc_mhz > k_ra8_mipi_phy_mosc_max_mhz)) {
812 /* HUM Ch 64.1 "Overview" p 3822 */
814 }
815 const ra8_err_t n_err = internal_mipi_phy_validate_pll(pll);
816 RA8_RETURN_ON_ERROR(n_err, s_tag, "validate_pll_band: NMUL out of range");
817
818 /* HUM Ch 64.2.2 "DPHYPLFCR : D-PHY PLL Frequency Control Register" p 3824 */
819 const uint32_t f_mhz = priv_mipi_phy_compute_freq(pll, mosc_mhz);
820 uint16_t lo = 0U;
821 uint16_t hi = 0U;
822 switch (pll->pmul) {
826 break;
830 break;
834 break;
838 break;
839 default:
841 }
842 if ((f_mhz < (uint32_t)lo) || (f_mhz > (uint32_t)hi)) {
844 }
845 return k_ra8_ok;
846}
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#define RA8_ISR_SAFE
The function is callable from interrupt context.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_RETURN_ON_ERROR(err, tag, message)
Early return on error, propagating the code upward.
Definition ra8_check.h:184
#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_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_hw_timeout
Hardware timed out waiting for a flag or handshake.
Definition ra8_err.h:304
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
static ra8_err_t internal_mipi_phy_validate_pll(const ra8_mipi_phy_pll_t *pll)
Validate a ra8_mipi_phy_pll_t against HUM 64.2.2 p 3823 limits.
ra8_err_t ra8_mipi_phy_set_eotp(ra8_mipi_phy_eotp_t eotp)
Set the EoTP packet emission preference (DSI host only).
ra8_err_t ra8_mipi_phy_ldo_enable(void)
Enable the D-PHY LDO (DPHYPWRCR.PWRSEN = 1) only.
static void internal_mipi_phy_mstp_unstop(void)
Clear MSTPCRC bit 13, ungating MIPI PHY.
ra8_err_t ra8_mipi_phy_deinit(void)
Stop the D-PHY per HUM Ch 64.3.2 p 3837 (DPHYEN -> PLLSTP -> PWRSEN).
ra8_err_t ra8_mipi_phy_exit_stop(const ra8_mipi_phy_config_t *cfg)
Post-standby resume: re-run the start-up procedure.
ra8_err_t ra8_mipi_phy_set_escape_divisor(uint8_t escdiv)
Update DPHYESCCR.ESCDIV at runtime.
ra8_err_t ra8_mipi_phy_set_pclka_freq(uint8_t mhz)
Update DPHYREFCR.RFREQ at runtime.
static uint8_t s_lane_enable_mask
Bitmap of enabled lanes (bit 0 = clock, bit N = data lane N-1).
void ra8_mipi_phy_dispatch(void)
Read DPHYSFR, snapshot it, decode events, and fire the callback.
ra8_err_t ra8_mipi_phy_pll_start(void)
Release the PLL (DPHYPLOCR.PLLSTP = 0) and wait for lock.
bool ra8_mipi_phy_is_lane_enabled(ra8_mipi_phy_lane_id_t lane)
Query whether the given lane is currently enabled.
ra8_err_t ra8_mipi_phy_validate_pll_band(const ra8_mipi_phy_pll_t *pll, uint8_t mosc_mhz)
Validate a PLL coefficient block against HUM 64.2.2 p 3823-3824.
static void * s_mipi_phy_ctx
Opaque context forwarded to s_mipi_phy_fn.
bool ra8_mipi_phy_is_pll_locked(void)
Test whether the PLL is locked (DPHYSFR.PLLSF = 1).
ra8_err_t ra8_mipi_phy_init(const ra8_mipi_phy_config_t *cfg)
Bring up the D-PHY end-to-end per HUM Ch 64.3.1 p 3837.
static ra8_err_t internal_mipi_phy_init_power_up(const ra8_mipi_phy_config_t *cfg)
Apply common init steps 1-5 (mode, refclk, LDO power-up).
ra8_err_t ra8_mipi_phy_set_lane_count(ra8_mipi_phy_lane_count_t count)
Configure the active lane count.
ra8_mipi_phy_eotp_t ra8_mipi_phy_get_eotp(void)
Query the EoTP setting last configured.
static ra8_err_t internal_mipi_phy_wait_set(volatile const uint32_t *reg, uint32_t mask)
ra8_mipi_phy_limits_t
Validation guard rails for ra8_mipi_phy_init.
@ k_ra8_mipi_phy_pclka_min_mhz
Lower bound on RFREQ value.
@ k_ra8_mipi_phy_pclka_max_mhz
Upper bound on RFREQ value.
@ k_ra8_mipi_phy_spin_budget
Max poll iterations.
@ k_ra8_mipi_phy_escdiv_max
5-bit field width.
@ k_ra8_mipi_phy_nmul_min
NMUL_int floor.
@ k_ra8_mipi_phy_nmul_max
NMUL_int ceiling.
static ra8_mipi_phy_clk_mode_t s_clk_mode
HS clock-lane operating mode (continuous vs non-continuous).
static uint32_t s_last_sfr
Previous DPHYSFR snapshot, used for edge detection in dispatch.
ra8_err_t ra8_mipi_phy_set_lane_speed(const ra8_mipi_phy_pll_t *pll)
Reprogram the PLL coefficients (DPHYPLFCR) at runtime.
ra8_err_t ra8_mipi_phy_switch_mode(ra8_mipi_phy_mode_t mode)
Switch the PHY between DSI host and CSI device mode.
ra8_err_t ra8_mipi_phy_recover_from_error(const ra8_mipi_phy_config_t *cfg)
Reset and re-arm the PHY after an LDO drop / PLL unlock.
static ra8_err_t internal_mipi_phy_validate_init_cfg(const ra8_mipi_phy_config_t *cfg)
Validate ranges/lane-count for ra8_mipi_phy_init.
ra8_mipi_phy_lane_bit_t
Software-lane bitmap positions for s_lane_enable_mask.
@ k_ra8_mipi_phy_lane_bit_d0
bit 1: data lane 0.
@ k_ra8_mipi_phy_lane_bit_clk
bit 0: clock lane.
@ k_ra8_mipi_phy_lane_bit_d1
bit 2: data lane 1.
ra8_err_t ra8_mipi_phy_attach_handler(ra8_mipi_phy_event_fn_t fn, void *ctx)
Attach a status callback fired by ra8_mipi_phy_dispatch.
ra8_err_t ra8_mipi_phy_set_lane_enable(ra8_mipi_phy_lane_id_t lane, bool enable)
Enable or disable a single data lane.
ra8_mipi_phy_lane_mask_t
Default lane-enable bitmap (clock + d0 + d1 all on).
@ k_ra8_mipi_phy_lane_mask_default
RA8 mipi PHY lane mask default.
ra8_mipi_phy_lane_count_t ra8_mipi_phy_get_lane_count(void)
Read back the lane count last configured.
ra8_err_t ra8_mipi_phy_set_clock_mode(ra8_mipi_phy_clk_mode_t mode)
Set the HS clock-lane mode (continuous vs non-continuous).
void priv_mipi_phy_write_timing(const ra8_mipi_phy_timing_t *t)
Implementation of priv_mipi_phy_write_timing() – packs DPHYTIM1..6.
static ra8_mipi_phy_eotp_t s_eotp
Whether DSI host should append EoTP packets (host mode).
static ra8_mipi_phy_event_fn_t s_mipi_phy_fn
Registered callback for ra8_mipi_phy_dispatch.
ra8_mipi_phy_clk_mode_t ra8_mipi_phy_get_clock_mode(void)
Query the HS clock-lane mode last configured.
static void internal_mipi_phy_cache_state(const ra8_mipi_phy_config_t *cfg)
Latch cfg knobs into the driver's tracked-state cache.
bool ra8_mipi_phy_is_ldo_stable(void)
Test whether the LDO has stabilised (DPHYSFR.PWRSF = 1).
ra8_mipi_phy_mstpc_bit_t
Direct-write fallback for the MIPI PHY module-stop bit.
@ k_ra8_mipi_phy_mstpc_bit
Provisional MSTPC slot.
ra8_err_t ra8_mipi_phy_ldo_disable(void)
Disable the D-PHY LDO (DPHYPWRCR.PWRSEN = 0) only.
ra8_err_t ra8_mipi_phy_wait_ready(void)
Bounded poll until the PHY is fully ready (PWRSF & PLLSF).
ra8_err_t ra8_mipi_phy_get_status(uint32_t *out_mask)
Read the D-PHY status flags (DPHYSFR).
static uint32_t internal_mipi_phy_pack_plfcr(const ra8_mipi_phy_pll_t *pll)
ra8_err_t ra8_mipi_phy_reset(void)
Reset the PHY to its post-MSTPCRC-clear state without re-init.
static ra8_mipi_phy_lane_count_t s_lane_count
Last lane-count argument accepted by ra8_mipi_phy_set_lane_count.
ra8_err_t ra8_mipi_phy_enter_stop(void)
Pre-standby tear-down: disable D-PHY then drop the LDO.
static ra8_err_t internal_mipi_phy_init_host(const ra8_mipi_phy_config_t *cfg)
Apply DSI-host-only steps (6-9) of the init sequence.
ra8_err_t ra8_mipi_phy_pll_stop(void)
Stop the PLL (DPHYPLOCR.PLLSTP = 1).
MIPI D-PHY driver – physical layer shared by DSI and CSI.
Module-private link seam shared between the MIPI D-PHY drivertranslation units.
uint32_t priv_mipi_phy_compute_freq(const ra8_mipi_phy_pll_t *pll, uint8_t mosc_mhz)
Compute the PLL output frequency for a (mosc, pll) tuple.
MIPI D-PHY register layout for the RA8D2.
static volatile uint32_t * ra8_mipi_phy_reg32(ra8_mipi_phy_block_off_t offset)
Pointer to a 32-bit MIPI PHY register at the given offset.
@ k_ra8_mipi_phy_tim_shift_b1
Byte 1 (bits 15:8).
@ k_ra8_mipi_phy_tim_shift_b2
Byte 2 (bits 23:16).
@ k_ra8_mipi_phy_tim_shift_b0
Byte 0 (bits 7:0).
@ k_ra8_mipi_phy_tim_shift_b3
Byte 3 (bits 31:24).
@ k_ra8_mipi_phy_off_plocr
+0x008 DPHYPLOCR – PLL op ctrl.
@ k_ra8_mipi_phy_off_tim3
+0x02C DPHYTIM3 – THS PREP/SETT.
@ k_ra8_mipi_phy_off_tim4
+0x030 DPHYTIM4 – TCLK ZERO/PRE.
@ k_ra8_mipi_phy_off_plfcr
+0x004 DPHYPLFCR – PLL freq ctrl.
@ k_ra8_mipi_phy_off_ocr
+0x020 DPHYOCR – D-PHY enable.
@ k_ra8_mipi_phy_off_tim2
+0x028 DPHYTIM2 – TCLK PREP/SETT.
@ k_ra8_mipi_phy_off_esccr
+0x00C DPHYESCCR – escape clk div.
@ k_ra8_mipi_phy_off_pwrcr
+0x010 DPHYPWRCR – LDO pwr supply.
@ k_ra8_mipi_phy_off_tim5
+0x034 DPHYTIM5 – THS ZERO/TRL.
@ k_ra8_mipi_phy_off_tim1
+0x024 DPHYTIM1 – TINIT.
@ k_ra8_mipi_phy_off_refcr
+0x000 DPHYREFCR – ref clock cfg.
@ k_ra8_mipi_phy_off_sfr
+0x01C DPHYSFR – status flags.
@ k_ra8_mipi_phy_off_mdc
+0x048 DPHYMDC – host/device.
@ k_ra8_mipi_phy_off_tim6
+0x038 DPHYTIM6 – TLPX.
@ k_ra8_mipi_phy_plocr_pllstp
Bit 0 mask: stop the PLL.
@ k_ra8_mipi_phy_tim6_tlpx_mask
TLPX[7:0] field.
@ k_ra8_mipi_phy_plfcr_mask_idiv
IDIV[1:0] mask.
@ k_ra8_mipi_phy_plfcr_mask_nmul
NMUL[8:0] mask.
@ k_ra8_mipi_phy_plfcr_mask_nfmul
NFMUL[1:0] mask.
@ k_ra8_mipi_phy_plfcr_mask_pmul
PMUL[1:0] mask.
@ k_ra8_mipi_phy_pwrcr_pwrsen
Bit 0 mask: enable D-PHY LDO.
@ k_ra8_mipi_phy_plfcr_shift_nfmul
NFMUL[1:0] field shift.
@ k_ra8_mipi_phy_plfcr_shift_nmul
NMUL[8:0] field shift.
@ k_ra8_mipi_phy_plfcr_shift_pmul
PMUL[1:0] field shift.
@ k_ra8_mipi_phy_plfcr_shift_idiv
IDIV[1:0] field shift.
@ k_ra8_mipi_phy_tim1_tinit_mask
TINIT[18:0] field.
@ k_ra8_mipi_phy_mdc_hosten
DPHYMDC.MASTEREN bit 0: host (DSI) mode.
@ k_ra8_mipi_phy_sfr_ready_mask
PWRSF | PLLSF.
@ k_ra8_mipi_phy_sfr_pwrsf
Bit 0 mask: LDO stable.
@ k_ra8_mipi_phy_sfr_pllsf
Bit 8 mask: PLL clock stable.
@ k_ra8_mipi_phy_mosc_max_mhz
MOSC upper bound.
@ k_ra8_mipi_phy_mosc_min_mhz
MOSC lower bound.
@ k_ra8_mipi_phy_ocr_dphyen
Bit 0 mask: enable D-PHY.
@ k_ra8_mipi_phy_refcr_rfreq_mask
RFREQ[7:0] field.
@ k_ra8_mipi_phy_esccr_escdiv_mask
ESCDIV[4:0] field.
@ k_ra8_mipi_phy_refcr_rfreq_bias
RFREQ encodes (MHz - 1).
@ k_ra8_mipi_phy_tim_byte_mask
Mask for each 8-bit lane.
@ k_ra8_mipi_phy_pll_p4_min
P=1/4 floor.
@ k_ra8_mipi_phy_pll_p1_min
P=1 floor.
@ k_ra8_mipi_phy_pll_p2_min
P=1/2 floor.
@ k_ra8_mipi_phy_pll_p4_max
P=1/4 ceiling.
@ k_ra8_mipi_phy_pll_p8_max
P=1/8 ceiling.
@ k_ra8_mipi_phy_pll_p1_max
P=1 ceiling.
@ k_ra8_mipi_phy_pll_p8_min
P=1/8 floor.
@ k_ra8_mipi_phy_pll_p2_max
P=1/2 ceiling.
void(* ra8_mipi_phy_event_fn_t)(void *ctx, ra8_mipi_phy_event_t event, uint32_t sfr)
MIPI PHY status callback (LDO ready / PLL lock / PLL drop).
@ k_ra8_mipi_phy_event_pll_lost
DPHYSFR.PLLSF fell 1->0.
@ k_ra8_mipi_phy_event_ldo_ready
DPHYSFR.PWRSF rose 0->1.
@ k_ra8_mipi_phy_event_pll_locked
DPHYSFR.PLLSF rose 0->1.
@ k_ra8_mipi_phy_event_ldo_lost
DPHYSFR.PWRSF fell 1->0.
@ k_ra8_mipi_phy_event_status_chg
Catch-all status change.
ra8_mipi_phy_lane_count_t
Number of D-PHY data lanes activated for a transfer.
@ k_ra8_mipi_phy_lane_count_1
1 data lane.
@ k_ra8_mipi_phy_lane_count_4
4 data lanes – rejected on RA8D2.
@ k_ra8_mipi_phy_lane_count_2
2 data lanes (silicon maximum).
@ k_ra8_mipi_phy_lane_count_3
3 data lanes – rejected on RA8D2.
ra8_mipi_phy_mode_t
D-PHY host vs device mode select (DPHYMDC.MASTEREN).
@ k_ra8_mipi_phy_mode_csi_device
Device mode used by MIPI CSI.
@ k_ra8_mipi_phy_mode_dsi_host
Host mode used by MIPI DSI.
ra8_mipi_phy_clk_mode_t
HS clock-lane operating mode.
@ k_ra8_mipi_phy_clk_noncontinuous
Drop to LP-11 between bursts.
@ k_ra8_mipi_phy_clk_continuous
Keep HS clock running.
@ k_ra8_mipi_phy_pmul_8
P = 1/8 (120.
@ k_ra8_mipi_phy_pmul_1
P = 1 (960.
@ k_ra8_mipi_phy_pmul_4
P = 1/4 (240.
@ k_ra8_mipi_phy_pmul_2
P = 1/2 (480.
ra8_mipi_phy_lane_id_t
Per-lane identifier passed to ra8_mipi_phy_set_lane_enable.
@ k_ra8_mipi_phy_lane_d3
Data lane 3 – not on RA8D2.
@ k_ra8_mipi_phy_lane_d1
Data lane 1.
@ k_ra8_mipi_phy_lane_d2
Data lane 2 – not on RA8D2.
@ k_ra8_mipi_phy_lane_d0
Data lane 0.
@ k_ra8_mipi_phy_lane_clk
Clock lane (always-on).
ra8_mipi_phy_eotp_t
End-of-Transmission Packet emission setting (DSI host only).
@ k_ra8_mipi_phy_eotp_disabled
Do not append EoTP.
@ k_ra8_mipi_phy_eotp_enabled
Append EoTP packet.
Module Stop Control (MSTP) register layout for the Renesas RA8D2.
static volatile r_mstp_regs_t * ra8_mstp(void)
Get pointer to the MSTP register block.
volatile uint32_t MSTPCRC
Module Stop Control Register C (+0x08).
Top-level configuration for ra8_mipi_phy_init.
ra8_mipi_phy_clk_mode_t clk_mode
Continuous vs non-continuous HS clock.
const ra8_mipi_phy_timing_t * p_timing
Non-NULL timing block.
ra8_mipi_phy_pll_t pll
PLL coefficients.
ra8_mipi_phy_mode_t mode
Host (DSI) or device (CSI).
uint8_t escdiv
Escape clk divisor (0..31).
ra8_mipi_phy_lane_count_t lane_count
1 or 2 data lanes.
ra8_mipi_phy_eotp_t eotp
Append EoTP (DSI only).
uint8_t pclka_mhz
PCLKA frequency, MHz (40..125).
D-PHY PLL coefficients written into DPHYPLFCR.
ra8_mipi_phy_pll_pmul_t pmul
PMUL[1:0] output divisor.
ra8_mipi_phy_pll_nfmul_t nfmul
NFMUL[1:0] fractional N.
uint16_t nmul_int
NMUL[8:0] integer N (40..375).
ra8_mipi_phy_pll_idiv_t idiv
IDIV[1:0] input divisor.
D-PHY HS/LP transition timing values (DPHYTIM1..6).
uint8_t tclkprep
DPHYTIM2.TCLKPREP[7:0].
uint8_t thssett
DPHYTIM3.THSSETT[7:0].
uint8_t thszero
DPHYTIM5.THSZERO[7:0].
uint8_t tclkzero
DPHYTIM4.TCLKZERO[7:0].
uint8_t thstrl
DPHYTIM5.THSTRL[7:0].
uint8_t tclktrl
DPHYTIM4.TCLKTRL[7:0].
uint8_t tclkmiss
DPHYTIM2.TCLKMISS[7:0].
uint8_t tlpx
DPHYTIM6.TLPX[7:0].
uint8_t tclkpre
DPHYTIM4.TCLKPRE[7:0].
uint8_t tclkpost
DPHYTIM4.TCLKPOST[7:0].
uint8_t thsprep
DPHYTIM3.THSPREP[7:0].
uint8_t thsexit
DPHYTIM5.THSEXIT[7:0].
uint8_t tclksett
DPHYTIM2.TCLKSETT[7:0].
uint32_t tinit
DPHYTIM1.TINIT[18:0].