blob: bd6de185f24e49c60dd1c566139adb47d2ecf352 [file] [log] [blame]
// Copyright 2019 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_SHAREDDMA_DRIVERS_SYN_DMA_SYN_DHUB_H_
#define SRC_DEVICES_SHAREDDMA_DRIVERS_SYN_DMA_SYN_DHUB_H_
#include <assert.h>
#include <lib/fzl/pinned-vmo.h>
#include <lib/mmio/mmio.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/interrupt.h>
#include <lib/zx/port.h>
#include <threads.h>
#include <zircon/types.h>
#include <memory>
#include <utility>
#include <ddk/device.h>
#include <ddktl/device.h>
#include <ddktl/protocol/shareddma.h>
#include <fbl/auto_lock.h>
#include <soc/as370/as370-dma.h>
namespace as370 {
class SynDhub;
using DeviceType = ddk::Device<SynDhub, ddk::Unbindable>;
class SynDhub : public DeviceType, public ddk::SharedDmaProtocol<SynDhub, ddk::base_protocol> {
public:
// Move operators are implicitly disabled.
SynDhub(const SynDhub&) = delete;
SynDhub& operator=(const SynDhub&) = delete;
static std::unique_ptr<SynDhub> Create(zx_device_t* parent);
// Shared DMA protocol.
zx_status_t SharedDmaInitializeAndGetBuffer(uint32_t dma_id, dma_type_t type, uint32_t t_len,
zx::vmo* out_vmo);
void SharedDmaStart(uint32_t dma_id) { Enable(dma_id, true); }
void SharedDmaStop(uint32_t dma_id) { Enable(dma_id, false); }
uint32_t SharedDmaGetTransferSize(uint32_t dma_id);
uint32_t SharedDmaGetBufferPosition(uint32_t dma_id);
zx_status_t SharedDmaSetNotifyCallback(uint32_t dma_id, const dma_notify_t* cb);
void DdkUnbind(ddk::UnbindTxn txn) {
Shutdown();
txn.Reply();
}
void DdkRelease() { delete this; }
protected:
SynDhub(zx_device_t* device, ddk::MmioBuffer mmio) : DeviceType(device), mmio_(std::move(mmio)) {}
void StartDma(uint32_t dma_id, bool trigger_interrupt); // protected for unit tests.
void SetBuffer(uint32_t dma_id, zx_paddr_t buf, size_t len); // protected for unit tests.
void Init(uint32_t dma_id); // protected for unit tests.
void Enable(uint32_t channel_id, bool enable); // protected for unit tests.
private:
static constexpr uint32_t kMtuSize = 128;
static constexpr uint32_t kConcurrentDmas = 1;
static constexpr struct {
uint32_t bank;
uint32_t fifo_data_depth;
uint32_t dma_mtus; // We use 64 for I2S and 128 for PDM.
} channel_info_[] = {
// clang-format off
{ 0, 60, 64},
{ 1, 60, 64},
{ 2, 60, 64},
{ 3, 60, 64},
{ 4, 60, 64},
{ 5, 60, 64},
{ 6, 60, 128},
{ 7, 252, 64},
{11, 48, 64},
{12, 60, 128},
{13, 60, 128},
{14, 60, 128},
{15, 60, 64},
{16, 60, 64},
{ 8, 252, 64},
{10, 252, 64},
// clang-format on
};
zx_status_t Bind();
int Thread();
void Shutdown();
void Ack(uint32_t channel_id);
void ProcessIrq(uint32_t channel_id);
ddk::MmioBuffer mmio_;
zx::port port_;
zx::interrupt interrupt_;
thrd_t thread_;
zx::bti bti_;
fbl::Mutex position_lock_;
// clang-format off
bool enabled_ [DmaId::kDmaIdMax] = {};
dma_notify_t callback_ [DmaId::kDmaIdMax] = {};
fzl::PinnedVmo pinned_dma_buffer_[DmaId::kDmaIdMax] = {};
zx::vmo dma_buffer_ [DmaId::kDmaIdMax] = {};
uint32_t dma_size_ [DmaId::kDmaIdMax] = {};
zx_paddr_t dma_base_ [DmaId::kDmaIdMax] = {};
zx_paddr_t dma_current_ [DmaId::kDmaIdMax] TA_GUARDED(position_lock_);
dma_type_t type_ [DmaId::kDmaIdMax] = {};
bool triggers_interrupt_ [DmaId::kDmaIdMax] = {};
// clang-format on
};
} // namespace as370
#endif // SRC_DEVICES_SHAREDDMA_DRIVERS_SYN_DMA_SYN_DHUB_H_