1/* 2 * Copyright (c) 2014-2015 ARM Limited 3 * All rights reserved 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * Authors: Andreas Sandberg 18 */ 19 20#include "jobcontrol.hh" 21 22#include "gpu.hh" 23#include "regutils.hh" 24 25namespace NoMali { 26 27JobControl::JobControl(GPU &_gpu) 28 : GPUBlockInt(_gpu, 29 RegAddr(JOB_IRQ_RAWSTAT), 30 RegAddr(JOB_IRQ_CLEAR), 31 RegAddr(JOB_IRQ_MASK), 32 RegAddr(JOB_IRQ_STATUS)) 33{ 34 slots.reserve(16); 35 for (int i = 0; i < 16; ++i) 36 slots.emplace_back(_gpu, *this, i); 37 38} 39 40JobControl::~JobControl() 41{ 42} 43 44void 45JobControl::reset() 46{ 47 GPUBlockInt::reset(); 48 49 for (auto &js : slots) 50 js.reset(); 51} 52 53uint32_t 54JobControl::readReg(RegAddr addr) 55{ 56 if (addr >= RegAddr(JOB_SLOT0)) { 57 return slots[getJobSlotNo(addr)].readReg(getJobSlotAddr(addr)); 58 } else { 59 return GPUBlockInt::readReg(addr); 60 } 61} 62 63void 64JobControl::writeReg(RegAddr addr, uint32_t value) 65{ 66 switch(addr.value) { 67 case JOB_IRQ_CLEAR: 68 // Update JS state for all jobs that were affected by the IRQ 69 // clear 70 updateJsState((value & 0xFFFF) | ((value & 0xFFFF0000) >> 16)); 71 72 // FALLTHROUGH - IRQ handling in base class 73 case JOB_IRQ_RAWSTAT: 74 case JOB_IRQ_MASK: 75 case JOB_IRQ_STATUS: 76 GPUBlockInt::writeReg(addr, value); 77 break; 78 79 default: 80 if (addr >= RegAddr(JOB_SLOT0)) 81 slots[getJobSlotNo(addr)].writeReg(getJobSlotAddr(addr), value); 82 break; 83 } 84} 85 86uint32_t 87JobControl::readRegRaw(RegAddr addr) 88{ 89 if (addr >= RegAddr(JOB_SLOT0)) { 90 return slots[getJobSlotNo(addr)].readRegRaw(getJobSlotAddr(addr)); 91 } else { 92 return GPUBlockInt::readRegRaw(addr); 93 } 94} 95 96 97void 98JobControl::writeRegRaw(RegAddr addr, uint32_t value) 99{ 100 if (addr >= RegAddr(JOB_SLOT0)) { 101 slots[getJobSlotNo(addr)].writeRegRaw(getJobSlotAddr(addr), value); 102 } else { 103 GPUBlockInt::writeRegRaw(addr, value); 104 } 105} 106 107void 108JobControl::jobDone(uint8_t slot) 109{ 110 assert(slot <= 15); 111 raiseInterrupt(1 << slot); 112} 113 114void 115JobControl::jobFailed(uint8_t slot) 116{ 117 assert(slot <= 15); 118 raiseInterrupt(0x10000 << slot); 119} 120 121void 122JobControl::updateJsState(uint16_t jobs) 123{ 124 // The JS_STATE register contains two bits per job slot; one bit 125 // representing an active job and one bit representing the queued 126 // job. We need to mask out bits of the jobs affected by this update. 127 const uint32_t job_mask(jobs | (jobs << 16)); 128 uint16_t js_state(regs[RegAddr(JOB_IRQ_JS_STATE)] & ~job_mask); 129 130 // Find if there is an active or active next job for all jobs in 131 // the job mask. 132 for (int i = 0; i < 16; ++i) { 133 const JobSlot &slot(slots[i]); 134 if (jobs & (1 << i)) { 135 js_state |= slot.active() ? (1 << i) : 0 | 136 slot.activeNext() ? (0x10000 << i) : 0; 137 } 138 } 139 regs[RegAddr(JOB_IRQ_JS_STATE)] = js_state; 140} 141 142void 143JobControl::onInterrupt(int set) 144{ 145 gpu.intJob(set); 146} 147 148} 149