blob: 3492ce51d4c155f20c89cb9ccef073a4bc5fc00f [file] [log] [blame]
// Copyright 2017 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 "garnet/bin/guest/vmm/arch/arm64/pl031.h"
#include <endian.h>
#include <stdio.h>
#include <lib/fxl/logging.h>
#include "garnet/bin/guest/vmm/guest.h"
#include "garnet/bin/guest/vmm/rtc.h"
__BEGIN_CDECLS;
#include <libfdt.h>
__END_CDECLS;
// PL031 registers.
enum class Pl031Register : uint64_t {
DR = 0x00,
};
static constexpr uint64_t kPl031PhysBase = 0x808301000;
static constexpr uint64_t kPl031Size = 0x1000;
zx_status_t Pl031::Init(Guest* guest) {
return guest->CreateMapping(TrapType::MMIO_SYNC, kPl031PhysBase, kPl031Size,
0, this);
}
zx_status_t Pl031::Read(uint64_t addr, IoValue* value) const {
switch (static_cast<Pl031Register>(addr)) {
case Pl031Register::DR:
if (value->access_size != 4) {
return ZX_ERR_IO_DATA_INTEGRITY;
}
value->u32 = rtc_time();
return ZX_OK;
default:
FXL_LOG(ERROR) << "Unhandled PL031 address read 0x" << std::hex << addr;
return ZX_ERR_IO;
}
}
zx_status_t Pl031::Write(uint64_t addr, const IoValue& value) {
FXL_LOG(ERROR) << "Unhandled PL031 address write 0x" << std::hex << addr;
return ZX_ERR_IO;
}
zx_status_t Pl031::ConfigureDtb(void* dtb) const {
uint64_t reg_val[2] = {htobe64(kPl031PhysBase), htobe64(kPl031Size)};
int node_off =
fdt_node_offset_by_prop_value(dtb, -1, "reg", reg_val, sizeof(reg_val));
if (node_off < 0) {
FXL_LOG(ERROR) << "Failed to find PL031 in DTB";
return ZX_ERR_INTERNAL;
}
int ret = fdt_node_check_compatible(dtb, node_off, "arm,pl031");
if (ret != 0) {
FXL_LOG(ERROR) << "Device with PL031 registers is not PL031 compatible";
return ZX_ERR_INTERNAL;
}
return ZX_OK;
}