// 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.

#include <memory>
#include <mutex>

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/device.h>
#include <ddk/driver.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/platform-device-lib.h>
#include <ddk/protocol/platform/device.h>

#include <ddktl/device.h>
#include <ddktl/pdev.h>
#include <ddktl/protocol/clock.h>
#include <ddktl/protocol/empty-protocol.h>
#include <fuchsia/gpu/magma/c/fidl.h>
#include <hw/reg.h>
#include <lib/fidl-utils/bind.h>

#include "magma_util/macros.h"
#include "sys_driver/magma_driver.h"

#define GPU_ERROR(fmt, ...) zxlogf(ERROR, "[%s %d]" fmt, __func__, __LINE__, ##__VA_ARGS__)

enum {
    // Indices into clocks provided by the board file.
    kClkSlowMfgIndex = 0,
    kClkAxiMfgIndex = 1,
    kClkMfgMmIndex = 2,
    kClockCount,

    // Indices into mmio buffers provided by the board file.
    kMfgMmioIndex = 0,
    kMfgTopMmioIndex = 1,
    kScpsysMmioIndex = 2,
    kXoMmioIndex = 3,

    kInfraTopAxiSi1Ctl = 0x1204,
    kInfraTopAxiProtectEn = 0x1220,
    kInfraTopAxiProtectSta1 = 0x1228,

    kPwrStatus = 0x60c,
    kPwrStatus2nd = 0x610,
};

struct ComponentDescription {
    zx_status_t PowerOn(ddk::MmioBuffer* power_gpu_buffer);
    bool IsPoweredOn(ddk::MmioBuffer* power_gpu_buffer, uint32_t bit);

    // offset into power_gpu_buffer registers
    uint32_t reg_offset;
    // Index into the power status registers, used to determine when powered on.
    uint32_t on_bit_offset;
    // Bits in the register that need to be set to zero to power on the SRAM.
    uint32_t sram_bits;
    // Bits in the register that will be cleared once the SRAM is powered on.
    uint32_t sram_ack_bits;
};

class Mt8167sGpu;

using DeviceType = ddk::Device<Mt8167sGpu, ddk::Messageable>;

class Mt8167sGpu : public DeviceType, public ddk::EmptyProtocol<ZX_PROTOCOL_GPU> {
public:
    Mt8167sGpu(zx_device_t* parent) : DeviceType(parent) {}

    ~Mt8167sGpu();

    zx_status_t Bind();
    void DdkRelease();

    zx_status_t DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn);

    zx_status_t Query(uint64_t query_id, fidl_txn_t* transaction);
    zx_status_t Connect(uint64_t client_id, fidl_txn_t* transaction);
    zx_status_t DumpState(uint32_t dump_type);
    zx_status_t Restart();

private:
    bool StartMagma() MAGMA_REQUIRES(magma_mutex_);
    void StopMagma() MAGMA_REQUIRES(magma_mutex_);

    // MFG is Mediatek's name for their graphics subsystem.
    zx_status_t PowerOnMfgAsync();
    zx_status_t PowerOnMfg2d();
    zx_status_t PowerOnMfg();

    void EnableMfgHwApm();

    ddk::ClockProtocolClient clks_[kClockCount];
    // MFG TOP MMIO - Controls mediatek's gpu-related power- and
    // clock-management hardware.
    std::optional<ddk::MmioBuffer> gpu_buffer_;
    // MFG MMIO (corresponds to the IMG GPU's registers)
    std::optional<ddk::MmioBuffer> real_gpu_buffer_;
    std::optional<ddk::MmioBuffer> power_gpu_buffer_; // SCPSYS MMIO
    std::optional<ddk::MmioBuffer> clock_gpu_buffer_; // XO MMIO

    std::mutex magma_mutex_;
    std::unique_ptr<MagmaDriver> magma_driver_ MAGMA_GUARDED(magma_mutex_);
    std::shared_ptr<MagmaSystemDevice> magma_system_device_ MAGMA_GUARDED(magma_mutex_);
};

Mt8167sGpu::~Mt8167sGpu()
{
    std::lock_guard<std::mutex> lock(magma_mutex_);
    StopMagma();
}

bool Mt8167sGpu::StartMagma()
{
    magma_system_device_ = magma_driver_->CreateDevice(parent());
    return !!magma_system_device_;
}

void Mt8167sGpu::StopMagma()
{
    if (magma_system_device_) {
        magma_system_device_->Shutdown();
        magma_system_device_.reset();
    }
}

void Mt8167sGpu::DdkRelease() { delete this; }

