ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_i3c.c
Go to the documentation of this file.
1
25
26#include "ra8_i3c.h"
27
28#include <stdint.h>
29
30#include "ra8_attributes.h"
31#include "ra8_check.h"
32#include "ra8_err.h"
33#include "ra8_i3c_i2c.h"
35#include "ra8_i3c_i2c_regs.h"
36#include "ra8_i3c_internal.h"
37#include "ra8_i3c_regs.h"
38#include "ra8_log.h"
39#include "ra8_mstp.h"
40#include "ra8_mstp_regs.h"
41
58bool priv_ra8_i3c_internal_recv_ccc_invalid(uint8_t addr_mask, uint8_t target, uint8_t max_len)
59{
60 return (target > addr_mask) || (max_len == 0U);
61}
62
81 uint32_t ddr_val,
82 uint32_t ts_val,
83 uint32_t mode)
84{
85 return (mode != sdr_val) && (mode != ddr_val) && (mode != ts_val);
86}
87
89static const char* s_tag = "I3C";
90
93
95static void* s_i3c_ctx;
96
105
108
109/* =============================================================================
110 * Private helpers
111 * =============================================================================
112 */
113
140{
141 /* HUM Ch 40 "CECTL : Clock Enable Control Register" p 2445-2701 */
142 reg->CECTL = 1U;
143 /* HUM Ch 40 "BCTL : Bus Control Register" p 2445-2701 */
144 reg->BCTL = 0U;
145 /* HUM Ch 40 "RSTCTL : Reset Control Register" p 2445-2701 */
147 reg->RSTCTL = 0U; /* fake-mmap clear / target HW already auto-cleared */
149 reg->RSTCTL = 0U;
150 reg->PRTS = 0U;
151}
152
176RA8_INTERNAL static uint32_t internal_ra8_i3c_xfer_cmd_word(uint8_t target_addr, bool rnw)
177{
178 uint32_t cmd = 0U;
179 cmd |= ((uint32_t)target_addr) << k_ra8_i3c_cmd_dev_index_shift;
180 if (rnw) {
181 cmd |= 1U << k_ra8_i3c_cmd_rnw_shift;
182 }
183 cmd |= 1U << k_ra8_i3c_cmd_roc_shift; /* response on completion */
184 cmd |= 1U << k_ra8_i3c_cmd_toc_shift; /* terminate (STOP) on completion */
185 return cmd;
186}
187
205RA8_INTERNAL static uint32_t
206internal_ra8_i3c_ccc_cmd_word(uint8_t ccc, uint8_t target_addr, bool rnw)
207{
208 uint32_t cmd = 0U;
209 cmd |= 1U << k_ra8_i3c_cmd_cp_shift; /* command-present (CCC). */
210 cmd |= ((uint32_t)ccc) << k_ra8_i3c_cmd_code_shift; /* CCC opcode in [14:7]. */
211 cmd |= ((uint32_t)target_addr) << k_ra8_i3c_cmd_dev_index_shift;
212 if (rnw) {
213 cmd |= 1U << k_ra8_i3c_cmd_rnw_shift;
214 }
215 cmd |= 1U << k_ra8_i3c_cmd_roc_shift;
216 cmd |= 1U << k_ra8_i3c_cmd_toc_shift;
217 return cmd;
218}
219
239RA8_INTERNAL static void
240internal_ra8_i3c_fifo_write(volatile r_i3c_regs_t* reg, const uint8_t* data, uint32_t len)
241{
242 uint32_t i = 0U;
243 const uint32_t k_word_size = k_ra8_i3c_word_size;
244 while (i + k_word_size <= len) {
245 uint32_t w = (uint32_t)data[i];
246 w |= ((uint32_t)data[i + 1U]) << k_ra8_i3c_shift_b1;
247 w |= ((uint32_t)data[i + 2U]) << k_ra8_i3c_shift_b2;
248 w |= ((uint32_t)data[i + 3U]) << k_ra8_i3c_shift_b3;
249 reg->NTDTBP0 = w;
250 i += k_word_size;
251 }
252 if (i < len) {
253 uint32_t w = 0U;
254 uint32_t s = 0U;
255 while (i < len) {
256 w |= ((uint32_t)data[i]) << s;
258 ++i;
259 }
260 reg->NTDTBP0 = w;
261 }
262}
263
282RA8_INTERNAL static void
283internal_ra8_i3c_fifo_read(volatile const r_i3c_regs_t* reg, uint8_t* out, uint32_t len)
284{
285 uint32_t i = 0U;
286 const uint32_t k_word_size = k_ra8_i3c_word_size;
287 while (i + k_word_size <= len) {
288 const uint32_t w = reg->NTDTBP0;
289 out[i] = (uint8_t)(w & k_ra8_i3c_byte_mask);
290 out[i + 1U] = (uint8_t)((w >> k_ra8_i3c_shift_b1) & k_ra8_i3c_byte_mask);
291 out[i + 2U] = (uint8_t)((w >> k_ra8_i3c_shift_b2) & k_ra8_i3c_byte_mask);
292 out[i + 3U] = (uint8_t)((w >> k_ra8_i3c_shift_b3) & k_ra8_i3c_byte_mask);
293 i += k_word_size;
294 }
295 if (i < len) {
296 const uint32_t w = reg->NTDTBP0;
297 uint32_t s = 0U;
298 while (i < len) {
299 out[i] = (uint8_t)((w >> s) & k_ra8_i3c_byte_mask);
301 ++i;
302 }
303 }
304}
305
306/* =============================================================================
307 * Lifecycle / status / IRQ
308 * =============================================================================
309 */
310
311ra8_err_t ra8_i3c_init(uint8_t channel, const ra8_i3c_cfg_t* cfg)
312{
313 RA8_CHECK_NULL_PTR(cfg, s_tag, "i3c_init: cfg");
314 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
316 }
317
318 if (cfg->mode == k_ra8_i3c_mode_i2c) {
319 /* I2C-compat: delegate bring-up to the legacy IIC_B path. */
320 const ra8_i3c_i2c_cfg_t bcfg = {.bus_hz = cfg->bus_hz, .pclka_hz = cfg->pclka_hz};
321 const ra8_err_t e = ra8_i3c_i2c_init(channel, &bcfg);
322 if (e != k_ra8_ok) {
323 return e;
324 }
325 } else {
326 /* Native I3C bring-up. HUM Ch 11.2.7 "MSTPCRB" p 444 + Ch 40. */
328 /* GCOVR_EXCL_BR_START -- MSTP HW readback */
329 RA8_RETURN_ON_ERROR(mst_err, s_tag, "i3c_init: mstp enable");
330 /* GCOVR_EXCL_BR_STOP */
331 volatile r_i3c_regs_t* reg = ra8_i3c();
333 /* Clear every status / enable register to a deterministic state.
334 * INSTFC is write-only (force-clear), so we treat it as a clear. */
335 reg->INST = 0U;
336 reg->INSTE = 0U;
337 reg->INIE = 0U;
338 reg->INSTFC = 0U;
339 reg->MSDVAD = 0U;
340 }
341
342 s_i3c_chan[channel].mode = cfg->mode;
343 s_i3c_chan[channel].initialized = true;
344 ra8_log_info(s_tag, "i3c_init");
345 return k_ra8_ok;
346}
347
348ra8_err_t ra8_i3c_deinit(uint8_t channel)
349{
350 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
352 }
353 ra8_err_t err;
354 if (s_i3c_chan[channel].mode == k_ra8_i3c_mode_i2c) {
355 err = ra8_i3c_i2c_deinit(channel);
356 } else {
357 volatile r_i3c_regs_t* reg = ra8_i3c();
358 /* HUM Ch 40 "BCTL : Bus Control Register" p 2445-2701 */
359 reg->INIE = 0U;
360 reg->INSTE = 0U;
361 reg->BCTL = 0U;
362 /* HUM Ch 40 "CECTL : Clock Enable Control Register" p 2445-2701 */
363 reg->CECTL = 0U;
364 s_i3c_fn = nullptr;
365 s_i3c_ctx = nullptr;
367 }
368 s_i3c_chan[channel].initialized = false;
369 return err;
370}
371
373{
374 if (addr > k_ra8_i3c_msdvad_addr_max) {
376 }
377 /* HUM Ch 40 MSDVAD device address register pp 2445-2701
378 * MDYAD occupies bits [22:16]; MDYADV (bit 31) marks the address
379 * as valid. */
380 const uint32_t mdyad = (addr << k_ra8_i3c_msdvad_mdyad_shift) & k_ra8_i3c_msdvad_mdyad_mask;
382 return k_ra8_ok;
383}
384
386{
387 volatile r_i3c_regs_t* reg = ra8_i3c();
388 /* HUM Ch 40 "BCTL : Bus Control Register" pp 2445-2701 -- BCTL.BUSE
389 * is bit 31, not bit 0; toggling it gates bus primary operation. */
390 if (enable) {
391 reg->BCTL = reg->BCTL | k_ra8_i3c_bctl_buse_mask;
392 } else {
393 reg->BCTL = reg->BCTL & ~k_ra8_i3c_bctl_buse_mask;
394 }
395 return k_ra8_ok;
396}
397
398ra8_err_t ra8_i3c_get_status(uint32_t* out_mask)
399{
400 RA8_CHECK_NULL_PTR(out_mask, s_tag, "out_mask must not be nullptr");
401 /* HUM Ch 40 "INST : Internal Status Register" p 2445-2701 */
402 *out_mask = ra8_i3c()->INST;
403 return k_ra8_ok;
404}
405
407{
408 volatile r_i3c_regs_t* reg = ra8_i3c();
409 /* HUM Ch 40 "INST : Internal Status Register" pp 2445-2701 -- the
410 * sticky flags are cleared by writing 0 to the matching bit. */
411 reg->INST = reg->INST & ~mask;
412 return k_ra8_ok;
413}
414
416{
417 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
419 }
420 s_i3c_fn = fn;
421 s_i3c_ctx = ctx;
422 return k_ra8_ok;
423}
424
426void ra8_i3c_dispatch(uint8_t channel)
427{
428 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
429 return;
430 }
431 const ra8_i3c_event_fn_t fn = s_i3c_fn;
432 void* const ctx = s_i3c_ctx;
433 if (s_i3c_chan[channel].mode == k_ra8_i3c_mode_i2c) {
434 /* Surface the latched I2C error mask through the public IIC_B API. */
435 uint8_t mask = 0U;
436 (void)ra8_i3c_i2c_get_errors(channel, &mask);
437 (void)ra8_i3c_i2c_clear_errors(channel);
438 if (fn != nullptr) {
439 fn(ctx, (uint32_t)mask);
440 }
441 return;
442 }
443 volatile r_i3c_regs_t* reg = ra8_i3c();
444 /* HUM Ch 40 "INST : Internal Status Register" p 2445-2701 */
445 const uint32_t mask = reg->INST;
446 reg->INST = 0U;
447 if (fn != nullptr) {
448 fn(ctx, mask);
449 }
450}
451
453{
454 /* HUM Ch 40 "BCTL : Bus Control Register" p 2445-2701 */
455 ra8_i3c()->BCTL = 0U;
456 ra8_i3c()->CECTL = 0U;
458}
459
464
465/* =============================================================================
466 * Dynamic Address Assignment (ENTDAA / SETDASA / RSTDAA)
467 * =============================================================================
468 */
469
471{
472 RA8_CHECK_NULL_PTR(targets, s_tag, "targets must not be nullptr");
473 if ((target_count == 0U) || (target_count > (uint8_t)k_ra8_i3c_max_targets)) {
475 }
476
477 volatile r_i3c_regs_t* reg = ra8_i3c();
478
479 /* Build the ENTDAA command descriptor. See HUM Ch 40 "Command
480 * Descriptor / Address Assignment" pp 2445-2701 and FSP
481 * R_I3C_DynamicAddressAssignmentStart for the field layout. */
482 uint32_t cmd = 0U;
485 cmd |= (uint32_t)target_count << k_ra8_i3c_cmd_addr_count_shift;
486 cmd |= 1U << k_ra8_i3c_cmd_roc_shift;
487 cmd |= 1U << k_ra8_i3c_cmd_toc_shift;
488 reg->NCMDQP = cmd;
489 reg->NCMDQP = 0U;
490
491 /* Per HUM Ch 40 "Enter Dynamic Address Assignment" each accepted
492 * target replies with PID(48) + BCR + DCR -- 8 bytes total -- which
493 * the controller pushes into the receive FIFO. We drain those
494 * bytes into the caller's array, then the controller latches the
495 * matching dynamic address from MSDVAD.MDYAD into each target. */
496 for (uint8_t i = 0U; i < target_count; ++i) {
497 /* PID(6) + BCR(1) + DCR(1) = 8 bytes per target. */
498 enum : uint8_t {
499 k_pid_bcr_dcr_bytes = 8U,
500 k_idx_bcr = 6U,
501 k_idx_dcr = 7U,
502 };
503 uint8_t pid_bcr_dcr[k_pid_bcr_dcr_bytes] = {};
504 internal_ra8_i3c_fifo_read(reg, pid_bcr_dcr, sizeof(pid_bcr_dcr));
505 for (uint8_t j = 0U; j < (uint8_t)k_ra8_i3c_pid_bytes; ++j) {
506 targets[i].pid[j] = pid_bcr_dcr[j];
507 }
508 targets[i].bcr = pid_bcr_dcr[k_idx_bcr];
509 targets[i].dcr = pid_bcr_dcr[k_idx_dcr];
510 /* targets[i].dynamic_address is left as the caller-supplied value. */
511 }
512
513 /* Clear command-queue-empty so the next push starts cleanly. */
515 return k_ra8_ok;
516}
517
518ra8_err_t ra8_i3c_set_dynamic_address(uint8_t static_addr, uint8_t dynamic_addr)
519{
520 if ((static_addr > (uint8_t)k_ra8_i3c_addr_mask) ||
521 (dynamic_addr > (uint8_t)k_ra8_i3c_addr_mask)) {
523 }
524
525 volatile r_i3c_regs_t* reg = ra8_i3c();
526 uint32_t cmd =
527 internal_ra8_i3c_ccc_cmd_word(k_ra8_i3c_ccc_d_setdasa, static_addr, false /* write */);
528 /* SETDASA carries a single payload byte (the new dynamic address)
529 * in immediate-data mode -- mirror the FSP path for transfers
530 * <= 4 bytes. */
533 reg->NCMDQP = cmd;
534 reg->NCMDQP = (uint32_t)dynamic_addr;
536 return k_ra8_ok;
537}
538
540{
541 volatile r_i3c_regs_t* reg = ra8_i3c();
542 /* RSTDAA is a payload-less broadcast CCC. */
543 uint32_t cmd = internal_ra8_i3c_ccc_cmd_word(k_ra8_i3c_ccc_b_rstdaa, 0U /* broadcast */, false);
544 reg->NCMDQP = cmd;
545 reg->NCMDQP = 0U;
547 return k_ra8_ok;
548}
549
550/* =============================================================================
551 * Generic CCC send / receive
552 * =============================================================================
553 */
554
555ra8_err_t ra8_i3c_send_ccc(uint8_t ccc, uint8_t target_addr, const uint8_t* payload, uint8_t len)
556{
557 if (target_addr > (uint8_t)k_ra8_i3c_addr_mask) {
559 }
560 if ((len > 0U) && (payload == nullptr)) {
561 return k_ra8_err_null_ptr;
562 }
563 /* @p len is uint8_t and k_ra8_i3c_cmd_xfer_length_max is 0xFFFF, so by
564 * construction every uint8_t fits in the descriptor's [31:16] length
565 * field -- the runtime range check is unnecessary here. */
566
567 volatile r_i3c_regs_t* reg = ra8_i3c();
568 uint32_t cmd = internal_ra8_i3c_ccc_cmd_word(ccc, target_addr, false);
569
570 if (len <= (uint8_t)k_ra8_i3c_immediate_max_bytes) {
571 /* Immediate-data transfer: byte count goes in cmd1, the actual
572 * bytes packed LSB-first into cmd2. */
574 cmd |= (uint32_t)len << k_ra8_i3c_cmd_immed_bytes_shift;
575 reg->NCMDQP = cmd;
576 uint32_t w = 0U;
577 for (uint8_t i = 0U; i < len; ++i) {
578 w |= (uint32_t)payload[i] << (i * k_ra8_i3c_byte_shift);
579 }
580 reg->NCMDQP = w;
581 } else {
582 /* Regular transfer: cmd1 declares the descriptor; cmd2 carries the
583 * length in [31:16]; payload pushed through NTDTBP0. */
584 reg->NCMDQP = cmd;
585 reg->NCMDQP = (uint32_t)len << k_ra8_i3c_cmd_xfer_length_shift;
586 internal_ra8_i3c_fifo_write(reg, payload, (uint32_t)len);
587 }
589 return k_ra8_ok;
590}
591
593ra8_i3c_recv_ccc(uint8_t ccc, uint8_t target_addr, uint8_t* buf, uint8_t max_len, uint8_t* got_len)
594{
595 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
596 RA8_CHECK_NULL_PTR(got_len, s_tag, "got_len must not be nullptr");
597 if ((ccc & k_ra8_i3c_ccc_direct_mask) == 0U) {
598 /* Only direct CCCs return data. */
600 }
601 if (priv_ra8_i3c_internal_recv_ccc_invalid((uint8_t)k_ra8_i3c_addr_mask, target_addr, max_len)) {
603 }
604
605 volatile r_i3c_regs_t* reg = ra8_i3c();
606 uint32_t cmd = internal_ra8_i3c_ccc_cmd_word(ccc, target_addr, true /* read */);
607 reg->NCMDQP = cmd;
608 reg->NCMDQP = (uint32_t)max_len << k_ra8_i3c_cmd_xfer_length_shift;
609 internal_ra8_i3c_fifo_read(reg, buf, (uint32_t)max_len);
610 *got_len = max_len;
612 return k_ra8_ok;
613}
614
615/* =============================================================================
616 * Private read / write
617 * =============================================================================
618 */
619
621ra8_i3c_write(uint8_t channel, uint8_t addr, const uint8_t* data, uint32_t len, bool restart)
622{
623 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
625 }
626 if (!s_i3c_chan[channel].initialized) {
628 }
629 if (s_i3c_chan[channel].mode == k_ra8_i3c_mode_i2c) {
630 return ra8_i3c_i2c_write(channel, addr, data, len, restart);
631 }
632 (void)restart;
633 const uint8_t target_addr = addr;
634 if (target_addr > (uint8_t)k_ra8_i3c_addr_mask) {
636 }
637 if ((len > 0U) && (data == nullptr)) {
638 return k_ra8_err_null_ptr;
639 }
642 }
643
644 volatile r_i3c_regs_t* reg = ra8_i3c();
645 uint32_t cmd = internal_ra8_i3c_xfer_cmd_word(target_addr, false);
646
650 reg->NCMDQP = cmd;
651 uint32_t w = 0U;
652 for (uint32_t i = 0U; i < len; ++i) {
653 w |= (uint32_t)data[i] << (i * k_ra8_i3c_byte_shift);
654 }
655 reg->NCMDQP = w;
656 } else {
657 reg->NCMDQP = cmd;
660 internal_ra8_i3c_fifo_write(reg, data, len);
661 }
663 return k_ra8_ok;
664}
665
666ra8_err_t ra8_i3c_read(uint8_t channel, uint8_t addr, uint8_t* buf, uint32_t len, bool restart)
667{
668 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
670 }
671 if (!s_i3c_chan[channel].initialized) {
673 }
674 if (s_i3c_chan[channel].mode == k_ra8_i3c_mode_i2c) {
675 return ra8_i3c_i2c_read(channel, addr, buf, len, restart);
676 }
677 (void)restart;
678 const uint8_t target_addr = addr;
679 RA8_CHECK_NULL_PTR(buf, s_tag, "buf must not be nullptr");
680 if (target_addr > (uint8_t)k_ra8_i3c_addr_mask) {
682 }
683 if ((len == 0U) || (len > k_ra8_i3c_cmd_xfer_length_max)) {
685 }
686
687 volatile r_i3c_regs_t* reg = ra8_i3c();
688 uint32_t cmd = internal_ra8_i3c_xfer_cmd_word(target_addr, true);
689 reg->NCMDQP = cmd;
692 internal_ra8_i3c_fifo_read(reg, buf, len);
694 return k_ra8_ok;
695}
696
697/* =============================================================================
698 * I2C-compatibility mode (delegates to the legacy IIC_B path)
699 * =============================================================================
700 */
701
703 uint8_t addr,
704 const uint8_t* wr,
705 uint32_t wr_len,
706 uint8_t* rd,
707 uint32_t rd_len)
708{
709 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
711 }
712 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
714 }
715 return ra8_i3c_i2c_transfer(channel, addr, wr, wr_len, rd, rd_len);
716}
717
718ra8_err_t ra8_i3c_set_clock(uint8_t channel, uint32_t bus_hz, uint32_t pclka_hz)
719{
720 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
722 }
723 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
725 }
726 return ra8_i3c_i2c_set_clock(channel, bus_hz, pclka_hz);
727}
728
729ra8_err_t ra8_i3c_scan(uint8_t channel, uint8_t addr, bool* out_acked)
730{
731 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
733 }
734 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
736 }
737 return ra8_i3c_i2c_scan(channel, addr, out_acked);
738}
739
740ra8_err_t ra8_i3c_get_errors(uint8_t channel, uint8_t* out_mask)
741{
742 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
744 }
745 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
747 }
748 return ra8_i3c_i2c_get_errors(channel, out_mask);
749}
750
752{
753 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
755 }
756 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
758 }
759 return ra8_i3c_i2c_clear_errors(channel);
760}
761
762ra8_err_t ra8_i3c_abort(uint8_t channel)
763{
764 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
766 }
767 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
769 }
770 return ra8_i3c_i2c_abort(channel);
771}
772
773/* =============================================================================
774 * I2C-compatibility peripheral (responder) mode
775 * =============================================================================
776 */
777
779{
780 RA8_CHECK_NULL_PTR(cfg, s_tag, "peripheral_open: cfg");
781 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
783 }
784 /* Responder open is a self-contained bring-up; mark the channel I2C so
785 * the close/send/receive/status guards accept it. */
786 const ra8_i3c_i2c_peripheral_cfg_t bcfg = {.peripheral_addr_7b = cfg->peripheral_addr_7b,
787 .general_call = cfg->general_call};
788 const ra8_err_t err = ra8_i3c_i2c_peripheral_open(channel, &bcfg);
789 if (err == k_ra8_ok) {
790 s_i3c_chan[channel].mode = k_ra8_i3c_mode_i2c;
791 s_i3c_chan[channel].initialized = true;
792 }
793 return err;
794}
795
797{
798 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
800 }
801 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
803 }
804 return ra8_i3c_i2c_peripheral_close(channel);
805}
806
807ra8_err_t ra8_i3c_peripheral_send(uint8_t channel, const uint8_t* data, uint32_t len)
808{
809 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
811 }
812 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
814 }
815 return ra8_i3c_i2c_peripheral_send(channel, data, len);
816}
817
818ra8_err_t ra8_i3c_peripheral_receive(uint8_t channel, uint8_t* buf, uint32_t len)
819{
820 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
822 }
823 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
825 }
826 return ra8_i3c_i2c_peripheral_receive(channel, buf, len);
827}
828
829ra8_err_t ra8_i3c_peripheral_status(uint8_t channel, uint8_t* out_mask)
830{
831 if ((uint16_t)channel >= (uint16_t)k_ra8_i3c_i2c_channel_count) {
833 }
834 if (s_i3c_chan[channel].mode != k_ra8_i3c_mode_i2c) {
836 }
837 return ra8_i3c_i2c_peripheral_status(channel, out_mask);
838}
839
840/* =============================================================================
841 * Sweep 15 / Phase 2: HDR mode + IBI control + peripheral-mode entry
842 * =============================================================================
843 */
844
846{
847 if (target_addr > (uint8_t)k_ra8_i3c_addr_mask) {
849 }
851 (uint32_t)k_ra8_i3c_hdr_mode_ddr,
852 (uint32_t)k_ra8_i3c_hdr_mode_ts,
853 (uint32_t)mode)) {
855 }
856
857 /* HUM Ch 40 "Command Descriptor / Transfer Mode" pp 2445-2701 --
858 * regular-xfer attribute (0) + dynamic address + transfer-mode
859 * bits at [27:26]. */
860 uint32_t cmd = internal_ra8_i3c_xfer_cmd_word(target_addr, false);
861 const uint32_t mode_bits = ((uint32_t)mode & k_ra8_i3c_cmd_hdr_mode_mask)
863 cmd |= mode_bits;
864
865 volatile r_i3c_regs_t* reg = ra8_i3c();
866 reg->NCMDQP = cmd;
868 return k_ra8_ok;
869}
870
871ra8_err_t ra8_i3c_ibi_enable(uint8_t target_addr)
872{
873 if (target_addr > (uint8_t)k_ra8_i3c_addr_mask) {
875 }
876 /* HUM Ch 40 "IBI Valid Control Register" pp 2445-2701 -- VLCNT[7:0]
877 * carries the count of IBI entries the controller will accept. */
878 enum : uint32_t {
879 k_ra8_i3c_ntibivctl_one_target = 1U,
880 };
881 volatile r_i3c_regs_t* reg = ra8_i3c();
882 reg->NTIBIVCTL = (k_ra8_i3c_ntibivctl_one_target << k_ra8_i3c_ntibivctl_vlcnt_shift) &
884 (void)target_addr;
885 return k_ra8_ok;
886}
887
892
893ra8_err_t ra8_i3c_target_open(uint8_t static_addr)
894{
895 if (static_addr > (uint8_t)k_ra8_i3c_addr_mask) {
897 }
898
899 volatile r_i3c_regs_t* reg = ra8_i3c();
900 /* HUM Ch 40 "BCTL : Bus Control Register" pp 2445-2701 -- drop BUSE
901 * before flipping the SLVE bit. */
902 reg->BCTL = reg->BCTL & ~k_ra8_i3c_bctl_buse_mask;
903
904 /* HUM Ch 40 "NSDVAD : Peripheral Device Address Register" p 2445-2701 */
905 const uint32_t sdyad =
906 (((uint32_t)static_addr) << k_ra8_i3c_nsdvad_sdyad_shift) & k_ra8_i3c_nsdvad_sdyad_mask;
908
909 /* HUM Ch 40 "BCTL : Bus Control Register" pp 2445-2701 -- bit 16
910 * (SLVE) gates peripheral-mode reception. */
911 reg->BCTL = reg->BCTL | k_ra8_i3c_bctl_slve_mask;
912 return k_ra8_ok;
913}
914
915/* =============================================================================
916 * IBI inbound queue
917 * =============================================================================
918 */
919
921{
922 RA8_CHECK_NULL_PTR(out_ibi, s_tag, "out_ibi must not be nullptr");
923
924 volatile r_i3c_regs_t* reg = ra8_i3c();
925 /* NTST.IBIQEFF (bit 2) is set when the IBI queue holds at least
926 * one entry. See HUM Ch 40 "NTST" pp 2445-2701. */
927 if ((reg->NTST & k_ra8_i3c_ntst_ibiqeff_mask) == 0U) {
928 return k_ra8_err_no_data;
929 }
930
931 const uint32_t status = reg->NIBIQP;
932 const uint8_t len =
934 const uint8_t ibi_id =
936
937 out_ibi->address = (uint8_t)(ibi_id >> k_ra8_i3c_addr_shift_in_ibi_id);
938 /* Encode IBI/HJ/MR using the lowest two bits of IBI ID. See HUM
939 * Ch 40 "IBI Status Descriptor" pp 2445-2701 -- bit 31 (IBI_ST)
940 * separates IBI from HJ/MR; IBI_ID 0x02 == hot-join, 0x04 ==
941 * mainship-request in the MIPI I3C spec. */
942 enum : uint8_t {
943 k_ibi_id_hot_join = 0x02U,
944 };
945 if ((status & k_ra8_i3c_ibi_status_ibi_st_mask) == 0U) {
947 } else if (ibi_id == k_ibi_id_hot_join) {
949 } else {
951 }
952
953 const uint8_t k_max_ibi_payload = (uint8_t)(sizeof(out_ibi->payload));
954 uint8_t to_copy = len;
955 if (to_copy > k_max_ibi_payload) {
956 to_copy = k_max_ibi_payload;
957 }
958 out_ibi->payload_len = to_copy;
959 for (uint8_t i = 0U; i < k_max_ibi_payload; ++i) {
960 out_ibi->payload[i] = 0U;
961 }
962 if (to_copy > 0U) {
963 internal_ra8_i3c_fifo_read(reg, out_ibi->payload, (uint32_t)to_copy);
964 }
965 enum : uint32_t {
966 k_ibi_last_mask = 1U,
967 };
968 out_ibi->last = (uint8_t)((status >> k_ra8_i3c_ibi_status_last_shift) & k_ibi_last_mask);
969
970 /* Clear IBIQEFF so the next read can detect a fresh entry. */
972 return k_ra8_ok;
973}
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_no_data
No application data available (e.g.
Definition ra8_err.h:202
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ 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
ra8_err_t ra8_i3c_exit_stop(void)
Exit MSTP-gated stop (native mode).
Definition ra8_i3c.c:460
static uint32_t internal_ra8_i3c_ccc_cmd_word(uint8_t ccc, uint8_t target_addr, bool rnw)
Build a CCC-type command descriptor word.
Definition ra8_i3c.c:206
ra8_err_t ra8_i3c_target_open(uint8_t static_addr)
Enter peripheral (target) mode (native mode).
Definition ra8_i3c.c:893
ra8_err_t ra8_i3c_read(uint8_t channel, uint8_t addr, uint8_t *buf, uint32_t len, bool restart)
Read len bytes from addr.
Definition ra8_i3c.c:666
ra8_err_t ra8_i3c_get_status(uint32_t *out_mask)
Read the native INST status register (native mode).
Definition ra8_i3c.c:398
static void internal_ra8_i3c_fifo_read(volatile const r_i3c_regs_t *reg, uint8_t *out, uint32_t len)
Drain len bytes from NTDTBP0 into out.
Definition ra8_i3c.c:283
ra8_err_t ra8_i3c_transfer(uint8_t channel, uint8_t addr, const uint8_t *wr, uint32_t wr_len, uint8_t *rd, uint32_t rd_len)
Write-then-read with repeated-START framing (I2C mode).
Definition ra8_i3c.c:702
ra8_err_t ra8_i3c_send_ccc(uint8_t ccc, uint8_t target_addr, const uint8_t *payload, uint8_t len)
Generic CCC send – broadcast or directed write (native mode).
Definition ra8_i3c.c:555
ra8_err_t ra8_i3c_peripheral_send(uint8_t channel, const uint8_t *data, uint32_t len)
Queue bytes for the controller to read (responder mode).
Definition ra8_i3c.c:807
ra8_err_t ra8_i3c_clear_status(uint32_t mask)
Clear native INST status bits (native mode).
Definition ra8_i3c.c:406
void ra8_i3c_dispatch(uint8_t channel)
Snapshot status and fire the channel's callback.
Definition ra8_i3c.c:426
ra8_err_t ra8_i3c_deinit(uint8_t channel)
Tear down an I3C channel and gate the peripheral.
Definition ra8_i3c.c:348
ra8_err_t ra8_i3c_peripheral_receive(uint8_t channel, uint8_t *buf, uint32_t len)
Read bytes the controller wrote (responder mode).
Definition ra8_i3c.c:818
ra8_err_t ra8_i3c_enter_stop(void)
Put native I3C0 into MSTP-gated stop (native mode).
Definition ra8_i3c.c:452
ra8_err_t ra8_i3c_peripheral_status(uint8_t channel, uint8_t *out_mask)
Read the latched responder-mode status (responder mode).
Definition ra8_i3c.c:829
ra8_err_t ra8_i3c_set_dynamic_address(uint8_t static_addr, uint8_t dynamic_addr)
Issue SETDASA to assign one target a dynamic address (native mode).
Definition ra8_i3c.c:518
ra8_err_t ra8_i3c_bus_enable(bool enable)
Enable/disable bus-primary operation via BCTL.BUSE (native mode).
Definition ra8_i3c.c:385
ra8_err_t ra8_i3c_dynamic_address_assign(ra8_i3c_daa_target_t *targets, uint8_t target_count)
Issue ENTDAA to enumerate I3C targets (native mode).
Definition ra8_i3c.c:470
bool priv_ra8_i3c_internal_hdr_mode_invalid(uint32_t sdr_val, uint32_t ddr_val, uint32_t ts_val, uint32_t mode)
Pure HDR-mode-invalid predicate – see header for full contract.
Definition ra8_i3c.c:80
ra8_err_t ra8_i3c_attach_handler(uint8_t channel, ra8_i3c_event_fn_t fn, void *ctx)
Attach an event callback for a channel.
Definition ra8_i3c.c:415
ra8_err_t ra8_i3c_ibi_enable(uint8_t target_addr)
Enable inbound IBI capture for a target (native mode).
Definition ra8_i3c.c:871
ra8_err_t ra8_i3c_abort(uint8_t channel)
Abort an in-flight I2C transfer and release the bus (I2C mode).
Definition ra8_i3c.c:762
bool priv_ra8_i3c_internal_recv_ccc_invalid(uint8_t addr_mask, uint8_t target, uint8_t max_len)
Pure recv-ccc-invalid predicate – see header for full contract.
Definition ra8_i3c.c:58
ra8_err_t ra8_i3c_scan(uint8_t channel, uint8_t addr, bool *out_acked)
Probe whether a 7-bit address acknowledges (I2C mode).
Definition ra8_i3c.c:729
static ra8_i3c_event_fn_t s_i3c_fn
Currently registered IRQ callback (NULL when detached).
Definition ra8_i3c.c:92
ra8_err_t ra8_i3c_ibi_read(ra8_i3c_ibi_t *out_ibi)
Drain one inbound IBI from NIBIQP (native mode).
Definition ra8_i3c.c:920
static void internal_ra8_i3c_reset_sequence(volatile r_i3c_regs_t *reg)
Internal-error reset bring-up sequence per FSP R_I3C_Open.
Definition ra8_i3c.c:139
static ra8_i3c_chan_state_t s_i3c_chan[k_ra8_i3c_i2c_channel_count]
One state slot per I3C channel (RA8D2 exposes I3C0 only).
Definition ra8_i3c.c:107
ra8_err_t ra8_i3c_recv_ccc(uint8_t ccc, uint8_t target_addr, uint8_t *buf, uint8_t max_len, uint8_t *got_len)
Generic CCC receive – directed read (native mode).
Definition ra8_i3c.c:593
ra8_err_t ra8_i3c_set_address(uint32_t addr)
Programme the primary dynamic address (native mode).
Definition ra8_i3c.c:372
ra8_err_t ra8_i3c_write(uint8_t channel, uint8_t addr, const uint8_t *data, uint32_t len, bool restart)
Write len bytes to addr.
Definition ra8_i3c.c:621
static void * s_i3c_ctx
Opaque context handed back to s_i3c_fn.
Definition ra8_i3c.c:95
ra8_err_t ra8_i3c_ibi_drain(ra8_i3c_ibi_t *ibi)
Pop one inbound IBI (alias of ra8_i3c_ibi_read, native mode).
Definition ra8_i3c.c:888
static uint32_t internal_ra8_i3c_xfer_cmd_word(uint8_t target_addr, bool rnw)
Build the first word of a regular-transfer command descriptor.
Definition ra8_i3c.c:176
ra8_err_t ra8_i3c_set_hdr_mode(uint8_t target_addr, ra8_i3c_hdr_mode_t mode)
Programme the NCMDQP transfer-mode field for a target (native mode).
Definition ra8_i3c.c:845
ra8_err_t ra8_i3c_get_errors(uint8_t channel, uint8_t *out_mask)
Read the latched I2C error mask (I2C mode).
Definition ra8_i3c.c:740
ra8_err_t ra8_i3c_peripheral_open(uint8_t channel, const ra8_i3c_peripheral_cfg_t *cfg)
Open a channel in I2C-compat responder mode.
Definition ra8_i3c.c:778
ra8_err_t ra8_i3c_clear_errors(uint8_t channel)
Clear latched I2C error bits (I2C mode).
Definition ra8_i3c.c:751
ra8_err_t ra8_i3c_reset_dynamic_addresses(void)
Issue RSTDAA to clear all dynamic addresses (native mode).
Definition ra8_i3c.c:539
ra8_err_t ra8_i3c_init(uint8_t channel, const ra8_i3c_cfg_t *cfg)
Initialise an I3C channel in the configured mode.
Definition ra8_i3c.c:311
ra8_err_t ra8_i3c_peripheral_close(uint8_t channel)
Close responder mode on a channel.
Definition ra8_i3c.c:796
ra8_err_t ra8_i3c_set_clock(uint8_t channel, uint32_t bus_hz, uint32_t pclka_hz)
Re-programme the I2C bit rate (I2C mode).
Definition ra8_i3c.c:718
static void internal_ra8_i3c_fifo_write(volatile r_i3c_regs_t *reg, const uint8_t *data, uint32_t len)
Push a payload buffer through NTDTBP0 in 32-bit chunks.
Definition ra8_i3c.c:240
I3C Bus Interface driver – unified native-I3C + I2C-compat modes.
ra8_i3c_mode_t
Operating mode selected per channel at ra8_i3c_init.
Definition ra8_i3c.h:67
@ k_ra8_i3c_mode_i2c
Legacy I2C-compatibility controller.
Definition ra8_i3c.h:69
@ k_ra8_i3c_ibi_type_main_request
Mainship request.
Definition ra8_i3c.h:155
@ k_ra8_i3c_ibi_type_interrupt
Peripheral-initiated IBI.
Definition ra8_i3c.h:153
@ k_ra8_i3c_ibi_type_hot_join
Hot-join request.
Definition ra8_i3c.h:154
void(* ra8_i3c_event_fn_t)(void *ctx, uint32_t status)
Event callback fired by ra8_i3c_dispatch.
Definition ra8_i3c.h:123
ra8_i3c_hdr_mode_t
HDR transfer-mode selector for ra8_i3c_set_hdr_mode (native).
Definition ra8_i3c.h:185
@ k_ra8_i3c_hdr_mode_sdr
Plain SDR transfer (default).
Definition ra8_i3c.h:186
@ k_ra8_i3c_hdr_mode_ts
HDR-TS.
Definition ra8_i3c.h:188
@ k_ra8_i3c_hdr_mode_ddr
HDR-DDR.
Definition ra8_i3c.h:187
IIC_B (I3C unified IP, I2C-only mode) controller driver.
ra8_err_t ra8_i3c_i2c_init(uint8_t channel, const ra8_i3c_i2c_cfg_t *cfg)
Initialise the IIC_B channel and bring the bus up.
ra8_err_t ra8_i3c_i2c_abort(uint8_t channel)
Cancel any in-flight transaction and return the channel to idle.
ra8_err_t ra8_i3c_i2c_get_errors(uint8_t channel, uint8_t *out_mask)
Read latched error flags from BST (AL / NACKDF / TODF).
ra8_err_t ra8_i3c_i2c_read(uint8_t channel, uint8_t target_7b, uint8_t *buf, uint32_t len, bool restart)
Polling read of len bytes from a 7-bit target.
ra8_err_t ra8_i3c_i2c_transfer(uint8_t channel, uint8_t target_7b, const uint8_t *tx, uint32_t tx_len, uint8_t *rx, uint32_t rx_len)
Combined write-then-RESTART-then-read in a single bus transaction.
ra8_err_t ra8_i3c_i2c_deinit(uint8_t channel)
Tear down the IIC_B channel.
ra8_err_t ra8_i3c_i2c_set_clock(uint8_t channel, uint32_t bus_hz, uint32_t pclka_hz)
Update the bus clock without tearing the channel down.
ra8_err_t ra8_i3c_i2c_clear_errors(uint8_t channel)
Clear latched error flags in BST.
ra8_err_t ra8_i3c_i2c_scan(uint8_t channel, uint8_t target_7b, bool *out_acked)
Probe whether a 7-bit address ACKs.
ra8_err_t ra8_i3c_i2c_write(uint8_t channel, uint8_t target_7b, const uint8_t *data, uint32_t len, bool restart)
Polling write of len bytes to a 7-bit target address.
IIC_B (I3C in I2C-only mode) peripheral driver – mirrors FSP r_iic_b_peripheral.
ra8_err_t ra8_i3c_i2c_peripheral_status(uint8_t channel, uint8_t *out_mask)
Read latched peripheral-side status mask.
ra8_err_t ra8_i3c_i2c_peripheral_send(uint8_t channel, const uint8_t *data, uint32_t len)
Push len bytes into NTDTBP0 in response to a controller-read.
ra8_err_t ra8_i3c_i2c_peripheral_open(uint8_t channel, const ra8_i3c_i2c_peripheral_cfg_t *cfg)
Open a channel as an IIC_B peripheral.
ra8_err_t ra8_i3c_i2c_peripheral_receive(uint8_t channel, uint8_t *buf, uint32_t len)
Drain len bytes from NTDTBP0 after a controller-write.
ra8_err_t ra8_i3c_i2c_peripheral_close(uint8_t channel)
Close the peripheral channel.
IIC_B (I3C-based I2C) register layout for the Renesas RA8D2.
@ k_ra8_i3c_i2c_channel_count
HUM Ch 40.1.1, p 2445.
Test-access surface for ra8_i3c internal helpers (MC/DC).
I3C Bus Interface register layout for the Renesas RA8D2.
@ k_ra8_i3c_shift_b1
Shift for byte 1 in a word.
@ k_ra8_i3c_byte_shift
Bits per byte.
@ k_ra8_i3c_addr_shift_in_ibi_id
IBI ID = (addr << 1) | RnW.
@ k_ra8_i3c_shift_b3
Shift for byte 3 in a word.
@ k_ra8_i3c_word_size
Bytes per FIFO word.
@ k_ra8_i3c_byte_mask
Mask covering one byte.
@ k_ra8_i3c_shift_b2
Shift for byte 2 in a word.
@ k_ra8_i3c_pid_bytes
48-bit Provisional ID.
@ k_ra8_i3c_immediate_max_bytes
Immediate-data transfer cap.
@ k_ra8_i3c_addr_mask
7-bit dynamic address mask.
@ k_ra8_i3c_setdasa_payload_bytes
SETDASA carries one address byte.
@ k_ra8_i3c_max_targets
Cap on ENTDAA device-table size.
@ k_ra8_i3c_ibi_status_last_shift
RA8 I3C ibi status last shift.
@ k_ra8_i3c_ibi_status_length_mask
RA8 I3C ibi status length mask.
@ k_ra8_i3c_ibi_status_ibi_st_mask
IBI status type bit 31.
@ k_ra8_i3c_ibi_status_id_mask
RA8 I3C ibi status ID mask.
@ k_ra8_i3c_ibi_status_id_shift
RA8 I3C ibi status ID shift.
@ k_ra8_i3c_ibi_status_length_shift
RA8 I3C ibi status length shift.
@ k_ra8_i3c_ntst_ibiqeff_mask
IBI Queue Empty/Full bit 2.
@ k_ra8_i3c_ntst_cmdqef_mask
Cmd Queue Empty bit 3.
static volatile r_i3c_regs_t * ra8_i3c(void)
Get pointer to I3C0.
@ k_ra8_i3c_ccc_b_rstdaa
Broadcast Reset Dynamic Address Assignment.
@ k_ra8_i3c_ccc_direct_mask
Bit set in direct CCC opcodes.
@ k_ra8_i3c_ccc_d_setdasa
Direct Set Dynamic Address from Static Address.
@ k_ra8_i3c_ccc_b_entdaa
Broadcast Enter Dynamic Address Assignment.
@ k_ra8_i3c_rstctl_intlrst_mask
Internal software reset.
@ k_ra8_i3c_rstctl_ri3crst_mask
I3C software reset.
@ k_ra8_i3c_cmd_code_shift
CCC opcode position.
@ k_ra8_i3c_cmd_attr_shift
RA8 I3C cmd attr shift.
@ k_ra8_i3c_cmd_immed_bytes_shift
Immediate byte count [24:23].
@ k_ra8_i3c_cmd_addr_count_shift
ENTDAA device count.
@ k_ra8_i3c_cmd_attr_immed
Immediate-data transfer attribute.
@ k_ra8_i3c_cmd_roc_shift
Response-on-Completion.
@ k_ra8_i3c_cmd_cp_shift
Command Present (CCC) flag.
@ k_ra8_i3c_cmd_xfer_mode_shift
RA8 I3C cmd xfer mode shift.
@ k_ra8_i3c_cmd_dev_index_shift
Device-table index.
@ k_ra8_i3c_cmd_attr_addr_assgn
Address-assignment attribute.
@ k_ra8_i3c_cmd_xfer_length_shift
Transfer length [31:16].
@ k_ra8_i3c_cmd_rnw_shift
Read-not-Write direction bit.
@ k_ra8_i3c_cmd_xfer_length_max
RA8 I3C cmd xfer length maximum.
@ k_ra8_i3c_cmd_toc_shift
Terminate-on-Completion (STOP).
@ k_ra8_i3c_cmd_hdr_mode_mask
RA8 I3C cmd hdr mode mask.
@ k_ra8_i3c_bctl_buse_mask
BUSE bit 31.
@ k_ra8_i3c_bctl_slve_mask
SLVE bit 16 (peripheral-mode enable).
@ k_ra8_i3c_nsdvad_sdyad_mask
RA8 I3C nsdvad sdyad mask.
@ k_ra8_i3c_nsdvad_sdyad_shift
SDYAD bits [22:16].
@ k_ra8_i3c_nsdvad_sdyadv_mask
SDYADV bit 31.
@ k_ra8_i3c_ntibivctl_vlcnt_shift
RA8 I3C ntibivctl vlcnt shift.
@ k_ra8_i3c_ntibivctl_vlcnt_mask
Valid-entry count [7:0].
@ k_ra8_i3c_msdvad_mdyad_shift
MDYAD bits [22:16].
@ k_ra8_i3c_msdvad_addr_max
7-bit dynamic address.
@ k_ra8_i3c_msdvad_mdyadv_mask
MDYADV bit 31.
@ k_ra8_i3c_msdvad_mdyad_mask
RA8 I3C msdvad mdyad mask.
Lightweight Logging Interface for ra8-firmware.
#define ra8_log_info(tag, message)
RA8 log info.
Definition ra8_log.h:364
Ref-counted Module Stop Control wrapper for the RA8D2.
ra8_err_t ra8_mstp_enable(ra8_mstp_t id)
Reference-counted "ungate this peripheral" request.
Definition ra8_mstp.c:343
ra8_err_t ra8_mstp_disable(ra8_mstp_t id)
Reference-counted "gate this peripheral" request.
Definition ra8_mstp.c:382
Module Stop Control (MSTP) register layout for the Renesas RA8D2.
@ k_ra8_mstp_i3c
MSTPB4 I3C.
Partial RA8D2 I3C0 register window.
volatile uint32_t NSDVAD
+0x0B4 Peripheral Device Address Register (peripheral-mode dynamic address + valid).
volatile uint32_t NTST
+0x1E0 Normal Transfer Status Register.
volatile uint32_t NTDTBP0
+0x158 Normal Transfer Data Buffer Port Register 0.
volatile uint32_t INSTFC
+0x03C Internal Status Force Register.
volatile uint32_t NCMDQP
+0x150 Normal Command Queue Port Register.
volatile uint32_t NIBIQP
+0x17C Normal IBI Queue Port Register.
volatile uint32_t INIE
+0x038 Internal Interrupt Enable Register.
volatile uint32_t BCTL
+0x014 Bus Control Register.
volatile uint32_t INST
+0x030 Internal Status Register.
volatile uint32_t NTIBIVCTL
+0x0B8 IBI Valid Control Register (peripheral-side IBI queue valid count).
volatile uint32_t PRTS
+0x000 Protocol Selection Register.
volatile uint32_t INSTE
+0x034 Internal Status Enable Register.
volatile uint32_t CECTL
+0x010 Clock Enable Control Register.
volatile uint32_t MSDVAD
+0x018 Controller Device Address Register.
volatile uint32_t RSTCTL
+0x020 Reset Control Register.
Per-channel bring-up configuration for ra8_i3c_init.
Definition ra8_i3c.h:90
uint32_t bus_hz
Target bus clock in Hz (I2C mode).
Definition ra8_i3c.h:92
ra8_i3c_mode_t mode
Operating mode for this channel.
Definition ra8_i3c.h:91
uint32_t pclka_hz
Source clock for the bit-rate calc (I2C).
Definition ra8_i3c.h:93
Per-channel driver bookkeeping for the unified driver.
Definition ra8_i3c.c:101
ra8_i3c_mode_t mode
Native vs I2C-compat for this channel.
Definition ra8_i3c.c:103
bool initialized
Set between ra8_i3c_init / _deinit.
Definition ra8_i3c.c:102
One target entry filled in by ENTDAA (native mode).
Definition ra8_i3c.h:137
Configuration descriptor for ra8_i3c_i2c_init.
Definition ra8_i3c_i2c.h:77
Configuration descriptor for ra8_i3c_i2c_peripheral_open.
Decoded IBI inbound descriptor (native mode).
Definition ra8_i3c.h:169
uint8_t payload[8]
Up to 8 bytes of payload.
Definition ra8_i3c.h:173
uint8_t payload_len
Bytes that follow in payload[].
Definition ra8_i3c.h:172
ra8_i3c_ibi_type_t type
IBI / HJ / MR classification.
Definition ra8_i3c.h:171
uint8_t address
Originating dynamic address.
Definition ra8_i3c.h:170
uint8_t last
1 if this is the final fragment.
Definition ra8_i3c.h:174
Bring-up configuration for I2C-compat responder mode.
Definition ra8_i3c.h:774
uint8_t peripheral_addr_7b
7-bit own address.
Definition ra8_i3c.h:775
uint8_t general_call
Non-zero -> answer general-call address.
Definition ra8_i3c.h:776