1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include <optional> 17 18 #include "fsl_clock.h" 19 #include "fsl_i3c.h" 20 #include "pw_bytes/span.h" 21 #include "pw_containers/vector.h" 22 #include "pw_i2c/initiator.h" 23 #include "pw_i2c_mcuxpresso/i3c_ccc.h" 24 #include "pw_status/status.h" 25 #include "pw_sync/mutex.h" 26 27 namespace pw::i2c { 28 29 // I2C initiator interface implementation fsl_i3c driver in NXP MCUXpresso SDK. 30 class I3cMcuxpressoInitiator final : public pw::i2c::Initiator { 31 public: 32 struct Config { 33 uint32_t base_address; // I3C peripheral base address. 34 uint32_t i2c_baud_rate; // I2C baud rate in Hz. 35 uint32_t i3c_open_drain_baud_rate; // I3C open drain baud rate in Hz. 36 uint32_t i3c_push_pull_baud_rate; // I3C push pull baud rate in Hz. 37 bool enable_open_drain_stop; // Whether to emit open-drain speed STOP. 38 bool enable_open_drain_high; // Enable Open-Drain High to be 1 PPBAUD count 39 // for I3C messages, or 1 ODBAUD. 40 }; I3cMcuxpressoInitiator(const Config & config)41 I3cMcuxpressoInitiator(const Config& config) 42 : config_(config), 43 base_(reinterpret_cast<I3C_Type*>(config.base_address)) {} 44 45 // Initializes the I3C controller peripheral as configured in the constructor. 46 void Enable() PW_LOCKS_EXCLUDED(mutex_); 47 48 // Deinitializes the I3C controller peripheral. 49 void Disable() PW_LOCKS_EXCLUDED(mutex_); 50 51 // Set dynamic address list, which will be used to assign dynamic addresses to 52 // I3C devices on the bus during bus initialization step, or to determine the 53 // type (I2C or I3C) for each transaction. 54 // 55 // Warning: dynamic address list can only be set once. 56 pw::Status SetDynamicAddressList( 57 pw::span<const uint8_t> dynamic_address_list); 58 59 // Initialize the I3C bus (Dynamic address assignment) 60 // 61 // Warning: Users should set correct dynamic addresses (SetDynamicAddressList) 62 // before calling this function. 63 pw::Status Initialize() PW_LOCKS_EXCLUDED(mutex_); 64 65 private: 66 pw::Status DoTransferCcc(I3cCccAction rnw, 67 I3cCcc ccc_id, 68 pw::i2c::Address address, 69 pw::ByteSpan buffer); 70 pw::Status DoWriteReadFor(pw::i2c::Address address, 71 pw::ConstByteSpan tx_buffer, 72 pw::ByteSpan rx_buffer, 73 pw::chrono::SystemClock::duration timeout) 74 PW_LOCKS_EXCLUDED(mutex_); 75 76 const Config& config_; 77 I3C_Type* base_; 78 i3c_device_info_t* device_list_ = nullptr; 79 uint8_t device_count_ = 0; 80 bool enabled_ PW_GUARDED_BY(mutex_) = false; 81 pw::sync::Mutex mutex_; 82 std::optional<pw::Vector<uint8_t, I3C_MAX_DEVCNT>> i3c_dynamic_address_list_; 83 }; 84 85 } // namespace pw::i2c 86