blob: 91ae05dbf71fb18abd9e6710e81db5545a5e4907 [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.
#ifndef SRC_DEVICES_RAM_DRIVERS_AML_RAM_AML_RAM_H_
#define SRC_DEVICES_RAM_DRIVERS_AML_RAM_AML_RAM_H_
#include <fuchsia/device/llcpp/fidl.h>
#include <fuchsia/hardware/ram/metrics/llcpp/fidl.h>
#include <lib/mmio/mmio.h>
#include <lib/zircon-internal/thread_annotations.h>
#include <lib/zx/interrupt.h>
#include <lib/zx/port.h>
#include <deque>
#include <thread>
#include <ddktl/device.h>
#include <fbl/mutex.h>
namespace ram_metrics = ::llcpp::fuchsia::hardware::ram::metrics;
namespace amlogic_ram {
// The AmlRam device provides FIDL services directly to applications
// to query performance counters. For example effective DDR bandwith.
//
// There are 4 monitoring channels and each one can agregate up to 64
// hardware memory ports. NOTE: the word channel and port in this file
// refer to hardware, not to zircon objects.
constexpr size_t MEMBW_MAX_CHANNELS = 4u;
// Controls start,stop and if polling or interrupt mode.
constexpr uint32_t MEMBW_PORTS_CTRL = (0x0020 << 2);
constexpr uint32_t DMC_QOS_ENABLE_CTRL = (0x01 << 31);
constexpr uint32_t DMC_QOS_CLEAR_CTRL = (0x01 << 30);
// Returns all granted cycles.
constexpr uint32_t MEMBW_ALL_GRANT_CNT = (0x2a << 2);
// Returns the granted cycles per channel.
constexpr uint32_t MEMBW_C0_GRANT_CNT = (0x2b << 2);
constexpr uint32_t MEMBW_C1_GRANT_CNT = (0x2c << 2);
constexpr uint32_t MEMBW_C2_GRANT_CNT = (0x2d << 2);
constexpr uint32_t MEMBW_C3_GRANT_CNT = (0x2e << 2);
// Controls how long to measure cycles for.
constexpr uint32_t MEMBW_TIMER = (0x002f << 2);
// Controls which ports are assigned to each channel.
constexpr uint32_t MEMBW_RP[MEMBW_MAX_CHANNELS] = {(0x0021 << 2), (0x0023 << 2), (0x0025 << 2),
(0x0027 << 2)};
// Controls wich subports are assinged to each channel.
constexpr uint32_t MEMBW_SP[MEMBW_MAX_CHANNELS] = {(0x0022 << 2), (0x0024 << 2), (0x0026 << 2),
(0x0028 << 2)};
// Contains the DDR frequency.
// TODO(reveman): Understand why we use 0x0300 instead of 0x0000.
constexpr uint32_t MEMBW_PLL_CNTL = (0x0300 << 2);
// Sticky bit that holds the DDR windowing tool results
// address is: 0xff638804
// We mapped at T931_DMC_BASE (0xff638000)
constexpr uint32_t DMC_STICKY_1 = 0x804;
constexpr uint64_t kMinimumCycleCount = 1024 * 512;
constexpr uint64_t kMaximumCycleCount = 0xffffffff;
class AmlRam;
using DeviceType = ddk::Device<AmlRam, ddk::Suspendable, ddk::Messageable>;
class AmlRam : public DeviceType, private ram_metrics::Device::Interface {
public:
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AmlRam);
static zx_status_t Create(void* context, zx_device_t* parent);
AmlRam(zx_device_t* parent, ddk::MmioBuffer mmio, zx::interrupt irq, zx::port port,
uint32_t device_pid);
~AmlRam();
void DdkRelease();
void DdkSuspend(ddk::SuspendTxn txn);
// Implements ddk::Messageable
zx_status_t DdkMessage(fidl_incoming_msg_t* msg, fidl_txn_t* txn);
private:
struct Job {
ram_metrics::BandwidthMeasurementConfig config;
MeasureBandwidthCompleter::Async completer;
zx_time_t start_time = 0;
Job() = delete;
Job(ram_metrics::BandwidthMeasurementConfig config, MeasureBandwidthCompleter::Async completer)
: config(std::move(config)), completer(std::move(completer)) {}
};
// Implementation of ram_metrics::Device::Interface FIDL service.
void MeasureBandwidth(ram_metrics::BandwidthMeasurementConfig config,
MeasureBandwidthCompleter::Sync& completer) override;
void GetDdrWindowingResults(GetDdrWindowingResultsCompleter::Sync& completer) override;
void StartReadBandwithCounters(Job* job);
void FinishReadBandwithCounters(ram_metrics::BandwidthInfo* bpi, zx_time_t start_time);
void CancelReadBandwithCounters();
zx_status_t Bind();
void ReadLoop();
void RevertJobs(std::deque<AmlRam::Job>* source);
void AcceptJobs(std::deque<AmlRam::Job>* source);
void Shutdown();
uint64_t ReadFrequency() const;
ddk::MmioBuffer mmio_;
zx::interrupt irq_;
zx::port port_;
std::thread thread_;
fbl::Mutex lock_;
std::deque<Job> requests_ TA_GUARDED(lock_);
bool shutdown_ TA_GUARDED(lock_) = false;
bool all_grant_broken_ = true;
bool windowing_data_supported_ = false;
};
} // namespace amlogic_ram
#endif // SRC_DEVICES_RAM_DRIVERS_AML_RAM_AML_RAM_H_