| /* | |
| * 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; | |
| } | |