1 /* 1 2 * linux/arch/arm/mach-omap1/time.c 3 * 4 * OMAP Timers 5 * 6 * Copyright (C) 2004 Nokia Corporation 7 * Partial timer rewrite and additional dynami 8 * Tony Lindgen <tony@atomide.com> and 9 * Tuukka Tikkanen <tuukka.tikkanen@elektrobit 10 * 11 * MPU timer code based on the older MPU timer 12 * Copyright (C) 2000 RidgeRun, Inc. 13 * Author: Greg Lonnon <glonnon@ridgerun.com> 14 * 15 * This program is free software; you can redi 16 * under the terms of the GNU General Public L 17 * Free Software Foundation; either version 2 18 * option) any later version. 19 * 20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY 21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULA 23 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUE 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE G 26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUP 27 * ANY THEORY OF LIABILITY, WHETHER IN CONTRAC 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI 30 * 31 * You should have received a copy of the GNU 32 * with this program; if not, write to the Fr 33 * 675 Mass Ave, Cambridge, MA 02139, USA. 34 */ 35 36 #include <linux/kernel.h> 37 #include <linux/init.h> 38 #include <linux/delay.h> 39 #include <linux/interrupt.h> 40 #include <linux/spinlock.h> 41 #include <linux/clk.h> 42 #include <linux/err.h> 43 #include <linux/clocksource.h> 44 #include <linux/clockchips.h> 45 #include <linux/io.h> 46 #include <linux/sched_clock.h> 47 48 #include <asm/irq.h> 49 50 #include <asm/mach/irq.h> 51 #include <asm/mach/time.h> 52 53 #include "hardware.h" 54 #include "mux.h" 55 #include "iomap.h" 56 #include "common.h" 57 #include "clock.h" 58 59 #ifdef CONFIG_OMAP_MPU_TIMER 60 61 #define OMAP_MPU_TIMER_BASE OMAP_M 62 #define OMAP_MPU_TIMER_OFFSET 0x100 63 64 typedef struct { 65 u32 cntl; /* CNT 66 u32 load_tim; /* LOA 67 u32 read_tim; /* REA 68 } omap_mpu_timer_regs_t; 69 70 #define omap_mpu_timer_base(n) 71 ((omap_mpu_timer_regs_t __iomem *)OMAP1_IO_ADD 72 (n)*OMAP_MPU_ 73 74 static inline unsigned long notrace omap_mpu_t 75 { 76 omap_mpu_timer_regs_t __iomem *timer = 77 return readl(&timer->read_tim); 78 } 79 80 static inline void omap_mpu_set_autoreset(int 81 { 82 omap_mpu_timer_regs_t __iomem *timer = 83 84 writel(readl(&timer->cntl) | MPU_TIMER 85 } 86 87 static inline void omap_mpu_remove_autoreset(i 88 { 89 omap_mpu_timer_regs_t __iomem *timer = 90 91 writel(readl(&timer->cntl) & ~MPU_TIME 92 } 93 94 static inline void omap_mpu_timer_start(int nr 95 int au 96 { 97 omap_mpu_timer_regs_t __iomem *timer = 98 unsigned int timerflags = MPU_TIMER_CL 99 100 if (autoreset) 101 timerflags |= MPU_TIMER_AR; 102 103 writel(MPU_TIMER_CLOCK_ENABLE, &timer- 104 udelay(1); 105 writel(load_val, &timer->load_tim); 106 udelay(1); 107 writel(timerflags, &timer->cntl); 108 } 109 110 static inline void omap_mpu_timer_stop(int nr) 111 { 112 omap_mpu_timer_regs_t __iomem *timer = 113 114 writel(readl(&timer->cntl) & ~MPU_TIME 115 } 116 117 /* 118 * ------------------------------------------- 119 * MPU timer 1 ... count down to zero, interru 120 * ------------------------------------------- 121 */ 122 static int omap_mpu_set_next_event(unsigned lo 123 struct cloc 124 { 125 omap_mpu_timer_start(0, cycles, 0); 126 return 0; 127 } 128 129 static int omap_mpu_set_oneshot(struct clock_e 130 { 131 omap_mpu_timer_stop(0); 132 omap_mpu_remove_autoreset(0); 133 return 0; 134 } 135 136 static int omap_mpu_set_periodic(struct clock_ 137 { 138 omap_mpu_set_autoreset(0); 139 return 0; 140 } 141 142 static struct clock_event_device clockevent_mp 143 .name = "mpu_timer1" 144 .features = CLOCK_EVT_FE 145 CLOCK_EVT_FE 146 .set_next_event = omap_mpu_set 147 .set_state_periodic = omap_mpu_set 148 .set_state_oneshot = omap_mpu_set 149 }; 150 151 static irqreturn_t omap_mpu_timer1_interrupt(i 152 { 153 struct clock_event_device *evt = &cloc 154 155 evt->event_handler(evt); 156 157 return IRQ_HANDLED; 158 } 159 160 static __init void omap_init_mpu_timer(unsigne 161 { 162 if (request_irq(INT_TIMER1, omap_mpu_t 163 IRQF_TIMER | IRQF_IRQP 164 pr_err("Failed to request irq 165 omap_mpu_timer_start(0, (rate / HZ) - 166 167 clockevent_mpu_timer1.cpumask = cpumas 168 clockevents_config_and_register(&clock 169 1, -1) 170 } 171 172 173 /* 174 * ------------------------------------------- 175 * MPU timer 2 ... free running 32-bit clock s 176 * ------------------------------------------- 177 */ 178 179 static u64 notrace omap_mpu_read_sched_clock(v 180 { 181 return ~omap_mpu_timer_read(1); 182 } 183 184 static void __init omap_init_clocksource(unsig 185 { 186 omap_mpu_timer_regs_t __iomem *timer = 187 static char err[] __initdata = KERN_ER 188 "%s: can't register cl 189 190 omap_mpu_timer_start(1, ~0, 1); 191 sched_clock_register(omap_mpu_read_sch 192 193 if (clocksource_mmio_init(&timer->read 194 300, 32, clocksource_m 195 printk(err, "mpu_timer2"); 196 } 197 198 static void __init omap_mpu_timer_init(void) 199 { 200 struct clk *ck_ref = clk_get(NULL 201 unsigned long rate; 202 203 BUG_ON(IS_ERR(ck_ref)); 204 205 rate = clk_get_rate(ck_ref); 206 clk_put(ck_ref); 207 208 /* PTV = 0 */ 209 rate /= 2; 210 211 omap_init_mpu_timer(rate); 212 omap_init_clocksource(rate); 213 } 214 215 #else 216 static inline void omap_mpu_timer_init(void) 217 { 218 pr_err("Bogus timer, should not happen 219 } 220 #endif /* CONFIG_OMAP_MPU_TIMER */ 221 222 /* 223 * ------------------------------------------- 224 * Timer initialization 225 * ------------------------------------------- 226 */ 227 void __init omap1_timer_init(void) 228 { 229 omap1_clk_init(); 230 omap1_mux_init(); 231 232 if (omap_32k_timer_init() != 0) 233 omap_mpu_timer_init(); 234 } 235
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.