blob: 3abd9ed2e6a9223d27110ffec58e74d4eed2cc3d [file] [log] [blame]
// 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 file.
#ifndef SRC_GRAPHICS_DISPLAY_DRIVERS_AMLOGIC_DISPLAY_RDMA_REGS_H_
#define SRC_GRAPHICS_DISPLAY_DRIVERS_AMLOGIC_DISPLAY_RDMA_REGS_H_
#include <lib/mmio/mmio-buffer.h>
#include <cstdint>
#include <hwreg/bitfields.h>
// The register definitions here are from AMLogic S912 Datasheet revision 0.1.
// The information was cross-checked against AMLogic's VLSI GXL RDMA
// Specification, Version 1.0, dated September 26, 2018.
// The RDMA (Register Direct Memory Access) is briefly described in the S912
// Datasheet section 27.3 "Video Output" > "RDMA".
//
// The A311D datasheet Section 10.2.1 "Video Output" > "Overview" mentions that
// the VPU includes an RDMA submodule, but does not list the registers. Our
// experiments and passing tests indicate that the RDMA functionality we use is
// unchanged.
// Register addresses from the S912 datasheet section 27.3 "RDMA", Table
// IV.29.3 "Register List of RDMA". The table specifies absolute addresses, but
// the addresses are relative to the VPU's MMIO block. S912 datasheet section
// 16 "Memory Map" indicates that the S912's VPU's MMIO block starts at
// 0xd0100000.
#define VPU_RDMA_AHB_START_ADDR_MAN 0x4400
#define VPU_RDMA_AHB_END_ADDR_MAN 0x4404
#define VPU_RDMA_AHB_START_ADDR_1 0x4408
#define VPU_RDMA_AHB_END_ADDR_1 0x440c
#define VPU_RDMA_AHB_START_ADDR_2 0x4410
#define VPU_RDMA_AHB_END_ADDR_2 0x4414
#define VPU_RDMA_AHB_START_ADDR_3 0x4418
#define VPU_RDMA_AHB_END_ADDR_3 0x441c
#define VPU_RDMA_AHB_START_ADDR_4 0x4420
#define VPU_RDMA_AHB_END_ADDR_4 0x4424
#define VPU_RDMA_AHB_START_ADDR_5 0x4428
#define VPU_RDMA_AHB_END_ADDR_5 0x442c
#define VPU_RDMA_AHB_START_ADDR_6 0x4430
#define VPU_RDMA_AHB_END_ADDR_6 0x4434
#define VPU_RDMA_AHB_START_ADDR_7 0x4438
#define VPU_RDMA_AHB_END_ADDR_7 0x443c
#define VPU_RDMA_ACCESS_AUTO 0x4440
#define VPU_RDMA_ACCESS_AUTO2 0x4444
#define VPU_RDMA_ACCESS_AUTO3 0x4448
#define VPU_RDMA_ACCESS_MAN 0x444c
#define VPU_RDMA_CTRL 0x4450
#define VPU_RDMA_STATUS 0x4454
#define VPU_RDMA_STATUS2 0x4458
#define VPU_RDMA_STATUS3 0x445c
#define VPU_RDMA_AHB_START_ADDR(x) (VPU_RDMA_AHB_START_ADDR_MAN + ((x) << 3))
#define VPU_RDMA_AHB_END_ADDR(x) (VPU_RDMA_AHB_END_ADDR_MAN + ((x) << 3))
// VPU_RDMA_ACCESS_AUTO Bit Definition
#define RDMA_ACCESS_AUTO_INT_EN(channel) (1 << ((channel) << 3))
#define RDMA_ACCESS_AUTO_WRITE(channel) (1 << ((channel) + 4))
// VPU_RDMA_CTRL Bit Definition
#define RDMA_CTRL_INT_DONE(channel) (1 << (channel))
// VPU_RDMA_STATUS Bit Definition
#define RDMA_STATUS_DONE(channel) (1 << (channel))
class RdmaStatusReg : public hwreg::RegisterBase<RdmaStatusReg, uint32_t> {
public:
// Both of these fields use bit 0 for manual RDMA. Auto RDMA is 1-indexed.
DEF_FIELD(31, 24, done);
DEF_FIELD(7, 0, req_latch);
static auto Get() { return hwreg::RegisterAddr<RdmaStatusReg>(VPU_RDMA_STATUS); }
bool RequestLatched(uint8_t chan) const { return req_latch() & (1 << chan); }
bool ChannelDone(uint8_t chan) const { return done() & (1 << chan); }
static bool ChannelDone(uint8_t chan, fdf::MmioBuffer* mmio) {
return Get().ReadFrom(mmio).ChannelDone(chan);
}
// compute a value for .done() to match given the current state of
// VPU_RDMA_ACCESS_AUTO, AUTO2, and AUTO3.
static uint32_t DoneFromAccessAuto(const uint32_t aa, const uint32_t aa2, const uint32_t aa3) {
const uint32_t chn7 = ((aa3 >> 24) & 0x1) << 7;
const uint32_t chn2 = ((aa >> 24) & 0x1) << 2;
const uint32_t chn1 = ((aa >> 16) & 0x1) << 1;
const uint32_t chn0 = ((aa >> 8) & 0x1) << 0;
return chn7 | chn2 | chn1 | chn0;
}
};
class RdmaCtrlReg : public hwreg::RegisterBase<RdmaCtrlReg, uint32_t> {
public:
// As with RDMA_STATUS, this field uses bit 0 for manual RDMA.
DEF_FIELD(31, 24, clear_done);
DEF_BIT(7, write_urgent);
DEF_BIT(6, read_urgent);
static auto Get() { return hwreg::RegisterAddr<RdmaCtrlReg>(VPU_RDMA_CTRL); }
static void ClearInterrupt(uint8_t chan, fdf::MmioBuffer* mmio) {
Get().ReadFrom(mmio).set_clear_done(1 << chan).WriteTo(mmio);
}
};
class RdmaAccessAutoReg : public hwreg::RegisterBase<RdmaAccessAutoReg, uint32_t> {
public:
DEF_FIELD(31, 24, chn3_intr);
DEF_FIELD(23, 16, chn2_intr);
DEF_FIELD(15, 8, chn1_intr);
DEF_BIT(7, chn3_auto_write);
DEF_BIT(6, chn2_auto_write);
DEF_BIT(5, chn1_auto_write);
static auto Get() { return hwreg::RegisterAddr<RdmaAccessAutoReg>(VPU_RDMA_ACCESS_AUTO); }
};
class RdmaAccessAuto2Reg : public hwreg::RegisterBase<RdmaAccessAuto2Reg, uint32_t> {
public:
DEF_BIT(7, chn7_auto_write);
static auto Get() { return hwreg::RegisterAddr<RdmaAccessAuto2Reg>(VPU_RDMA_ACCESS_AUTO2); }
};
class RdmaAccessAuto3Reg : public hwreg::RegisterBase<RdmaAccessAuto3Reg, uint32_t> {
public:
DEF_FIELD(31, 24, chn7_intr);
static auto Get() { return hwreg::RegisterAddr<RdmaAccessAuto3Reg>(VPU_RDMA_ACCESS_AUTO3); }
};
#endif // SRC_GRAPHICS_DISPLAY_DRIVERS_AMLOGIC_DISPLAY_RDMA_REGS_H_