static fuchsia_gpu_magma_Device_ops_t device_fidl_ops = {
    .Query = fidl::Binder<Mt8167sGpu>::BindMember<&Mt8167sGpu::Query>,
    .Connect = fidl::Binder<Mt8167sGpu>::BindMember<&Mt8167sGpu::Connect>,
    .DumpState = fidl::Binder<Mt8167sGpu>::BindMember<&Mt8167sGpu::DumpState>,
    .TestRestart = fidl::Binder<Mt8167sGpu>::BindMember<&Mt8167sGpu::Restart>,
};

zx_status_t Mt8167sGpu::DdkMessage(fidl_msg_t* msg, fidl_txn_t* txn)
{
    return fuchsia_gpu_magma_Device_dispatch(this, txn, msg, &device_fidl_ops);
}

zx_status_t ComponentDescription::PowerOn(ddk::MmioBuffer* power_gpu_buffer)
{
    enum {
        kPowerResetBBit = 0,
        kPowerIsoBit = 1,
        kPowerOnBit = 2,
        kPowerOn2ndBit = 3,
        kPowerOnClkDisBit = 4,
    };
    power_gpu_buffer->SetBit<uint32_t>(kPowerOnBit, reg_offset);
    power_gpu_buffer->SetBit<uint32_t>(kPowerOn2ndBit, reg_offset);
    zx::time timeout = zx::deadline_after(zx::msec(100)); // Arbitrary timeout
    while (!IsPoweredOn(power_gpu_buffer, on_bit_offset)) {
        if (zx::clock::get_monotonic() > timeout) {
            GPU_ERROR("Timed out powering on component");
            return ZX_ERR_TIMED_OUT;
        }
    }
    power_gpu_buffer->ClearBit<uint32_t>(kPowerOnClkDisBit, reg_offset);
    power_gpu_buffer->ClearBit<uint32_t>(kPowerIsoBit, reg_offset);
    power_gpu_buffer->SetBit<uint32_t>(kPowerResetBBit, reg_offset);
    if (sram_bits) {
        power_gpu_buffer->ClearBits32(sram_bits, reg_offset);
        zx::time timeout = zx::deadline_after(zx::msec(100)); // Arbitrary timeout
        while (power_gpu_buffer->ReadMasked32(sram_ack_bits, reg_offset)) {
            if (zx::clock::get_monotonic() > timeout) {
                GPU_ERROR("Timed out powering on SRAM");
                return ZX_ERR_TIMED_OUT;
            }
        }
    }
    return ZX_OK;
}

bool ComponentDescription::IsPoweredOn(ddk::MmioBuffer* power_gpu_buffer, uint32_t bit)
{
    return power_gpu_buffer->GetBit<uint32_t>(bit, kPwrStatus) &&
           power_gpu_buffer->GetBit<uint32_t>(bit, kPwrStatus2nd);
}

// Power on the asynchronous memory interface between the GPU and the DDR controller.
zx_status_t Mt8167sGpu::PowerOnMfgAsync()
{
    // Set clock sources properly. Some of these are also used by the 3D and 2D
    // cores.
    clock_gpu_buffer_->ModifyBits<uint32_t>(0, 20, 2, 0x40); // slow mfg mux to 26MHz
    // MFG AXI to mainpll_d11 (on version 2+ of chip)
    clock_gpu_buffer_->ModifyBits<uint32_t>(1, 18, 2, 0x40);
    clks_[kClkSlowMfgIndex].Enable();
    clks_[kClkAxiMfgIndex].Enable();
    constexpr uint32_t kAsyncPwrStatusBit = 25;
    constexpr uint32_t kAsyncPwrRegOffset = 0x2c4;
    ComponentDescription mfg_async = {kAsyncPwrRegOffset, kAsyncPwrStatusBit, 0, 0};
    return mfg_async.PowerOn(&power_gpu_buffer_.value());
}

// Power on the 2D engine (it's unclear whether this is needed to access the 3D
// GPU, but power it on anyway).
zx_status_t Mt8167sGpu::PowerOnMfg2d()
{
    // Enable access to AXI Bus
    clock_gpu_buffer_->SetBits32((1 << 7), kInfraTopAxiSi1Ctl);
    constexpr uint32_t k2dPwrStatusBit = 24;
    constexpr uint32_t k2dPwrRegOffset = 0x2c0;

    ComponentDescription mfg_2d = {k2dPwrRegOffset, k2dPwrStatusBit, 0xf << 8, 0xf << 12};
    zx_status_t status = mfg_2d.PowerOn(&power_gpu_buffer_.value());
    if (status != ZX_OK)
        return status;
    // Disable AXI protection after it's powered up.
    clock_gpu_buffer_->ClearBits32((1 << 2) | (1 << 5), kInfraTopAxiProtectEn);
    zx_nanosleep(zx_deadline_after(ZX_USEC(100)));
    return ZX_OK;
}

