blob: 688f5867e36abf4c7b9f8f44d86b2db135eecb04 [file] [log] [blame]
/*
* Copyright (c) 2014-2015 ARM Limited
* All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Authors: Andreas Sandberg
*/
#include "gpucontrol.hh"
#include "gpu.hh"
#include "regutils.hh"
namespace NoMali {
typedef void (GPUControl::*GpuCmdHandler)(uint32_t);
const std::vector<GpuCmdHandler> GPUControl::cmds {
&GPUControl::cmdNop, // GPU_COMMAND_NOP
&GPUControl::cmdSoftReset, // GPU_COMMAND_SOFT_RESET
&GPUControl::cmdHardReset, // GPU_COMMAND_HARD_RESET
&GPUControl::cmdPerfCntClear, // GPU_COMMAND_PRFCNT_CLEAR
&GPUControl::cmdPerfCntSample, // GPU_COMMAND_PRFCNT_SAMPLE
&GPUControl::cmdCycleCountStart, // GPU_COMMAND_CYCLE_COUNT_START
&GPUControl::cmdCycleCountStop, // GPU_COMMAND_COUNT_STOP
&GPUControl::cmdCleanCaches, // GPU_COMMAND_CLEAN_CACHES
&GPUControl::cmdCleanInvCaches, // GPU_COMMAND_CLEAN_INV_CACHES
};
GPUControl::GPUControl(GPU &_gpu)
: GPUBlockInt(_gpu,
RegAddr(GPU_IRQ_RAWSTAT),
RegAddr(GPU_IRQ_CLEAR),
RegAddr(GPU_IRQ_MASK),
RegAddr(GPU_IRQ_STATUS))
{
}
GPUControl::~GPUControl()
{
}
void
GPUControl::reset()
{
GPUBlock::reset();
}
void
GPUControl::writeReg(RegAddr addr, uint32_t value)
{
switch (addr.value) {
case GPU_IRQ_RAWSTAT:
case GPU_IRQ_CLEAR:
case GPU_IRQ_MASK:
case GPU_IRQ_STATUS:
GPUBlockInt::writeReg(addr, value);
break;
case GPU_COMMAND:
gpuCommand(value);
break;
case SHADER_PWRON_LO:
case SHADER_PWRON_HI:
case TILER_PWRON_LO:
case TILER_PWRON_HI:
case L2_PWRON_LO:
case L2_PWRON_HI:
case L3_PWRON_LO:
case L3_PWRON_HI: {
const RegAddr ready_reg(SHADER_READY_LO +
(addr.value - SHADER_PWRON_LO));
const RegAddr present_reg(SHADER_PRESENT_LO +
(addr.value - SHADER_PWRON_LO));
regs[ready_reg] |= value & regs[present_reg];
raiseInterrupt(POWER_CHANGED_SINGLE | POWER_CHANGED_ALL);
} break;
case SHADER_PWROFF_LO:
case SHADER_PWROFF_HI:
case TILER_PWROFF_LO:
case TILER_PWROFF_HI:
case L2_PWROFF_LO:
case L2_PWROFF_HI:
case L3_PWROFF_LO:
case L3_PWROFF_HI: {
const RegAddr ready_reg(SHADER_READY_LO +
(addr.value - SHADER_PWROFF_LO));
regs[ready_reg] &= ~value;
raiseInterrupt(POWER_CHANGED_SINGLE | POWER_CHANGED_ALL);
} break;
default:
// Ignore writes by default
break;
};
}
void
GPUControl::onInterrupt(int set)
{
gpu.intGPU(set);
}
void
GPUControl::gpuCommand(uint32_t cmd)
{
if (cmd < cmds.size())
(this->*cmds[cmd])(cmd);
}
void
GPUControl::cmdNop(uint32_t cmd)
{
}
void
GPUControl::cmdHardReset(uint32_t cmd)
{
gpu.reset();
raiseInterrupt(RESET_COMPLETED);
}
void
GPUControl::cmdSoftReset(uint32_t cmd)
{
gpu.reset();
raiseInterrupt(RESET_COMPLETED);
}
void
GPUControl::cmdPerfCntClear(uint32_t cmd)
{
}
void
GPUControl::cmdPerfCntSample(uint32_t cmd)
{
raiseInterrupt(PRFCNT_SAMPLE_COMPLETED);
}
void
GPUControl::cmdCycleCountStart(uint32_t cmd)
{
}
void
GPUControl::cmdCycleCountStop(uint32_t cmd)
{
}
void
GPUControl::cmdCleanCaches(uint32_t cmd)
{
raiseInterrupt(CLEAN_CACHES_COMPLETED);
}
void
GPUControl::cmdCleanInvCaches(uint32_t cmd)
{
raiseInterrupt(CLEAN_CACHES_COMPLETED);
}
}