1 /*
2  * Copyright (C) 2019 ETH Zurich and University of Bologna
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  * SPDX-License-Identifier: Apache-2.0
17  */
18 
19 /* Driver to configure PULP timer as periodic interrupt source */
20 /* Author: Robert Balas (balasr@iis.ee.ethz.ch)
21  *         Germain Haugou (germain.haugou@iis.ee.ethz.ch)
22 */
23 
24 #include <bits.h>
25 #include <pulp_io.h>
26 #include <stdint.h>
27 #include <stdbool.h>
28 #include "core-v-mcu-pulp-mem-map.h"
29 #include "hal_timer.h"
30 #include "hal_timer_irq.h"
31 
32 /* TODO: used to measure elapsed time since last "visit" */
33 static uint32_t last_count;
timer_irq_disable()34 int timer_irq_disable(){
35 	writew (0,(uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CFG_LO_OFFSET));
36 	writew (0,(uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CFG_HI_OFFSET));
37 
38 }
39 
timer_irq_init(uint32_t ticks)40 int timer_irq_init(uint32_t ticks)
41 {
42 	/* TODO: enable soc_eu timer interrupt */
43 
44 	/* set the interrupt interval */
45 	timer_irq_set_timeout(ticks, false);
46 
47 	/* We use only one of the 32-bit timer, leaving the other half available
48 	 * as an additional timer. We didn't opt for using both together as
49 	 * 64-bit timer.
50 	 *
51 	 * Enable timer, use 32khz ref clock as source. Timer will reset
52 	 * automatically to zero after causing an interrupt.
53 	 */
54 /* use high timer for now as int actually gets to cpu */
55 #ifdef configMTIME_BASE_ADDRESS
56 	writew(0xc000000f,(uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CFG_LO_OFFSET));
57 #else
58 	writew(TIMER_CFG_LO_ENABLE_MASK | TIMER_CFG_LO_RESET_MASK |
59 		       TIMER_CFG_LO_MODE_MASK |
60 		       TIMER_CFG_LO_IRQEN_MASK,
61 	       (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CFG_LO_OFFSET));
62 #endif
63 
64 	return 0;
65 }
66 
timer_irq_set_timeout(uint32_t ticks,bool idle)67 int timer_irq_set_timeout(uint32_t ticks, bool idle)
68 {
69 	(void)idle;
70 	/* fast reset, value doesn't matter */
71 
72 	writew(1, (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_RESET_LO_OFFSET));
73 	writew(ticks, (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CMP_LO_OFFSET));
74 	writew(1, (uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_RESET_HI_OFFSET));
75 
76 	return 0;
77 }
78 
79 /* TODO: implement */
timer_irq_clock_elapsed()80 uint32_t timer_irq_clock_elapsed()
81 {
82 	return 0;
83 }
84 
timer_irq_cycle_get_32()85 uint32_t timer_irq_cycle_get_32()
86 {
87 	return readw((uintptr_t)(PULP_FC_TIMER_ADDR + TIMER_CNT_LO_OFFSET));
88 }
89