1/* 2 * Copyright (c) 2014-2016 ARM Limited 3 * All rights reserved 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * Authors: Andreas Sandberg 18 */ 19 20#include "libnomali/nomali.h" 21 22#include <cstring> 23 24#include "mali_t6xx.hh" 25#include "mali_t7xx.hh" 26 27#define EXPORT __attribute__ ((visibility ("default"))) 28 29static const char *errstrs[] = { 30 "No error", 31 "Unknown error", 32 "Memory allocation failed", 33 "Invalid model handle", 34 "Invalid parameter", 35}; 36 37static_assert(sizeof(errstrs) / sizeof(*errstrs) == NOMALI_E_NUM_ERRORS, 38 "NoMali API error descriptions out of sync!"); 39 40class NoMaliApi 41{ 42 public: 43 NoMaliApi(); 44 ~NoMaliApi(); 45 46 void setGpu(NoMali::GPU *gpu) { _gpu = gpu; } 47 48 public: 49 nomali_error_t setCallback(const nomali_callback_t *callback); 50 51 nomali_error_t getInfo(nomali_info_t *info); 52 53 nomali_error_t reset(); 54 nomali_error_t regRead(uint32_t *value, nomali_addr_t addr); 55 nomali_error_t regWrite(nomali_addr_t addr, uint32_t value); 56 nomali_error_t regReadRaw(uint32_t *value, nomali_addr_t addr); 57 nomali_error_t regWriteRaw(nomali_addr_t addr, uint32_t value); 58 nomali_error_t intState(int *state, nomali_int_t intno) const; 59 60 public: 61 void callbackInt(nomali_int_t intno, int set); 62 void callbackReset(); 63 64 private: 65 nomali_callback_t callbacks[NOMALI_CALLBACK_NUM_CALLBACKS]; 66 67 NoMali::GPU *_gpu; 68}; 69 70template<class BaseGpu> 71class NoMaliApiGpu 72 : public BaseGpu 73{ 74 public: 75 template<typename... Args> 76 NoMaliApiGpu(NoMaliApi &_api, Args &&... args) 77 : BaseGpu(std::forward<Args>(args)...), 78 api(_api) 79 { 80 reset(); 81 } 82 83 void reset() override { 84 BaseGpu::reset(); 85 api.callbackReset(); 86 } 87 88 public: 89 void intJob(int set) override { api.callbackInt(NOMALI_INT_JOB, set); } 90 void intMMU(int set) override { api.callbackInt(NOMALI_INT_MMU, set); } 91 void intGPU(int set) override { api.callbackInt(NOMALI_INT_GPU, set); } 92 93 private: 94 NoMaliApi &api; 95}; 96 97 98NoMaliApi::NoMaliApi() 99 : _gpu(nullptr) 100{ 101 memset(callbacks, 0, sizeof(callbacks)); 102} 103 104 105NoMaliApi::~NoMaliApi() 106{ 107} 108 109nomali_error_t 110NoMaliApi::setCallback(const nomali_callback_t *callback) 111{ 112 if (!callback || 113 callback->type >= NOMALI_CALLBACK_NUM_CALLBACKS) 114 return NOMALI_E_INVALID; 115 116 callbacks[callback->type] = *callback; 117 118 return NOMALI_E_OK; 119} 120 121nomali_error_t 122NoMaliApi::getInfo(nomali_info_t *info) 123{ 124 if (!info) 125 return NOMALI_E_INVALID; 126 127 info->reg_size = 0x4000; 128 129 return NOMALI_E_OK; 130} 131 132nomali_error_t 133NoMaliApi::reset() 134{ 135 _gpu->reset(); 136 return NOMALI_E_OK; 137} 138 139nomali_error_t 140NoMaliApi::regRead(uint32_t *value, nomali_addr_t addr) 141{ 142 if (!value) 143 return NOMALI_E_INVALID; 144 145 *value = _gpu->readReg(NoMali::RegAddr(addr)); 146 147 return NOMALI_E_OK; 148} 149 150nomali_error_t 151NoMaliApi::regWrite(nomali_addr_t addr, uint32_t value) 152{ 153 _gpu->writeReg(NoMali::RegAddr(addr), value); 154 155 return NOMALI_E_OK; 156} 157 158 159nomali_error_t 160NoMaliApi::regReadRaw(uint32_t *value, nomali_addr_t addr) 161{ 162 if (!value) 163 return NOMALI_E_INVALID; 164 165 *value = _gpu->readRegRaw(NoMali::RegAddr(addr)); 166 167 return NOMALI_E_OK; 168} 169 170nomali_error_t 171NoMaliApi::regWriteRaw(nomali_addr_t addr, uint32_t value) 172{ 173 _gpu->writeRegRaw(NoMali::RegAddr(addr), value); 174 175 return NOMALI_E_OK; 176} 177 178nomali_error_t 179NoMaliApi::intState(int *state, nomali_int_t intno) const 180{ 181 if (!state) 182 return NOMALI_E_INVALID; 183 184 switch (intno) { 185 case NOMALI_INT_GPU: 186 *state = _gpu->intGPUAsserted(); 187 break; 188 189 case NOMALI_INT_JOB: 190 *state = _gpu->intJobAsserted(); 191 break; 192 193 case NOMALI_INT_MMU: 194 *state = _gpu->intMMUAsserted(); 195 break; 196 197 default: 198 return NOMALI_E_INVALID; 199 } 200 201 return NOMALI_E_OK; 202} 203 204 205void 206NoMaliApi::callbackInt(nomali_int_t intno, int set) 207{ 208 const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_INT]); 209 210 if (c.func.interrupt) 211 c.func.interrupt(static_cast<nomali_handle_t>(this), c.usr, intno, set); 212} 213 214void 215NoMaliApi::callbackReset() 216{ 217 const nomali_callback_t &c(callbacks[NOMALI_CALLBACK_RESET]); 218 219 if (c.func.reset) 220 c.func.reset(static_cast<nomali_handle_t>(this), c.usr); 221} 222 223 224 225static NoMaliApi * 226get_gpu(nomali_handle_t h) 227{ 228 return h ? static_cast<NoMaliApi *>(h) : nullptr; 229} 230 231 232extern "C" EXPORT nomali_api_version_t 233nomali_api_version() 234{ 235 return NOMALI_API_VERSION; 236} 237 238extern "C" EXPORT nomali_error_t 239nomali_create(nomali_handle_t *h, const nomali_config_t *cfg) 240{ 241 if (h && cfg) { 242 NoMaliApi *api(new NoMaliApi()); 243 *h = api; 244 if (!h) 245 return NOMALI_E_MEMORY; 246 247 NoMali::GPU *gpu; 248 switch (cfg->type) { 249 case NOMALI_GPU_T60X: 250 gpu = new NoMaliApiGpu<NoMali::MaliT60x>( 251 *api, 252 cfg->ver_maj, cfg->ver_min, cfg->ver_status); 253 break; 254 255 case NOMALI_GPU_T62X: 256 gpu = new NoMaliApiGpu<NoMali::MaliT62x>( 257 *api, 258 cfg->ver_maj, cfg->ver_min, cfg->ver_status); 259 break; 260 261 262 case NOMALI_GPU_T76X: 263 gpu = new NoMaliApiGpu<NoMali::MaliT76x>( 264 *api, 265 cfg->ver_maj, cfg->ver_min, cfg->ver_status); 266 break; 267 268 default: 269 delete api; 270 return NOMALI_E_INVALID; 271 }; 272 273 if (!gpu) { 274 delete api; 275 return NOMALI_E_MEMORY; 276 } 277 278 api->setGpu(gpu); 279 280 return NOMALI_E_OK; 281 } else { 282 return NOMALI_E_INVALID; 283 } 284} 285 286extern "C" EXPORT nomali_error_t 287nomali_destroy(nomali_handle_t h) 288{ 289 NoMaliApi *gpu(get_gpu(h)); 290 291 if (gpu) { 292 delete gpu; 293 return NOMALI_E_OK; 294 } else { 295 return NOMALI_E_HANDLE; 296 } 297} 298 299extern "C" EXPORT const char * 300nomali_errstr(nomali_error_t error) 301{ 302 if (error < NOMALI_E_NUM_ERRORS) 303 return errstrs[error]; 304 else 305 return "Invalid error number"; 306} 307 308extern "C" EXPORT nomali_error_t 309nomali_set_callback(nomali_handle_t h, 310 const nomali_callback_t *callback) 311{ 312 NoMaliApi *gpu(get_gpu(h)); 313 return gpu ? gpu->setCallback(callback) : NOMALI_E_HANDLE; 314} 315 316extern "C" EXPORT nomali_error_t 317nomali_get_info(nomali_handle_t h, nomali_info_t *info) 318{ 319 NoMaliApi *gpu(get_gpu(h)); 320 return gpu ? gpu->getInfo(info) : NOMALI_E_HANDLE; 321} 322 323extern "C" EXPORT nomali_error_t 324nomali_reset(nomali_handle_t h) 325{ 326 NoMaliApi *gpu(get_gpu(h)); 327 return gpu ? gpu->reset() : NOMALI_E_HANDLE; 328} 329 330extern "C" EXPORT nomali_error_t 331nomali_reg_read(nomali_handle_t h, uint32_t *value, 332 nomali_addr_t addr) 333{ 334 NoMaliApi *gpu(get_gpu(h)); 335 return gpu ? gpu->regRead(value, addr) : NOMALI_E_HANDLE; 336} 337 338extern "C" EXPORT nomali_error_t 339nomali_reg_write(nomali_handle_t h, 340 nomali_addr_t addr, uint32_t value) 341{ 342 NoMaliApi *gpu(get_gpu(h)); 343 return gpu ? gpu->regWrite(addr, value) : NOMALI_E_HANDLE; 344} 345 346 347extern "C" EXPORT nomali_error_t 348nomali_reg_read_raw(nomali_handle_t h, uint32_t *value, 349 nomali_addr_t addr) 350{ 351 NoMaliApi *gpu(get_gpu(h)); 352 return gpu ? gpu->regReadRaw(value, addr) : NOMALI_E_HANDLE; 353} 354 355extern "C" EXPORT nomali_error_t 356nomali_reg_write_raw(nomali_handle_t h, 357 nomali_addr_t addr, uint32_t value) 358{ 359 NoMaliApi *gpu(get_gpu(h)); 360 return gpu ? gpu->regWriteRaw(addr, value) : NOMALI_E_HANDLE; 361} 362 363extern "C" EXPORT nomali_error_t 364nomali_int_state(nomali_handle_t h, int *state, 365 nomali_int_t intno) 366{ 367 NoMaliApi *gpu(get_gpu(h)); 368 return gpu ? gpu->intState(state, intno) : NOMALI_E_HANDLE; 369} 370 371