blob: 9e14b2d158eb3a15cd271c90252360031b4699a6 [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
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080042#define QTMR_TYPE_PHYSICAL 1
43#define QTMR_TYPE_VIRTUAL 2
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080044
45static platform_timer_callback timer_callback;
46static void *timer_arg;
47static time_t timer_interval;
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080048static unsigned int timer_type = QTMR_TYPE_PHYSICAL;
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080049static volatile uint32_t ticks;
Deepa Dinamanib5364242012-03-17 12:22:02 -070050static uint32_t tick_count;
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080051static uint32_t ppi_num = -1;
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080052
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080053static enum handler_return qtimer_irq(void *arg)
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080054{
55 ticks += timer_interval;
56
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080057 if (timer_type == QTMR_TYPE_VIRTUAL)
Deepa Dinamanib5364242012-03-17 12:22:02 -070058 __asm__("mcr p15, 0, %0, c14, c3, 0"::"r"(tick_count));
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080059 else if (timer_type == QTMR_TYPE_PHYSICAL)
Deepa Dinamanib5364242012-03-17 12:22:02 -070060 __asm__("mcr p15, 0, %0, c14, c2, 0" : :"r" (tick_count));
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080061
62 return timer_callback(timer_arg, ticks);
63}
64
65/* Programs the Virtual Down counter timer.
66 * interval : Counter ticks till expiry interrupt is fired.
67 */
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080068static unsigned int qtimer_set_virtual_timer(uint32_t interval)
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080069{
70 uint32_t ctrl;
71
72 /* Program CTRL Register */
73 ctrl =0;
74 ctrl |= QTMR_TIMER_CTRL_ENABLE;
75 ctrl &= ~QTMR_TIMER_CTRL_INT_MASK;
76
77 __asm__("mcr p15, 0, %0, c14, c3, 1"::"r"(ctrl));
78
79 /* Set Virtual Down Counter */
80 __asm__("mcr p15, 0, %0, c14, c3, 0"::"r"(interval));
81
82 return INT_QTMR_VIRTUAL_TIMER_EXP;
83
84}
85
86/* Programs the Physical Secure Down counter timer.
87 * interval : Counter ticks till expiry interrupt is fired.
88 */
Deepa Dinamani7d6c8972011-12-14 15:16:56 -080089static unsigned int qtimer_set_physical_timer(uint32_t interval)
Deepa Dinamanidc036ae2011-12-20 18:19:52 -080090{
91 uint32_t ctrl;
92
93 /* Program CTRL Register */
94 ctrl =0;
95 ctrl |= QTMR_TIMER_CTRL_ENABLE;
96 ctrl &= ~QTMR_TIMER_CTRL_INT_MASK;
97
98 __asm__("mcr p15, 0, %0, c14, c2, 1" : :"r" (ctrl));
99
100 /* Set Physical Down Counter */
101 __asm__("mcr p15, 0, %0, c14, c2, 0" : :"r" (interval));
102
103 return INT_QTMR_SECURE_PHYSICAL_TIMER_EXP;
104
105}
106
107
108status_t platform_set_periodic_timer(platform_timer_callback callback,
109 void *arg, time_t interval)
110{
Deepa Dinamanib5364242012-03-17 12:22:02 -0700111 tick_count = interval * platform_tick_rate() / 1000;
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800112
113 enter_critical_section();
114
115 timer_callback = callback;
116 timer_arg = arg;
117 timer_interval = interval;
118
Deepa Dinamani7d6c8972011-12-14 15:16:56 -0800119 if (timer_type == QTMR_TYPE_VIRTUAL)
120 ppi_num = qtimer_set_virtual_timer(tick_count);
121 else if (timer_type == QTMR_TYPE_PHYSICAL)
122 ppi_num = qtimer_set_physical_timer(tick_count);
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800123
Deepa Dinamani7d6c8972011-12-14 15:16:56 -0800124 register_int_handler(ppi_num, qtimer_irq, 0);
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800125 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
Deepa Dinamani7d6c8972011-12-14 15:16:56 -0800136void uninit_qtimer()
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800137{
138 uint32_t ctrl;
139
Deepa Dinamani7d6c8972011-12-14 15:16:56 -0800140 if (ppi_num == -1)
141 {
142 dprintf(CRITICAL, "Qtimer unintialized before initializing\n");
143 return;
144 }
145
146 mask_interrupt(ppi_num);
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800147
148 /* program cntrl register */
149 ctrl =0;
150 ctrl |= ~QTMR_TIMER_CTRL_ENABLE;
151 ctrl &= QTMR_TIMER_CTRL_INT_MASK;
152
Deepa Dinamani7d6c8972011-12-14 15:16:56 -0800153 if (timer_type == QTMR_TYPE_VIRTUAL)
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800154 __asm__("mcr p15, 0, %0, c14, c3, 1"::"r"(ctrl));
Deepa Dinamani7d6c8972011-12-14 15:16:56 -0800155 else if (timer_type == QTMR_TYPE_PHYSICAL)
Deepa Dinamanidc036ae2011-12-20 18:19:52 -0800156 __asm__("mcr p15, 0, %0, c14, c2, 1" : :"r" (ctrl));
157
158}
159
160void mdelay(unsigned msecs)
161{
162 uint32_t phy_cnt_lo, phy_cnt_hi, cnt, timeout = 0;
163 uint64_t phy_cnt;
164 msecs = msecs * platform_tick_rate() / 1000;
165
166 do{
167 /* read global counter */
168 __asm__("mrrc p15,0,%0,%1, c14":"=r"(phy_cnt_lo),"=r"(phy_cnt_hi));
169 phy_cnt = ((uint64_t)phy_cnt_hi << 32) | phy_cnt_lo;
170 /*Actual counter used in the simulation is only 32 bits
171 * in reality the counter is actually 56 bits.
172 */
173 cnt = phy_cnt & (uint32_t)~0;
174 if (timeout == 0)
175 timeout = cnt + msecs;
176 } while (cnt < timeout);
177
178}
179
180void udelay(unsigned usecs)
181{
182 uint32_t phy_cnt_lo, phy_cnt_hi, cnt, timeout = 0;
183 uint64_t phy_cnt;
184 usecs = (usecs * platform_tick_rate()) / 1000000;
185
186 do{
187 /* read global counter */
188 __asm__("mrrc p15,0,%0,%1, c14":"=r"(phy_cnt_lo),"=r"(phy_cnt_hi));
189 phy_cnt = ((uint64_t)phy_cnt_hi << 32) | phy_cnt_lo;
190
191 /*Actual counter used in the simulation is only 32 bits
192 * in reality the counter is actually 56 bits.
193 */
194 cnt = phy_cnt & (uint32_t)~0;
195 if (timeout == 0)
196 timeout = cnt + usecs;
197 } while (cnt < timeout);
198}
199
200/* Return current time in micro seconds */
201bigtime_t current_time_hires(void)
202{
203 return ticks * 1000000ULL;
204}