1 /*
2  * Copyright (c) 2016-2022 Arm Limited. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * \file timer_cmsdk_drv.h
19  * \brief Generic driver for CMSDK APB Timers.
20  *        The timer is a 32-bit down-counter with the following features:
21  *        - optional programmable external clock source
22  *        - programmable interrupt source, triggered if counter reaches 0
23  *        - automatic reload if counter reaches 0
24  */
25 
26 #ifndef __TIMER_CMSDK_DRV_H__
27 #define __TIMER_CMSDK_DRV_H__
28 
29 #include <stdint.h>
30 #include <stdbool.h>
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 /* Maximum reload value */
37 #define TIMER_CMSDK_MAX_RELOAD        UINT32_MAX /* max of 32-bit */
38 #define TIMER_CMSDK_DEFAULT_RELOAD    TIMER_CMSDK_MAX_RELOAD
39 
40 /** CMSDK timer device configuration structure */
41 struct timer_cmsdk_dev_cfg_t {
42     const uintptr_t base;  /*!< Timer base address */
43 };
44 
45 /** CMSDK timer device data structure */
46 struct timer_cmsdk_dev_data_t {
47     bool is_initialized;  /*!< Indicates if the timer is initialized */
48 };
49 
50 /* CMSDK timer device structure */
51 struct timer_cmsdk_dev_t {
52     const struct timer_cmsdk_dev_cfg_t* const cfg;  /*!< Timer configuration */
53     struct timer_cmsdk_dev_data_t* const data;      /*!< Timer data */
54 };
55 
56 /**
57  * \brief Initializes timer to a known default state, which is:
58  *          - timer disabled
59  *          - timer interrupt disabled
60  *          - clock source set to internal
61  *          - external input disabled
62  *          - reload value maxed out
63  *        Init should be called prior to any other process and
64  *        it's the caller's responsibility to follow proper call order.
65  *
66  * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
67  */
68 void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev);
69 
70 /**
71  * \brief Checks if a timer is initialized.
72  *
73  * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
74  *
75  * \return true if initialized, false otherwise
76  */
77 bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev);
78 
79 /**
80  * \brief Enables external input, which could be used as clock source
81  *        by calling \ref timer_cmsdk_set_clock_to_external.
82  *
83  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
84  */
85 void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev);
86 
87 /**
88  * \brief Disables external input.
89  *        Make sure if the timer is explicitly wanted to be stopped or set
90  *        the clock source to internal by \ref timer_cmsdk_set_clock_to_internal
91  *
92  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
93  */
94 void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev);
95 
96 /**
97  * \brief Checks if external input is enabled.
98  *
99  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
100  *
101  * \return true if enabled, false otherwise
102  */
103 bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev);
104 
105 /**
106  * \brief Sets the clock source to internal.
107  *
108  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
109  */
110 void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev);
111 
112 /**
113  * \brief Sets the clock source to external.
114  *        Make sure external input is enabled correspondingly
115  *        by \ref timer_cmsdk_enable_external_input.
116  *
117  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
118  */
119 void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev);
120 
121 /**
122  * \brief Checks if clock source is external input.
123  *
124  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
125  *
126  * \return true if external, false if internal
127  */
128 bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev);
129 
130 /**
131  * \brief Enables timer operation.
132  *
133  * \param[in] dev Timer configuration \ref timer_cmsdk_dev_t
134  */
135 void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev);
136 
137 /**
138  * \brief Disables the given hardware timer.
139  *
140  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
141  */
142 void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev);
143 
144 /**
145  * \brief Checks if a timer is enabled.
146  *
147  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
148  *
149  * \return true if enabled, false otherwise
150  */
151 bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev);
152 
153 /**
154  * \brief Enables timer interrupt.
155  *
156  * \param[in] dev       Timer configuration \ref timer_cmsdk_dev_t
157  */
158 void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev);
159 
160 /**
161  * \brief Disables timer interrupt.
162  *
163  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
164  */
165 void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev);
166 
167 /**
168  * \brief Checks if a timer interrupt is enabled.
169  *
170  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
171  *
172  * \return true if enabled, false otherwise
173  */
174 bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev);
175 
176 /**
177  * \brief Gets timer interrupt status
178  *
179  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
180  *
181  * * \return true if active, false otherwise
182  */
183 bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev);
184 
185 /**
186  * \brief Clears timer interrupt
187  *        The interrupt request is held until it is cleared.
188  *
189  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
190  */
191 void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev);
192 
193 /**
194  * \brief Reads timer current value.
195  *
196  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
197  *
198  * \return Timer value
199  */
200 uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev);
201 
202 /**
203  * \brief Sets the reload value of the selected timer.
204  *
205  *        New reload value takes effect when:
206  *        - timer is restarted
207  *        - on timer underflow
208  *        - when timer_cmsdk_reset is called
209  *
210  * \note  In r1p0 technical reference manual it's incorrectly stated
211  *        writing the reload value automatically sets the current value also.
212  *        r1p1 technical reference manual includes the fix.
213  *
214  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
215  * \param[in] reload Timer reload value to set.
216  *            This is the start value of the 32-bit down counter,
217  *            which automatically reloaded if 0 is reached.
218  */
219 void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
220                                   uint32_t reload);
221 
222 /**
223  * \brief Resets the timer counter to the reload value instantly
224  *        (i.e. without waiting for underflow).
225  *
226  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
227  */
228 void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev);
229 
230 /**
231  * \brief Gets the reload value of the selected timer.
232  *        This is the start value of the 32-bit down counter,
233  *        which is automatically reloaded if 0 is reached by the counter.
234  *
235  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
236  *
237  * \return Reload value of the selected timer.
238  */
239 uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev);
240 
241 /**
242  * \brief Reads the number of ticks elapsed in the current cycle.
243  *
244  * \param[in] dev  Timer configuration \ref timer_cmsdk_dev_t
245  *
246  * \return Get elapsed number of ticks since last reload was set.
247  *         Elapsed = (Reload value - Current value)
248  */
249 uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev);
250 
251 #ifdef __cplusplus
252 }
253 #endif
254 #endif /* __TIMER_CMSDK_DRV_H__ */
255