1/* Ported over from i386 by AK, original copyright was: 2 * 3 * (C) Dominik Brodowski <linux@brodo.de> 2003 4 * 5 * Driver to use the Power Management Timer (PMTMR) available in some 6 * southbridges as primary timing source for the Linux kernel. 7 * 8 * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c, 9 * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4. 10 * 11 * This file is licensed under the GPL v2. 12 * 13 * Dropped all the hardware bug workarounds for now. Hopefully they 14 * are not needed on 64bit chipsets. 15 */ 16 17#include <linux/jiffies.h> 18#include <linux/kernel.h> 19#include <linux/time.h> 20#include <linux/init.h> 21#include <linux/cpumask.h> 22#include <asm/io.h> 23#include <asm/proto.h> 24#include <asm/msr.h> 25#include <asm/vsyscall.h> 26 27#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */ 28 29static inline u32 cyc2us(u32 cycles) 30{ 31 /* The Power Management Timer ticks at 3.579545 ticks per microsecond. 32 * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%] 33 * 34 * Even with HZ = 100, delta is at maximum 35796 ticks, so it can 35 * easily be multiplied with 286 (=0x11E) without having to fear 36 * u32 overflows. 37 */ 38 cycles *= 286; 39 return (cycles >> 10); 40} 41 42static unsigned pmtimer_wait_tick(void) 43{ 44 u32 a, b; 45 for (a = b = inl(pmtmr_ioport) & ACPI_PM_MASK; 46 a == b; 47 b = inl(pmtmr_ioport) & ACPI_PM_MASK) 48 cpu_relax(); 49 return b; 50} 51 52/* note: wait time is rounded up to one tick */ 53void pmtimer_wait(unsigned us) 54{ 55 u32 a, b; 56 a = pmtimer_wait_tick(); 57 do { 58 b = inl(pmtmr_ioport); 59 cpu_relax(); 60 } while (cyc2us(b - a) < us); 61} 62 63static int __init nopmtimer_setup(char *s) 64{ 65 pmtmr_ioport = 0; 66 return 1; 67} 68 69__setup("nopmtimer", nopmtimer_setup); 70