blob: 9712bb76456973be21fc0d0b2f74b04571e5e377 [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.
#include <stdint.h>
#include <zircon/errors.h>
#include <zircon/syscalls/types.h>
#include <ddk/debug.h>
#include <ddk/platform-defs.h>
#include <fbl/alloc_checker.h>
#include <fbl/auto_call.h>
#include "qemu-bus.h"
#include "qemu-virt.h"
namespace board_qemu_arm64 {
zx_status_t QemuArm64::PciInit() {
zx_status_t status;
zx_pci_init_arg_t* arg1;
size_t arg_size = sizeof(*arg1) + sizeof(arg1->addr_windows[0]); // room for one addr window
fbl::AllocChecker ac;
std::unique_ptr<uint8_t[]> buf(new (&ac) uint8_t[arg_size]);
if (!ac.check()) {
return ZX_ERR_NO_MEMORY;
}
auto* arg = reinterpret_cast<zx_pci_init_arg_t*>(buf.get());
// Please do not use get_root_resource() in new code. See fxbug.dev/31358.
status = zx_pci_add_subtract_io_range(get_root_resource(), true /* mmio */, PCIE_MMIO_BASE_PHYS,
PCIE_MMIO_SIZE, true /* add */);
if (status != ZX_OK) {
return status;
}
// Please do not use get_root_resource() in new code. See fxbug.dev/31358.
status = zx_pci_add_subtract_io_range(get_root_resource(), false /* pio */, PCIE_PIO_BASE_PHYS,
PCIE_PIO_SIZE, true /* add */);
if (status != ZX_OK) {
return status;
}
// initialize our swizzle table
zx_pci_irq_swizzle_lut_t* lut = &arg->dev_pin_to_global_irq;
for (unsigned dev_id = 0; dev_id < ZX_PCI_MAX_DEVICES_PER_BUS; dev_id++) {
for (unsigned func_id = 0; func_id < ZX_PCI_MAX_FUNCTIONS_PER_DEVICE; func_id++) {
for (unsigned pin = 0; pin < ZX_PCI_MAX_LEGACY_IRQ_PINS; pin++) {
(*lut)[dev_id][func_id][pin] = PCIE_INT_BASE + (pin + dev_id) % ZX_PCI_MAX_LEGACY_IRQ_PINS;
}
}
}
arg->num_irqs = 0;
arg->addr_window_count = 1;
arg->addr_windows[0].cfg_space_type = PCI_CFG_SPACE_TYPE_MMIO;
arg->addr_windows[0].has_ecam = true;
arg->addr_windows[0].base = PCIE_ECAM_BASE_PHYS;
arg->addr_windows[0].size = PCIE_ECAM_SIZE;
arg->addr_windows[0].bus_start = 0;
arg->addr_windows[0].bus_end = (PCIE_ECAM_SIZE / ZX_PCI_ECAM_BYTE_PER_BUS) - 1;
// Please do not use get_root_resource() in new code. See fxbug.dev/31358.
status = zx_pci_init(get_root_resource(), arg, static_cast<uint32_t>(arg_size));
if (status != ZX_OK) {
zxlogf(ERROR, "%s: error %d in zx_pci_init", __func__, status);
return status;
}
return ZX_OK;
}
zx_status_t QemuArm64::PciAdd() {
constexpr pbus_bti_t kPciBtis[] = {
{
.iommu_index = 0,
.bti_id = 0,
},
};
pbus_dev_t pci_dev = {};
pci_dev.name = "pci";
pci_dev.vid = PDEV_VID_GENERIC;
pci_dev.pid = PDEV_PID_GENERIC;
pci_dev.did = PDEV_DID_KPCI;
pci_dev.bti_list = kPciBtis;
pci_dev.bti_count = countof(kPciBtis);
auto status = pbus_.DeviceAdd(&pci_dev);
if (status != ZX_OK) {
zxlogf(ERROR, "%s: DeviceAdd failed %d", __func__, status);
return status;
}
return ZX_OK;
}
} // namespace board_qemu_arm64