blob: bd556f3c9bd58a435d0103b5f77cab3aba854a7d [file] [log] [blame] [edit]
/*
* Copyright (c) 2014-2016 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 "libnomali/nomali.h"
#include <cstring>
#include "mali_t6xx.hh"
#include "mali_t7xx.hh"
#define EXPORT __attribute__ ((visibility ("default")))
static const char *errstrs[] = {
"No error",
"Unknown error",
"Memory allocation failed",
"Invalid model handle",
"Invalid parameter",
};
static_assert(sizeof(errstrs) / sizeof(*errstrs) == NOMALI_E_NUM_ERRORS,
"NoMali API error descriptions out of sync!");
class NoMaliApi
{
public:
NoMaliApi();
~NoMaliApi();
void setGpu(NoMali::GPU *gpu) { _gpu = gpu; }
public:
nomali_error_t setCallback(const nomali_callback_t *callback);
nomali_error_t getInfo(nomali_info_t *info);
nomali_error_t reset();
nomali_error_t regRead(uint32_t *value, nomali_addr_t addr);
nomali_error_t regWrite(nomali_addr_t addr, uint32_t value);
nomali_error_t regReadRaw(uint32_t *value, nomali_addr_t addr);
nomali_error_t regWriteRaw(nomali_addr_t addr, uint32_t value);
nomali_error_t intState(int *state, nomali_int_t intno) const;
public:
void callbackInt(nomali_int_t intno, int set);
void callbackReset();
private:
nomali_callback_t callbacks[NOMALI_CALLBACK_NUM_CALLBACKS];
NoMali::GPU *_gpu;
};
template<class BaseGpu>
class NoMaliApiGpu
: public BaseGpu
{
public:
template<typename... Args>
NoMaliApiGpu(NoMaliApi &_api, Args &&... args)
: BaseGpu(std::forward<Args>(args)...),
api(_api)
{
reset();
}
void reset() override {
BaseGpu::reset();
api.callbackReset();
}
public:
void intJob(int set) override { api.callbackInt(NOMALI_INT_JOB, set); }
void intMMU(int set) override { api.callbackInt(NOMALI_INT_MMU, set); }
void intGPU(int set) override { api.callbackInt(NOMALI_INT_GPU, set); }
private:
NoMaliApi &api;
};
NoMaliApi::NoMaliApi()
: _gpu(nullptr)
{
memset(callbacks, 0, sizeof(callbacks));
}
NoMaliApi::~NoMaliApi()
{
}
nomali_error_t
NoMaliApi::setCallback(const nomali_callback_t *callback)
{
if (!callback ||
callback->type >= NOMALI_CALLBACK_NUM_CALLBACKS)
return NOMALI_E_INVALID;
callbacks[callback->type] = *callback;
return NOMALI_E_OK;
}
nomali_error_t
NoMaliApi::getInfo(nomali_info_t *info)
{
if (!info)
return NOMALI_E_INVALID;
info->reg_size = 0x4000;
return NOMALI_E_OK;
}
nomali_error_t
NoMaliApi::reset()
{
_gpu->reset();
return NOMALI_E_OK;
}
nomali_error_t
NoMaliApi::regRead(uint32_t *value, nomali_addr_t addr)
{
if (!value)
return NOMALI_E_INVALID;
*value = _gpu->readReg(NoMali::RegAddr(addr));
return NOMALI_E_OK;
}
nomali_error_t
NoMaliApi::regWrite(nomali_addr_t addr, uint32_t value)
{
_gpu->writeReg(NoMali::RegAddr(addr), value);
return NOMALI_E_OK;
}
nomali_error_t
NoMaliApi::regReadRaw(uint32_t *value, nomali_addr_t addr)
{
if (!value)
return NOMALI_E_INVALID;
*value = _gpu->readRegRaw(NoMali::RegAddr(addr));
return NOMALI_E_OK;
}
nomali_error_t
NoMaliApi::regWriteRaw(nomali_addr_t addr, uint32_t value)
{
_gpu->writeRegRaw(NoMali::RegAddr(addr), value);
return NOMALI_E_OK;
}
nomali_error_t
NoMaliApi::intState(int *state, nomali_int_t intno) const
{
if (!state)
return NOMALI_E_INVALID;
switch (intno) {
case NOMALI_INT_GPU:
*state = _gpu->intGPUAsserted();
break;
case NOMALI_INT_JOB:
*state = _gpu->intJobAsserted();
break;
case NOMALI_INT_MMU:
*state = _gpu->intMMUAsserted();
break;
default:
return NOMALI_E_INVALID;
}
return NOMALI_E_OK;
}
void
NoMaliApi::callbackInt(nomali_int_t intno, int set)
{
const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_INT]);
if (c.func.interrupt)
c.func.interrupt(static_cast<nomali_handle_t>(this), c.usr, intno, set);
}
void
NoMaliApi::callbackReset()
{
const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_RESET]);
if (c.func.reset)
c.func.reset(static_cast<nomali_handle_t>(this), c.usr);
}
static NoMaliApi *
get_gpu(nomali_handle_t h)
{
return h ? static_cast<NoMaliApi *>(h) : nullptr;
}
extern "C" EXPORT nomali_api_version_t
nomali_api_version()
{
return NOMALI_API_VERSION;
}
extern "C" EXPORT nomali_error_t
nomali_create(nomali_handle_t *h, const nomali_config_t *cfg)
{
if (h && cfg) {
NoMaliApi *api(new NoMaliApi());
*h = api;
if (!h)
return NOMALI_E_MEMORY;
NoMali::GPU *gpu;
switch (cfg->type) {
case NOMALI_GPU_T60X:
gpu = new NoMaliApiGpu<NoMali::MaliT60x>(
*api,
cfg->ver_maj, cfg->ver_min, cfg->ver_status);
break;
case NOMALI_GPU_T62X:
gpu = new NoMaliApiGpu<NoMali::MaliT62x>(
*api,
cfg->ver_maj, cfg->ver_min, cfg->ver_status);
break;
case NOMALI_GPU_T76X:
gpu = new NoMaliApiGpu<NoMali::MaliT76x>(
*api,
cfg->ver_maj, cfg->ver_min, cfg->ver_status);
break;
default:
delete api;
return NOMALI_E_INVALID;
};
if (!gpu) {
delete api;
return NOMALI_E_MEMORY;
}
api->setGpu(gpu);
return NOMALI_E_OK;
} else {
return NOMALI_E_INVALID;
}
}
extern "C" EXPORT nomali_error_t
nomali_destroy(nomali_handle_t h)
{
NoMaliApi *gpu(get_gpu(h));
if (gpu) {
delete gpu;
return NOMALI_E_OK;
} else {
return NOMALI_E_HANDLE;
}
}
extern "C" EXPORT const char *
nomali_errstr(nomali_error_t error)
{
if (error < NOMALI_E_NUM_ERRORS)
return errstrs[error];
else
return "Invalid error number";
}
extern "C" EXPORT nomali_error_t
nomali_set_callback(nomali_handle_t h,
const nomali_callback_t *callback)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->setCallback(callback) : NOMALI_E_HANDLE;
}
extern "C" EXPORT nomali_error_t
nomali_get_info(nomali_handle_t h, nomali_info_t *info)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->getInfo(info) : NOMALI_E_HANDLE;
}
extern "C" EXPORT nomali_error_t
nomali_reset(nomali_handle_t h)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->reset() : NOMALI_E_HANDLE;
}
extern "C" EXPORT nomali_error_t
nomali_reg_read(nomali_handle_t h, uint32_t *value,
nomali_addr_t addr)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->regRead(value, addr) : NOMALI_E_HANDLE;
}
extern "C" EXPORT nomali_error_t
nomali_reg_write(nomali_handle_t h,
nomali_addr_t addr, uint32_t value)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->regWrite(addr, value) : NOMALI_E_HANDLE;
}
extern "C" EXPORT nomali_error_t
nomali_reg_read_raw(nomali_handle_t h, uint32_t *value,
nomali_addr_t addr)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->regReadRaw(value, addr) : NOMALI_E_HANDLE;
}
extern "C" EXPORT nomali_error_t
nomali_reg_write_raw(nomali_handle_t h,
nomali_addr_t addr, uint32_t value)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->regWriteRaw(addr, value) : NOMALI_E_HANDLE;
}
extern "C" EXPORT nomali_error_t
nomali_int_state(nomali_handle_t h, int *state,
nomali_int_t intno)
{
NoMaliApi *gpu(get_gpu(h));
return gpu ? gpu->intState(state, intno) : NOMALI_E_HANDLE;
}