/* * 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 #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 NoMaliApiGpu : public BaseGpu { public: template NoMaliApiGpu(NoMaliApi &_api, Args &&... args) : BaseGpu(std::forward(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(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(this), c.usr); } static NoMaliApi * get_gpu(nomali_handle_t h) { return h ? static_cast(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( *api, cfg->ver_maj, cfg->ver_min, cfg->ver_status); break; case NOMALI_GPU_T62X: gpu = new NoMaliApiGpu( *api, cfg->ver_maj, cfg->ver_min, cfg->ver_status); break; case NOMALI_GPU_T76X: gpu = new NoMaliApiGpu( *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; }