10constexpr uint16_t kSharedMax7BitAddress = 0x7FU;
11constexpr uint16_t kSharedMax10BitAddress = 0x3FFU;
15 return mode == HPMI2C::AddressMode::ADDR_10BIT ? kSharedMax10BitAddress
16 : kSharedMax7BitAddress;
21 return (slave_addr <= ResolveHpmI2cMaxSlaveAddress(mode)) ? ErrorCode::OK
25ErrorCode ResolveHpmI2cMemAddressSize(I2C::MemAddrLength len, uint32_t& addr_size)
29 case I2C::MemAddrLength::BYTE_8:
32 case I2C::MemAddrLength::BYTE_16:
37 return ErrorCode::ARG_ERR;
41void FillHpmI2cMemAddress(uint16_t mem_addr, I2C::MemAddrLength len, uint8_t out[2])
43 if (len == I2C::MemAddrLength::BYTE_16)
45 out[0] =
static_cast<uint8_t
>((mem_addr >> 8) & 0xFFU);
46 out[1] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
50 out[0] =
static_cast<uint8_t
>(mem_addr & 0xFFU);
56uint16_t HPMI2C::GetMaxSlaveAddress(AddressMode mode)
58 return ResolveHpmI2cMaxSlaveAddress(mode);
61ErrorCode HPMI2C::ValidateSlaveAddress(uint16_t slave_addr)
const
63 return ValidateHpmI2cSlaveAddress(address_mode_, slave_addr);
66ErrorCode HPMI2C::ResolveMemAddressSize(MemAddrLength len, uint32_t& addr_size)
68 return ResolveHpmI2cMemAddressSize(len, addr_size);
71void HPMI2C::FillMemAddress(uint16_t mem_addr, MemAddrLength len, uint8_t out[2])
73 FillHpmI2cMemAddress(mem_addr, len, out);
78 if (policy.addr_hit_timeout_us == 0U || policy.stop_timeout_us == 0U ||
79 policy.bus_idle_timeout_us == 0U || policy.transfer_timeout_us == 0U)
84 if (AsyncTransferActive())
89 wait_policy_ = policy;
93#if LIBXR_HPM_I2C_SUPPORTED
95#if __has_include("hpm_interrupt.h")
96#include "hpm_interrupt.h"
97#define LIBXR_HPM_I2C_HAS_INTERRUPT 1
99#define LIBXR_HPM_I2C_HAS_INTERRUPT 0
102#if __has_include("hpm_l1c_drv.h")
103#include "hpm_l1c_drv.h"
104#define LIBXR_HPM_I2C_HAS_L1C 1
106#define LIBXR_HPM_I2C_HAS_L1C 0
109#if defined(__GNUC__) || defined(__clang__)
115extern "C" void libxr_hpm_i2c_wait_relax_hook(
void) __attribute__((weak));
116#define LIBXR_HPM_I2C_HAS_WAIT_RELAX_HOOK 1
118#define LIBXR_HPM_I2C_HAS_WAIT_RELAX_HOOK 0
127constexpr uint16_t kI2CFlagRead = I2C_RD;
128constexpr uint16_t kI2CFlagAddr10Bit = I2C_ADDR_10BIT;
129constexpr uint16_t kI2CFlagNoStart = I2C_NO_START;
130constexpr uint16_t kI2CFlagNoAddress = I2C_NO_ADDRESS;
131constexpr uint16_t kI2CFlagNoStop = I2C_NO_STOP;
132constexpr uint16_t kI2CFlagWriteCheckAck = I2C_WRITE_CHECK_ACK;
136static_assert(
sizeof(uintptr_t) <=
sizeof(uint32_t),
137 "HPM I2C DMA helper assumes a 32-bit address space.");
139uint32_t ToHpmI2cDmaAddress(
const volatile void* addr)
141 return static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(addr));
145constexpr size_t kHpmI2cInstanceCount = 8U;
146#elif defined(HPM_I2C6)
147constexpr size_t kHpmI2cInstanceCount = 7U;
148#elif defined(HPM_I2C5)
149constexpr size_t kHpmI2cInstanceCount = 6U;
150#elif defined(HPM_I2C4)
151constexpr size_t kHpmI2cInstanceCount = 5U;
153constexpr size_t kHpmI2cInstanceCount = 4U;
155HPMI2C* g_hpm_i2c_instance_map[kHpmI2cInstanceCount] = {};
157using HPMI2CPlatform::kInvalidDmaSource;
158using HPMI2CPlatform::ResolveI2cDmaSource;
159using HPMI2CPlatform::ResolveI2cIndex;
160using HPMI2CPlatform::ResolveI2cIrq;
162#if LIBXR_HPM_I2C_HAS_L1C
163static bool ResolveDCacheRange(
const void* addr, uint32_t size, uint32_t& start,
164 uint32_t& aligned_size)
166 if (addr ==
nullptr || size == 0U)
173 const uint64_t line_size = HPM_L1C_CACHELINE_SIZE;
174 const uint64_t address = ToHpmI2cDmaAddress(addr);
175 const uint64_t end = address +
static_cast<uint64_t
>(size);
176 constexpr uint64_t kAddressSpaceSize =
static_cast<uint64_t
>(UINT32_MAX) + 1ULL;
177 if (end > kAddressSpaceSize)
184 const uint64_t aligned_start = address - (address % line_size);
185 const uint64_t aligned_end = ((end + line_size - 1U) / line_size) * line_size;
186 const uint64_t range_size = aligned_end - aligned_start;
187 if (aligned_end > kAddressSpaceSize || range_size > UINT32_MAX)
194 start =
static_cast<uint32_t
>(aligned_start);
195 aligned_size =
static_cast<uint32_t
>(range_size);
196 return aligned_size > 0U;
200static void FlushDCacheIfNeeded(
const void* addr, uint32_t size)
202#if LIBXR_HPM_I2C_HAS_L1C
203 if (addr !=
nullptr && size > 0U && l1c_dc_is_enabled())
206 uint32_t aligned_size = 0U;
207 if (ResolveDCacheRange(addr, size, start, aligned_size))
209 l1c_dc_flush(start, aligned_size);
218static void InvalidateDCacheIfNeeded(
const void* addr, uint32_t size)
220#if LIBXR_HPM_I2C_HAS_L1C
221 if (addr !=
nullptr && size > 0U && l1c_dc_is_enabled())
224 uint32_t aligned_size = 0U;
225 if (ResolveDCacheRange(addr, size, start, aligned_size))
227 l1c_dc_invalidate(start, aligned_size);
238#if LIBXR_HPM_I2C_HAS_WAIT_RELAX_HOOK
239 if (libxr_hpm_i2c_wait_relax_hook !=
nullptr)
241 libxr_hpm_i2c_wait_relax_hook();
245 __asm
volatile(
"nop");
248uint32_t GetI2cWaitTicksPerUs()
250 static uint32_t ticks_per_us = 0U;
251 if (ticks_per_us == 0U)
253 ticks_per_us = clock_get_core_clock_ticks_per_us();
258uint64_t GetI2cWaitTimeoutTicks(uint64_t timeout_us)
260 const uint64_t ticks_per_us = GetI2cWaitTicksPerUs();
261 if (ticks_per_us != 0U && timeout_us > (UINT64_MAX / ticks_per_us))
265 return ticks_per_us * timeout_us;
268uint64_t GetI2cWaitCycle() {
return hpm_csr_get_core_cycle(); }
270template <
typename Predicate>
271bool WaitUntil(
const Predicate& predicate, uint64_t timeout_us)
273 const uint64_t start = GetI2cWaitCycle();
274 const uint64_t timeout_ticks = GetI2cWaitTimeoutTicks(timeout_us);
277 if ((GetI2cWaitCycle() - start) > timeout_ticks)
286bool WaitForBusIdle(I2C_Type* i2c, uint64_t timeout_us)
288 return WaitUntil([i2c]()
289 {
return (i2c_get_status(i2c) & I2C_STATUS_BUSBUSY_MASK) == 0U; },
300 i2c_clear_status(i2c, I2C_STATUS_CMPL_MASK);
301 i2c->CTRL = I2C_CTRL_PHASE_STOP_MASK;
302 i2c_master_issue_data_transmission(i2c);
306 const uint32_t status = i2c_get_status(i2c);
307 return ((status & I2C_STATUS_CMPL_MASK) != 0U) ||
308 ((status & I2C_STATUS_BUSBUSY_MASK) == 0U);
310 policy.stop_timeout_us);
312 i2c, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_BYTETRANS_MASK);
316hpm_stat_t DoManualTransferWithFlagsImpl(I2C_Type* i2c, uint16_t slave_addr,
RawData data,
319 if (i2c ==
nullptr || data.
addr_ ==
nullptr || data.
size_ == 0U)
321 return status_invalid_argument;
324 i2c_enable_10bit_address_mode(i2c, (flags & I2C_ADDR_10BIT) != 0U);
326 i2c, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_BYTETRANS_MASK);
328 i2c_master_set_slave_address(i2c, slave_addr);
330 if ((flags & I2C_RD) != 0U)
332 i2c_set_direction(i2c, I2C_DIR_MASTER_READ);
336 i2c_set_direction(i2c, I2C_DIR_MASTER_WRITE);
339 if ((flags & I2C_NO_START) != 0U)
341 i2c_master_disable_start_phase(i2c);
345 i2c_master_enable_start_phase(i2c);
348 if ((flags & I2C_NO_ADDRESS) != 0U)
350 i2c_master_disable_addr_phase(i2c);
354 i2c_master_enable_addr_phase(i2c);
357 if ((flags & I2C_NO_STOP) != 0U)
359 i2c_master_disable_stop_phase(i2c);
363 i2c_master_enable_stop_phase(i2c);
366 i2c_master_enable_data_phase(i2c);
367 i2c_set_data_count(i2c,
static_cast<uint32_t
>(data.
size_));
368 const uint32_t saved_inten = i2c->INTEN;
369 i2c->INTEN = saved_inten | I2C_EVENT_BYTE_RECEIVED;
370 i2c_master_issue_data_transmission(i2c);
372 hpm_stat_t raw_status = status_success;
373 auto* bytes =
static_cast<uint8_t*
>(data.
addr_);
374 uint32_t left =
static_cast<uint32_t
>(data.
size_);
376 if ((flags & I2C_NO_ADDRESS) == 0U)
378 const bool addr_hit = WaitUntil(
379 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_ADDRHIT_MASK) != 0U; },
380 policy.addr_hit_timeout_us);
383 raw_status = status_i2c_no_addr_hit;
387 i2c_clear_status(i2c, I2C_STATUS_ADDRHIT_MASK);
391 if (raw_status == status_success && (flags & I2C_RD) != 0U)
395 const bool ready = WaitUntil(
396 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_FIFOEMPTY_MASK) == 0U; },
397 policy.transfer_timeout_us);
400 raw_status = status_timeout;
404 *(bytes++) = i2c_read_byte(i2c);
408 i2c_respond_Nack(i2c);
410 else if ((flags & I2C_NO_READ_ACK) == 0U)
412 i2c_respond_ack(i2c);
416 else if (raw_status == status_success)
420 if ((flags & I2C_WRITE_CHECK_ACK) != 0U)
422 i2c_write_byte(i2c, *(bytes++));
425 const bool ready = WaitUntil(
426 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_BYTETRANS_MASK) != 0U; },
427 policy.transfer_timeout_us);
430 raw_status = status_timeout;
434 const uint32_t status = i2c_get_status(i2c);
435 i2c_clear_status(i2c, I2C_STATUS_BYTETRANS_MASK);
436 if (!I2C_STATUS_ACK_GET(status))
438 raw_status = status_i2c_no_ack;
444 const bool ready = WaitUntil(
445 [i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_FIFOFULL_MASK) == 0U; },
446 policy.transfer_timeout_us);
449 raw_status = status_timeout;
453 i2c_write_byte(i2c, *(bytes++));
459 if (raw_status == status_success)
461 const bool complete =
462 WaitUntil([i2c]() {
return (i2c_get_status(i2c) & I2C_STATUS_CMPL_MASK) != 0U; },
463 policy.transfer_timeout_us);
466 raw_status = status_timeout;
470 i2c_clear_status(i2c, I2C_STATUS_CMPL_MASK);
471 if (i2c_get_data_count(i2c) != 0U)
473 raw_status = status_i2c_transmit_not_completed;
478 if (raw_status != status_success)
480 IssueStopAndWait(i2c, policy);
482 i2c, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_BYTETRANS_MASK);
483 i2c_master_disable_data_phase(i2c);
484 i2c_master_disable_addr_phase(i2c);
485 i2c_master_disable_start_phase(i2c);
486 i2c_master_disable_stop_phase(i2c);
489 i2c->INTEN = saved_inten;
495#if LIBXR_HPM_I2C_HAS_INTERRUPT
496extern "C" void libxr_hpm_i2c_process_interrupt(I2C_Type* ptr)
498 const int32_t index = ResolveI2cIndex(ptr);
499 if (index >= 0 &&
static_cast<size_t>(index) < kHpmI2cInstanceCount &&
500 g_hpm_i2c_instance_map[index] !=
nullptr)
502 g_hpm_i2c_instance_map[index]->HandleAsyncInterrupt(
true);
506#if defined(IRQn_I2C0) && defined(HPM_I2C0)
507SDK_DECLARE_EXT_ISR_M(IRQn_I2C0, libxr_hpm_i2c0_isr)
508void libxr_hpm_i2c0_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C0); }
510#if defined(IRQn_I2C1) && defined(HPM_I2C1)
511SDK_DECLARE_EXT_ISR_M(IRQn_I2C1, libxr_hpm_i2c1_isr)
512void libxr_hpm_i2c1_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C1); }
514#if defined(IRQn_I2C2) && defined(HPM_I2C2)
515SDK_DECLARE_EXT_ISR_M(IRQn_I2C2, libxr_hpm_i2c2_isr)
516void libxr_hpm_i2c2_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C2); }
518#if defined(IRQn_I2C3) && defined(HPM_I2C3)
519SDK_DECLARE_EXT_ISR_M(IRQn_I2C3, libxr_hpm_i2c3_isr)
520void libxr_hpm_i2c3_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C3); }
522#if defined(IRQn_I2C4) && defined(HPM_I2C4)
523SDK_DECLARE_EXT_ISR_M(IRQn_I2C4, libxr_hpm_i2c4_isr)
524void libxr_hpm_i2c4_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C4); }
526#if defined(IRQn_I2C5) && defined(HPM_I2C5)
527SDK_DECLARE_EXT_ISR_M(IRQn_I2C5, libxr_hpm_i2c5_isr)
528void libxr_hpm_i2c5_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C5); }
530#if defined(IRQn_I2C6) && defined(HPM_I2C6)
531SDK_DECLARE_EXT_ISR_M(IRQn_I2C6, libxr_hpm_i2c6_isr)
532void libxr_hpm_i2c6_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C6); }
534#if defined(IRQn_I2C7) && defined(HPM_I2C7)
535SDK_DECLARE_EXT_ISR_M(IRQn_I2C7, libxr_hpm_i2c7_isr)
536void libxr_hpm_i2c7_isr(
void) { libxr_hpm_i2c_process_interrupt(HPM_I2C7); }
539extern "C" void libxr_hpm_i2c_process_interrupt(I2C_Type* ptr) { UNUSED(ptr); }
543 : i2c_(i2c), clock_(clock), current_config_(config)
545 ASSERT(i2c_ !=
nullptr);
550 clock_add_to_group(clock_, 0);
551 source_clock_hz_ = clock_get_frequency(clock_);
553 REQUIRE(source_clock_hz_ != 0);
565 if (address_mode_ == mode && configured_)
570 if (AsyncTransferActive())
574 DisableAsyncI2cIrq();
576 IssueStopAndWait(i2c_, wait_policy_);
577 (void)WaitForBusIdle(i2c_, wait_policy_.bus_idle_timeout_us);
580 address_mode_ = mode;
581 const ErrorCode ans = ApplyConfig(current_config_);
582 (void)WaitForBusIdle(i2c_, wait_policy_.bus_idle_timeout_us);
585 address_mode_ = previous_mode;
588 (void)ApplyConfig(current_config_);
594ErrorCode HPMI2C::ConvertStatus(hpm_stat_t status)
602 case status_invalid_argument:
604 case status_i2c_bus_busy:
606 case status_i2c_not_supported:
608 case status_i2c_no_ack:
609 case status_i2c_no_addr_hit:
611 case status_i2c_invalid_data:
613 case status_i2c_transmit_not_completed:
620ErrorCode HPMI2C::ResolveMode(uint32_t clock_speed, i2c_mode_t& mode)
622 if (clock_speed == 100000UL)
624 mode = i2c_mode_normal;
626 else if (clock_speed == 400000UL)
628 mode = i2c_mode_fast;
630 else if (clock_speed == 1000000UL)
632 mode = i2c_mode_fast_plus;
634 else if (clock_speed == 0)
646ErrorCode HPMI2C::ConvertDmaStatus(hpm_stat_t status)
652 case status_invalid_argument:
654 case status_dma_mgr_no_resource:
661i2c_seq_transfer_opt_t HPMI2C::ConvertSequenceFrame(SequenceFrame frame)
666 return i2c_frist_frame;
668 return i2c_next_frame;
671 return i2c_last_frame;
675uint16_t HPMI2C::BuildTransferFlags(uint16_t flags)
const
688 clock_add_to_group(clock_, 0);
689 source_clock_hz_ = clock_get_frequency(clock_);
690 if (source_clock_hz_ == 0)
710 return ApplyConfig(current_config_);
713ErrorCode HPMI2C::ApplyConfig(
const Configuration& config)
720 i2c_mode_t mode = i2c_mode_normal;
721 ErrorCode ans = ResolveMode(config.clock_speed, mode);
727 ans = EnsureClockReady();
733 i2c_config_t i2c_config{};
734 i2c_config.i2c_mode = mode;
737 const uint32_t previous_setup = i2c_->SETUP;
738 const uint32_t previous_tpm = i2c_->TPM;
739 const uint32_t previous_interrupts = i2c_->INTEN;
740 ans = ConvertStatus(i2c_init_master(i2c_, source_clock_hz_, &i2c_config));
743 current_config_ = config;
746 else if (configured_)
750 i2c_->TPM = previous_tpm;
751 i2c_->SETUP = previous_setup;
752 i2c_->INTEN = previous_interrupts;
758bool HPMI2C::ShouldRecover(hpm_stat_t status)
763 case status_i2c_bus_busy:
764 case status_i2c_no_ack:
765 case status_i2c_no_addr_hit:
772void HPMI2C::RecoverController()
779 IssueStopAndWait(i2c_, wait_policy_);
780 (void)WaitForBusIdle(i2c_, wait_policy_.bus_idle_timeout_us);
781 TryRecoverBusLines();
785 (void)ApplyConfig(current_config_);
787 (void)WaitForBusIdle(i2c_, wait_policy_.bus_idle_timeout_us);
790void HPMI2C::TryRecoverBusLines()
797#if defined(HPM_IP_FEATURE_I2C_SUPPORT_RESET) && (HPM_IP_FEATURE_I2C_SUPPORT_RESET == 1)
798 if (i2c_get_line_scl_status(i2c_) && !i2c_get_line_sda_status(i2c_))
800 i2c_gen_reset_signal(i2c_, 9);
805uint32_t HPMI2C::ToSystemAddress(
const void* addr)
807 return core_local_mem_to_sys_address(HPM_CORE0, ToHpmI2cDmaAddress(addr));
810ErrorCode HPMI2C::PrepareAsyncTransfer(uint16_t slave_addr, uint16_t flags, uint32_t size,
811 bool clear_fifo,
bool require_bus_idle)
818 if (require_bus_idle)
820 if (!WaitForBusIdle(i2c_, wait_policy_.transfer_timeout_us))
826 i2c_clear_status(i2c_, I2C_STATUS_CMPL_MASK);
829 i2c_clear_fifo(i2c_);
832 const uint16_t final_flags = BuildTransferFlags(flags);
833 i2c_master_set_slave_address(i2c_, slave_addr);
834 if ((final_flags & I2C_RD) != 0U)
836 i2c_set_direction(i2c_, I2C_DIR_MASTER_READ);
840 i2c_set_direction(i2c_, I2C_DIR_MASTER_WRITE);
843 if ((final_flags & I2C_NO_START) != 0U)
845 i2c_master_disable_start_phase(i2c_);
849 i2c_master_enable_start_phase(i2c_);
852 if ((final_flags & I2C_NO_ADDRESS) != 0U)
854 i2c_master_disable_addr_phase(i2c_);
858 i2c_master_enable_addr_phase(i2c_);
861 if ((final_flags & I2C_NO_STOP) != 0U)
863 i2c_master_disable_stop_phase(i2c_);
867 i2c_master_enable_stop_phase(i2c_);
872 i2c_master_enable_data_phase(i2c_);
873 i2c_set_data_count(i2c_, size);
877 i2c_master_disable_data_phase(i2c_);
880 i2c_dma_disable(i2c_);
881 i2c_master_issue_data_transmission(i2c_);
883 if ((final_flags & I2C_NO_ADDRESS) == 0U)
885 const bool addr_hit = WaitUntil(
886 [
this]() {
return (i2c_get_status(i2c_) & I2C_STATUS_ADDRHIT_MASK) != 0U; },
887 wait_policy_.addr_hit_timeout_us);
890 StopAndReleaseAsyncBus();
893 i2c_clear_status(i2c_, I2C_STATUS_ADDRHIT_MASK);
899ErrorCode HPMI2C::StartAsyncReadDma(
void* dst, uint32_t size)
901 if (i2c_ ==
nullptr || dst ==
nullptr || size == 0U)
911 FlushDCacheIfNeeded(dst, size);
914 dma_mgr_set_chn_dst_addr(&async_dma_resource_, ToSystemAddress(dst));
915 if (status != status_success)
917 return ConvertDmaStatus(status);
920 dma_mgr_set_chn_dst_work_mode(&async_dma_resource_, DMA_MGR_HANDSHAKE_MODE_NORMAL);
921 if (status != status_success)
923 return ConvertDmaStatus(status);
925 status = dma_mgr_set_chn_dst_addr_ctrl(&async_dma_resource_,
926 DMA_MGR_ADDRESS_CONTROL_INCREMENT);
927 if (status != status_success)
929 return ConvertDmaStatus(status);
932 dma_mgr_set_chn_src_addr(&async_dma_resource_, ToHpmI2cDmaAddress(&i2c_->DATA));
933 if (status != status_success)
935 return ConvertDmaStatus(status);
937 status = dma_mgr_set_chn_src_work_mode(&async_dma_resource_,
938 DMA_MGR_HANDSHAKE_MODE_HANDSHAKE);
939 if (status != status_success)
941 return ConvertDmaStatus(status);
944 dma_mgr_set_chn_src_addr_ctrl(&async_dma_resource_, DMA_MGR_ADDRESS_CONTROL_FIXED);
945 if (status != status_success)
947 return ConvertDmaStatus(status);
949 status = dma_mgr_set_chn_src_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
950 if (status != status_success)
952 return ConvertDmaStatus(status);
954 status = dma_mgr_set_chn_dst_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
955 if (status != status_success)
957 return ConvertDmaStatus(status);
959 status = dma_mgr_set_chn_transize(&async_dma_resource_, size);
960 if (status != status_success)
962 return ConvertDmaStatus(status);
965 i2c_dma_enable(i2c_);
966 dma_clear_transfer_status(async_dma_resource_.base, async_dma_resource_.channel);
967 status = dma_mgr_enable_channel(&async_dma_resource_);
968 if (status != status_success)
970 i2c_dma_disable(i2c_);
971 return ConvertDmaStatus(status);
976ErrorCode HPMI2C::StartAsyncWriteDma(
const void* src, uint32_t size)
978 if (i2c_ ==
nullptr || src ==
nullptr || size == 0U)
988 FlushDCacheIfNeeded(src, size);
991 dma_mgr_set_chn_src_addr(&async_dma_resource_, ToSystemAddress(src));
992 if (status != status_success)
994 return ConvertDmaStatus(status);
997 dma_mgr_set_chn_src_work_mode(&async_dma_resource_, DMA_MGR_HANDSHAKE_MODE_NORMAL);
998 if (status != status_success)
1000 return ConvertDmaStatus(status);
1002 status = dma_mgr_set_chn_src_addr_ctrl(&async_dma_resource_,
1003 DMA_MGR_ADDRESS_CONTROL_INCREMENT);
1004 if (status != status_success)
1006 return ConvertDmaStatus(status);
1009 dma_mgr_set_chn_dst_addr(&async_dma_resource_, ToHpmI2cDmaAddress(&i2c_->DATA));
1010 if (status != status_success)
1012 return ConvertDmaStatus(status);
1014 status = dma_mgr_set_chn_dst_work_mode(&async_dma_resource_,
1015 DMA_MGR_HANDSHAKE_MODE_HANDSHAKE);
1016 if (status != status_success)
1018 return ConvertDmaStatus(status);
1021 dma_mgr_set_chn_dst_addr_ctrl(&async_dma_resource_, DMA_MGR_ADDRESS_CONTROL_FIXED);
1022 if (status != status_success)
1024 return ConvertDmaStatus(status);
1026 status = dma_mgr_set_chn_src_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
1027 if (status != status_success)
1029 return ConvertDmaStatus(status);
1031 status = dma_mgr_set_chn_dst_width(&async_dma_resource_, DMA_MGR_TRANSFER_WIDTH_BYTE);
1032 if (status != status_success)
1034 return ConvertDmaStatus(status);
1036 status = dma_mgr_set_chn_transize(&async_dma_resource_, size);
1037 if (status != status_success)
1039 return ConvertDmaStatus(status);
1042 i2c_dma_enable(i2c_);
1043 dma_clear_transfer_status(async_dma_resource_.base, async_dma_resource_.channel);
1044 status = dma_mgr_enable_channel(&async_dma_resource_);
1045 if (status != status_success)
1047 i2c_dma_disable(i2c_);
1048 return ConvertDmaStatus(status);
1053void HPMI2C::StopAsyncDma()
1055 if (async_dma_ready_)
1057 (void)dma_mgr_disable_channel(&async_dma_resource_);
1059 if (i2c_ !=
nullptr)
1061 i2c_dma_disable(i2c_);
1065void HPMI2C::StopAndReleaseAsyncBus()
1067 IssueStopAndWait(i2c_, wait_policy_);
1071void HPMI2C::AsyncCompletionStateMachine::Reset(AsyncTransferContext& ctx)
1073 ctx.final_status.store(status_success, std::memory_order_release);
1074 ctx.should_recover.store(
false, std::memory_order_release);
1075 ctx.dma_done.store(
false, std::memory_order_release);
1076 ctx.cmpl_done.store(
false, std::memory_order_release);
1079void HPMI2C::AsyncCompletionStateMachine::MarkDmaDone(AsyncTransferContext& ctx)
1081 ctx.dma_done.store(
true, std::memory_order_release);
1084void HPMI2C::AsyncCompletionStateMachine::MarkI2cDone(AsyncTransferContext& ctx,
1085 hpm_stat_t status,
bool recover)
1087 ctx.cmpl_done.store(
true, std::memory_order_release);
1088 ctx.final_status.store(status, std::memory_order_release);
1089 ctx.should_recover.store(recover, std::memory_order_release);
1092void HPMI2C::AsyncCompletionStateMachine::MarkFailure(AsyncTransferContext& ctx,
1093 hpm_stat_t status,
bool recover)
1095 ctx.final_status.store(status, std::memory_order_release);
1096 ctx.should_recover.store(recover, std::memory_order_release);
1099void HPMI2C::AsyncCompletionStateMachine::SetFinalStatus(AsyncTransferContext& ctx,
1102 ctx.final_status.store(status, std::memory_order_release);
1105bool HPMI2C::AsyncCompletionStateMachine::DmaDone(
const AsyncTransferContext& ctx)
1107 return ctx.dma_done.load(std::memory_order_acquire);
1110bool HPMI2C::AsyncCompletionStateMachine::Ready(
const AsyncTransferContext& ctx)
1112 return DmaDone(ctx) && ctx.cmpl_done.load(std::memory_order_acquire);
1115hpm_stat_t HPMI2C::AsyncCompletionStateMachine::FinalStatus(
1116 const AsyncTransferContext& ctx)
1118 return ctx.final_status.load(std::memory_order_acquire);
1121bool HPMI2C::AsyncCompletionStateMachine::ShouldRecover(
const AsyncTransferContext& ctx)
1123 return ctx.should_recover.load(std::memory_order_acquire);
1126void HPMI2C::ClearAsyncContext()
1128 async_ctx_.kind = AsyncTransferKind::NONE;
1129 async_ctx_.slave_addr = 0U;
1130 async_ctx_.mem_addr_size = MemAddrLength::BYTE_8;
1131 async_ctx_.mem_addr = 0U;
1132 async_ctx_.mem_addr_size_in_byte = 0U;
1133 async_ctx_.mem_addr_bytes[0] = 0U;
1134 async_ctx_.mem_addr_bytes[1] = 0U;
1135 async_ctx_.flags = 0U;
1136 async_ctx_.read_data = {
nullptr, 0};
1137 async_ctx_.write_data = {
nullptr, 0};
1138 async_ctx_.read_op = {};
1139 async_ctx_.write_op = {};
1140 AsyncCompletionStateMachine::Reset(async_ctx_);
1143void HPMI2C::ResetAsyncState()
1145 ClearAsyncContext();
1146 async_busy_.store(0U, std::memory_order_release);
1147 async_completion_claim_.store(0U, std::memory_order_release);
1150void HPMI2C::AbortAsyncStart(
bool stop_dma,
bool disable_irq,
bool recover_controller)
1158 DisableAsyncI2cIrq();
1161 if (recover_controller)
1163 RecoverController();
1175 if (!TryClaimAsyncCompletion())
1179 DisableAsyncI2cIrq();
1183 const bool should_recover = AsyncCompletionStateMachine::ShouldRecover(async_ctx_);
1186 RecoverController();
1192 async_ctx_.kind = AsyncTransferKind::NONE;
1195 if (kind == AsyncTransferKind::WRITE)
1197 CompleteAsyncOperation(write_op, in_isr, ans);
1201 CompleteAsyncOperation(read_op, in_isr, ans);
1208 if (AsyncTransferActive())
1213 ErrorCode ans = EnsureControllerReady();
1219 async_busy_.store(1U, std::memory_order_release);
1220 ClearAsyncContext();
1221 async_ctx_.kind = AsyncTransferKind::WRITE;
1222 async_ctx_.slave_addr = slave_addr;
1223 async_ctx_.write_data = write_data;
1224 async_ctx_.write_op = op;
1225 async_ctx_.flags = BuildTransferFlags(kI2CFlagWriteCheckAck);
1226 async_completion_claim_.store(0U, std::memory_order_release);
1229 StartAsyncBlockWaitIfNeeded(op);
1231 ans = EnableAsyncI2cIrq();
1234 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1235 AbortAsyncStart(
false,
false,
false);
1236 CancelAsyncBlockWaitIfNeeded(op);
1240 i2c_clear_fifo(i2c_);
1241 ans = StartAsyncWriteDma(write_data.
addr_,
static_cast<uint32_t
>(write_data.
size_));
1244 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1245 AbortAsyncStart(
false,
true,
false);
1246 CancelAsyncBlockWaitIfNeeded(op);
1250 hpm_stat_t start_status = i2c_master_start_dma_write(
1251 i2c_, slave_addr,
static_cast<uint32_t
>(write_data.
size_));
1252 ans = ConvertStatus(start_status);
1255 AsyncCompletionStateMachine::MarkFailure(async_ctx_, start_status,
1256 ShouldRecover(start_status));
1257 AbortAsyncStart(
true,
true, ShouldRecover(start_status));
1258 CancelAsyncBlockWaitIfNeeded(op);
1262 if (op.
type == WriteOperation::OperationType::BLOCK)
1264 return WaitForAsyncBlockResult(op.
data.sem_info.
timeout);
1272 if (AsyncTransferActive())
1277 ErrorCode ans = EnsureControllerReady();
1283 async_busy_.store(1U, std::memory_order_release);
1284 ClearAsyncContext();
1285 async_ctx_.kind = AsyncTransferKind::READ;
1286 async_ctx_.slave_addr = slave_addr;
1287 async_ctx_.read_data = read_data;
1288 async_ctx_.read_op = op;
1289 async_ctx_.flags = kI2CFlagRead;
1290 async_completion_claim_.store(0U, std::memory_order_release);
1293 StartAsyncBlockWaitIfNeeded(op);
1295 ans = EnableAsyncI2cIrq();
1298 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1299 AbortAsyncStart(
false,
false,
false);
1300 CancelAsyncBlockWaitIfNeeded(op);
1304 i2c_clear_fifo(i2c_);
1305 ans = StartAsyncReadDma(read_data.
addr_,
static_cast<uint32_t
>(read_data.
size_));
1308 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1309 AbortAsyncStart(
false,
true,
false);
1310 CancelAsyncBlockWaitIfNeeded(op);
1314 hpm_stat_t start_status =
1315 i2c_master_start_dma_read(i2c_, slave_addr,
static_cast<uint32_t
>(read_data.
size_));
1316 ans = ConvertStatus(start_status);
1319 AsyncCompletionStateMachine::MarkFailure(async_ctx_, start_status,
1320 ShouldRecover(start_status));
1321 AbortAsyncStart(
true,
true, ShouldRecover(start_status));
1322 CancelAsyncBlockWaitIfNeeded(op);
1326 if (op.
type == ReadOperation::OperationType::BLOCK)
1328 return WaitForAsyncBlockResult(op.
data.sem_info.
timeout);
1333ErrorCode HPMI2C::StartMemReadAsync(uint16_t slave_addr, uint16_t mem_addr,
1335 MemAddrLength mem_addr_size)
1337 if (AsyncTransferActive())
1342 uint32_t addr_size = 0U;
1343 ErrorCode ans = ResolveMemAddressSize(mem_addr_size, addr_size);
1348 if (addr_size > I2C_SOC_TRANSFER_COUNT_MAX)
1353 ans = EnsureControllerReady();
1359 async_busy_.store(1U, std::memory_order_release);
1360 ClearAsyncContext();
1361 async_ctx_.kind = AsyncTransferKind::MEM_READ;
1362 async_ctx_.slave_addr = slave_addr;
1363 async_ctx_.mem_addr = mem_addr;
1364 async_ctx_.mem_addr_size = mem_addr_size;
1365 async_ctx_.mem_addr_size_in_byte = addr_size;
1366 FillMemAddress(mem_addr, mem_addr_size, async_ctx_.mem_addr_bytes);
1367 async_ctx_.read_data = read_data;
1368 async_ctx_.read_op = op;
1369 async_ctx_.flags = kI2CFlagRead;
1370 async_completion_claim_.store(0U, std::memory_order_release);
1373 StartAsyncBlockWaitIfNeeded(op);
1375 ans = PrepareAsyncTransfer(slave_addr, kI2CFlagNoStop, async_ctx_.mem_addr_size_in_byte,
1380 CancelAsyncBlockWaitIfNeeded(op);
1384 for (uint32_t i = 0U; i < async_ctx_.mem_addr_size_in_byte; ++i)
1386 i2c_write_byte(i2c_, async_ctx_.mem_addr_bytes[i]);
1389 const bool mem_addr_complete =
1390 WaitUntil([
this]() {
return (i2c_get_status(i2c_) & I2C_STATUS_CMPL_MASK) != 0U; },
1391 wait_policy_.transfer_timeout_us);
1392 if (!mem_addr_complete)
1394 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_timeout,
true);
1395 StopAndReleaseAsyncBus();
1397 CancelAsyncBlockWaitIfNeeded(op);
1400 i2c_clear_status(i2c_, I2C_STATUS_CMPL_MASK);
1401 i2c_clear_fifo(i2c_);
1403 const uint16_t final_flags = BuildTransferFlags(kI2CFlagRead);
1404 i2c_master_set_slave_address(i2c_, slave_addr);
1405 i2c_set_direction(i2c_, I2C_DIR_MASTER_READ);
1406 i2c_master_enable_start_phase(i2c_);
1407 i2c_master_enable_addr_phase(i2c_);
1408 i2c_master_enable_stop_phase(i2c_);
1409 i2c_master_enable_data_phase(i2c_);
1410 i2c_set_data_count(i2c_,
static_cast<uint32_t
>(read_data.
size_));
1411 i2c_dma_disable(i2c_);
1412 if ((final_flags & kI2CFlagAddr10Bit) != 0U)
1414 i2c_enable_10bit_address_mode(i2c_,
true);
1417 ans = EnableAsyncI2cIrq();
1420 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1421 StopAndReleaseAsyncBus();
1423 CancelAsyncBlockWaitIfNeeded(op);
1427 ans = StartAsyncReadDma(read_data.
addr_,
static_cast<uint32_t
>(read_data.
size_));
1430 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_fail,
true);
1431 DisableAsyncI2cIrq();
1432 StopAndReleaseAsyncBus();
1434 CancelAsyncBlockWaitIfNeeded(op);
1438 i2c_master_issue_data_transmission(i2c_);
1439 const bool addr_hit = WaitUntil(
1440 [
this]() {
return (i2c_get_status(i2c_) & I2C_STATUS_ADDRHIT_MASK) != 0U; },
1441 wait_policy_.addr_hit_timeout_us);
1444 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_i2c_no_addr_hit,
true);
1445 AbortAsyncStart(
true,
true,
true);
1446 CancelAsyncBlockWaitIfNeeded(op);
1449 i2c_clear_status(i2c_, I2C_STATUS_ADDRHIT_MASK);
1451 if (op.
type == ReadOperation::OperationType::BLOCK)
1453 return WaitForAsyncBlockResult(op.
data.sem_info.
timeout);
1460 if (async_dma_ready_)
1465 if (i2c_ ==
nullptr)
1470 async_dma_source_ = ResolveI2cDmaSource(i2c_);
1471 if (async_dma_source_ == kInvalidDmaSource)
1477 hpm_stat_t status = dma_mgr_request_resource(&async_dma_resource_);
1478 if (status != status_success)
1480 return ConvertDmaStatus(status);
1483 dma_mgr_chn_conf_t cfg{};
1484 dma_mgr_get_default_chn_config(&cfg);
1485 cfg.src_width = DMA_MGR_TRANSFER_WIDTH_BYTE;
1486 cfg.dst_width = DMA_MGR_TRANSFER_WIDTH_BYTE;
1487 cfg.en_dmamux =
true;
1488 cfg.dmamux_src = async_dma_source_;
1489 cfg.interrupt_mask = DMA_MGR_INTERRUPT_MASK_ALL;
1490 status = dma_mgr_setup_channel(&async_dma_resource_, &cfg);
1491 if (status != status_success)
1493 (void)dma_mgr_release_resource(&async_dma_resource_);
1494 async_dma_resource_ = {
nullptr, 0U, -1};
1495 return ConvertDmaStatus(status);
1498 status = dma_mgr_install_chn_tc_callback(&async_dma_resource_, &HPMI2C::OnDmaTcCallback,
1500 if (status != status_success)
1502 (void)dma_mgr_release_resource(&async_dma_resource_);
1503 async_dma_resource_ = {
nullptr, 0U, -1};
1504 return ConvertDmaStatus(status);
1506 status = dma_mgr_install_chn_error_callback(&async_dma_resource_,
1507 &HPMI2C::OnDmaErrorCallback,
this);
1508 if (status != status_success)
1510 (void)dma_mgr_release_resource(&async_dma_resource_);
1511 async_dma_resource_ = {
nullptr, 0U, -1};
1512 return ConvertDmaStatus(status);
1514 status = dma_mgr_install_chn_abort_callback(&async_dma_resource_,
1515 &HPMI2C::OnDmaAbortCallback,
this);
1516 if (status != status_success)
1518 (void)dma_mgr_release_resource(&async_dma_resource_);
1519 async_dma_resource_ = {
nullptr, 0U, -1};
1520 return ConvertDmaStatus(status);
1522 status = dma_mgr_enable_chn_irq(&async_dma_resource_, DMA_MGR_INTERRUPT_MASK_TC |
1523 DMA_MGR_INTERRUPT_MASK_ERROR |
1524 DMA_MGR_INTERRUPT_MASK_ABORT);
1525 if (status != status_success)
1527 (void)dma_mgr_release_resource(&async_dma_resource_);
1528 async_dma_resource_ = {
nullptr, 0U, -1};
1529 return ConvertDmaStatus(status);
1531 status = dma_mgr_enable_dma_irq_with_priority(&async_dma_resource_, 1U);
1532 if (status != status_success)
1534 (void)dma_mgr_release_resource(&async_dma_resource_);
1535 async_dma_resource_ = {
nullptr, 0U, -1};
1536 return ConvertDmaStatus(status);
1539 async_dma_ready_ =
true;
1543ErrorCode HPMI2C::WaitForAsyncBlockResult(uint32_t timeout)
1548 AsyncCompletionStateMachine::MarkFailure(async_ctx_, status_timeout,
true);
1554void HPMI2C::ReleaseAsyncBus()
1556 if (i2c_ ==
nullptr)
1561 i2c_clear_status(i2c_, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK);
1562 i2c_master_disable_data_phase(i2c_);
1563 i2c_master_disable_addr_phase(i2c_);
1564 i2c_master_disable_start_phase(i2c_);
1565 i2c_master_disable_stop_phase(i2c_);
1566 i2c_master_issue_data_transmission(i2c_);
1571#if !LIBXR_HPM_I2C_HAS_INTERRUPT
1574 const int32_t irq = ResolveI2cIrq(i2c_);
1575 const int32_t index = ResolveI2cIndex(i2c_);
1576 if (irq < 0 || index < 0 ||
static_cast<size_t>(index) >= kHpmI2cInstanceCount)
1580 if (g_hpm_i2c_instance_map[index] !=
nullptr && g_hpm_i2c_instance_map[index] !=
this)
1585 g_hpm_i2c_instance_map[index] =
this;
1587 i2c_, I2C_STATUS_CMPL_MASK | I2C_STATUS_ADDRHIT_MASK | I2C_STATUS_ARBLOSE_MASK);
1588 i2c_enable_irq(i2c_, I2C_EVENT_TRANSACTION_COMPLETE | I2C_EVENT_LOSS_ARBITRATION);
1589 intc_m_enable_irq_with_priority(
static_cast<uint32_t
>(irq), 1U);
1594void HPMI2C::DisableAsyncI2cIrq()
1596#if LIBXR_HPM_I2C_HAS_INTERRUPT
1597 if (i2c_ !=
nullptr)
1599 i2c_disable_irq(i2c_, I2C_EVENT_TRANSACTION_COMPLETE | I2C_EVENT_LOSS_ARBITRATION);
1600 const int32_t irq = ResolveI2cIrq(i2c_);
1603 intc_m_disable_irq(
static_cast<uint32_t
>(irq));
1606 const int32_t index = ResolveI2cIndex(i2c_);
1607 if (index >= 0 &&
static_cast<size_t>(index) < kHpmI2cInstanceCount &&
1608 g_hpm_i2c_instance_map[index] ==
this)
1610 g_hpm_i2c_instance_map[index] =
nullptr;
1615void HPMI2C::HandleAsyncInterrupt(
bool in_isr)
1617 if (!AsyncTransferActive() || i2c_ ==
nullptr)
1622 const uint32_t status = i2c_get_status(i2c_);
1623 if ((status & I2C_STATUS_ARBLOSE_MASK) != 0U)
1625 i2c_clear_status(i2c_, I2C_STATUS_ARBLOSE_MASK);
1626 AsyncCompletionStateMachine::MarkI2cDone(async_ctx_, status_timeout,
true);
1631 if ((status & I2C_STATUS_CMPL_MASK) != 0U)
1633 i2c_clear_status(i2c_, I2C_STATUS_CMPL_MASK);
1634 if (async_ctx_.kind == AsyncTransferKind::WRITE &&
1635 (async_ctx_.flags & kI2CFlagWriteCheckAck) != 0U && !I2C_STATUS_ACK_GET(status))
1637 AsyncCompletionStateMachine::MarkI2cDone(async_ctx_, status_i2c_no_ack,
true);
1641 AsyncCompletionStateMachine::MarkI2cDone(async_ctx_, status_success,
false);
1645 MaybeCompleteAsyncTransfer(in_isr);
1648void HPMI2C::MaybeCompleteAsyncTransfer(
bool in_isr)
1650 if (!AsyncTransferActive() || !AsyncCompletionStateMachine::Ready(async_ctx_))
1655 if (async_ctx_.kind == AsyncTransferKind::READ ||
1656 async_ctx_.kind == AsyncTransferKind::MEM_READ)
1658 InvalidateDCacheIfNeeded(async_ctx_.read_data.
addr_,
1659 static_cast<uint32_t
>(async_ctx_.read_data.
size_));
1661 hpm_stat_t final_status = AsyncCompletionStateMachine::FinalStatus(async_ctx_);
1662 if (final_status == status_success && i2c_get_data_count(i2c_) != 0U)
1664 final_status = status_i2c_transmit_not_completed;
1665 AsyncCompletionStateMachine::SetFinalStatus(async_ctx_, final_status);
1670bool HPMI2C::TryClaimAsyncCompletion()
1672 uint32_t expected = 0U;
1673 return async_completion_claim_.compare_exchange_strong(
1674 expected, 1U, std::memory_order_acq_rel, std::memory_order_acquire);
1677void HPMI2C::OnDmaTcCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr)
1681 auto* self =
static_cast<HPMI2C*
>(cb_data_ptr);
1682 if (self ==
nullptr || !self->AsyncTransferActive())
1687 AsyncCompletionStateMachine::MarkDmaDone(self->async_ctx_);
1688 self->MaybeCompleteAsyncTransfer(
true);
1691void HPMI2C::OnDmaErrorCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr)
1695 auto* self =
static_cast<HPMI2C*
>(cb_data_ptr);
1696 if (self ==
nullptr || !self->AsyncTransferActive())
1700 if (AsyncCompletionStateMachine::DmaDone(self->async_ctx_))
1704 AsyncCompletionStateMachine::MarkFailure(self->async_ctx_, status_fail,
true);
1708void HPMI2C::OnDmaAbortCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr)
1712 auto* self =
static_cast<HPMI2C*
>(cb_data_ptr);
1713 if (self ==
nullptr || !self->AsyncTransferActive())
1717 if (AsyncCompletionStateMachine::DmaDone(self->async_ctx_))
1721 AsyncCompletionStateMachine::MarkFailure(self->async_ctx_, status_fail,
true);
1726 bool allow_zero_size)
const
1728 if (data.
size_ == 0)
1732 if (data.
addr_ ==
nullptr)
1736 if (data.
size_ > I2C_SOC_TRANSFER_COUNT_MAX)
1740 return ValidateSlaveAddress(slave_addr);
1744 bool allow_zero_size)
const
1746 if (data.
size_ == 0)
1750 if (data.
addr_ ==
nullptr)
1754 if (data.
size_ > I2C_SOC_TRANSFER_COUNT_MAX)
1758 return ValidateSlaveAddress(slave_addr);
1762 MemAddrLength mem_addr_size,
1763 uint32_t& addr_size)
const
1765 if (write_data.
size_ > 0 && write_data.
addr_ ==
nullptr)
1770 ErrorCode ans = ResolveMemAddressSize(mem_addr_size, addr_size);
1775 if ((addr_size + write_data.
size_) > I2C_SOC_TRANSFER_COUNT_MAX)
1779 return ValidateSlaveAddress(slave_addr);
1784 if (i2c_ ==
nullptr)
1788 if (AsyncTransferActive())
1792 if ((i2c_get_status(i2c_) & I2C_STATUS_BUSBUSY_MASK) != 0U)
1797 return ApplyConfig(config);
1803 const ErrorCode arg_ans = ValidateTransferArgs(slave_addr, read_data,
true);
1806 return FinishOperation(op, in_isr, arg_ans);
1809 if (AsyncTransferActive())
1814 if (op.
type != ReadOperation::OperationType::BLOCK)
1816 const ErrorCode ans = StartReadAsync(slave_addr, read_data, op);
1824 ErrorCode ans = EnsureControllerReady();
1827 return FinishOperation(op, in_isr, ans);
1831 i2c_master_read(i2c_, slave_addr,
static_cast<uint8_t*
>(read_data.
addr_),
1832 static_cast<uint32_t
>(read_data.
size_));
1833 ans = ConvertStatus(status);
1834 if (ShouldRecover(status))
1836 RecoverController();
1838 return FinishOperation(op, in_isr, ans);
1844 if (AsyncTransferActive())
1849 ErrorCode ans = EnsureControllerReady();
1858 uint16_t flags = kI2CFlagWriteCheckAck;
1867 flags |= kI2CFlagAddr10Bit;
1868 flags |= kI2CFlagNoStop;
1871 flags |= kI2CFlagAddr10Bit | I2C_NO_START | I2C_NO_ADDRESS | kI2CFlagNoStop;
1875 flags |= kI2CFlagAddr10Bit | I2C_NO_START | I2C_NO_ADDRESS;
1878 const hpm_stat_t raw_status = DoManualTransferWithFlags(
1881 status = raw_status;
1885 status = i2c_master_seq_transmit_check_ack(
1887 const_cast<uint8_t*
>(
static_cast<const uint8_t*
>(write_data.
addr_)),
1888 static_cast<uint32_t
>(write_data.
size_), ConvertSequenceFrame(frame), check_ack);
1891 ans = ConvertStatus(status);
1892 if (ShouldRecover(status))
1894 RecoverController();
1902 if (AsyncTransferActive())
1907 ErrorCode ans = EnsureControllerReady();
1916 uint16_t flags = kI2CFlagRead | kI2CFlagAddr10Bit;
1920 flags |= kI2CFlagNoStop;
1923 flags |= I2C_NO_START | I2C_NO_ADDRESS | kI2CFlagNoStop;
1927 flags |= I2C_NO_START | I2C_NO_ADDRESS;
1930 status = DoManualTransferWithFlags(slave_addr, read_data, flags);
1934 status = i2c_master_seq_receive(
1935 i2c_, slave_addr,
static_cast<uint8_t*
>(read_data.
addr_),
1936 static_cast<uint32_t
>(read_data.
size_), ConvertSequenceFrame(frame));
1939 ans = ConvertStatus(status);
1940 if (ShouldRecover(status))
1942 RecoverController();
1947ErrorCode HPMI2C::DoTransferWithFlags(uint16_t slave_addr,
RawData data, uint16_t flags)
1949 if (AsyncTransferActive())
1954 ErrorCode ans = EnsureControllerReady();
1960 const uint16_t final_flags = BuildTransferFlags(flags);
1961 const hpm_stat_t status = DoManualTransferWithFlags(slave_addr, data, final_flags);
1962 ans = ConvertStatus(status);
1963 if (ShouldRecover(status))
1965 RecoverController();
1970hpm_stat_t HPMI2C::DoManualTransferWithFlags(uint16_t slave_addr,
RawData data,
1973 if (AsyncTransferActive())
1975 return status_i2c_bus_busy;
1978 return DoManualTransferWithFlagsImpl(i2c_, slave_addr, data, flags, wait_policy_);
1985 const ErrorCode arg_ans = ValidateTransferArgs(slave_addr, write_data,
false);
1988 return FinishOperation(op, in_isr, arg_ans);
1990 if (AsyncTransferActive())
1994 return FinishOperation(op, in_isr,
1995 DoSequenceWrite(slave_addr, write_data, frame, check_ack));
2001 const ErrorCode arg_ans = ValidateTransferArgs(slave_addr, read_data,
false);
2004 return FinishOperation(op, in_isr, arg_ans);
2006 if (AsyncTransferActive())
2010 return FinishOperation(op, in_isr, DoSequenceRead(slave_addr, read_data, frame));
2016 const ErrorCode arg_ans = ValidateTransferArgs(slave_addr, data,
false);
2019 return FinishOperation(op, in_isr, arg_ans);
2021 if (AsyncTransferActive())
2025 return FinishOperation(op, in_isr, DoTransferWithFlags(slave_addr, data, flags));
2031 const ErrorCode arg_ans = ValidateTransferArgs(slave_addr, data,
false);
2034 return FinishOperation(op, in_isr, arg_ans);
2036 if (AsyncTransferActive())
2040 return FinishOperation(
2042 DoTransferWithFlags(slave_addr,
RawData(
const_cast<void*
>(data.
addr_), data.
size_),
2043 static_cast<uint16_t
>(flags & ~kI2CFlagRead)));
2049 const ErrorCode arg_ans = ValidateTransferArgs(slave_addr, write_data,
true);
2052 return FinishOperation(op, in_isr, arg_ans);
2055 if (AsyncTransferActive())
2060 if (op.
type != WriteOperation::OperationType::BLOCK)
2062 const ErrorCode ans = StartWriteAsync(slave_addr, write_data, op);
2070 ErrorCode ans = EnsureControllerReady();
2073 return FinishOperation(op, in_isr, ans);
2076 hpm_stat_t status = i2c_master_write(
2078 const_cast<uint8_t*
>(
static_cast<const uint8_t*
>(write_data.
addr_)),
2079 static_cast<uint32_t
>(write_data.
size_));
2080 ans = ConvertStatus(status);
2081 if (ShouldRecover(status))
2083 RecoverController();
2085 return FinishOperation(op, in_isr, ans);
2089 ReadOperation& op, MemAddrLength mem_addr_size,
bool in_isr)
2091 const ErrorCode arg_ans = ValidateTransferArgs(slave_addr, read_data,
true);
2094 return FinishOperation(op, in_isr, arg_ans);
2097 if (AsyncTransferActive())
2102 if (op.
type != ReadOperation::OperationType::BLOCK)
2105 StartMemReadAsync(slave_addr, mem_addr, read_data, op, mem_addr_size);
2113 uint32_t addr_size = 0;
2114 ErrorCode ans = ResolveMemAddressSize(mem_addr_size, addr_size);
2117 return FinishOperation(op, in_isr, ans);
2119 if (addr_size > I2C_SOC_TRANSFER_COUNT_MAX)
2124 ans = EnsureControllerReady();
2127 return FinishOperation(op, in_isr, ans);
2130 uint8_t addr[2] = {};
2131 FillMemAddress(mem_addr, mem_addr_size, addr);
2144 const hpm_stat_t status = i2c_master_address_read(
2145 i2c_, slave_addr, addr, addr_size,
static_cast<uint8_t*
>(read_data.
addr_),
2146 static_cast<uint32_t
>(read_data.
size_));
2147 ans = ConvertStatus(status);
2148 if (ShouldRecover(status))
2150 RecoverController();
2153 return FinishOperation(op, in_isr, ans);
2158 MemAddrLength mem_addr_size,
bool in_isr)
2160 uint32_t addr_size = 0;
2161 ErrorCode ans = ValidateMemWriteArgs(slave_addr, write_data, mem_addr_size, addr_size);
2164 return FinishOperation(op, in_isr, ans);
2167 if (AsyncTransferActive())
2172 ans = EnsureControllerReady();
2175 return FinishOperation(op, in_isr, ans);
2178 uint8_t addr[2] = {};
2179 FillMemAddress(mem_addr, mem_addr_size, addr);
2183 if (write_data.
size_ == 0)
2186 DoManualTransferWithFlags(slave_addr,
RawData(addr, addr_size),
2187 kI2CFlagAddr10Bit | kI2CFlagWriteCheckAck);
2188 ans = ConvertStatus(status);
2189 if (ShouldRecover(status))
2191 RecoverController();
2196 ans = DoSequenceWrite(slave_addr,
ConstRawData(addr, addr_size),
2207 if (write_data.
size_ == 0)
2209 status = i2c_master_write(i2c_, slave_addr, addr, addr_size);
2213 status = i2c_master_address_write(
2214 i2c_, slave_addr, addr, addr_size,
2215 const_cast<uint8_t*
>(
static_cast<const uint8_t*
>(write_data.
addr_)),
2216 static_cast<uint32_t
>(write_data.
size_));
2219 ans = ConvertStatus(status);
2220 if (ShouldRecover(status))
2222 RecoverController();
2225 return FinishOperation(op, in_isr, ans);
2230extern "C" void libxr_hpm_i2c_process_interrupt(LibXRHpmI2cType* ptr) { UNUSED(ptr); }
2233 : i2c_(i2c), clock_(clock), current_config_(config)
2241 address_mode_ = mode;
2245ErrorCode HPMI2C::ConvertStatus(hpm_stat_t status)
2251uint16_t HPMI2C::BuildTransferFlags(uint16_t flags)
const {
return flags; }
2254 SequenceFrame frame,
bool check_ack)
2264 SequenceFrame frame)
2272ErrorCode HPMI2C::DoTransferWithFlags(uint16_t slave_addr,
RawData data, uint16_t flags)
2280hpm_stat_t HPMI2C::DoManualTransferWithFlags(uint16_t slave_addr,
RawData data,
2293ErrorCode HPMI2C::ApplyConfig(
const Configuration& config)
2295 current_config_ = config;
2296 configured_ =
false;
2300bool HPMI2C::ShouldRecover(hpm_stat_t status)
2306void HPMI2C::RecoverController() {}
2308void HPMI2C::TryRecoverBusLines() {}
2312 current_config_ = config;
2313 configured_ =
false;
2334 ReadOperation& op, MemAddrLength mem_addr_size,
bool in_isr)
2339 UNUSED(mem_addr_size);
2345 MemAddrLength mem_addr_size,
bool in_isr)
2350 UNUSED(mem_addr_size);
ErrorCode Wait(uint32_t timeout)
等待完成或超时交接 / Wait for completion or a timeout handoff.
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
static void EnsureInitialized()
确保 dma_mgr_init() 已执行且只执行一次 / Ensure dma_mgr_init() has run, exactly once.
HPM SDK I2C 主机驱动,适配 LibXR I2C 接口 / HPM SDK based I2C master driver for the LibXR I2C interface.
ErrorCode MemRead(uint16_t slave_addr, uint16_t mem_addr, RawData read_data, ReadOperation &op, MemAddrLength mem_addr_size=MemAddrLength::BYTE_8, bool in_isr=false) override
从 I2C 从设备寄存器或存储器地址读取字节 / Read bytes from an I2C slave register or memory address.
ErrorCode TransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags, ReadOperation &op, bool in_isr=false)
执行一段 HPM 扩展标志主机事务 / Execute one HPM master transfer with extended SDK flags.
ErrorCode SequenceRead(uint16_t slave_addr, RawData read_data, SequenceFrame frame, ReadOperation &op, bool in_isr=false)
执行一段 HPM 主机顺序读事务 / Execute one HPM master sequential read frame.
HPMI2C(LibXRHpmI2cType *i2c, clock_name_t clock, I2C::Configuration config)
构造 HPM I2C 主机对象 / Construct an HPM I2C master object.
ErrorCode SetWaitPolicy(WaitPolicy policy)
设置当前实例的忙等超时策略 / Set the busy-wait timeout policy for this instance.
ErrorCode Write(uint16_t slave_addr, ConstRawData write_data, WriteOperation &op, bool in_isr=false) override
向 I2C 从设备写入字节 / Write bytes to an I2C slave.
ErrorCode Read(uint16_t slave_addr, RawData read_data, ReadOperation &op, bool in_isr=false) override
从 I2C 从设备读取字节 / Read bytes from an I2C slave.
ErrorCode SetAddressMode(AddressMode mode)
设置 HPM 主机寻址模式并重建控制器 / Set HPM master addressing mode and rebuild the controller.
ErrorCode MemWrite(uint16_t slave_addr, uint16_t mem_addr, ConstRawData write_data, WriteOperation &op, MemAddrLength mem_addr_size=MemAddrLength::BYTE_8, bool in_isr=false) override
向 I2C 从设备寄存器或存储器地址写入字节 / Write bytes to an I2C slave register or memory address.
AddressMode
HPM I2C 主机寻址模式 / HPM I2C master addressing mode.
@ ADDR_10BIT
10-bit 从地址 / 10-bit slave addressing.
AsyncTransferKind
HPM I2C 后台事务类型 / HPM I2C asynchronous transfer kind.
SequenceFrame
HPM 主机顺序事务分段类型 / HPM master sequential transfer frame type.
@ FIRST
带 START 和地址阶段 / Includes START and address phase.
@ NEXT
中间段,不带 START/STOP / Middle frame without START/STOP.
@ LAST
末段,带 STOP / Final frame with STOP.
ErrorCode SequenceWrite(uint16_t slave_addr, ConstRawData write_data, SequenceFrame frame, bool check_ack, WriteOperation &op, bool in_isr=false)
执行一段 HPM 主机顺序写事务 / Execute one HPM master sequential write frame.
void CompleteAsyncTransfer(bool in_isr, ErrorCode ans)
供 DMA / 中断完成路径调用的完成入口 / Completion entry used by DMA / interrupt driven paths.
ErrorCode SetConfig(Configuration config) override
应用 I2C 时序配置 / Apply I2C timing configuration.
uint32_t timeout
等待超时值 / Wait timeout.
void UpdateStatus(bool in_isr, Status &&status)
按通知方式报告完成结果 / Report completion using the selected mode.
union LibXR::Operation::@6 data
完成通知对象,由 type 选择有效成员 / Notification target selected by type.
void MarkAsRunning()
标记轮询操作正在执行 / Mark a polling operation as running.
OperationType type
当前通知方式 / Current notification mode.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
HPM I2C 主机驱动适配头文件 / Adapter header for the HPM I2C master driver.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ SIZE_ERR
尺寸错误 / Size error
@ CHECK_ERR
校验错误 / Check error
@ INIT_ERR
初始化错误 / Initialization error
@ NO_RESPONSE
无响应 / No response
@ PTR_NULL
空指针 / Null pointer
@ NOT_SUPPORT
不支持 / Not supported
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
HPM I2C 忙等超时策略 / HPM I2C busy-wait timeout policy.
I2C 设备的配置信息结构体。 Configuration structure for an I2C device.