| /* |
| * 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 "gpublock.hh" |
| |
| #include "gpu.hh" |
| #include "regutils.hh" |
| |
| namespace NoMali { |
| |
| GPUBlock::GPUBlock(GPU &_gpu) |
| : gpu(_gpu), regs(BLOCK_NUM_REGS) |
| { |
| } |
| |
| GPUBlock::GPUBlock(GPU &_gpu, RegVector::size_type no_regs) |
| : gpu(_gpu), regs(no_regs) |
| { |
| } |
| |
| GPUBlock::GPUBlock(GPUBlock &&rhs) |
| : gpu(rhs.gpu), |
| regs(std::move(rhs.regs)) |
| { |
| } |
| |
| GPUBlock::~GPUBlock() |
| { |
| } |
| |
| void |
| GPUBlock::reset() |
| { |
| for (auto &r : regs) |
| r = 0; |
| } |
| |
| uint32_t |
| GPUBlock::readReg(RegAddr addr) |
| { |
| return readRegRaw(addr); |
| } |
| |
| void |
| GPUBlock::writeReg(RegAddr addr, uint32_t value) |
| { |
| writeRegRaw(addr, value); |
| } |
| |
| uint32_t |
| GPUBlock::readRegRaw(RegAddr addr) |
| { |
| return regs[addr]; |
| } |
| |
| void |
| GPUBlock::writeRegRaw(RegAddr addr, uint32_t value) |
| { |
| regs[addr] = value; |
| } |
| |
| |
| |
| GPUBlockInt::GPUBlockInt(GPU &_gpu, |
| const RegAddr &irq_raw_stat, |
| const RegAddr &irq_clear, |
| const RegAddr &irq_mask, |
| const RegAddr &irq_stat) |
| : GPUBlock(_gpu), |
| addrIrqRawStat(irq_raw_stat), addrIrqClear(irq_clear), |
| addrIrqMask(irq_mask), addrIrqStat(irq_stat) |
| { |
| } |
| |
| GPUBlockInt::~GPUBlockInt() |
| { |
| } |
| |
| uint32_t |
| GPUBlockInt::readReg(RegAddr addr) |
| { |
| if (addr == addrIrqStat) { |
| return irqStatus(); |
| } else { |
| return GPUBlock::readReg(addr); |
| } |
| } |
| |
| void |
| GPUBlockInt::writeReg(RegAddr addr, uint32_t value) |
| { |
| if (addr == addrIrqRawStat) { |
| raiseInterrupt(value); |
| } else if (addr == addrIrqClear) { |
| clearInterrupt(value); |
| } else if (addr == addrIrqMask ) { |
| const bool old_int(intAsserted()); |
| GPUBlock::writeReg(addr, value); |
| if (old_int != intAsserted()) |
| onInterrupt(intAsserted()); |
| } else if (addr == addrIrqStat ) { |
| // Ignore writes to the IRQ status register |
| } else { |
| // Handle addrIrqMask & defaults |
| GPUBlock::writeReg(addr, value); |
| } |
| } |
| |
| |
| |
| void |
| GPUBlockInt::raiseInterrupt(uint32_t ints) |
| { |
| const bool old_int(intAsserted()); |
| |
| regs[addrIrqRawStat] |= ints; |
| // Is the interrupt line going high? |
| if (!old_int && intAsserted()) |
| onInterrupt(1); |
| } |
| |
| void |
| GPUBlockInt::clearInterrupt(uint32_t ints) |
| { |
| const bool old_int(intAsserted()); |
| |
| regs[addrIrqRawStat] &= ~ints; |
| // Is the interrupt line going low? |
| if (old_int && !intAsserted()) |
| onInterrupt(0); |
| } |
| |
| uint32_t |
| GPUBlockInt::irqStatus() const |
| { |
| return regs[addrIrqRawStat] & regs[addrIrqMask]; |
| } |
| |
| |
| } |