blob: 905d367f247f271ae425b13f1483d34c990c475d [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_DEVICES_I2C_DRIVERS_AML_I2C_AML_I2C_H_
#define SRC_DEVICES_I2C_DRIVERS_AML_I2C_AML_I2C_H_
#include <fidl/fuchsia.hardware.i2cimpl/cpp/driver/wire.h>
#include <fidl/fuchsia.hardware.platform.device/cpp/wire.h>
#include <lib/async/cpp/irq.h>
#include <lib/driver/compat/cpp/compat.h>
#include <lib/driver/component/cpp/driver_base.h>
#include <lib/mmio/mmio-buffer.h>
#include <lib/zx/event.h>
#include <lib/zx/interrupt.h>
#include <lib/zx/time.h>
namespace aml_i2c {
class AmlI2c : public fdf::DriverBase, public fdf::WireServer<fuchsia_hardware_i2cimpl::Device> {
public:
AmlI2c(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher);
zx::result<> Start() override;
void PrepareStop(fdf::PrepareStopCompleter completer) override;
// I2cImpl protocol implementation
void GetMaxTransferSize(fdf::Arena& arena, GetMaxTransferSizeCompleter::Sync& completer) override;
void SetBitrate(SetBitrateRequestView request, fdf::Arena& arena,
SetBitrateCompleter::Sync& completer) override;
void Transact(TransactRequestView request, fdf::Arena& arena,
TransactCompleter::Sync& completer) override;
void handle_unknown_method(fidl::UnknownMethodMetadata<fuchsia_hardware_i2cimpl::Device> metadata,
fidl::UnknownMethodCompleter::Sync& completer) override;
void SetTimeout(zx::duration timeout) { timeout_ = timeout; }
protected:
// Visible for testing
virtual zx::result<fdf::MmioBuffer> MapMmio(
const fidl::WireSyncClient<fuchsia_hardware_platform_device::Device>& pdev);
private:
zx_status_t ServeI2cImpl();
compat::DeviceServer::BanjoConfig CreateBanjoConfig();
zx_status_t CreateChildNode();
void SetTargetAddr(uint16_t addr) const;
void StartXfer() const;
zx_status_t WaitTransferComplete() const;
zx_status_t Read(cpp20::span<uint8_t> dst, bool stop) const;
zx_status_t Write(cpp20::span<uint8_t> src, bool stop) const;
zx_status_t StartIrqThread();
void HandleIrq(async_dispatcher_t* dispatcher, async::IrqBase* irq, zx_status_t status,
const zx_packet_interrupt_t* interrupt);
const fdf::MmioBuffer& regs_iobuff() const;
zx::interrupt irq_;
zx::event event_;
std::optional<fdf::MmioBuffer> regs_iobuff_;
zx::duration timeout_ = zx::sec(1);
fdf::ServerBindingGroup<fuchsia_hardware_i2cimpl::Device> i2cimpl_bindings_;
fidl::WireSyncClient<fuchsia_driver_framework::NodeController> child_controller_;
compat::SyncInitializedDeviceServer device_server_;
// Only needed in order to set the role name for the code that waits for irq's.
std::optional<fdf::Dispatcher> irq_dispatcher_;
std::optional<fdf::PrepareStopCompleter> completer_;
async::IrqMethod<AmlI2c, &AmlI2c::HandleIrq> irq_handler_{this};
};
} // namespace aml_i2c
#endif // SRC_DEVICES_I2C_DRIVERS_AML_I2C_AML_I2C_H_