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.c
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 #include "timer_cmsdk_drv.h"
27 
28 /** Setter bit manipulation macro */
29 #define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
30 /** Clearing bit manipulation macro */
31 #define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
32 /** Getter bit manipulation macro */
33 #define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
34 
35 /**
36  * \brief Timer register map structure
37  *
38  */
39 struct timer_cmsdk_reg_map_t {
40     volatile uint32_t ctrl;    /* Offset: 0x000 (R/W) control register */
41     volatile uint32_t value;   /* Offset: 0x004 (R/W) current value register */
42     volatile uint32_t reload;  /* Offset: 0x008 (R/W) reload value register */
43     union {
44         volatile uint32_t intstatus;  /* Offset: 0x00C (R/ ) interrupt
45                                        * status register
46                                        */
47         volatile uint32_t intclear;   /* Offset: 0x00C ( /W) interrupt
48                                        * clear register
49                                        */
50     }intreg;
51 };
52 
53 /**
54  * \brief CTRL register bit definitions
55  *
56  */
57 enum ctrl_reg_bits_t {
58     CTRL_REG_ENUM_ENABLE_INDEX = 0,
59     CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX = 1,
60     CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX = 2,
61     CTRL_REG_ENUM_IRQ_ENABLE_INDEX = 3
62 };
63 
64 /**
65  * \brief INTSTATUS/INTCLEAR register bit definitions
66  *
67  */
68 enum interrupt_reg_bits_t {
69     INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX = 0
70 };
71 
timer_cmsdk_init(const struct timer_cmsdk_dev_t * dev)72 void timer_cmsdk_init(const struct timer_cmsdk_dev_t* dev)
73 {
74     struct timer_cmsdk_reg_map_t* register_map =
75             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
76 
77     if (dev->data->is_initialized == 0) {
78         register_map->ctrl = 0;
79         register_map->reload = TIMER_CMSDK_DEFAULT_RELOAD;
80         dev->data->is_initialized = 1;
81     }
82 }
83 
timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t * dev)84 bool timer_cmsdk_is_initialized(const struct timer_cmsdk_dev_t* dev)
85 {
86     return dev->data->is_initialized;
87 }
88 
timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t * dev)89 void timer_cmsdk_enable_external_input(const struct timer_cmsdk_dev_t* dev)
90 {
91     struct timer_cmsdk_reg_map_t* register_map =
92             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
93     SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
94 }
95 
timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t * dev)96 void timer_cmsdk_disable_external_input(const struct timer_cmsdk_dev_t* dev)
97 {
98     struct timer_cmsdk_reg_map_t* register_map =
99             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
100     CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
101 }
102 
timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t * dev)103 bool timer_cmsdk_is_external_input_enabled(const struct timer_cmsdk_dev_t* dev)
104 {
105     struct timer_cmsdk_reg_map_t* register_map =
106             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
107     return GET_BIT(register_map->ctrl,
108                    CTRL_REG_ENUM_EXTERNAL_INPUT_ENABLE_INDEX);
109 }
110 
timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t * dev)111 void timer_cmsdk_set_clock_to_internal(const struct timer_cmsdk_dev_t* dev)
112 {
113     struct timer_cmsdk_reg_map_t* register_map =
114             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
115     CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
116 }
117 
timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t * dev)118 void timer_cmsdk_set_clock_to_external(const struct timer_cmsdk_dev_t* dev)
119 {
120     struct timer_cmsdk_reg_map_t* register_map =
121             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
122     SET_BIT(register_map->ctrl, CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
123 }
124 
timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t * dev)125 bool timer_cmsdk_is_clock_external(const struct timer_cmsdk_dev_t* dev)
126 {
127     struct timer_cmsdk_reg_map_t* register_map =
128             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
129     return GET_BIT(register_map->ctrl,
130                    CTRL_REG_ENUM_EXTERNAL_INPUT_CLOCK_INDEX);
131 }
132 
timer_cmsdk_enable(const struct timer_cmsdk_dev_t * dev)133 void timer_cmsdk_enable(const struct timer_cmsdk_dev_t* dev)
134 {
135     struct timer_cmsdk_reg_map_t* register_map =
136             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
137     SET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
138 }
139 
timer_cmsdk_disable(const struct timer_cmsdk_dev_t * dev)140 void timer_cmsdk_disable(const struct timer_cmsdk_dev_t* dev)
141 {
142     struct timer_cmsdk_reg_map_t* register_map =
143             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
144     CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
145 }
146 
timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t * dev)147 bool timer_cmsdk_is_enabled(const struct timer_cmsdk_dev_t* dev)
148 {
149     struct timer_cmsdk_reg_map_t* register_map =
150             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
151     return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_ENABLE_INDEX);
152 }
153 
timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t * dev)154 void timer_cmsdk_enable_interrupt(const struct timer_cmsdk_dev_t* dev)
155 {
156     struct timer_cmsdk_reg_map_t* register_map =
157             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
158     SET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
159 }
160 
timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t * dev)161 void timer_cmsdk_disable_interrupt(const struct timer_cmsdk_dev_t* dev)
162 {
163     struct timer_cmsdk_reg_map_t* register_map =
164             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
165     CLR_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
166 }
167 
timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t * dev)168 bool timer_cmsdk_is_interrupt_enabled(const struct timer_cmsdk_dev_t* dev)
169 {
170     struct timer_cmsdk_reg_map_t* register_map =
171             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
172     return GET_BIT(register_map->ctrl, CTRL_REG_ENUM_IRQ_ENABLE_INDEX);
173 }
174 
timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t * dev)175 bool timer_cmsdk_is_interrupt_active(const struct timer_cmsdk_dev_t* dev)
176 {
177     struct timer_cmsdk_reg_map_t* register_map =
178             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
179     return GET_BIT(register_map->intreg.intstatus,
180                    INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
181 }
182 
timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t * dev)183 void timer_cmsdk_clear_interrupt(const struct timer_cmsdk_dev_t* dev)
184 {
185     struct timer_cmsdk_reg_map_t* register_map =
186             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
187     SET_BIT(register_map->intreg.intclear,
188             INTERRUPT_REG_ENUM_STATUS_AND_CLEAR_INDEX);
189 }
190 
timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t * dev)191 uint32_t timer_cmsdk_get_current_value(const struct timer_cmsdk_dev_t* dev)
192 {
193     struct timer_cmsdk_reg_map_t* register_map =
194             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
195     return register_map->value;
196 }
197 
timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t * dev,uint32_t reload)198 void timer_cmsdk_set_reload_value(const struct timer_cmsdk_dev_t* dev,
199                                 uint32_t reload)
200 {
201     struct timer_cmsdk_reg_map_t* register_map =
202             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
203     register_map->reload = reload;
204 }
205 
timer_cmsdk_reset(const struct timer_cmsdk_dev_t * dev)206 void timer_cmsdk_reset(const struct timer_cmsdk_dev_t* dev)
207 {
208     struct timer_cmsdk_reg_map_t* register_map =
209             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
210     register_map->value = register_map->reload;
211 }
212 
timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t * dev)213 uint32_t timer_cmsdk_get_reload_value(const struct timer_cmsdk_dev_t* dev)
214 {
215     struct timer_cmsdk_reg_map_t* register_map =
216             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
217     return register_map->reload;
218 }
219 
timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t * dev)220 uint32_t timer_cmsdk_get_elapsed_value(const struct timer_cmsdk_dev_t* dev)
221 {
222     struct timer_cmsdk_reg_map_t* register_map =
223             (struct timer_cmsdk_reg_map_t*)dev->cfg->base;
224     return register_map->reload - register_map->value;
225 }
226