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