1 #include "bflb_timer.h"
2 #include "bflb_gpio.h"
3 #include "hardware/timer_reg.h"
4
bflb_timer_init(struct bflb_device_s * dev,const struct bflb_timer_config_s * config)5 void bflb_timer_init(struct bflb_device_s *dev, const struct bflb_timer_config_s *config)
6 {
7 uint32_t regval;
8 uint32_t reg_base;
9
10 reg_base = dev->reg_base;
11
12 /* Disable timer */
13 regval = getreg32(reg_base + TIMER_TCER_OFFSET);
14 regval &= ~(1 << (dev->idx + 1));
15 putreg32(regval, reg_base + TIMER_TCER_OFFSET);
16
17 /* Timer interrupr clear */
18 bflb_timer_compint_clear(dev, TIMER_COMP_ID_0);
19 bflb_timer_compint_clear(dev, TIMER_COMP_ID_1);
20 bflb_timer_compint_clear(dev, TIMER_COMP_ID_2);
21
22 /* Configure clock source */
23 regval = getreg32(reg_base + TIMER_TCCR_OFFSET);
24 if (dev->idx == 0) {
25 regval &= ~TIMER_CS_0_MASK;
26 regval |= (config->clock_source << TIMER_CS_0_SHIFT);
27 } else {
28 regval &= ~TIMER_CS_1_MASK;
29 regval |= (config->clock_source << TIMER_CS_1_SHIFT);
30 }
31 putreg32(regval, reg_base + TIMER_TCCR_OFFSET);
32
33 /* Configure clock div */
34 regval = getreg32(reg_base + TIMER_TCDR_OFFSET);
35 regval &= ~(0xff << (TIMER_TCDR0_SHIFT + 8 * dev->idx));
36 regval |= (config->clock_div << (TIMER_TCDR0_SHIFT + 8 * dev->idx));
37 putreg32(regval, reg_base + TIMER_TCDR_OFFSET);
38
39 /* Configure counter mode */
40 regval = getreg32(reg_base + TIMER_TCMR_OFFSET);
41 if (config->counter_mode == TIMER_COUNTER_MODE_PROLOAD) {
42 regval &= ~(1 << (1 + dev->idx));
43 } else {
44 regval |= (1 << (1 + dev->idx));
45 }
46 putreg32(regval, reg_base + TIMER_TCMR_OFFSET);
47
48 /* Configure preload trigger source */
49 regval = getreg32(reg_base + TIMER_TPLCR0_OFFSET + 4 * dev->idx);
50 regval &= ~TIMER_TPLCR0_MASK;
51 if (config->trigger_comp_id != TIMER_COMP_NONE) {
52 regval |= ((config->trigger_comp_id + 1) << TIMER_TPLCR0_SHIFT);
53 }
54 putreg32(regval, reg_base + TIMER_TPLCR0_OFFSET + 4 * dev->idx);
55
56 if (config->counter_mode == TIMER_COUNTER_MODE_PROLOAD) {
57 bflb_timer_set_preloadvalue(dev, config->preload_val);
58 }
59
60 if (config->trigger_comp_id < TIMER_COMP_ID_1) {
61 bflb_timer_compint_mask(dev, TIMER_COMP_ID_0, false);
62 bflb_timer_compint_mask(dev, TIMER_COMP_ID_1, true);
63 bflb_timer_compint_mask(dev, TIMER_COMP_ID_2, true);
64 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_0, config->comp0_val - 2);
65 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_1, 0xffffffff);
66 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_2, 0xffffffff);
67 } else if (config->trigger_comp_id < TIMER_COMP_ID_2) {
68 bflb_timer_compint_mask(dev, TIMER_COMP_ID_0, false);
69 bflb_timer_compint_mask(dev, TIMER_COMP_ID_1, false);
70 bflb_timer_compint_mask(dev, TIMER_COMP_ID_2, true);
71 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_0, config->comp0_val - 2);
72 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_1, config->comp1_val - 2);
73 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_2, 0xffffffff);
74 } else if (config->trigger_comp_id < TIMER_COMP_NONE) {
75 bflb_timer_compint_mask(dev, TIMER_COMP_ID_0, false);
76 bflb_timer_compint_mask(dev, TIMER_COMP_ID_1, false);
77 bflb_timer_compint_mask(dev, TIMER_COMP_ID_2, false);
78 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_0, config->comp0_val - 2);
79 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_1, config->comp1_val - 2);
80 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_2, config->comp2_val - 2);
81 } else {
82 bflb_timer_compint_mask(dev, TIMER_COMP_ID_0, true);
83 bflb_timer_compint_mask(dev, TIMER_COMP_ID_1, true);
84 bflb_timer_compint_mask(dev, TIMER_COMP_ID_2, true);
85 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_0, 0xffffffff);
86 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_1, 0xffffffff);
87 bflb_timer_set_compvalue(dev, TIMER_COMP_ID_2, 0xffffffff);
88 }
89 }
90
bflb_timer_deinit(struct bflb_device_s * dev)91 void bflb_timer_deinit(struct bflb_device_s *dev)
92 {
93 uint32_t regval;
94 uint32_t reg_base;
95
96 reg_base = dev->reg_base;
97
98 regval = getreg32(reg_base + TIMER_TCER_OFFSET);
99 regval &= ~(1 << (dev->idx + 1));
100 putreg32(regval, reg_base + TIMER_TCER_OFFSET);
101 }
102
bflb_timer_start(struct bflb_device_s * dev)103 void bflb_timer_start(struct bflb_device_s *dev)
104 {
105 uint32_t regval;
106 uint32_t reg_base;
107
108 reg_base = dev->reg_base;
109
110 regval = getreg32(reg_base + TIMER_TCER_OFFSET);
111 regval |= (1 << (dev->idx + 1));
112 putreg32(regval, reg_base + TIMER_TCER_OFFSET);
113 }
114
bflb_timer_stop(struct bflb_device_s * dev)115 void bflb_timer_stop(struct bflb_device_s *dev)
116 {
117 uint32_t regval;
118 uint32_t reg_base;
119
120 reg_base = dev->reg_base;
121
122 regval = getreg32(reg_base + TIMER_TCER_OFFSET);
123 regval &= ~(1 << (dev->idx + 1));
124 putreg32(regval, reg_base + TIMER_TCER_OFFSET);
125 }
126
bflb_timer_set_preloadvalue(struct bflb_device_s * dev,uint32_t val)127 void bflb_timer_set_preloadvalue(struct bflb_device_s *dev, uint32_t val)
128 {
129 uint32_t reg_base;
130
131 reg_base = dev->reg_base;
132
133 putreg32(val, reg_base + TIMER_TPLVR0_OFFSET + 4 * dev->idx);
134 }
135
bflb_timer_set_compvalue(struct bflb_device_s * dev,uint8_t cmp_no,uint32_t val)136 void bflb_timer_set_compvalue(struct bflb_device_s *dev, uint8_t cmp_no, uint32_t val)
137 {
138 uint32_t reg_base;
139
140 reg_base = dev->reg_base;
141
142 putreg32(val, reg_base + TIMER_TMR0_0_OFFSET + 0x0c * dev->idx + 4 * cmp_no);
143 }
144
bflb_timer_get_compvalue(struct bflb_device_s * dev,uint8_t cmp_no)145 uint32_t bflb_timer_get_compvalue(struct bflb_device_s *dev, uint8_t cmp_no)
146 {
147 uint32_t reg_base;
148
149 reg_base = dev->reg_base;
150
151 return getreg32(reg_base + TIMER_TMR0_0_OFFSET + 0x0c * dev->idx + 4 * cmp_no);
152 }
153
bflb_timer_get_countervalue(struct bflb_device_s * dev)154 uint32_t bflb_timer_get_countervalue(struct bflb_device_s *dev)
155 {
156 uint32_t reg_base;
157
158 reg_base = dev->reg_base;
159
160 return getreg32(reg_base + TIMER_TCR0_OFFSET + 4 * dev->idx);
161 }
162
bflb_timer_compint_mask(struct bflb_device_s * dev,uint8_t cmp_no,bool mask)163 void bflb_timer_compint_mask(struct bflb_device_s *dev, uint8_t cmp_no, bool mask)
164 {
165 uint32_t regval;
166 uint32_t reg_base;
167
168 reg_base = dev->reg_base;
169 regval = getreg32(reg_base + TIMER_TIER0_OFFSET + 4 * dev->idx);
170 if (mask) {
171 regval &= ~(1 << cmp_no);
172 } else {
173 regval |= (1 << cmp_no);
174 }
175 putreg32(regval, reg_base + TIMER_TIER0_OFFSET + 4 * dev->idx);
176 }
177
bflb_timer_get_compint_status(struct bflb_device_s * dev,uint8_t cmp_no)178 bool bflb_timer_get_compint_status(struct bflb_device_s *dev, uint8_t cmp_no)
179 {
180 uint32_t regval;
181 uint32_t reg_base;
182
183 reg_base = dev->reg_base;
184 regval = getreg32(reg_base + TIMER_TSR0_OFFSET + 4 * dev->idx);
185
186 if (regval & (1 << cmp_no)) {
187 return true;
188 } else {
189 return false;
190 }
191 }
192
bflb_timer_compint_clear(struct bflb_device_s * dev,uint8_t cmp_no)193 void bflb_timer_compint_clear(struct bflb_device_s *dev, uint8_t cmp_no)
194 {
195 uint32_t regval;
196 uint32_t reg_base;
197
198 reg_base = dev->reg_base;
199 regval = getreg32(reg_base + TIMER_TICR0_OFFSET + 4 * dev->idx);
200 regval |= (1 << cmp_no);
201 putreg32(regval, reg_base + TIMER_TICR0_OFFSET + 4 * dev->idx);
202 }
203
204 #if !defined(BL702) && !defined(BL602)
bflb_timer_capture_init(struct bflb_device_s * dev,const struct bflb_timer_capture_config_s * config)205 void bflb_timer_capture_init(struct bflb_device_s *dev, const struct bflb_timer_capture_config_s *config)
206 {
207 uint32_t regval;
208 uint32_t reg_base;
209
210 reg_base = dev->reg_base;
211 #if defined(BL702L)
212 regval = getreg32(0x20000000 + 0xc);
213 regval &= ~(0x3 << 14);
214 switch (config->pin & 0x03) {
215 case 0:
216 regval &= ~(1 << 10);
217 regval |= (0 << 14);
218 break;
219 case 1:
220 regval &= ~(1 << 11);
221 regval |= (1 << 14);
222 break;
223 case 2:
224 regval &= ~(1 << 12);
225 regval |= (2 << 14);
226 break;
227 case 3:
228 regval &= ~(1 << 13);
229 regval |= (3 << 14);
230 break;
231
232 default:
233 break;
234 }
235 putreg32(regval, 0x20000000 + 0xc);
236 struct bflb_device_s *gpio = bflb_device_get_by_name("gpio");
237 bflb_gpio_init(gpio, config->pin, (0 << GPIO_FUNC_SHIFT) | GPIO_ALTERNATE | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_1);
238 #else
239 regval = getreg32(0x20000000 + 0x258);
240 regval &= ~(3 << 12);
241 switch (config->pin & 0x03) {
242 case 0:
243 regval &= ~(1 << 8);
244 regval |= (0 << 12);
245 break;
246 case 1:
247 regval &= ~(1 << 9);
248 regval |= (1 << 12);
249 break;
250 case 2:
251 regval &= ~(1 << 10);
252 regval |= (2 << 12);
253 break;
254 case 3:
255 regval &= ~(1 << 11);
256 regval |= (3 << 12);
257 break;
258
259 default:
260 break;
261 }
262 putreg32(regval, 0x20000000 + 0x258);
263 struct bflb_device_s *gpio = bflb_device_get_by_name("gpio");
264 bflb_gpio_init(gpio, config->pin, (31 << GPIO_FUNC_SHIFT) | GPIO_ALTERNATE | GPIO_FLOAT | GPIO_SMT_EN | GPIO_DRV_1);
265 #endif
266
267 regval = getreg32(reg_base + TIMER_GPIO_OFFSET);
268 /* polarity: 1->neg, 0->pos */
269 if (config->polarity == TIMER_CAPTURE_POLARITY_NEGATIVE) {
270 regval |= (1 << (5 + dev->idx));
271 } else {
272 regval &= ~(1 << (5 + dev->idx));
273 }
274 regval |= TIMER0_GPIO_EN;
275 putreg32(regval, reg_base + TIMER_GPIO_OFFSET);
276 }
277
bflb_timer_capture_get_pulsewidth(struct bflb_device_s * dev)278 uint32_t bflb_timer_capture_get_pulsewidth(struct bflb_device_s *dev)
279 {
280 uint32_t reg_base;
281 uint32_t lat1 = 0;
282 uint32_t lat2 = 0;
283 reg_base = dev->reg_base;
284
285 do {
286 lat1 = getreg32(reg_base + TIMER_GPIO_LAT1_OFFSET);
287 lat2 = getreg32(reg_base + TIMER_GPIO_LAT2_OFFSET);
288 } while (!(getreg32(reg_base + TIMER_GPIO_OFFSET) & TIMER_GPIO_LAT_OK) || (lat1 >= lat2));
289
290 return (lat2 - lat1);
291 }
292 #endif
293