gpu_nomali.cc revision 11349:9e46b77e5e56
112855Sgabeblack@google.com/*
212855Sgabeblack@google.com * Copyright (c) 2014-2016 ARM Limited
312855Sgabeblack@google.com * All rights reserved
412855Sgabeblack@google.com *
512855Sgabeblack@google.com * The license below extends only to copyright in the software and shall
612855Sgabeblack@google.com * not be construed as granting a license to any other intellectual
712855Sgabeblack@google.com * property including but not limited to intellectual property relating
812855Sgabeblack@google.com * to a hardware implementation of the functionality of the software
912855Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1012855Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1112855Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1212855Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1312855Sgabeblack@google.com *
1412855Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
1512855Sgabeblack@google.com * modification, are permitted provided that the following conditions are
1612855Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
1712855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
1812855Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1912855Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2012855Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2112855Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2212855Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2312855Sgabeblack@google.com * this software without specific prior written permission.
2412855Sgabeblack@google.com *
2512855Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612855Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712855Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812855Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912855Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012855Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112855Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212855Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312855Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412855Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512855Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612855Sgabeblack@google.com *
3712855Sgabeblack@google.com * Authors: Andreas Sandberg
3812855Sgabeblack@google.com */
3912855Sgabeblack@google.com
4012855Sgabeblack@google.com#include "dev/arm/gpu_nomali.hh"
4112855Sgabeblack@google.com
4212855Sgabeblack@google.com#include "debug/NoMali.hh"
4312855Sgabeblack@google.com#include "dev/arm/base_gic.hh"
4412855Sgabeblack@google.com#include "dev/arm/realview.hh"
4512855Sgabeblack@google.com#include "enums/MemoryMode.hh"
4612855Sgabeblack@google.com#include "mem/packet_access.hh"
4712855Sgabeblack@google.com#include "params/NoMaliGpu.hh"
4812855Sgabeblack@google.com
4912855Sgabeblack@google.comstatic const std::map<Enums::NoMaliGpuType, nomali_gpu_type_t> gpuTypeMap{
5012855Sgabeblack@google.com    { Enums::T60x, NOMALI_GPU_T60X },
5112855Sgabeblack@google.com    { Enums::T62x, NOMALI_GPU_T62X },
5212855Sgabeblack@google.com    { Enums::T760, NOMALI_GPU_T760 },
5312855Sgabeblack@google.com};
5412855Sgabeblack@google.com
5512855Sgabeblack@google.comNoMaliGpu::NoMaliGpu(const NoMaliGpuParams *p)
5612855Sgabeblack@google.com    : PioDevice(p),
5712855Sgabeblack@google.com      pioAddr(p->pio_addr),
5812855Sgabeblack@google.com      platform(p->platform),
5912855Sgabeblack@google.com      interruptMap{
6012855Sgabeblack@google.com          { NOMALI_INT_GPU, p->int_gpu },
6112855Sgabeblack@google.com          { NOMALI_INT_JOB, p->int_job },
62          { NOMALI_INT_MMU, p->int_mmu },
63      }
64{
65    if (nomali_api_version() != NOMALI_API_VERSION)
66        panic("NoMali library API mismatch!\n");
67
68    /* Setup the GPU configuration based on our param struct */
69    nomali_config_t cfg;
70    memset(&cfg, 0, sizeof(cfg));
71
72    const auto it_gpu(gpuTypeMap.find(p->gpu_type));
73    if (it_gpu == gpuTypeMap.end()) {
74        fatal("Unrecognized GPU type: %s (%i)\n",
75              Enums::NoMaliGpuTypeStrings[p->gpu_type], p->gpu_type);
76    }
77    cfg.type = it_gpu->second;
78
79    cfg.ver_maj = p->ver_maj;
80    cfg.ver_min = p->ver_min;
81    cfg.ver_status = p->ver_status;
82
83    panicOnErr(
84        nomali_create(&nomali, &cfg),
85        "Failed to instantiate NoMali");
86
87
88    /* Setup an interrupt callback */
89    nomali_callback_t cbk_int;
90    cbk_int.type = NOMALI_CALLBACK_INT;
91    cbk_int.usr = (void *)this;
92    cbk_int.func.interrupt = NoMaliGpu::_interrupt;
93    setCallback(cbk_int);
94
95    panicOnErr(
96        nomali_get_info(nomali, &nomaliInfo),
97        "Failed to get NoMali information struct");
98}
99
100NoMaliGpu::~NoMaliGpu()
101{
102    nomali_destroy(nomali);
103}
104
105void
106NoMaliGpu::serialize(CheckpointOut &cp) const
107{
108    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);
109
110    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
111        regs[i >> 2] = readRegRaw(i);
112
113    SERIALIZE_CONTAINER(regs);
114}
115
116void
117NoMaliGpu::unserialize(CheckpointIn &cp)
118{
119    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);
120
121    UNSERIALIZE_CONTAINER(regs);
122
123    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
124        writeRegRaw(i, regs[i >> 2]);
125}
126
127Tick
128NoMaliGpu::read(PacketPtr pkt)
129{
130    assert(pkt->getAddr() >= pioAddr);
131    const Addr addr(pkt->getAddr() - pioAddr);
132    const unsigned size(pkt->getSize());
133
134    if (addr + size >= nomaliInfo.reg_size)
135        panic("GPU register '0x%x' out of range!\n", addr);
136
137    if (size != 4)
138        panic("Unexpected GPU register read size: %i\n", size);
139    else if (addr & 0x3)
140        panic("Unaligned GPU read: %i\n", size);
141
142    pkt->set<uint32_t>(readReg(addr));
143    pkt->makeResponse();
144
145    return 0;
146}
147
148Tick
149NoMaliGpu::write(PacketPtr pkt)
150{
151    assert(pkt->getAddr() >= pioAddr);
152    const Addr addr(pkt->getAddr() - pioAddr);
153    const unsigned size(pkt->getSize());
154
155    if (addr + size >= nomaliInfo.reg_size)
156        panic("GPU register '0x%x' out of range!\n", addr);
157
158    if (size != 4)
159        panic("Unexpected GPU register write size: %i\n", size);
160    else if (addr & 0x3)
161        panic("Unaligned GPU write: %i\n", size);
162
163    writeReg(addr, pkt->get<uint32_t>());
164    pkt->makeAtomicResponse();
165
166    return 0;
167}
168
169AddrRangeList
170NoMaliGpu::getAddrRanges() const
171{
172    return AddrRangeList({ RangeSize(pioAddr, nomaliInfo.reg_size) });
173}
174
175void
176NoMaliGpu::reset()
177{
178    DPRINTF(NoMali, "reset()\n");
179
180    panicOnErr(
181        nomali_reset(nomali),
182        "Failed to reset GPU");
183}
184
185uint32_t
186NoMaliGpu::readReg(nomali_addr_t reg)
187{
188    uint32_t value;
189
190    panicOnErr(
191        nomali_reg_read(nomali, &value, reg),
192        "GPU register read failed");
193
194    DPRINTF(NoMali, "readReg(0x%x): 0x%x\n",
195            reg, value);
196
197    return value;
198}
199
200
201void
202NoMaliGpu::writeReg(nomali_addr_t reg, uint32_t value)
203{
204    DPRINTF(NoMali, "writeReg(0x%x, 0x%x)\n",
205            reg, value);
206
207    panicOnErr(
208        nomali_reg_write(nomali, reg, value),
209        "GPU register write failed");
210}
211
212uint32_t
213NoMaliGpu::readRegRaw(nomali_addr_t reg) const
214{
215    uint32_t value;
216
217    panicOnErr(
218        nomali_reg_read_raw(nomali, &value, reg),
219        "GPU raw register read failed");
220
221    return value;
222}
223
224
225void
226NoMaliGpu::writeRegRaw(nomali_addr_t reg, uint32_t value)
227{
228    panicOnErr(
229        nomali_reg_write_raw(nomali, reg, value),
230        "GPU raw register write failed");
231}
232
233bool
234NoMaliGpu::intState(nomali_int_t intno)
235{
236    int state = 0;
237    panicOnErr(
238        nomali_int_state(nomali, &state, intno),
239        "Failed to get interrupt state");
240
241    return !!state;
242}
243
244void
245NoMaliGpu::gpuPanic(nomali_error_t err, const char *msg)
246{
247    panic("%s: %s\n", msg, nomali_errstr(err));
248}
249
250
251void
252NoMaliGpu::onInterrupt(nomali_int_t intno, bool set)
253{
254    const auto it_int(interruptMap.find(intno));
255    if (it_int == interruptMap.end())
256        panic("Unhandled interrupt from NoMali: %i\n", intno);
257
258    DPRINTF(NoMali, "Interrupt %i->%i: %i\n",
259            intno, it_int->second, set);
260
261    assert(platform);
262    assert(platform->gic);
263
264    if (set)
265        platform->gic->sendInt(it_int->second);
266    else
267        platform->gic->clearInt(it_int->second);
268}
269
270void
271NoMaliGpu::setCallback(const nomali_callback_t &callback)
272{
273    DPRINTF(NoMali, "Registering callback %i\n",
274            callback.type);
275
276    panicOnErr(
277        nomali_set_callback(nomali, &callback),
278        "Failed to register callback");
279}
280
281void
282NoMaliGpu::_interrupt(nomali_handle_t h, void *usr,
283                      nomali_int_t intno, int set)
284{
285    NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr));
286
287    _this->onInterrupt(intno, !!set);
288}
289
290NoMaliGpu *
291NoMaliGpuParams::create()
292{
293    return new NoMaliGpu(this);
294}
295