blob: 8af01f4567685d0405da5ef87d9170e2f6d96342 [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;
50
51static enum handler_return timer_irq(void *arg)
52{
53 ticks += timer_interval;
54
55 if (timer_type == PLATFORM_TIMER_TYPE_VIRTUAL)
56 __asm__("mcr p15, 0, %0, c14, c3, 0"::"r"(timer_interval));
57 else if (timer_type == PLATFORM_TIMER_TYPE_PHYSICAL)
58 __asm__("mcr p15, 0, %0, c14, c2, 0" : :"r" (timer_interval));
59
60 return timer_callback(timer_arg, ticks);
61}
62
63/* Programs the Virtual Down counter timer.
64 * interval : Counter ticks till expiry interrupt is fired.
65 */
66unsigned int platform_set_virtual_timer(uint32_t interval)
67{
68 uint32_t ctrl;
69
70 /* Program CTRL Register */
71 ctrl =0;
72 ctrl |= QTMR_TIMER_CTRL_ENABLE;
73 ctrl &= ~QTMR_TIMER_CTRL_INT_MASK;
74
75 __asm__("mcr p15, 0, %0, c14, c3, 1"::"r"(ctrl));
76
77 /* Set Virtual Down Counter */
78 __asm__("mcr p15, 0, %0, c14, c3, 0"::"r"(interval));
79
80 return INT_QTMR_VIRTUAL_TIMER_EXP;
81
82}
83
84/* Programs the Physical Secure Down counter timer.
85 * interval : Counter ticks till expiry interrupt is fired.
86 */
87unsigned int platform_set_physical_timer(uint32_t interval)
88{
89 uint32_t ctrl;
90
91 /* Program CTRL Register */
92 ctrl =0;
93 ctrl |= QTMR_TIMER_CTRL_ENABLE;
94 ctrl &= ~QTMR_TIMER_CTRL_INT_MASK;
95
96 __asm__("mcr p15, 0, %0, c14, c2, 1" : :"r" (ctrl));
97
98 /* Set Physical Down Counter */
99 __asm__("mcr p15, 0, %0, c14, c2, 0" : :"r" (interval));
100
101 return INT_QTMR_SECURE_PHYSICAL_TIMER_EXP;
102
103}
104
105
106status_t platform_set_periodic_timer(platform_timer_callback callback,
107 void *arg, time_t interval)
108{
109 uint32_t ppi_num;
110 unsigned long ctrl;
111 uint32_t tick_count = interval * platform_tick_rate() / 1000;
112
113 enter_critical_section();
114
115 timer_callback = callback;
116 timer_arg = arg;
117 timer_interval = interval;
118
119 if (timer_type == PLATFORM_TIMER_TYPE_VIRTUAL)
120 ppi_num = platform_set_virtual_timer(tick_count);
121 else if (timer_type == PLATFORM_TIMER_TYPE_PHYSICAL)
122 ppi_num = platform_set_physical_timer(tick_count);
123
124 register_int_handler(ppi_num, timer_irq, 0);
125 unmask_interrupt(ppi_num);
126
127 exit_critical_section();
128 return 0;
129}
130
131time_t current_time(void)
132{
133 return ticks;
134}
135
136void platform_uninit_timer(void)
137{
138 uint32_t ctrl;
139
140 unmask_interrupt(INT_DEBUG_TIMER_EXP);
141
142 /* program cntrl register */
143 ctrl =0;
144 ctrl |= ~QTMR_TIMER_CTRL_ENABLE;
145 ctrl &= QTMR_TIMER_CTRL_INT_MASK;
146
147 if (timer_type == PLATFORM_TIMER_TYPE_VIRTUAL)
148 __asm__("mcr p15, 0, %0, c14, c3, 1"::"r"(ctrl));
149 else if (timer_type == PLATFORM_TIMER_TYPE_PHYSICAL)
150 __asm__("mcr p15, 0, %0, c14, c2, 1" : :"r" (ctrl));
151
152}
153
154void mdelay(unsigned msecs)
155{
156 uint32_t phy_cnt_lo, phy_cnt_hi, cnt, timeout = 0;
157 uint64_t phy_cnt;
158 msecs = msecs * platform_tick_rate() / 1000;
159
160 do{
161 /* read global counter */
162 __asm__("mrrc p15,0,%0,%1, c14":"=r"(phy_cnt_lo),"=r"(phy_cnt_hi));
163 phy_cnt = ((uint64_t)phy_cnt_hi << 32) | phy_cnt_lo;
164 /*Actual counter used in the simulation is only 32 bits
165 * in reality the counter is actually 56 bits.
166 */
167 cnt = phy_cnt & (uint32_t)~0;
168 if (timeout == 0)
169 timeout = cnt + msecs;
170 } while (cnt < timeout);
171
172}
173
174void udelay(unsigned usecs)
175{
176 uint32_t phy_cnt_lo, phy_cnt_hi, cnt, timeout = 0;
177 uint64_t phy_cnt;
178 usecs = (usecs * platform_tick_rate()) / 1000000;
179
180 do{
181 /* read global counter */
182 __asm__("mrrc p15,0,%0,%1, c14":"=r"(phy_cnt_lo),"=r"(phy_cnt_hi));
183 phy_cnt = ((uint64_t)phy_cnt_hi << 32) | phy_cnt_lo;
184
185 /*Actual counter used in the simulation is only 32 bits
186 * in reality the counter is actually 56 bits.
187 */
188 cnt = phy_cnt & (uint32_t)~0;
189 if (timeout == 0)
190 timeout = cnt + usecs;
191 } while (cnt < timeout);
192}
193
194/* Return current time in micro seconds */
195bigtime_t current_time_hires(void)
196{
197 return ticks * 1000000ULL;
198}