gpu_nomali.cc revision 10916
110916Sandreas.sandberg@arm.com/* 210916Sandreas.sandberg@arm.com * Copyright (c) 2014-2015 ARM Limited 310916Sandreas.sandberg@arm.com * All rights reserved 410916Sandreas.sandberg@arm.com * 510916Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall 610916Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual 710916Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating 810916Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software 910916Sandreas.sandberg@arm.com * licensed hereunder. You may use the software subject to the license 1010916Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated 1110916Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software, 1210916Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form. 1310916Sandreas.sandberg@arm.com * 1410916Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 1510916Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 1610916Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 1710916Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 1810916Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1910916Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 2010916Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 2110916Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 2210916Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 2310916Sandreas.sandberg@arm.com * this software without specific prior written permission. 2410916Sandreas.sandberg@arm.com * 2510916Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2610916Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2710916Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2810916Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2910916Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3010916Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3110916Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3210916Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3310916Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3410916Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3510916Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3610916Sandreas.sandberg@arm.com * 3710916Sandreas.sandberg@arm.com * Authors: Andreas Sandberg 3810916Sandreas.sandberg@arm.com */ 3910916Sandreas.sandberg@arm.com 4010916Sandreas.sandberg@arm.com#include "dev/arm/gpu_nomali.hh" 4110916Sandreas.sandberg@arm.com 4210916Sandreas.sandberg@arm.com#include "debug/NoMali.hh" 4310916Sandreas.sandberg@arm.com#include "dev/arm/base_gic.hh" 4410916Sandreas.sandberg@arm.com#include "dev/arm/realview.hh" 4510916Sandreas.sandberg@arm.com#include "enums/MemoryMode.hh" 4610916Sandreas.sandberg@arm.com#include "mem/packet_access.hh" 4710916Sandreas.sandberg@arm.com#include "params/NoMaliGpu.hh" 4810916Sandreas.sandberg@arm.com 4910916Sandreas.sandberg@arm.comNoMaliGpu::NoMaliGpu(const NoMaliGpuParams *p) 5010916Sandreas.sandberg@arm.com : PioDevice(p), 5110916Sandreas.sandberg@arm.com pioAddr(p->pio_addr), 5210916Sandreas.sandberg@arm.com platform(p->platform), 5310916Sandreas.sandberg@arm.com interruptMap{ 5410916Sandreas.sandberg@arm.com { NOMALI_INT_GPU, p->int_gpu }, 5510916Sandreas.sandberg@arm.com { NOMALI_INT_JOB, p->int_job }, 5610916Sandreas.sandberg@arm.com { NOMALI_INT_MMU, p->int_mmu }, 5710916Sandreas.sandberg@arm.com } 5810916Sandreas.sandberg@arm.com{ 5910916Sandreas.sandberg@arm.com if (nomali_api_version() != NOMALI_API_VERSION) 6010916Sandreas.sandberg@arm.com panic("NoMali library API mismatch!\n"); 6110916Sandreas.sandberg@arm.com 6210916Sandreas.sandberg@arm.com /* Setup the GPU configuration based on our param struct */ 6310916Sandreas.sandberg@arm.com nomali_config_t cfg; 6410916Sandreas.sandberg@arm.com memset(&cfg, 0, sizeof(cfg)); 6510916Sandreas.sandberg@arm.com 6610916Sandreas.sandberg@arm.com switch (p->gpu_type) { 6710916Sandreas.sandberg@arm.com case Enums::T60x: 6810916Sandreas.sandberg@arm.com cfg.type = NOMALI_GPU_T60X; 6910916Sandreas.sandberg@arm.com break; 7010916Sandreas.sandberg@arm.com 7110916Sandreas.sandberg@arm.com case Enums::T62x: 7210916Sandreas.sandberg@arm.com cfg.type = NOMALI_GPU_T62X; 7310916Sandreas.sandberg@arm.com break; 7410916Sandreas.sandberg@arm.com 7510916Sandreas.sandberg@arm.com case Enums::T760: 7610916Sandreas.sandberg@arm.com cfg.type = NOMALI_GPU_T760; 7710916Sandreas.sandberg@arm.com break; 7810916Sandreas.sandberg@arm.com 7910916Sandreas.sandberg@arm.com default: 8010916Sandreas.sandberg@arm.com fatal("Unknown GPU type\n"); 8110916Sandreas.sandberg@arm.com } 8210916Sandreas.sandberg@arm.com 8310916Sandreas.sandberg@arm.com cfg.ver_maj = p->ver_maj; 8410916Sandreas.sandberg@arm.com cfg.ver_min = p->ver_min; 8510916Sandreas.sandberg@arm.com cfg.ver_status = p->ver_status; 8610916Sandreas.sandberg@arm.com 8710916Sandreas.sandberg@arm.com panicOnErr( 8810916Sandreas.sandberg@arm.com nomali_create(&nomali, &cfg), 8910916Sandreas.sandberg@arm.com "Failed to instantiate NoMali"); 9010916Sandreas.sandberg@arm.com 9110916Sandreas.sandberg@arm.com 9210916Sandreas.sandberg@arm.com /* Setup an interrupt callback */ 9310916Sandreas.sandberg@arm.com nomali_callback_t cbk_int; 9410916Sandreas.sandberg@arm.com cbk_int.type = NOMALI_CALLBACK_INT; 9510916Sandreas.sandberg@arm.com cbk_int.usr = (void *)this; 9610916Sandreas.sandberg@arm.com cbk_int.func.interrupt = NoMaliGpu::_interrupt; 9710916Sandreas.sandberg@arm.com panicOnErr( 9810916Sandreas.sandberg@arm.com nomali_set_callback(nomali, &cbk_int), 9910916Sandreas.sandberg@arm.com "Failed to setup interrupt callback"); 10010916Sandreas.sandberg@arm.com 10110916Sandreas.sandberg@arm.com panicOnErr( 10210916Sandreas.sandberg@arm.com nomali_get_info(nomali, &nomaliInfo), 10310916Sandreas.sandberg@arm.com "Failed to get NoMali information struct"); 10410916Sandreas.sandberg@arm.com} 10510916Sandreas.sandberg@arm.com 10610916Sandreas.sandberg@arm.comNoMaliGpu::~NoMaliGpu() 10710916Sandreas.sandberg@arm.com{ 10810916Sandreas.sandberg@arm.com nomali_destroy(nomali); 10910916Sandreas.sandberg@arm.com} 11010916Sandreas.sandberg@arm.com 11110916Sandreas.sandberg@arm.com 11210916Sandreas.sandberg@arm.comvoid 11310916Sandreas.sandberg@arm.comNoMaliGpu::serialize(CheckpointOut &cp) const 11410916Sandreas.sandberg@arm.com{ 11510916Sandreas.sandberg@arm.com std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2); 11610916Sandreas.sandberg@arm.com 11710916Sandreas.sandberg@arm.com for (int i = 0; i < nomaliInfo.reg_size; i += 4) 11810916Sandreas.sandberg@arm.com regs[i >> 2] = readRegRaw(i); 11910916Sandreas.sandberg@arm.com 12010916Sandreas.sandberg@arm.com SERIALIZE_CONTAINER(regs); 12110916Sandreas.sandberg@arm.com} 12210916Sandreas.sandberg@arm.com 12310916Sandreas.sandberg@arm.comvoid 12410916Sandreas.sandberg@arm.comNoMaliGpu::unserialize(CheckpointIn &cp) 12510916Sandreas.sandberg@arm.com{ 12610916Sandreas.sandberg@arm.com std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2); 12710916Sandreas.sandberg@arm.com 12810916Sandreas.sandberg@arm.com UNSERIALIZE_CONTAINER(regs); 12910916Sandreas.sandberg@arm.com 13010916Sandreas.sandberg@arm.com for (int i = 0; i < nomaliInfo.reg_size; i += 4) 13110916Sandreas.sandberg@arm.com writeRegRaw(i, regs[i >> 2]); 13210916Sandreas.sandberg@arm.com} 13310916Sandreas.sandberg@arm.com 13410916Sandreas.sandberg@arm.comTick 13510916Sandreas.sandberg@arm.comNoMaliGpu::read(PacketPtr pkt) 13610916Sandreas.sandberg@arm.com{ 13710916Sandreas.sandberg@arm.com assert(pkt->getAddr() >= pioAddr); 13810916Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr() - pioAddr); 13910916Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 14010916Sandreas.sandberg@arm.com 14110916Sandreas.sandberg@arm.com if (addr + size >= nomaliInfo.reg_size) 14210916Sandreas.sandberg@arm.com panic("GPU register '0x%x' out of range!\n", addr); 14310916Sandreas.sandberg@arm.com 14410916Sandreas.sandberg@arm.com if (size != 4) 14510916Sandreas.sandberg@arm.com panic("Unexpected GPU register read size: %i\n", size); 14610916Sandreas.sandberg@arm.com else if (addr & 0x3) 14710916Sandreas.sandberg@arm.com panic("Unaligned GPU read: %i\n", size); 14810916Sandreas.sandberg@arm.com 14910916Sandreas.sandberg@arm.com pkt->set<uint32_t>(readReg(addr)); 15010916Sandreas.sandberg@arm.com pkt->makeResponse(); 15110916Sandreas.sandberg@arm.com 15210916Sandreas.sandberg@arm.com return 0; 15310916Sandreas.sandberg@arm.com} 15410916Sandreas.sandberg@arm.com 15510916Sandreas.sandberg@arm.comTick 15610916Sandreas.sandberg@arm.comNoMaliGpu::write(PacketPtr pkt) 15710916Sandreas.sandberg@arm.com{ 15810916Sandreas.sandberg@arm.com assert(pkt->getAddr() >= pioAddr); 15910916Sandreas.sandberg@arm.com const Addr addr(pkt->getAddr() - pioAddr); 16010916Sandreas.sandberg@arm.com const unsigned size(pkt->getSize()); 16110916Sandreas.sandberg@arm.com 16210916Sandreas.sandberg@arm.com if (addr + size >= nomaliInfo.reg_size) 16310916Sandreas.sandberg@arm.com panic("GPU register '0x%x' out of range!\n", addr); 16410916Sandreas.sandberg@arm.com 16510916Sandreas.sandberg@arm.com if (size != 4) 16610916Sandreas.sandberg@arm.com panic("Unexpected GPU register write size: %i\n", size); 16710916Sandreas.sandberg@arm.com else if (addr & 0x3) 16810916Sandreas.sandberg@arm.com panic("Unaligned GPU write: %i\n", size); 16910916Sandreas.sandberg@arm.com 17010916Sandreas.sandberg@arm.com writeReg(addr, pkt->get<uint32_t>()); 17110916Sandreas.sandberg@arm.com pkt->makeAtomicResponse(); 17210916Sandreas.sandberg@arm.com 17310916Sandreas.sandberg@arm.com return 0; 17410916Sandreas.sandberg@arm.com} 17510916Sandreas.sandberg@arm.com 17610916Sandreas.sandberg@arm.comAddrRangeList 17710916Sandreas.sandberg@arm.comNoMaliGpu::getAddrRanges() const 17810916Sandreas.sandberg@arm.com{ 17910916Sandreas.sandberg@arm.com return AddrRangeList({ RangeSize(pioAddr, nomaliInfo.reg_size) }); 18010916Sandreas.sandberg@arm.com} 18110916Sandreas.sandberg@arm.com 18210916Sandreas.sandberg@arm.comuint32_t 18310916Sandreas.sandberg@arm.comNoMaliGpu::readReg(nomali_addr_t reg) 18410916Sandreas.sandberg@arm.com{ 18510916Sandreas.sandberg@arm.com uint32_t value; 18610916Sandreas.sandberg@arm.com 18710916Sandreas.sandberg@arm.com panicOnErr( 18810916Sandreas.sandberg@arm.com nomali_reg_read(nomali, &value, reg), 18910916Sandreas.sandberg@arm.com "GPU register read failed"); 19010916Sandreas.sandberg@arm.com 19110916Sandreas.sandberg@arm.com DPRINTF(NoMali, "readReg(0x%x): 0x%x\n", 19210916Sandreas.sandberg@arm.com reg, value); 19310916Sandreas.sandberg@arm.com 19410916Sandreas.sandberg@arm.com return value; 19510916Sandreas.sandberg@arm.com} 19610916Sandreas.sandberg@arm.com 19710916Sandreas.sandberg@arm.com 19810916Sandreas.sandberg@arm.comvoid 19910916Sandreas.sandberg@arm.comNoMaliGpu::writeReg(nomali_addr_t reg, uint32_t value) 20010916Sandreas.sandberg@arm.com{ 20110916Sandreas.sandberg@arm.com DPRINTF(NoMali, "writeReg(0x%x, 0x%x)\n", 20210916Sandreas.sandberg@arm.com reg, value); 20310916Sandreas.sandberg@arm.com 20410916Sandreas.sandberg@arm.com panicOnErr( 20510916Sandreas.sandberg@arm.com nomali_reg_write(nomali, reg, value), 20610916Sandreas.sandberg@arm.com "GPU register write failed"); 20710916Sandreas.sandberg@arm.com} 20810916Sandreas.sandberg@arm.com 20910916Sandreas.sandberg@arm.comuint32_t 21010916Sandreas.sandberg@arm.comNoMaliGpu::readRegRaw(nomali_addr_t reg) const 21110916Sandreas.sandberg@arm.com{ 21210916Sandreas.sandberg@arm.com uint32_t value; 21310916Sandreas.sandberg@arm.com 21410916Sandreas.sandberg@arm.com panicOnErr( 21510916Sandreas.sandberg@arm.com nomali_reg_read_raw(nomali, &value, reg), 21610916Sandreas.sandberg@arm.com "GPU raw register read failed"); 21710916Sandreas.sandberg@arm.com 21810916Sandreas.sandberg@arm.com return value; 21910916Sandreas.sandberg@arm.com} 22010916Sandreas.sandberg@arm.com 22110916Sandreas.sandberg@arm.com 22210916Sandreas.sandberg@arm.comvoid 22310916Sandreas.sandberg@arm.comNoMaliGpu::writeRegRaw(nomali_addr_t reg, uint32_t value) 22410916Sandreas.sandberg@arm.com{ 22510916Sandreas.sandberg@arm.com panicOnErr( 22610916Sandreas.sandberg@arm.com nomali_reg_write_raw(nomali, reg, value), 22710916Sandreas.sandberg@arm.com "GPU raw register write failed"); 22810916Sandreas.sandberg@arm.com} 22910916Sandreas.sandberg@arm.com 23010916Sandreas.sandberg@arm.comvoid 23110916Sandreas.sandberg@arm.comNoMaliGpu::_interrupt(nomali_handle_t h, void *usr, nomali_int_t intno, int set) 23210916Sandreas.sandberg@arm.com{ 23310916Sandreas.sandberg@arm.com NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr)); 23410916Sandreas.sandberg@arm.com 23510916Sandreas.sandberg@arm.com _this->onInterrupt(h, intno, !!set); 23610916Sandreas.sandberg@arm.com} 23710916Sandreas.sandberg@arm.com 23810916Sandreas.sandberg@arm.comvoid 23910916Sandreas.sandberg@arm.comNoMaliGpu::onInterrupt(nomali_handle_t h, nomali_int_t intno, bool set) 24010916Sandreas.sandberg@arm.com{ 24110916Sandreas.sandberg@arm.com const auto it_int(interruptMap.find(intno)); 24210916Sandreas.sandberg@arm.com if (it_int == interruptMap.end()) 24310916Sandreas.sandberg@arm.com panic("Unhandled interrupt from NoMali: %i\n", intno); 24410916Sandreas.sandberg@arm.com 24510916Sandreas.sandberg@arm.com DPRINTF(NoMali, "Interrupt %i->%i: %i\n", 24610916Sandreas.sandberg@arm.com intno, it_int->second, set); 24710916Sandreas.sandberg@arm.com 24810916Sandreas.sandberg@arm.com assert(platform); 24910916Sandreas.sandberg@arm.com assert(platform->gic); 25010916Sandreas.sandberg@arm.com 25110916Sandreas.sandberg@arm.com if (set) 25210916Sandreas.sandberg@arm.com platform->gic->sendInt(it_int->second); 25310916Sandreas.sandberg@arm.com else 25410916Sandreas.sandberg@arm.com platform->gic->clearInt(it_int->second); 25510916Sandreas.sandberg@arm.com} 25610916Sandreas.sandberg@arm.com 25710916Sandreas.sandberg@arm.comvoid 25810916Sandreas.sandberg@arm.comNoMaliGpu::gpuPanic(nomali_error_t err, const char *msg) 25910916Sandreas.sandberg@arm.com{ 26010916Sandreas.sandberg@arm.com panic("%s: %s\n", msg, nomali_errstr(err)); 26110916Sandreas.sandberg@arm.com} 26210916Sandreas.sandberg@arm.com 26310916Sandreas.sandberg@arm.comNoMaliGpu * 26410916Sandreas.sandberg@arm.comNoMaliGpuParams::create() 26510916Sandreas.sandberg@arm.com{ 26610916Sandreas.sandberg@arm.com return new NoMaliGpu(this); 26710916Sandreas.sandberg@arm.com} 268