gpu_nomali.cc revision 10916
1/*
2 * Copyright (c) 2014-2015 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Authors: Andreas Sandberg
38 */
39
40#include "dev/arm/gpu_nomali.hh"
41
42#include "debug/NoMali.hh"
43#include "dev/arm/base_gic.hh"
44#include "dev/arm/realview.hh"
45#include "enums/MemoryMode.hh"
46#include "mem/packet_access.hh"
47#include "params/NoMaliGpu.hh"
48
49NoMaliGpu::NoMaliGpu(const NoMaliGpuParams *p)
50    : PioDevice(p),
51      pioAddr(p->pio_addr),
52      platform(p->platform),
53      interruptMap{
54          { NOMALI_INT_GPU, p->int_gpu },
55          { NOMALI_INT_JOB, p->int_job },
56          { NOMALI_INT_MMU, p->int_mmu },
57      }
58{
59    if (nomali_api_version() != NOMALI_API_VERSION)
60        panic("NoMali library API mismatch!\n");
61
62    /* Setup the GPU configuration based on our param struct */
63    nomali_config_t cfg;
64    memset(&cfg, 0, sizeof(cfg));
65
66    switch (p->gpu_type) {
67      case Enums::T60x:
68        cfg.type = NOMALI_GPU_T60X;
69        break;
70
71      case Enums::T62x:
72        cfg.type = NOMALI_GPU_T62X;
73        break;
74
75      case Enums::T760:
76        cfg.type = NOMALI_GPU_T760;
77        break;
78
79      default:
80        fatal("Unknown GPU type\n");
81    }
82
83    cfg.ver_maj = p->ver_maj;
84    cfg.ver_min = p->ver_min;
85    cfg.ver_status = p->ver_status;
86
87    panicOnErr(
88        nomali_create(&nomali, &cfg),
89        "Failed to instantiate NoMali");
90
91
92    /* Setup an interrupt callback */
93    nomali_callback_t cbk_int;
94    cbk_int.type = NOMALI_CALLBACK_INT;
95    cbk_int.usr = (void *)this;
96    cbk_int.func.interrupt = NoMaliGpu::_interrupt;
97    panicOnErr(
98        nomali_set_callback(nomali, &cbk_int),
99        "Failed to setup interrupt callback");
100
101    panicOnErr(
102        nomali_get_info(nomali, &nomaliInfo),
103        "Failed to get NoMali information struct");
104}
105
106NoMaliGpu::~NoMaliGpu()
107{
108    nomali_destroy(nomali);
109}
110
111
112void
113NoMaliGpu::serialize(CheckpointOut &cp) const
114{
115    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);
116
117    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
118        regs[i >> 2] = readRegRaw(i);
119
120    SERIALIZE_CONTAINER(regs);
121}
122
123void
124NoMaliGpu::unserialize(CheckpointIn &cp)
125{
126    std::vector<uint32_t> regs(nomaliInfo.reg_size >> 2);
127
128    UNSERIALIZE_CONTAINER(regs);
129
130    for (int i = 0; i < nomaliInfo.reg_size; i += 4)
131        writeRegRaw(i, regs[i >> 2]);
132}
133
134Tick
135NoMaliGpu::read(PacketPtr pkt)
136{
137    assert(pkt->getAddr() >= pioAddr);
138    const Addr addr(pkt->getAddr() - pioAddr);
139    const unsigned size(pkt->getSize());
140
141    if (addr + size >= nomaliInfo.reg_size)
142        panic("GPU register '0x%x' out of range!\n", addr);
143
144    if (size != 4)
145        panic("Unexpected GPU register read size: %i\n", size);
146    else if (addr & 0x3)
147        panic("Unaligned GPU read: %i\n", size);
148
149    pkt->set<uint32_t>(readReg(addr));
150    pkt->makeResponse();
151
152    return 0;
153}
154
155Tick
156NoMaliGpu::write(PacketPtr pkt)
157{
158    assert(pkt->getAddr() >= pioAddr);
159    const Addr addr(pkt->getAddr() - pioAddr);
160    const unsigned size(pkt->getSize());
161
162    if (addr + size >= nomaliInfo.reg_size)
163        panic("GPU register '0x%x' out of range!\n", addr);
164
165    if (size != 4)
166        panic("Unexpected GPU register write size: %i\n", size);
167    else if (addr & 0x3)
168        panic("Unaligned GPU write: %i\n", size);
169
170    writeReg(addr, pkt->get<uint32_t>());
171    pkt->makeAtomicResponse();
172
173    return 0;
174}
175
176AddrRangeList
177NoMaliGpu::getAddrRanges() const
178{
179    return AddrRangeList({ RangeSize(pioAddr, nomaliInfo.reg_size) });
180}
181
182uint32_t
183NoMaliGpu::readReg(nomali_addr_t reg)
184{
185    uint32_t value;
186
187    panicOnErr(
188        nomali_reg_read(nomali, &value, reg),
189        "GPU register read failed");
190
191    DPRINTF(NoMali, "readReg(0x%x): 0x%x\n",
192            reg, value);
193
194    return value;
195}
196
197
198void
199NoMaliGpu::writeReg(nomali_addr_t reg, uint32_t value)
200{
201    DPRINTF(NoMali, "writeReg(0x%x, 0x%x)\n",
202            reg, value);
203
204    panicOnErr(
205        nomali_reg_write(nomali, reg, value),
206        "GPU register write failed");
207}
208
209uint32_t
210NoMaliGpu::readRegRaw(nomali_addr_t reg) const
211{
212    uint32_t value;
213
214    panicOnErr(
215        nomali_reg_read_raw(nomali, &value, reg),
216        "GPU raw register read failed");
217
218    return value;
219}
220
221
222void
223NoMaliGpu::writeRegRaw(nomali_addr_t reg, uint32_t value)
224{
225    panicOnErr(
226        nomali_reg_write_raw(nomali, reg, value),
227        "GPU raw register write failed");
228}
229
230void
231NoMaliGpu::_interrupt(nomali_handle_t h, void *usr, nomali_int_t intno, int set)
232{
233    NoMaliGpu *_this(static_cast<NoMaliGpu *>(usr));
234
235    _this->onInterrupt(h, intno, !!set);
236}
237
238void
239NoMaliGpu::onInterrupt(nomali_handle_t h, nomali_int_t intno, bool set)
240{
241    const auto it_int(interruptMap.find(intno));
242    if (it_int == interruptMap.end())
243        panic("Unhandled interrupt from NoMali: %i\n", intno);
244
245    DPRINTF(NoMali, "Interrupt %i->%i: %i\n",
246            intno, it_int->second, set);
247
248    assert(platform);
249    assert(platform->gic);
250
251    if (set)
252        platform->gic->sendInt(it_int->second);
253    else
254        platform->gic->clearInt(it_int->second);
255}
256
257void
258NoMaliGpu::gpuPanic(nomali_error_t err, const char *msg)
259{
260    panic("%s: %s\n", msg, nomali_errstr(err));
261}
262
263NoMaliGpu *
264NoMaliGpuParams::create()
265{
266    return new NoMaliGpu(this);
267}
268