/* * 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 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); } }