// Power on the 3D engine (IMG GPU).
zx_status_t Mt8167sGpu::PowerOnMfg()
{
    clks_[kClkMfgMmIndex].Enable();
    static constexpr uint32_t kMfg3dPwrCon = 0x214;
    ComponentDescription mfg = {kMfg3dPwrCon, 4, 0xf << 8, 0xf << 12};
    zx_status_t status = mfg.PowerOn(&power_gpu_buffer_.value());
    if (status != ZX_OK)
        return status;

    // Power on MFG (internal to TOP)

    constexpr uint32_t kMfgCgClr = 0x8;
    constexpr uint32_t kBAxiClr = (1 << 0);
    constexpr uint32_t kBMemClr = (1 << 1);
    constexpr uint32_t kBG3dClr = (1 << 2);
    constexpr uint32_t kB26MClr = (1 << 3);
    gpu_buffer_->SetBits32(kBAxiClr | kBMemClr | kBG3dClr | kB26MClr, kMfgCgClr);
    EnableMfgHwApm();
    return ZX_OK;
}

// Enable hardware-controlled power management.
void Mt8167sGpu::EnableMfgHwApm()
{
    struct {
        uint32_t value;
        uint32_t offset;
    } writes[] = {
        {0x01a80000, 0x504}, {0x00080010, 0x508}, {0x00080010, 0x50c}, {0x00b800b8, 0x510},
        {0x00b000b0, 0x514}, {0x00c000c8, 0x518}, {0x00c000c8, 0x51c}, {0x00d000d8, 0x520},
        {0x00d800d8, 0x524}, {0x00d800d8, 0x528}, {0x9000001b, 0x24},  {0x8000001b, 0x24},
    };

    for (uint32_t i = 0; i < countof(writes); i++) {
        gpu_buffer_->Write32(writes[i].value, writes[i].offset);
    }
}

static uint64_t ReadHW64(const ddk::MmioBuffer* buffer, uint32_t offset)
{
    // Read 2 registers to combine into a 64-bit register.
    return (static_cast<uint64_t>(buffer->Read32(offset + 4)) << 32) | buffer->Read32(offset);
}

zx_status_t Mt8167sGpu::Bind()
{
    pdev_protocol_t pdev_proto;
    zx_status_t status;

    if ((status = device_get_protocol(parent(), ZX_PROTOCOL_PDEV, &pdev_proto)) != ZX_OK) {
        GPU_ERROR("ZX_PROTOCOL_PDEV not available\n");
        return status;
    }

    ddk::PDev pdev(&pdev_proto);

    for (unsigned i = 0; i < kClockCount; i++) {
        clks_[i] = pdev.GetClk(i);
        if (!clks_[i].is_valid()) {
            zxlogf(ERROR, "%s GetClk failed %d\n", __func__, status);
            return status;
        }
    }

    status = pdev.MapMmio(kMfgMmioIndex, &real_gpu_buffer_);
    if (status != ZX_OK) {
        GPU_ERROR("pdev_map_mmio_buffer failed\n");
        return status;
    }
    status = pdev.MapMmio(kMfgTopMmioIndex, &gpu_buffer_);
    if (status != ZX_OK) {
        GPU_ERROR("pdev_map_mmio_buffer failed\n");
        return status;
    }
    status = pdev.MapMmio(kScpsysMmioIndex, &power_gpu_buffer_);
    if (status != ZX_OK) {
        GPU_ERROR("pdev_map_mmio_buffer failed\n");
        return status;
    }
    status = pdev.MapMmio(kXoMmioIndex, &clock_gpu_buffer_);
    if (status != ZX_OK) {
        GPU_ERROR("pdev_map_mmio_buffer failed\n");
        return status;
    }

    // Power on in order.
    status = PowerOnMfgAsync();
    if (status != ZX_OK) {
        GPU_ERROR("Failed to power on MFG ASYNC\n");
        return status;
    }
    status = PowerOnMfg2d();
    if (status != ZX_OK) {
        GPU_ERROR("Failed to power on MFG 2D\n");
        return status;
    }
    status = PowerOnMfg();
    if (status != ZX_OK) {
        GPU_ERROR("Failed to power on MFG\n");
        return status;
    }
    zxlogf(INFO, "[mt8167s-gpu] GPU ID: %lx\n", ReadHW64(&real_gpu_buffer_.value(), 0x18));
    zxlogf(INFO, "[mt8167s-gpu] GPU core revision: %lx\n",
           ReadHW64(&real_gpu_buffer_.value(), 0x20));

    {
        std::lock_guard<std::mutex> lock(magma_mutex_);
        magma_driver_ = MagmaDriver::Create();
        if (!magma_driver_) {
            GPU_ERROR("Failed to create MagmaDriver\n");
            return ZX_ERR_INTERNAL;
        }

        if (!StartMagma()) {
            GPU_ERROR("Failed to start Magma system device\n");
            return ZX_ERR_INTERNAL;
        }
    }

    return DdkAdd("mt8167s-gpu");
}

