// Copyright 2018 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

#include <dev/pci/designware/dw-pcie.h>

#include <zircon/syscalls.h>

#include "dw-pcie-hw.h"

namespace {

const uint64_t kMask32 = 0xffffffff;

inline uint32_t lo32(const uint64_t v) {
    return static_cast<uint32_t>(v & kMask32);
}

inline uint32_t hi32(const uint64_t v) {
    return static_cast<uint32_t>((v >> 32));
}

}  // namespace

namespace pcie {

namespace designware {

bool DwPcie::IsLinkUp() {
    auto phyDebugR1 = PortLogic::DebugR1::Get().ReadFrom(dbi_.get());

    const bool isLinkUp = phyDebugR1.link_up();
    const bool isLinkTraining = phyDebugR1.link_in_training();

    return isLinkUp && !isLinkTraining;
}

uint32_t DwPcie::ReadRC(const uint32_t offset) {
    return dbi_->Read32(offset);
}

void DwPcie::WriteRC(const uint32_t offset, const uint32_t val) {
    return dbi_->Write32(val, offset);
}

/*
 * Program a region into the outbound ATU
 * The ATU supports 16 regions that can be programmed independently.
 *   pcie,              PCIe Device Struct
 *   index,             Which iATU region are we programming?
 *   type,              Type of PCIe txn being generated on the PCIe bus
 *   cpu_addr,          Physical source address to translate in the CPU's address space
 *   pci_addr,          Destination Address in the PCIe address space
 *   size               Size of the aperature that we're translating.
 */
zx_status_t DwPcie::ProgramOutboundAtu(const uint32_t index,
                                       const uint32_t type,
                                       const zx_paddr_t cpu_addr,
                                       const uintptr_t pci_addr,
                                       const size_t size) {
    // The ATU supports a limited number of regions.
    ZX_DEBUG_ASSERT(index < kAtuRegionCount);

    // Each ATU region has its own bank of registers at this offset from the
    // DBI base
    const size_t bank_offset = (0x3 << 20) | (index << 9);
    volatile uint8_t* atu_base =
        reinterpret_cast<volatile uint8_t*>(dbi_->get()) + bank_offset;

    volatile atu_ctrl_regs_t* regs =
        reinterpret_cast<volatile atu_ctrl_regs_t*>(atu_base);

    // Memory transactions that are in the following range will get translated
    // to PCI bus transactions:
    //
    // [cpu_addr, cpu_addr + size - 1]
    regs->unroll_lower_base = lo32(cpu_addr);
    regs->unroll_upper_base = hi32(cpu_addr);

    regs->unroll_limit = lo32(cpu_addr + size - 1);

    // Target of the transactions above.
    regs->unroll_lower_target = lo32(pci_addr);
    regs->unroll_upper_target = hi32(pci_addr);

    // Region Ctrl 1 contains a number of fields. The Low 5 bits of the field
    // indicate the type of transaction to dispatch onto the PCIe bus.
    regs->region_ctrl1 = type;

    // Each region can individually be marked as Enabled or Disabled.
    regs->region_ctrl2 |= kAtuRegionCtrlEnable;
    regs->region_ctrl2 |= kAtuCfgShiftMode;

    // Wait for the enable to take effect.
    for (unsigned int i = 0; i < kAtuProgramRetries; ++i) {
        if (regs->region_ctrl2 & kAtuRegionCtrlEnable) {
            return ZX_OK;
        }

        // Wait a little bit before trying again.
        zx_nanosleep(zx_deadline_after(ZX_USEC(kAtuWaitEnableTimeoutUs)));
    }

    return ZX_ERR_TIMED_OUT;
}

void DwPcie::LinkSpeedChange() {
    dbi_->SetBits32(G2_CTRL_DIRECT_SPEED_CHANGE, GEN2_CTRL_OFF);
}

zx_status_t DwPcie::SetupRootComplex(
    const iatu_translation_entry_t* cfg,
    const iatu_translation_entry_t* io,
    const iatu_translation_entry_t* mem
) {
    uint32_t portLinkMode = 0;
    const uint32_t g2ctrlNoOfLanes = G2_CTRL_NO_OF_LANES(nLanes_);

    switch (nLanes_) {
        case 1:
            portLinkMode = PLC_LINK_CAPABLE_X1;
            break;
        case 2:
            portLinkMode = PLC_LINK_CAPABLE_X2;
            break;
        case 4:
            portLinkMode = PLC_LINK_CAPABLE_X4;
            break;
        case 8:
            portLinkMode = PLC_LINK_CAPABLE_X8;
            break;
        default:
            return ZX_ERR_INVALID_ARGS;
    }

    uint32_t val;
    val = ReadRC(PORT_LINK_CTRL_OFF);
    val &= ~PLC_LINK_CAPABLE_MASK;
    val |= portLinkMode;
    WriteRC(PORT_LINK_CTRL_OFF, val);

    val = ReadRC(GEN2_CTRL_OFF);
    val &= ~G2_CTRL_NUM_OF_LANES_MASK;
    val |= g2ctrlNoOfLanes;
    WriteRC(GEN2_CTRL_OFF, g2ctrlNoOfLanes);

    WriteRC(PCI_TYPE1_BAR0, 0x4);
    WriteRC(PCI_TYPE1_BAR1, 0x0);

    uint32_t idx = 0;
    if (cfg) {
        ProgramOutboundAtu(idx, PCIE_TLP_TYPE_CFG0, cfg->cpu_addr,
                           cfg->pci_addr, cfg->length);
        idx++;
    }

    if (io) {
        ProgramOutboundAtu(idx, PCIE_TLP_TYPE_IO_RW, cfg->cpu_addr,
                           cfg->pci_addr, cfg->length);
        idx++;
    }

    if (mem) {
        ProgramOutboundAtu(idx, PCIE_TLP_TYPE_MEM_RW, cfg->cpu_addr,
                           cfg->pci_addr, cfg->length);
        idx++;
    }

    LinkSpeedChange();

    return ZX_OK;

}

} // namespace designware
} // namespace pcie
