1/* 2 * arch/arm/mach-pxa/time.c 3 * 4 * PXA clocksource, clockevents, and OST interrupt handlers. 5 * Copyright (c) 2007 by Bill Gatliff <bgat@billgatliff.com>. 6 * 7 * Derived from Nicolas Pitre's PXA timer handler Copyright (c) 2001 8 * by MontaVista Software, Inc. (Nico, your code rocks!) 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/interrupt.h> 18#include <linux/clockchips.h> 19#include <linux/sched.h> 20#include <linux/cnt32_to_63.h> 21 22#include <asm/div64.h> 23#include <asm/mach/irq.h> 24#include <asm/mach/time.h> 25#include <mach/regs-ost.h> 26 27/* 28 * This is PXA's sched_clock implementation. This has a resolution 29 * of at least 308 ns and a maximum value of 208 days. 30 * 31 * The return value is guaranteed to be monotonic in that range as 32 * long as there is always less than 582 seconds between successive 33 * calls to sched_clock() which should always be the case in practice. 34 */ 35 36#define OSCR2NS_SCALE_FACTOR 10 37 38static unsigned long oscr2ns_scale; 39 40static void __init set_oscr2ns_scale(unsigned long oscr_rate) 41{ 42 unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR; 43 do_div(v, oscr_rate); 44 oscr2ns_scale = v; 45 /* 46 * We want an even value to automatically clear the top bit 47 * returned by cnt32_to_63() without an additional run time 48 * instruction. So if the LSB is 1 then round it up. 49 */ 50 if (oscr2ns_scale & 1) 51 oscr2ns_scale++; 52} 53 54unsigned long long sched_clock(void) 55{ 56 unsigned long long v = cnt32_to_63(OSCR); 57 return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR; 58} 59 60 61#define MIN_OSCR_DELTA 16 62 63static irqreturn_t 64pxa_ost0_interrupt(int irq, void *dev_id) 65{ 66 struct clock_event_device *c = dev_id; 67 68 /* Disarm the compare/match, signal the event. */ 69 OIER &= ~OIER_E0; 70 OSSR = OSSR_M0; 71 c->event_handler(c); 72 73 return IRQ_HANDLED; 74} 75 76static int 77pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev) 78{ 79 unsigned long next, oscr; 80 81 OIER |= OIER_E0; 82 next = OSCR + delta; 83 OSMR0 = next; 84 oscr = OSCR; 85 86 return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; 87} 88 89static void 90pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) 91{ 92 switch (mode) { 93 case CLOCK_EVT_MODE_ONESHOT: 94 OIER &= ~OIER_E0; 95 OSSR = OSSR_M0; 96 break; 97 98 case CLOCK_EVT_MODE_UNUSED: 99 case CLOCK_EVT_MODE_SHUTDOWN: 100 /* initializing, released, or preparing for suspend */ 101 OIER &= ~OIER_E0; 102 OSSR = OSSR_M0; 103 break; 104 105 case CLOCK_EVT_MODE_RESUME: 106 case CLOCK_EVT_MODE_PERIODIC: 107 break; 108 } 109} 110 111static struct clock_event_device ckevt_pxa_osmr0 = { 112 .name = "osmr0", 113 .features = CLOCK_EVT_FEAT_ONESHOT, 114 .shift = 32, 115 .rating = 200, 116 .set_next_event = pxa_osmr0_set_next_event, 117 .set_mode = pxa_osmr0_set_mode, 118}; 119 120static cycle_t pxa_read_oscr(struct clocksource *cs) 121{ 122 return OSCR; 123} 124 125static struct clocksource cksrc_pxa_oscr0 = { 126 .name = "oscr0", 127 .rating = 200, 128 .read = pxa_read_oscr, 129 .mask = CLOCKSOURCE_MASK(32), 130 .shift = 20, 131 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 132}; 133 134static struct irqaction pxa_ost0_irq = { 135 .name = "ost0", 136 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL, 137 .handler = pxa_ost0_interrupt, 138 .dev_id = &ckevt_pxa_osmr0, 139}; 140 141static void __init pxa_timer_init(void) 142{ 143 unsigned long clock_tick_rate = get_clock_tick_rate(); 144 145 OIER = 0; 146 OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; 147 148 set_oscr2ns_scale(clock_tick_rate); 149 150 ckevt_pxa_osmr0.mult = 151 div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift); 152 ckevt_pxa_osmr0.max_delta_ns = 153 clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0); 154 ckevt_pxa_osmr0.min_delta_ns = 155 clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1; 156 ckevt_pxa_osmr0.cpumask = cpumask_of(0); 157 158 cksrc_pxa_oscr0.mult = 159 clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift); 160 161 setup_irq(IRQ_OST0, &pxa_ost0_irq); 162 163 clocksource_register(&cksrc_pxa_oscr0); 164 clockevents_register_device(&ckevt_pxa_osmr0); 165} 166 167#ifdef CONFIG_PM 168static unsigned long osmr[4], oier, oscr; 169 170static void pxa_timer_suspend(void) 171{ 172 osmr[0] = OSMR0; 173 osmr[1] = OSMR1; 174 osmr[2] = OSMR2; 175 osmr[3] = OSMR3; 176 oier = OIER; 177 oscr = OSCR; 178} 179 180static void pxa_timer_resume(void) 181{ 182 /* 183 * Ensure that we have at least MIN_OSCR_DELTA between match 184 * register 0 and the OSCR, to guarantee that we will receive 185 * the one-shot timer interrupt. We adjust OSMR0 in preference 186 * to OSCR to guarantee that OSCR is monotonically incrementing. 187 */ 188 if (osmr[0] - oscr < MIN_OSCR_DELTA) 189 osmr[0] += MIN_OSCR_DELTA; 190 191 OSMR0 = osmr[0]; 192 OSMR1 = osmr[1]; 193 OSMR2 = osmr[2]; 194 OSMR3 = osmr[3]; 195 OIER = oier; 196 OSCR = oscr; 197} 198#else 199#define pxa_timer_suspend NULL 200#define pxa_timer_resume NULL 201#endif 202 203struct sys_timer pxa_timer = { 204 .init = pxa_timer_init, 205 .suspend = pxa_timer_suspend, 206 .resume = pxa_timer_resume, 207}; 208