1/* 2 * Copyright 2019, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13/* Implementation of a logical timer for imx platforms 14 * 15 * Currently all imx platforms use some combination of GPT and EPIT timers to provide ltimer functionality. See platform specific timer.h for details. 16 */ 17#include <platsupport/timer.h> 18#include <platsupport/ltimer.h> 19#include <platsupport/plat/timer.h> 20#include <platsupport/irq.h> 21 22#include <utils/util.h> 23 24#include "../../ltimer.h" 25 26typedef struct { 27 imx_timers_t timers; 28 bool timestamp_initialised; 29 bool timeout_initialised; 30 ps_io_ops_t ops; 31} imx_ltimer_t; 32 33static int get_time(void *data, uint64_t *time) 34{ 35 assert(data != NULL); 36 assert(time != NULL); 37 38 imx_ltimer_t *imx_ltimer = data; 39 *time = imx_get_time(&imx_ltimer->timers); 40 return 0; 41} 42 43static int get_resolution(void *data, uint64_t *resolution) 44{ 45 return ENOSYS; 46} 47 48static int set_timeout(void *data, uint64_t ns, timeout_type_t type) 49{ 50 assert(data != NULL); 51 imx_ltimer_t *imx_ltimer = data; 52 53 if (type == TIMEOUT_ABSOLUTE) { 54 uint64_t current_time = imx_get_time(&imx_ltimer->timers); 55 ns -= current_time; 56 } 57 58 return imx_set_timeout(&imx_ltimer->timers, ns, type == TIMEOUT_PERIODIC); 59} 60 61static int reset(void *data) 62{ 63 assert(data != NULL); 64 imx_ltimer_t *imx_ltimer = data; 65 66 /* reset the timers */ 67 imx_stop_timeout(&imx_ltimer->timers); 68 imx_stop_timestamp(&imx_ltimer->timers); 69 imx_start_timestamp(&imx_ltimer->timers); 70 71 return 0; 72} 73 74static void destroy(void *data) 75{ 76 assert(data); 77 78 imx_ltimer_t *imx_ltimer = data; 79 80 if (imx_ltimer->timestamp_initialised) { 81 imx_stop_timestamp(&imx_ltimer->timers); 82 ZF_LOGF_IF(imx_destroy_timestamp(&imx_ltimer->timers), "Failed to destroy the timestamp timer"); 83 } 84 85 if (imx_ltimer->timeout_initialised) { 86 imx_stop_timeout(&imx_ltimer->timers); 87 ZF_LOGF_IF(imx_destroy_timeout(&imx_ltimer->timers), "Failed to destroy the timeout timer"); 88 } 89 90 ps_free(&imx_ltimer->ops.malloc_ops, sizeof(imx_ltimer), imx_ltimer); 91} 92 93static int create_ltimer(ltimer_t *ltimer, ps_io_ops_t ops) 94{ 95 assert(ltimer != NULL); 96 ltimer->get_time = get_time; 97 ltimer->get_resolution = get_resolution; 98 ltimer->set_timeout = set_timeout; 99 ltimer->reset = reset; 100 ltimer->destroy = destroy; 101 102 int error = ps_calloc(&ops.malloc_ops, 1, sizeof(imx_ltimer_t), <imer->data); 103 if (error) { 104 return error; 105 } 106 assert(ltimer->data != NULL); 107 108 return 0; 109} 110 111int ltimer_default_init(ltimer_t *ltimer, ps_io_ops_t ops, ltimer_callback_fn_t callback, void *callback_token) 112{ 113 int error = create_ltimer(ltimer, ops); 114 if (error) { 115 return error; 116 } 117 118 imx_ltimer_t *imx_ltimer = ltimer->data; 119 120 imx_ltimer->ops = ops; 121 122 error = imx_init_timestamp(&imx_ltimer->timers, ops, callback, callback_token); 123 if (error) { 124 ZF_LOGE("Failed to init timestamp timer"); 125 ltimer_destroy(ltimer); 126 return error; 127 } 128 129 imx_ltimer->timestamp_initialised = true; 130 131 imx_start_timestamp(&imx_ltimer->timers); 132 133 error = imx_init_timeout(&imx_ltimer->timers, ops, callback, callback_token); 134 if (error) { 135 ZF_LOGE("Failed to init timeout timer"); 136 ltimer_destroy(ltimer); 137 return error; 138 } 139 imx_ltimer->timeout_initialised = true; 140 141 /* success! */ 142 return 0; 143} 144 145/* This function is intended to be deleted, 146 * this is just left here for now so that stuff can compile */ 147int ltimer_default_describe(ltimer_t *ltimer, ps_io_ops_t ops) 148{ 149 ZF_LOGE("get_(nth/num)_(irqs/pmems) are not valid"); 150 return EINVAL; 151} 152