blob: bc77f6f2695ff4bb484603b0c329fa87f2515c45 [file] [log] [blame]
Deepa Dinamanidc036ae2011-12-20 18:19:52 -08001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of Code Aurora Forum, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <reg.h>
31#include <sys/types.h>
32
33#include <platform/timer.h>
34#include <platform/irqs.h>
35#include <platform/iomap.h>
36#include <platform/interrupts.h>
37#include <kernel/thread.h>
38
39#define QTMR_TIMER_CTRL_ENABLE (1 << 0)
40#define QTMR_TIMER_CTRL_INT_MASK (1 << 1)
41
42#define PLATFORM_TIMER_TYPE_PHYSICAL 1
43#define PLATFORM_TIMER_TYPE_VIRTUAL 2
44
45static platform_timer_callback timer_callback;
46static void *timer_arg;
47static time_t timer_interval;
48static unsigned int timer_type = PLATFORM_TIMER_TYPE_PHYSICAL;
49static volatile uint32_t ticks;
Deepa Dinamanib5364242012-03-17 12:22:02 -070050static uint32_t tick_count;
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080051
52static enum handler_return timer_irq(void *arg)
53{
54 ticks += timer_interval;
55
56 if (timer_type == PLATFORM_TIMER_TYPE_VIRTUAL)
Deepa Dinamanib5364242012-03-17 12:22:02 -070057 __asm__("mcr p15, 0, %0, c14, c3, 0"::"r"(tick_count));
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080058 else if (timer_type == PLATFORM_TIMER_TYPE_PHYSICAL)
Deepa Dinamanib5364242012-03-17 12:22:02 -070059 __asm__("mcr p15, 0, %0, c14, c2, 0" : :"r" (tick_count));
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080060
61 return timer_callback(timer_arg, ticks);
62}
63
64/* Programs the Virtual Down counter timer.
65 * interval : Counter ticks till expiry interrupt is fired.
66 */
67unsigned int platform_set_virtual_timer(uint32_t interval)
68{
69 uint32_t ctrl;
70
71 /* Program CTRL Register */
72 ctrl =0;
73 ctrl |= QTMR_TIMER_CTRL_ENABLE;
74 ctrl &= ~QTMR_TIMER_CTRL_INT_MASK;
75
76 __asm__("mcr p15, 0, %0, c14, c3, 1"::"r"(ctrl));
77
78 /* Set Virtual Down Counter */
79 __asm__("mcr p15, 0, %0, c14, c3, 0"::"r"(interval));
80
81 return INT_QTMR_VIRTUAL_TIMER_EXP;
82
83}
84
85/* Programs the Physical Secure Down counter timer.
86 * interval : Counter ticks till expiry interrupt is fired.
87 */
88unsigned int platform_set_physical_timer(uint32_t interval)
89{
90 uint32_t ctrl;
91
92 /* Program CTRL Register */
93 ctrl =0;
94 ctrl |= QTMR_TIMER_CTRL_ENABLE;
95 ctrl &= ~QTMR_TIMER_CTRL_INT_MASK;
96
97 __asm__("mcr p15, 0, %0, c14, c2, 1" : :"r" (ctrl));
98
99 /* Set Physical Down Counter */
100 __asm__("mcr p15, 0, %0, c14, c2, 0" : :"r" (interval));
101
102 return INT_QTMR_SECURE_PHYSICAL_TIMER_EXP;
103
104}
105
106
107status_t platform_set_periodic_timer(platform_timer_callback callback,
108 void *arg, time_t interval)
109{
110 uint32_t ppi_num;
111 unsigned long ctrl;
Deepa Dinamanib5364242012-03-17 12:22:02 -0700112
113 tick_count = interval * platform_tick_rate() / 1000;
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800114
115 enter_critical_section();
116
117 timer_callback = callback;
118 timer_arg = arg;
119 timer_interval = interval;
120
121 if (timer_type == PLATFORM_TIMER_TYPE_VIRTUAL)
122 ppi_num = platform_set_virtual_timer(tick_count);
123 else if (timer_type == PLATFORM_TIMER_TYPE_PHYSICAL)
124 ppi_num = platform_set_physical_timer(tick_count);
125
126 register_int_handler(ppi_num, timer_irq, 0);
127 unmask_interrupt(ppi_num);
128
129 exit_critical_section();
130 return 0;
131}
132
133time_t current_time(void)
134{
135 return ticks;
136}
137
138void platform_uninit_timer(void)
139{
140 uint32_t ctrl;
141
142 unmask_interrupt(INT_DEBUG_TIMER_EXP);
143
144 /* program cntrl register */
145 ctrl =0;
146 ctrl |= ~QTMR_TIMER_CTRL_ENABLE;
147 ctrl &= QTMR_TIMER_CTRL_INT_MASK;
148
149 if (timer_type == PLATFORM_TIMER_TYPE_VIRTUAL)
150 __asm__("mcr p15, 0, %0, c14, c3, 1"::"r"(ctrl));
151 else if (timer_type == PLATFORM_TIMER_TYPE_PHYSICAL)
152 __asm__("mcr p15, 0, %0, c14, c2, 1" : :"r" (ctrl));
153
154}
155
156void mdelay(unsigned msecs)
157{
158 uint32_t phy_cnt_lo, phy_cnt_hi, cnt, timeout = 0;
159 uint64_t phy_cnt;
160 msecs = msecs * platform_tick_rate() / 1000;
161
162 do{
163 /* read global counter */
164 __asm__("mrrc p15,0,%0,%1, c14":"=r"(phy_cnt_lo),"=r"(phy_cnt_hi));
165 phy_cnt = ((uint64_t)phy_cnt_hi << 32) | phy_cnt_lo;
166 /*Actual counter used in the simulation is only 32 bits
167 * in reality the counter is actually 56 bits.
168 */
169 cnt = phy_cnt & (uint32_t)~0;
170 if (timeout == 0)
171 timeout = cnt + msecs;
172 } while (cnt < timeout);
173
174}
175
176void udelay(unsigned usecs)
177{
178 uint32_t phy_cnt_lo, phy_cnt_hi, cnt, timeout = 0;
179 uint64_t phy_cnt;
180 usecs = (usecs * platform_tick_rate()) / 1000000;
181
182 do{
183 /* read global counter */
184 __asm__("mrrc p15,0,%0,%1, c14":"=r"(phy_cnt_lo),"=r"(phy_cnt_hi));
185 phy_cnt = ((uint64_t)phy_cnt_hi << 32) | phy_cnt_lo;
186
187 /*Actual counter used in the simulation is only 32 bits
188 * in reality the counter is actually 56 bits.
189 */
190 cnt = phy_cnt & (uint32_t)~0;
191 if (timeout == 0)
192 timeout = cnt + usecs;
193 } while (cnt < timeout);
194}
195
196/* Return current time in micro seconds */
197bigtime_t current_time_hires(void)
198{
199 return ticks * 1000000ULL;
200}