blob: c5d6f87374e75e1bc1369a7654ea7639d3faf49a [file] [log] [blame]
// Copyright 2020 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.
#include <fuchsia/hardware/usb/phy/cpp/banjo.h>
#include <lib/device-protocol/pdev-fidl.h>
#include <lib/mmio/mmio.h>
#include <lib/sync/completion.h>
#include <lib/zx/interrupt.h>
#include <threads.h>
#include <ddktl/device.h>
#include <fbl/mutex.h>
namespace nelson_usb_phy {
class NelsonUsbPhy;
using NelsonUsbPhyType = ddk::Device<NelsonUsbPhy, ddk::Unbindable, ddk::ChildPreReleaseable>;
// This is the main class for the platform bus driver.
class NelsonUsbPhy : public NelsonUsbPhyType,
public ddk::UsbPhyProtocol<NelsonUsbPhy, ddk::base_protocol> {
explicit NelsonUsbPhy(zx_device_t* parent) : NelsonUsbPhyType(parent), pdev_(parent) {}
static zx_status_t Create(void* ctx, zx_device_t* parent);
// USB PHY protocol implementation.
void UsbPhyConnectStatusChanged(bool connected);
zx_status_t UsbPhyNotifyDeviceRemoved();
// Device protocol implementation.
void DdkUnbind(ddk::UnbindTxn txn);
void DdkRelease();
void DdkChildPreRelease(void* child_ctx);
enum class UsbMode {
void InitPll(fdf::MmioBuffer* mmio);
zx_status_t InitPhy();
zx_status_t InitOtg();
void SetMode(UsbMode mode) __TA_REQUIRES(lock_);
zx_status_t AddXhciDevice();
void RemoveXhciDevice(bool wait);
zx_status_t AddDwc2Device();
void RemoveDwc2Device(bool wait);
zx_status_t Init();
int IrqThread();
ddk::PDevFidl pdev_;
std::optional<fdf::MmioBuffer> reset_mmio_;
std::optional<fdf::MmioBuffer> usbctrl_mmio_;
std::optional<fdf::MmioBuffer> usbphy20_mmio_;
std::optional<fdf::MmioBuffer> usbphy21_mmio_;
std::optional<fdf::MmioBuffer> power_mmio_;
std::optional<fdf::MmioBuffer> sleep_mmio_;
zx::interrupt irq_;
thrd_t irq_thread_;
// Lock used to synchronize access to this driver between the interrupt
// thread and a child device calling SetMode through Banjo on a separate thread.
fbl::Mutex lock_;
// Magic numbers for PLL from metadata
uint32_t pll_settings_[8];
// Device node for binding XHCI driver.
zx_device_t* xhci_device_ = nullptr;
zx_device_t* dwc2_device_ = nullptr;
sync_completion_t remove_event_;
UsbMode mode_ = UsbMode::UNKNOWN;
bool dwc2_connected_ = false;
} // namespace nelson_usb_phy