1/*
2 * Copyright 2017, 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#pragma once
14
15#include <sel4platsupport/pmem.h>
16#include <platsupport/timer.h>
17#include <platsupport/ltimer.h>
18#include <sel4platsupport/irq.h>
19#include <simple/simple.h>
20#include <vka/vka.h>
21#include <vka/object.h>
22#include <vspace/vspace.h>
23
24#define MAX_IRQS 4
25#define MAX_OBJS 4
26
27typedef struct seL4_timer seL4_timer_t;
28
29typedef void (*handle_irq_fn_t)(seL4_timer_t *timer, uint32_t irq);
30typedef void (*destroy_fn_t)(seL4_timer_t *timer, vka_t *vka, vspace_t *vspace);
31
32typedef struct timer_objects {
33    /* this struct is copied using c's struct deep copy semantics.
34     * avoid adding pointers to it */
35    size_t nirqs;
36    sel4ps_irq_t irqs[MAX_IRQS];
37    size_t nobjs;
38    sel4ps_pmem_t objs[MAX_OBJS];
39} timer_objects_t;
40
41struct seL4_timer {
42    /* os independent timer interface */
43    ltimer_t ltimer;
44
45    /* objects allocated for this timer */
46    timer_objects_t to;
47
48    /* sel4 specific functions to call to deal with timer */
49    handle_irq_fn_t handle_irq;
50
51    /* destroy this timer, it will no longer be valid */
52    destroy_fn_t destroy;
53};
54
55/**
56 * Creates caps required for calling sel4platsupport_get_default_timer and stores them
57 * in supplied timer_objects_t.
58 *
59 * Uses the provided vka, vspace and simple interfaces for creating the caps.
60 * (A vspace is required because on some platforms devices may need to be mapped in
61 *  order to query hardware features.)
62 *
63 * @param  vka           Allocator to allocate objects with
64 * @param  vspace        vspace for mapping device frames into memory if necessary.
65 * @param  simple        simple interface for access to init caps
66 * @param  timer_objects struct for returning cap meta data.
67 * @return               0 on success, otherwise failure.
68 */
69int sel4platsupport_init_default_timer_caps(vka_t *vka, vspace_t *vspace, simple_t *simple,
70                                            timer_objects_t *timer_objects);
71
72/*
73 * Initialise the default timer for this platform and do all of the seL4 related work.
74 *
75 * After this operation is complete, the irqs from the ltimer will be delivered to the
76 * provided notification object with badges of BIT(seL4_BadgeBits - 1) - n where n is the index
77 * of the irq in the default ltimer.
78 *
79 * The passed ops interface is retained by the timer and must stay valid until the timer is destroyed
80 *
81 * @param vka          an initialised vka implementation that can allocate the physical
82 *                     addresses (if any) required by the ltimer.
83 * @param vspace       an initialised vspace for manging virtual memory.
84 * @param simple       for getting irq capabilities for the ltimer irqs.
85 * @param ops          I/O ops interface for interacting with hardware resources
86 * @param ntfn         notification object capability for irqs to be delivered to.
87 * @param timer        a timer structure to initialise.
88 * @return             0 on success.
89 */
90int sel4platsupport_init_default_timer_ops(vka_t *vka, vspace_t *vspace, simple_t *simple, ps_io_ops_t ops,
91                                           seL4_CPtr notification, seL4_timer_t *timer);
92
93/*
94 * Wrapper around sel4platsupport_init_default_timer_ops that generates as much of an
95 * io_ops interface as it can from the given vka and vspace
96 */
97int sel4platsupport_init_default_timer(vka_t *vka, vspace_t *vspace, simple_t *simple,
98                                       seL4_CPtr notification, seL4_timer_t *timer);
99/*
100 * Initialise an seL4_timer with irqs from provided timer objects. As per sel4platsupport_init_timer,
101 * timer_objects are provided and the user is expected to initialise the ltimer after calling this function
102 * (to avoid unacked irqs due to irq caps not being set up).
103 *
104 * This function just does the seL4 parts of the timer init.
105 *
106 *
107 * @param vka          an initialised vka implementation that can allocate the physical
108 *                     address returned by sel4platsupport_get_default_timer_paddr.
109 * @param simple       for getting irq capabilities for the ltimer irqs.
110 * @param ntfn         notification object capability for irqs to be delivered to.
111 * @param timer        a timer structure to populate.
112 * @param objects      the timer objects that this timer needs to initialise.
113 * @return             0 on success.
114 */
115int sel4platsupport_init_timer_irqs(vka_t *vka, simple_t *simple, seL4_CPtr ntfn,
116                                    seL4_timer_t *timer, timer_objects_t *objects);
117
118/*
119 * Handle a timer irq for this timer.
120 *
121 * @param timer       initialised timer.
122 * @param badge       badge recieved on the notification object this timer was initialised with.
123 */
124void sel4platsupport_handle_timer_irq(seL4_timer_t *timer, seL4_Word badge);
125
126/*
127 * Destroy the timer, freeing any resources allocated during initialisation.
128 *
129 * @param timer       initialised timer.
130 * @param vka         vka used to initialise the timer.
131 *
132 */
133void sel4platsupport_destroy_timer(seL4_timer_t *timer, vka_t *vka);
134
135/*
136 * Helper function for getting the nth irq cap out of the timer_objects struct if its type is
137 * known.  This is often used for initialising an arch_simple interface.
138 *
139 * @param to       timer_objects struct containing irq caps.
140 * @param id       index of irq in the struct.
141 * @param type     Interrupt type
142 *
143 * @return         IRQ cap on success, otherwise seL4_CapNull on failure.
144 */
145seL4_CPtr sel4platsupport_timer_objs_get_irq_cap(timer_objects_t *to, int id, irq_type_t type);
146