170#if LIBXR_HPM_I2C_SUPPORTED
173 NO_START = I2C_NO_START,
174 NO_ADDRESS = I2C_NO_ADDRESS,
175 NO_READ_ACK = I2C_NO_READ_ACK,
176 NO_STOP = I2C_NO_STOP,
177 WRITE_CHECK_ACK = I2C_WRITE_CHECK_ACK
182 NO_ADDRESS = 0x0008U,
183 NO_READ_ACK = 0x0010U,
185 WRITE_CHECK_ACK = 0x0040U
212 uint64_t addr_hit_timeout_us;
213 uint64_t stop_timeout_us;
214 uint64_t bus_idle_timeout_us;
215 uint64_t transfer_timeout_us;
224 return {500ULL, 1000ULL, 1000ULL, 500000ULL};
303 bool in_isr =
false);
372 bool in_isr =
false)
override;
397 bool in_isr =
false)
override;
433 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
434 bool in_isr =
false)
override;
470 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8,
471 bool in_isr =
false)
override;
502 friend void ::libxr_hpm_i2c_process_interrupt(LibXRHpmI2cType* ptr);
508 struct AsyncTransferContext
511 uint16_t slave_addr = 0U;
512 MemAddrLength mem_addr_size = MemAddrLength::BYTE_8;
513 uint16_t mem_addr = 0U;
514 uint32_t mem_addr_size_in_byte = 0U;
515 uint8_t mem_addr_bytes[2] = {};
517 RawData read_data = {
nullptr, 0};
518 ConstRawData write_data = {
nullptr, 0};
521 std::atomic<hpm_stat_t> final_status{
523 std::atomic<bool> should_recover{
525 std::atomic<bool> dma_done{
527 std::atomic<bool> cmpl_done{
false};
539 struct AsyncCompletionStateMachine
541 static void Reset(AsyncTransferContext& ctx);
542 static void MarkDmaDone(AsyncTransferContext& ctx);
543 static void MarkI2cDone(AsyncTransferContext& ctx, hpm_stat_t status,
bool recover);
544 static void MarkFailure(AsyncTransferContext& ctx, hpm_stat_t status,
bool recover);
545 static void SetFinalStatus(AsyncTransferContext& ctx, hpm_stat_t status);
546 static bool DmaDone(
const AsyncTransferContext& ctx);
547 static bool Ready(
const AsyncTransferContext& ctx);
548 static hpm_stat_t FinalStatus(
const AsyncTransferContext& ctx);
549 static bool ShouldRecover(
const AsyncTransferContext& ctx);
556 static constexpr uint16_t kMax7BitAddress = 0x7FU;
562 static constexpr uint16_t kMax10BitAddress = 0x3FFU;
568 static ErrorCode ConvertStatus(hpm_stat_t status);
574#if LIBXR_HPM_I2C_SUPPORTED
575 static ErrorCode ResolveMode(uint32_t clock_speed, i2c_mode_t& mode);
582 static ErrorCode ConvertDmaStatus(hpm_stat_t status);
588#if LIBXR_HPM_I2C_SUPPORTED
589 static i2c_seq_transfer_opt_t ConvertSequenceFrame(
SequenceFrame frame);
596 uint16_t BuildTransferFlags(uint16_t flags)
const;
602 static uint16_t GetMaxSlaveAddress(
AddressMode mode);
608 ErrorCode ValidateSlaveAddress(uint16_t slave_addr)
const;
613 ErrorCode ValidateTransferArgs(uint16_t slave_addr, RawData data,
614 bool allow_zero_size)
const;
619 ErrorCode ValidateTransferArgs(uint16_t slave_addr, ConstRawData data,
620 bool allow_zero_size)
const;
626 ErrorCode ValidateMemWriteArgs(uint16_t slave_addr, ConstRawData write_data,
627 MemAddrLength mem_addr_size, uint32_t& addr_size)
const;
633 static ErrorCode ResolveMemAddressSize(MemAddrLength len, uint32_t& addr_size);
639 static void FillMemAddress(uint16_t mem_addr, MemAddrLength len, uint8_t out[2]);
645 ErrorCode DoSequenceWrite(uint16_t slave_addr, ConstRawData write_data,
658 ErrorCode DoTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags);
664 hpm_stat_t DoManualTransferWithFlags(uint16_t slave_addr, RawData data, uint16_t flags);
670 ErrorCode PrepareAsyncTransfer(uint16_t slave_addr, uint16_t flags, uint32_t size,
671 bool clear_fifo =
true,
bool require_bus_idle =
true);
677 static uint32_t ToSystemAddress(
const void* addr);
683 ErrorCode StartAsyncReadDma(
void* dst, uint32_t size);
689 ErrorCode StartAsyncWriteDma(
const void* src, uint32_t size);
701 void StopAndReleaseAsyncBus();
706 void ResetAsyncState();
712 void ClearAsyncContext();
717 void AbortAsyncStart(
bool stop_dma,
bool disable_irq,
bool recover_controller);
722 template <
typename Op>
723 void StartAsyncBlockWaitIfNeeded(Op& op)
725 if (op.type == Op::OperationType::BLOCK)
727 block_wait_.
Start(*op.data.sem_info.sem);
734 template <
typename Op>
735 void CancelAsyncBlockWaitIfNeeded(Op& op)
737 if (op.type == Op::OperationType::BLOCK)
746 template <
typename Op>
747 void CompleteAsyncOperation(Op& op,
bool in_isr,
ErrorCode ans)
749 if (op.type == Op::OperationType::BLOCK)
751 (void)block_wait_.
TryPost(in_isr, ans);
755 op.UpdateStatus(in_isr, ans);
763 ErrorCode StartWriteAsync(uint16_t slave_addr, ConstRawData write_data,
776 ErrorCode StartMemReadAsync(uint16_t slave_addr, uint16_t mem_addr, RawData read_data,
788 ErrorCode WaitForAsyncBlockResult(uint32_t timeout);
793 void ReleaseAsyncBus();
805 void DisableAsyncI2cIrq();
817 void HandleAsyncInterrupt(
bool in_isr);
823 void MaybeCompleteAsyncTransfer(
bool in_isr);
829 bool TryClaimAsyncCompletion();
834 static void OnDmaTcCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr);
839 static void OnDmaErrorCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr);
844 static void OnDmaAbortCallback(DMA_Type* base, uint32_t channel,
void* cb_data_ptr);
850 bool AsyncTransferActive()
const
852 return async_busy_.load(std::memory_order_acquire) != 0U;
871 ErrorCode ApplyConfig(
const Configuration& config);
877 static bool ShouldRecover(hpm_stat_t status);
883 void RecoverController();
889 void TryRecoverBusLines();
895 template <
typename Op>
898 if (op.type != Op::OperationType::BLOCK)
900 op.UpdateStatus(in_isr, ans);
905 LibXRHpmI2cType* i2c_;
907 uint32_t source_clock_hz_ = 0;
908 Configuration current_config_{
910 WaitPolicy wait_policy_ =
914 bool configured_ =
false;
915 std::atomic<uint32_t> async_busy_{
917 AsyncTransferContext async_ctx_{};
918 AsyncBlockWait block_wait_{};
919 std::atomic<uint32_t> async_completion_claim_{
921 dma_resource_t async_dma_resource_{
nullptr, 0U,
923 uint8_t async_dma_source_ =
925 bool async_dma_ready_ =