diff options
Diffstat (limited to 'arch/x86/kernel/apb_timer.c')
| -rw-r--r-- | arch/x86/kernel/apb_timer.c | 495 | 
1 files changed, 82 insertions, 413 deletions
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c index 92543c73cf8..af5b08ab3b7 100644 --- a/arch/x86/kernel/apb_timer.c +++ b/arch/x86/kernel/apb_timer.c @@ -27,15 +27,12 @@   * timer, but by default APB timer has higher rating than local APIC timers.   */ -#include <linux/clocksource.h> -#include <linux/clockchips.h>  #include <linux/delay.h> +#include <linux/dw_apb_timer.h>  #include <linux/errno.h>  #include <linux/init.h> -#include <linux/sysdev.h>  #include <linux/slab.h>  #include <linux/pm.h> -#include <linux/pci.h>  #include <linux/sfi.h>  #include <linux/interrupt.h>  #include <linux/cpu.h> @@ -43,77 +40,49 @@  #include <asm/fixmap.h>  #include <asm/apb_timer.h> -#include <asm/mrst.h> +#include <asm/intel-mid.h> +#include <asm/time.h> -#define APBT_MASK			CLOCKSOURCE_MASK(32) -#define APBT_SHIFT			22  #define APBT_CLOCKEVENT_RATING		110  #define APBT_CLOCKSOURCE_RATING		250 -#define APBT_MIN_DELTA_USEC		200 -#define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt)  #define APBT_CLOCKEVENT0_NUM   (0) -#define APBT_CLOCKEVENT1_NUM   (1)  #define APBT_CLOCKSOURCE_NUM   (2) -static unsigned long apbt_address; +static phys_addr_t apbt_address;  static int apb_timer_block_enabled;  static void __iomem *apbt_virt_address; -static int phy_cs_timer_id;  /*   * Common DW APB timer info   */ -static uint64_t apbt_freq; - -static void apbt_set_mode(enum clock_event_mode mode, -			  struct clock_event_device *evt); -static int apbt_next_event(unsigned long delta, -			   struct clock_event_device *evt); -static cycle_t apbt_read_clocksource(struct clocksource *cs); -static void apbt_restart_clocksource(struct clocksource *cs); +static unsigned long apbt_freq;  struct apbt_dev { -	struct clock_event_device evt; -	unsigned int num; -	int cpu; -	unsigned int irq; -	unsigned int tick; -	unsigned int count; -	unsigned int flags; -	char name[10]; +	struct dw_apb_clock_event_device	*timer; +	unsigned int				num; +	int					cpu; +	unsigned int				irq; +	char					name[10];  }; -static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); - -#ifdef CONFIG_SMP -static unsigned int apbt_num_timers_used; -static struct apbt_dev *apbt_devs; -#endif - -static	inline unsigned long apbt_readl_reg(unsigned long a) -{ -	return readl(apbt_virt_address + a); -} +static struct dw_apb_clocksource *clocksource_apbt; -static inline void apbt_writel_reg(unsigned long d, unsigned long a) +static inline void __iomem *adev_virt_addr(struct apbt_dev *adev)  { -	writel(d, apbt_virt_address + a); +	return apbt_virt_address + adev->num * APBTMRS_REG_SIZE;  } -static inline unsigned long apbt_readl(int n, unsigned long a) -{ -	return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE); -} +static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev); -static inline void apbt_writel(int n, unsigned long d, unsigned long a) -{ -	writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE); -} +#ifdef CONFIG_SMP +static unsigned int apbt_num_timers_used; +#endif  static inline void apbt_set_mapping(void)  {  	struct sfi_timer_table_entry *mtmr; +	int phy_cs_timer_id = 0;  	if (apbt_virt_address) {  		pr_debug("APBT base already mapped\n"); @@ -125,21 +94,18 @@ static inline void apbt_set_mapping(void)  		       APBT_CLOCKEVENT0_NUM);  		return;  	} -	apbt_address = (unsigned long)mtmr->phys_addr; +	apbt_address = (phys_addr_t)mtmr->phys_addr;  	if (!apbt_address) {  		printk(KERN_WARNING "No timer base from SFI, use default\n");  		apbt_address = APBT_DEFAULT_BASE;  	}  	apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE); -	if (apbt_virt_address) { -		pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\ -			 (void *)apbt_address, (void *)apbt_virt_address); -	} else { -		pr_debug("Failed mapping APBT phy address at %p\n",\ -			 (void *)apbt_address); +	if (!apbt_virt_address) { +		pr_debug("Failed mapping APBT phy address at %lu\n",\ +			 (unsigned long)apbt_address);  		goto panic_noapbt;  	} -	apbt_freq = mtmr->freq_hz / USEC_PER_SEC; +	apbt_freq = mtmr->freq_hz;  	sfi_free_mtmr(mtmr);  	/* Now figure out the physical timer id for clocksource device */ @@ -148,9 +114,14 @@ static inline void apbt_set_mapping(void)  		goto panic_noapbt;  	/* Now figure out the physical timer id */ -	phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) -		/ APBTMRS_REG_SIZE; -	pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id); +	pr_debug("Use timer %d for clocksource\n", +		 (int)(mtmr->phys_addr & 0xff) / APBTMRS_REG_SIZE); +	phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff) / +		APBTMRS_REG_SIZE; + +	clocksource_apbt = dw_apb_clocksource_init(APBT_CLOCKSOURCE_RATING, +		"apbt0", apbt_virt_address + phy_cs_timer_id * +		APBTMRS_REG_SIZE, apbt_freq);  	return;  panic_noapbt: @@ -172,83 +143,6 @@ static inline int is_apbt_capable(void)  	return apbt_virt_address ? 1 : 0;  } -static struct clocksource clocksource_apbt = { -	.name		= "apbt", -	.rating		= APBT_CLOCKSOURCE_RATING, -	.read		= apbt_read_clocksource, -	.mask		= APBT_MASK, -	.shift		= APBT_SHIFT, -	.flags		= CLOCK_SOURCE_IS_CONTINUOUS, -	.resume		= apbt_restart_clocksource, -}; - -/* boot APB clock event device */ -static struct clock_event_device apbt_clockevent = { -	.name		= "apbt0", -	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, -	.set_mode	= apbt_set_mode, -	.set_next_event = apbt_next_event, -	.shift		= APBT_SHIFT, -	.irq		= 0, -	.rating		= APBT_CLOCKEVENT_RATING, -}; - -/* - * start count down from 0xffff_ffff. this is done by toggling the enable bit - * then load initial load count to ~0. - */ -static void apbt_start_counter(int n) -{ -	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); - -	ctrl &= ~APBTMR_CONTROL_ENABLE; -	apbt_writel(n, ctrl, APBTMR_N_CONTROL); -	apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT); -	/* enable, mask interrupt */ -	ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; -	ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT); -	apbt_writel(n, ctrl, APBTMR_N_CONTROL); -	/* read it once to get cached counter value initialized */ -	apbt_read_clocksource(&clocksource_apbt); -} - -static irqreturn_t apbt_interrupt_handler(int irq, void *data) -{ -	struct apbt_dev *dev = (struct apbt_dev *)data; -	struct clock_event_device *aevt = &dev->evt; - -	if (!aevt->event_handler) { -		printk(KERN_INFO "Spurious APBT timer interrupt on %d\n", -		       dev->num); -		return IRQ_NONE; -	} -	aevt->event_handler(aevt); -	return IRQ_HANDLED; -} - -static void apbt_restart_clocksource(struct clocksource *cs) -{ -	apbt_start_counter(phy_cs_timer_id); -} - -static void apbt_enable_int(int n) -{ -	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); -	/* clear pending intr */ -	apbt_readl(n, APBTMR_N_EOI); -	ctrl &= ~APBTMR_CONTROL_INT; -	apbt_writel(n, ctrl, APBTMR_N_CONTROL); -} - -static void apbt_disable_int(int n) -{ -	unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL); - -	ctrl |= APBTMR_CONTROL_INT; -	apbt_writel(n, ctrl, APBTMR_N_CONTROL); -} - -  static int __init apbt_clockevent_register(void)  {  	struct sfi_timer_table_entry *mtmr; @@ -261,45 +155,21 @@ static int __init apbt_clockevent_register(void)  		return -ENODEV;  	} -	/* -	 * We need to calculate the scaled math multiplication factor for -	 * nanosecond to apbt tick conversion. -	 * mult = (nsec/cycle)*2^APBT_SHIFT -	 */ -	apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz -				      , NSEC_PER_SEC, APBT_SHIFT); - -	/* Calculate the min / max delta */ -	apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, -							   &apbt_clockevent); -	apbt_clockevent.min_delta_ns = clockevent_delta2ns( -		APBT_MIN_DELTA_USEC*apbt_freq, -		&apbt_clockevent); -	/* -	 * Start apbt with the boot cpu mask and make it -	 * global if not used for per cpu timer. -	 */ -	apbt_clockevent.cpumask = cpumask_of(smp_processor_id());  	adev->num = smp_processor_id(); -	memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device)); - -	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { -		apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100; -		global_clock_event = &adev->evt; +	adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0", +		intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ? +		APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING, +		adev_virt_addr(adev), 0, apbt_freq); +	/* Firmware does EOI handling for us. */ +	adev->timer->eoi = NULL; + +	if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) { +		global_clock_event = &adev->timer->ced;  		printk(KERN_DEBUG "%s clockevent registered as global\n",  		       global_clock_event->name);  	} -	if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler, -			IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, -			apbt_clockevent.name, adev)) { -		printk(KERN_ERR "Failed request IRQ for APBT%d\n", -		       apbt_clockevent.irq); -	} - -	clockevents_register_device(&adev->evt); -	/* Start APBT 0 interrupts */ -	apbt_enable_int(APBT_CLOCKEVENT0_NUM); +	dw_apb_clockevent_register(adev->timer);  	sfi_free_mtmr(mtmr);  	return 0; @@ -313,53 +183,38 @@ static void apbt_setup_irq(struct apbt_dev *adev)  	if (adev->irq == 0)  		return; -	if (system_state == SYSTEM_BOOTING) { -		irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); -		/* APB timer irqs are set up as mp_irqs, timer is edge type */ -		__set_irq_handler(adev->irq, handle_edge_irq, 0, "edge"); -		if (request_irq(adev->irq, apbt_interrupt_handler, -				IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING, -				adev->name, adev)) { -			printk(KERN_ERR "Failed request IRQ for APBT%d\n", -			       adev->num); -		} -	} else -		enable_irq(adev->irq); +	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT); +	irq_set_affinity(adev->irq, cpumask_of(adev->cpu)); +	/* APB timer irqs are set up as mp_irqs, timer is edge type */ +	__irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");  }  /* Should be called with per cpu */  void apbt_setup_secondary_clock(void)  {  	struct apbt_dev *adev; -	struct clock_event_device *aevt;  	int cpu;  	/* Don't register boot CPU clockevent */  	cpu = smp_processor_id();  	if (!cpu)  		return; -	/* -	 * We need to calculate the scaled math multiplication factor for -	 * nanosecond to apbt tick conversion. -	 * mult = (nsec/cycle)*2^APBT_SHIFT -	 */ -	printk(KERN_INFO "Init per CPU clockevent %d\n", cpu); -	adev = &per_cpu(cpu_apbt_dev, cpu); -	aevt = &adev->evt; -	memcpy(aevt, &apbt_clockevent, sizeof(*aevt)); -	aevt->cpumask = cpumask_of(cpu); -	aevt->name = adev->name; -	aevt->mode = CLOCK_EVT_MODE_UNUSED; +	adev = &__get_cpu_var(cpu_apbt_dev); +	if (!adev->timer) { +		adev->timer = dw_apb_clockevent_init(cpu, adev->name, +			APBT_CLOCKEVENT_RATING, adev_virt_addr(adev), +			adev->irq, apbt_freq); +		adev->timer->eoi = NULL; +	} else { +		dw_apb_clockevent_resume(adev->timer); +	} -	printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n", -	       cpu, aevt->name, *(u32 *)aevt->cpumask); +	printk(KERN_INFO "Registering CPU %d clockevent device %s, cpu %08x\n", +	       cpu, adev->name, adev->cpu);  	apbt_setup_irq(adev); - -	clockevents_register_device(aevt); - -	apbt_enable_int(cpu); +	dw_apb_clockevent_register(adev->timer);  	return;  } @@ -382,13 +237,12 @@ static int apbt_cpuhp_notify(struct notifier_block *n,  	switch (action & 0xf) {  	case CPU_DEAD: -		disable_irq(adev->irq); -		apbt_disable_int(cpu); +		dw_apb_clockevent_pause(adev->timer);  		if (system_state == SYSTEM_RUNNING) {  			pr_debug("skipping APBT CPU %lu offline\n", cpu); -		} else if (adev) { +		} else {  			pr_debug("APBT clockevent for cpu %lu offline\n", cpu); -			free_irq(adev->irq, adev); +			dw_apb_clockevent_stop(adev->timer);  		}  		break;  	default: @@ -399,7 +253,7 @@ static int apbt_cpuhp_notify(struct notifier_block *n,  static __init int apbt_late_init(void)  { -	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT || +	if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ||  		!apb_timer_block_enabled)  		return 0;  	/* This notifier should be called after workqueue is ready */ @@ -413,168 +267,16 @@ void apbt_setup_secondary_clock(void) {}  #endif /* CONFIG_SMP */ -static void apbt_set_mode(enum clock_event_mode mode, -			  struct clock_event_device *evt) -{ -	unsigned long ctrl; -	uint64_t delta; -	int timer_num; -	struct apbt_dev *adev = EVT_TO_APBT_DEV(evt); - -	BUG_ON(!apbt_virt_address); - -	timer_num = adev->num; -	pr_debug("%s CPU %d timer %d mode=%d\n", -		 __func__, first_cpu(*evt->cpumask), timer_num, mode); - -	switch (mode) { -	case CLOCK_EVT_MODE_PERIODIC: -		delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult; -		delta >>= apbt_clockevent.shift; -		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); -		ctrl |= APBTMR_CONTROL_MODE_PERIODIC; -		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -		/* -		 * DW APB p. 46, have to disable timer before load counter, -		 * may cause sync problem. -		 */ -		ctrl &= ~APBTMR_CONTROL_ENABLE; -		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -		udelay(1); -		pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ); -		apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT); -		ctrl |= APBTMR_CONTROL_ENABLE; -		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -		break; -		/* APB timer does not have one-shot mode, use free running mode */ -	case CLOCK_EVT_MODE_ONESHOT: -		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); -		/* -		 * set free running mode, this mode will let timer reload max -		 * timeout which will give time (3min on 25MHz clock) to rearm -		 * the next event, therefore emulate the one-shot mode. -		 */ -		ctrl &= ~APBTMR_CONTROL_ENABLE; -		ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC; - -		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -		/* write again to set free running mode */ -		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); - -		/* -		 * DW APB p. 46, load counter with all 1s before starting free -		 * running mode. -		 */ -		apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT); -		ctrl &= ~APBTMR_CONTROL_INT; -		ctrl |= APBTMR_CONTROL_ENABLE; -		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -		break; - -	case CLOCK_EVT_MODE_UNUSED: -	case CLOCK_EVT_MODE_SHUTDOWN: -		apbt_disable_int(timer_num); -		ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); -		ctrl &= ~APBTMR_CONTROL_ENABLE; -		apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -		break; - -	case CLOCK_EVT_MODE_RESUME: -		apbt_enable_int(timer_num); -		break; -	} -} - -static int apbt_next_event(unsigned long delta, -			   struct clock_event_device *evt) -{ -	unsigned long ctrl; -	int timer_num; - -	struct apbt_dev *adev = EVT_TO_APBT_DEV(evt); - -	timer_num = adev->num; -	/* Disable timer */ -	ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL); -	ctrl &= ~APBTMR_CONTROL_ENABLE; -	apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -	/* write new count */ -	apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT); -	ctrl |= APBTMR_CONTROL_ENABLE; -	apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL); -	return 0; -} - -/* - * APB timer clock is not in sync with pclk on Langwell, which translates to - * unreliable read value caused by sampling error. the error does not add up - * overtime and only happens when sampling a 0 as a 1 by mistake. so the time - * would go backwards. the following code is trying to prevent time traveling - * backwards. little bit paranoid. - */ -static cycle_t apbt_read_clocksource(struct clocksource *cs) -{ -	unsigned long t0, t1, t2; -	static unsigned long last_read; - -bad_count: -	t1 = apbt_readl(phy_cs_timer_id, -			APBTMR_N_CURRENT_VALUE); -	t2 = apbt_readl(phy_cs_timer_id, -			APBTMR_N_CURRENT_VALUE); -	if (unlikely(t1 < t2)) { -		pr_debug("APBT: read current count error %lx:%lx:%lx\n", -			 t1, t2, t2 - t1); -		goto bad_count; -	} -	/* -	 * check against cached last read, makes sure time does not go back. -	 * it could be a normal rollover but we will do tripple check anyway -	 */ -	if (unlikely(t2 > last_read)) { -		/* check if we have a normal rollover */ -		unsigned long raw_intr_status = -			apbt_readl_reg(APBTMRS_RAW_INT_STATUS); -		/* -		 * cs timer interrupt is masked but raw intr bit is set if -		 * rollover occurs. then we read EOI reg to clear it. -		 */ -		if (raw_intr_status & (1 << phy_cs_timer_id)) { -			apbt_readl(phy_cs_timer_id, APBTMR_N_EOI); -			goto out; -		} -		pr_debug("APB CS going back %lx:%lx:%lx ", -			 t2, last_read, t2 - last_read); -bad_count_x3: -		pr_debug("triple check enforced\n"); -		t0 = apbt_readl(phy_cs_timer_id, -				APBTMR_N_CURRENT_VALUE); -		udelay(1); -		t1 = apbt_readl(phy_cs_timer_id, -				APBTMR_N_CURRENT_VALUE); -		udelay(1); -		t2 = apbt_readl(phy_cs_timer_id, -				APBTMR_N_CURRENT_VALUE); -		if ((t2 > t1) || (t1 > t0)) { -			printk(KERN_ERR "Error: APB CS tripple check failed\n"); -			goto bad_count_x3; -		} -	} -out: -	last_read = t2; -	return (cycle_t)~t2; -} -  static int apbt_clocksource_register(void)  {  	u64 start, now;  	cycle_t t1;  	/* Start the counter, use timer 2 as source, timer 0/1 for event */ -	apbt_start_counter(phy_cs_timer_id); +	dw_apb_clocksource_start(clocksource_apbt);  	/* Verify whether apbt counter works */ -	t1 = apbt_read_clocksource(&clocksource_apbt); +	t1 = dw_apb_clocksource_read(clocksource_apbt);  	rdtscll(start);  	/* @@ -589,17 +291,10 @@ static int apbt_clocksource_register(void)  	} while ((now - start) < 200000UL);  	/* APBT is the only always on clocksource, it has to work! */ -	if (t1 == apbt_read_clocksource(&clocksource_apbt)) +	if (t1 == dw_apb_clocksource_read(clocksource_apbt))  		panic("APBT counter not counting. APBT disabled\n"); -	/* -	 * initialize and register APBT clocksource -	 * convert that to ns/clock cycle -	 * mult = (ns/c) * 2^APBT_SHIFT -	 */ -	clocksource_apbt.mult = div_sc(MSEC_PER_SEC, -				       (unsigned long) apbt_freq, APBT_SHIFT); -	clocksource_register(&clocksource_apbt); +	dw_apb_clocksource_register(clocksource_apbt);  	return 0;  } @@ -616,17 +311,13 @@ void __init apbt_time_init(void)  #ifdef CONFIG_SMP  	int i;  	struct sfi_timer_table_entry *p_mtmr; -	unsigned int percpu_timer;  	struct apbt_dev *adev;  #endif  	if (apb_timer_block_enabled)  		return;  	apbt_set_mapping(); -	if (apbt_virt_address) { -		pr_debug("Found APBT version 0x%lx\n",\ -			 apbt_readl_reg(APBTMRS_COMP_VERSION)); -	} else +	if (!apbt_virt_address)  		goto out_noapbt;  	/*  	 * Read the frequency and check for a sane value, for ESL model @@ -634,7 +325,7 @@ void __init apbt_time_init(void)  	 */  	if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) { -		pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq); +		pr_debug("APBT has invalid freq 0x%lx\n", apbt_freq);  		goto out_noapbt;  	}  	if (apbt_clocksource_register()) { @@ -649,41 +340,28 @@ void __init apbt_time_init(void)  	}  #ifdef CONFIG_SMP  	/* kernel cmdline disable apb timer, so we will use lapic timers */ -	if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { +	if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) {  		printk(KERN_INFO "apbt: disabled per cpu timer\n");  		return;  	}  	pr_debug("%s: %d CPUs online\n", __func__, num_online_cpus()); -	if (num_possible_cpus() <= sfi_mtimer_num) { -		percpu_timer = 1; +	if (num_possible_cpus() <= sfi_mtimer_num)  		apbt_num_timers_used = num_possible_cpus(); -	} else { -		percpu_timer = 0; +	else  		apbt_num_timers_used = 1; -		adev = &per_cpu(cpu_apbt_dev, 0); -		adev->flags &= ~APBT_DEV_USED; -	}  	pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);  	/* here we set up per CPU timer data structure */ -	apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used, -			    GFP_KERNEL); -	if (!apbt_devs) { -		printk(KERN_ERR "Failed to allocate APB timer devices\n"); -		return; -	}  	for (i = 0; i < apbt_num_timers_used; i++) {  		adev = &per_cpu(cpu_apbt_dev, i);  		adev->num = i;  		adev->cpu = i;  		p_mtmr = sfi_get_mtmr(i); -		if (p_mtmr) { -			adev->tick = p_mtmr->freq_hz; +		if (p_mtmr)  			adev->irq = p_mtmr->irq; -		} else +		else  			printk(KERN_ERR "Failed to get timer for cpu %d\n", i); -		adev->count = 0; -		sprintf(adev->name, "apbt%d", i); +		snprintf(adev->name, sizeof(adev->name) - 1, "apbt%d", i);  	}  #endif @@ -695,17 +373,8 @@ out_noapbt:  	panic("failed to enable APB timer\n");  } -static inline void apbt_disable(int n) -{ -	if (is_apbt_capable()) { -		unsigned long ctrl =  apbt_readl(n, APBTMR_N_CONTROL); -		ctrl &= ~APBTMR_CONTROL_ENABLE; -		apbt_writel(n, ctrl, APBTMR_N_CONTROL); -	} -} -  /* called before apb_timer_enable, use early map */ -unsigned long apbt_quick_calibrate() +unsigned long apbt_quick_calibrate(void)  {  	int i, scale;  	u64 old, new; @@ -714,31 +383,31 @@ unsigned long apbt_quick_calibrate()  	u32 loop, shift;  	apbt_set_mapping(); -	apbt_start_counter(phy_cs_timer_id); +	dw_apb_clocksource_start(clocksource_apbt);  	/* check if the timer can count down, otherwise return */ -	old = apbt_read_clocksource(&clocksource_apbt); +	old = dw_apb_clocksource_read(clocksource_apbt);  	i = 10000;  	while (--i) { -		if (old != apbt_read_clocksource(&clocksource_apbt)) +		if (old != dw_apb_clocksource_read(clocksource_apbt))  			break;  	}  	if (!i)  		goto failed;  	/* count 16 ms */ -	loop = (apbt_freq * 1000) << 4; +	loop = (apbt_freq / 1000) << 4;  	/* restart the timer to ensure it won't get to 0 in the calibration */ -	apbt_start_counter(phy_cs_timer_id); +	dw_apb_clocksource_start(clocksource_apbt); -	old = apbt_read_clocksource(&clocksource_apbt); +	old = dw_apb_clocksource_read(clocksource_apbt);  	old += loop;  	t1 = __native_read_tsc();  	do { -		new = apbt_read_clocksource(&clocksource_apbt); +		new = dw_apb_clocksource_read(clocksource_apbt);  	} while (new < old);  	t2 = __native_read_tsc(); @@ -750,7 +419,7 @@ unsigned long apbt_quick_calibrate()  		return 0;  	}  	scale = (int)div_u64((t2 - t1), loop >> shift); -	khz = (scale * apbt_freq * 1000) >> shift; +	khz = (scale * (apbt_freq / 1000)) >> shift;  	printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz);  	return khz;  failed:  | 
