189284Smarkm/* 289284Smarkm * Copyright 2017, Data61 3265420Simp * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4156813Sru * ABN 41 687 119 230. 5321269Sngie * 6151326Sru * This software may be distributed and modified according to the terms of 789284Smarkm * the BSD 2-Clause license. Note that NO WARRANTY is provided. 889284Smarkm * See "LICENSE_BSD2.txt" for details. 9115669Sobrien * 10291348Sbdrewery * @TAG(DATA61_BSD) 1189284Smarkm */ 1289284Smarkm 1389284Smarkm/* 14156813Sru * Implementation of a logical timer for NVIDIA platforms. 1589284Smarkm * NVIDIA has their own local timer implementations, 1689284Smarkm * that vary slightly from platform to platform. TK1 and TX1 are similar; 1789284Smarkm * TX2 spreads them out over multiple 64k blocks. TX2 also requires specific 18275077Sbapt * interrupt routing from the NVidia timer to the shared interrupt controller. 1989284Smarkm * Refer to the respective reference manual for more specific platform differences. 20201380Sed */ 21201380Sed#include <stdbool.h> 2289284Smarkm#include <platsupport/timer.h> 23#include <platsupport/ltimer.h> 24#include <platsupport/plat/timer.h> 25#include <utils/util.h> 26 27#include "../../ltimer.h" 28 29typedef struct { 30 bool started; 31 nv_tmr_t nv_tmr; 32 ps_io_ops_t ops; 33} nv_tmr_ltimer_t; 34 35static int get_time(void *data, uint64_t *time) 36{ 37 assert(data != NULL); 38 assert(time != NULL); 39 40 nv_tmr_ltimer_t *nv_tmr_ltimer = data; 41 *time = nv_tmr_get_time(&nv_tmr_ltimer->nv_tmr); 42 return 0; 43} 44 45static int get_resolution(void *data, uint64_t *resolution) 46{ 47 return ENOSYS; 48} 49 50static int set_timeout(void *data, uint64_t ns, timeout_type_t type) 51{ 52 assert(data != NULL); 53 nv_tmr_ltimer_t *nv_tmr_ltimer = data; 54 55 switch (type) { 56 case TIMEOUT_ABSOLUTE: { 57 uint64_t time = nv_tmr_get_time(&nv_tmr_ltimer->nv_tmr); 58 if (time >= ns) { 59 return ETIME; 60 } 61 return nv_tmr_set_timeout(&nv_tmr_ltimer->nv_tmr, false, ns - time); 62 } 63 case TIMEOUT_PERIODIC: 64 case TIMEOUT_RELATIVE: 65 return nv_tmr_set_timeout(&nv_tmr_ltimer->nv_tmr, (type == TIMEOUT_PERIODIC), ns); 66 } 67 68 return EINVAL; 69} 70 71static int reset(void *data) 72{ 73 assert(data != NULL); 74 nv_tmr_ltimer_t *nv_tmr_ltimer = data; 75 nv_tmr_start(&nv_tmr_ltimer->nv_tmr); 76 nv_tmr_stop(&nv_tmr_ltimer->nv_tmr); 77 return 0; 78} 79 80static void destroy(void *data) 81{ 82 assert(data); 83 nv_tmr_ltimer_t *nv_tmr_ltimer = data; 84 if (nv_tmr_ltimer->started) { 85 nv_tmr_stop(&nv_tmr_ltimer->nv_tmr); 86 nv_tmr_destroy(&nv_tmr_ltimer->nv_tmr); 87 } 88 ps_free(&nv_tmr_ltimer->ops.malloc_ops, sizeof(nv_tmr_ltimer), nv_tmr_ltimer); 89} 90 91int ltimer_default_init(ltimer_t *ltimer, ps_io_ops_t ops, ltimer_callback_fn_t callback, void *callback_token) 92{ 93 if (!ltimer) { 94 return EINVAL; 95 } 96 97 ltimer->get_time = get_time; 98 ltimer->get_resolution = get_resolution; 99 ltimer->set_timeout = set_timeout; 100 ltimer->reset = reset; 101 ltimer->destroy = destroy; 102 103 int error = ps_calloc(&ops.malloc_ops, 1, sizeof(nv_tmr_ltimer_t), <imer->data); 104 if (error) { 105 return error; 106 } 107 assert(ltimer->data != NULL); 108 nv_tmr_ltimer_t *nv_tmr_ltimer = ltimer->data; 109 nv_tmr_ltimer->ops = ops; 110 111 error = nv_tmr_init(&nv_tmr_ltimer->nv_tmr, ops, NV_TMR_PATH, callback, callback_token); 112 if (error) { 113 destroy(ltimer->data); 114 return error; 115 } 116 117 nv_tmr_start(&nv_tmr_ltimer->nv_tmr); 118 nv_tmr_ltimer->started = true; 119 /* success! */ 120 return 0; 121} 122 123/* This function is intended to be deleted, 124 * this is just left here for now so that stuff can compile */ 125int ltimer_default_describe(ltimer_t *ltimer, ps_io_ops_t ops) 126{ 127 ZF_LOGE("get_(nth/num)_(irqs/pmems) are not valid"); 128 return EINVAL; 129} 130