blob: c36f8363f1cbbfef8b8199130ee27b803b962e96 [file] [log] [blame]
// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
#include <optional>
#include "fsl_clock.h"
#include "fsl_i3c.h"
#include "pw_bytes/span.h"
#include "pw_containers/vector.h"
#include "pw_i2c/initiator.h"
#include "pw_i2c_mcuxpresso/i3c_ccc.h"
#include "pw_status/status.h"
#include "pw_sync/mutex.h"
namespace pw::i2c {
// I2C initiator interface implementation fsl_i3c driver in NXP MCUXpresso SDK.
class I3cMcuxpressoInitiator final : public pw::i2c::Initiator {
public:
struct Config {
uint32_t base_address; // I3C peripheral base address.
uint32_t i2c_baud_rate; // I2C baud rate in Hz.
uint32_t i3c_open_drain_baud_rate; // I3C open drain baud rate in Hz.
uint32_t i3c_push_pull_baud_rate; // I3C push pull baud rate in Hz.
bool enable_open_drain_stop; // Whether to emit open-drain speed STOP.
bool enable_open_drain_high; // Enable Open-Drain High to be 1 PPBAUD count
// for I3C messages, or 1 ODBAUD.
};
I3cMcuxpressoInitiator(const Config& config)
: config_(config),
base_(reinterpret_cast<I3C_Type*>(config.base_address)) {}
// Initializes the I3C controller peripheral as configured in the constructor.
void Enable() PW_LOCKS_EXCLUDED(mutex_);
// Deinitializes the I3C controller peripheral.
void Disable() PW_LOCKS_EXCLUDED(mutex_);
// Set dynamic address list, which will be used to assign dynamic addresses to
// I3C devices on the bus during bus initialization step, or to determine the
// type (I2C or I3C) for each transaction.
//
// Warning: dynamic address list can only be set once.
pw::Status SetDynamicAddressList(
pw::span<const uint8_t> dynamic_address_list);
// Initialize the I3C bus (Dynamic address assignment)
//
// Warning: Users should set correct dynamic addresses (SetDynamicAddressList)
// before calling this function.
pw::Status Initialize() PW_LOCKS_EXCLUDED(mutex_);
private:
pw::Status DoTransferCcc(I3cCccAction rnw,
I3cCcc ccc_id,
pw::i2c::Address address,
pw::ByteSpan buffer);
pw::Status DoWriteReadFor(pw::i2c::Address address,
pw::ConstByteSpan tx_buffer,
pw::ByteSpan rx_buffer,
pw::chrono::SystemClock::duration timeout)
PW_LOCKS_EXCLUDED(mutex_);
const Config& config_;
I3C_Type* base_;
i3c_device_info_t* device_list_ = nullptr;
uint8_t device_count_ = 0;
bool enabled_ PW_GUARDED_BY(mutex_) = false;
pw::sync::Mutex mutex_;
std::optional<pw::Vector<uint8_t, I3C_MAX_DEVCNT>> i3c_dynamic_address_list_;
};
} // namespace pw::i2c