zx_status_t Mt8167sGpu::Query(uint64_t query_id, fidl_txn_t* transaction)
{
    DLOG("Mt8167sGpu::Query");
    std::lock_guard<std::mutex> lock(magma_mutex_);

    uint64_t result;
    switch (query_id) {
        case MAGMA_QUERY_DEVICE_ID:
            result = magma_system_device_->GetDeviceId();
            break;
        case MAGMA_QUERY_IS_TEST_RESTART_SUPPORTED:
            result = 0;
            break;
        default:
            if (!magma_system_device_->Query(query_id, &result))
                return DRET_MSG(ZX_ERR_INVALID_ARGS, "unhandled query param 0x%" PRIx64, result);
    }
    DLOG("query query_id 0x%" PRIx64 " returning 0x%" PRIx64, query_id, result);

    zx_status_t status = fuchsia_gpu_magma_DeviceQuery_reply(transaction, result);
    if (status != ZX_OK)
        return DRET_MSG(ZX_ERR_INTERNAL, "magma_DeviceQuery_reply failed: %d", status);
    return ZX_OK;
}

zx_status_t Mt8167sGpu::Connect(uint64_t client_id, fidl_txn_t* transaction)
{
    DLOG("Mt8167sGpu::Connect");
    std::lock_guard<std::mutex> lock(magma_mutex_);

    auto connection = MagmaSystemDevice::Open(magma_system_device_, client_id);
    if (!connection)
        return DRET_MSG(ZX_ERR_INVALID_ARGS, "MagmaSystemDevice::Open failed");

    zx_status_t status = fuchsia_gpu_magma_DeviceConnect_reply(
        transaction, connection->GetClientEndpoint(), connection->GetClientNotificationEndpoint());
    if (status != ZX_OK)
        return DRET_MSG(ZX_ERR_INTERNAL, "magma_DeviceConnect_reply failed: %d", status);

    magma_system_device_->StartConnectionThread(std::move(connection));
    return ZX_OK;
}

zx_status_t Mt8167sGpu::DumpState(uint32_t dump_type)
{
    DLOG("Mt8167sGpu::DumpState");
    std::lock_guard<std::mutex> lock(magma_mutex_);
    if (dump_type & ~(MAGMA_DUMP_TYPE_NORMAL | MAGMA_DUMP_TYPE_PERF_COUNTERS |
                      MAGMA_DUMP_TYPE_PERF_COUNTER_ENABLE))
        return DRET_MSG(ZX_ERR_INVALID_ARGS, "Invalid dump type %x", dump_type);

    if (magma_system_device_)
        magma_system_device_->DumpStatus(dump_type);
    return ZX_OK;
}

zx_status_t Mt8167sGpu::Restart() { return ZX_ERR_NOT_SUPPORTED; }

extern "C" zx_status_t mt8167s_gpu_bind(void* ctx, zx_device_t* parent)
{
    auto dev = std::make_unique<Mt8167sGpu>(parent);
    auto status = dev->Bind();
    if (status == ZX_OK) {
        // devmgr is now in charge of the memory for dev
        dev.release();
    }
    return status;
}

static zx_driver_ops_t mt8167s_gpu_driver_ops = {
    .version = DRIVER_OPS_VERSION,
    .init = nullptr,
    .bind = mt8167s_gpu_bind,
    .create = nullptr,
    .release = nullptr,
};

// clang-format off
ZIRCON_DRIVER_BEGIN(mt8167s_gpu, mt8167s_gpu_driver_ops, "zircon", "0.1", 3)
    BI_ABORT_IF(NE, BIND_PROTOCOL, ZX_PROTOCOL_PDEV),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_MEDIATEK),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_MEDIATEK_GPU),
ZIRCON_DRIVER_END(mt8167s_gpu)
