x86: hpet: Cleanup the clockevents init and register code
No need to recalculate the frequency and the conversion factors over and over. Calculate the frequency once and use the new config/register interface and let the core code do the math. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Cc: John Stultz <john.stultz@linaro.org> Reviewed-by: Ingo Molnar <mingo@elte.hu> Link: http://lkml.kernel.org/r/%3C20110518210136.646482357%40linutronix.de%3E
This commit is contained in:
		
					parent
					
						
							
								61ee9a4ba0
							
						
					
				
			
			
				commit
				
					
						ab0e08f15d
					
				
			
		
					 1 changed files with 16 additions and 56 deletions
				
			
		| 
						 | 
					@ -217,7 +217,7 @@ static void hpet_reserve_platform_timers(unsigned int id) { }
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Common hpet info
 | 
					 * Common hpet info
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static unsigned long hpet_period;
 | 
					static unsigned long hpet_freq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void hpet_legacy_set_mode(enum clock_event_mode mode,
 | 
					static void hpet_legacy_set_mode(enum clock_event_mode mode,
 | 
				
			||||||
			  struct clock_event_device *evt);
 | 
								  struct clock_event_device *evt);
 | 
				
			||||||
| 
						 | 
					@ -232,7 +232,6 @@ static struct clock_event_device hpet_clockevent = {
 | 
				
			||||||
	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 | 
						.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 | 
				
			||||||
	.set_mode	= hpet_legacy_set_mode,
 | 
						.set_mode	= hpet_legacy_set_mode,
 | 
				
			||||||
	.set_next_event = hpet_legacy_next_event,
 | 
						.set_next_event = hpet_legacy_next_event,
 | 
				
			||||||
	.shift		= 32,
 | 
					 | 
				
			||||||
	.irq		= 0,
 | 
						.irq		= 0,
 | 
				
			||||||
	.rating		= 50,
 | 
						.rating		= 50,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -289,29 +288,13 @@ static void hpet_legacy_clockevent_register(void)
 | 
				
			||||||
	/* Start HPET legacy interrupts */
 | 
						/* Start HPET legacy interrupts */
 | 
				
			||||||
	hpet_enable_legacy_int();
 | 
						hpet_enable_legacy_int();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * The mult factor is defined as (include/linux/clockchips.h)
 | 
					 | 
				
			||||||
	 *  mult/2^shift = cyc/ns (in contrast to ns/cyc in clocksource.h)
 | 
					 | 
				
			||||||
	 * hpet_period is in units of femtoseconds (per cycle), so
 | 
					 | 
				
			||||||
	 *  mult/2^shift = cyc/ns = 10^6/hpet_period
 | 
					 | 
				
			||||||
	 *  mult = (10^6 * 2^shift)/hpet_period
 | 
					 | 
				
			||||||
	 *  mult = (FSEC_PER_NSEC << hpet_clockevent.shift)/hpet_period
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	hpet_clockevent.mult = div_sc((unsigned long) FSEC_PER_NSEC,
 | 
					 | 
				
			||||||
				      hpet_period, hpet_clockevent.shift);
 | 
					 | 
				
			||||||
	/* Calculate the min / max delta */
 | 
					 | 
				
			||||||
	hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
 | 
					 | 
				
			||||||
							   &hpet_clockevent);
 | 
					 | 
				
			||||||
	/* Setup minimum reprogramming delta. */
 | 
					 | 
				
			||||||
	hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA,
 | 
					 | 
				
			||||||
							   &hpet_clockevent);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Start hpet with the boot cpu mask and make it
 | 
						 * Start hpet with the boot cpu mask and make it
 | 
				
			||||||
	 * global after the IO_APIC has been initialized.
 | 
						 * global after the IO_APIC has been initialized.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	hpet_clockevent.cpumask = cpumask_of(smp_processor_id());
 | 
						hpet_clockevent.cpumask = cpumask_of(smp_processor_id());
 | 
				
			||||||
	clockevents_register_device(&hpet_clockevent);
 | 
						clockevents_config_and_register(&hpet_clockevent, hpet_freq,
 | 
				
			||||||
 | 
										HPET_MIN_PROG_DELTA, 0x7FFFFFFF);
 | 
				
			||||||
	global_clock_event = &hpet_clockevent;
 | 
						global_clock_event = &hpet_clockevent;
 | 
				
			||||||
	printk(KERN_DEBUG "hpet clockevent registered\n");
 | 
						printk(KERN_DEBUG "hpet clockevent registered\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -549,7 +532,6 @@ static int hpet_setup_irq(struct hpet_dev *dev)
 | 
				
			||||||
static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 | 
					static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct clock_event_device *evt = &hdev->evt;
 | 
						struct clock_event_device *evt = &hdev->evt;
 | 
				
			||||||
	uint64_t hpet_freq;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	WARN_ON(cpu != smp_processor_id());
 | 
						WARN_ON(cpu != smp_processor_id());
 | 
				
			||||||
	if (!(hdev->flags & HPET_DEV_VALID))
 | 
						if (!(hdev->flags & HPET_DEV_VALID))
 | 
				
			||||||
| 
						 | 
					@ -571,24 +553,10 @@ static void init_one_hpet_msi_clockevent(struct hpet_dev *hdev, int cpu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	evt->set_mode = hpet_msi_set_mode;
 | 
						evt->set_mode = hpet_msi_set_mode;
 | 
				
			||||||
	evt->set_next_event = hpet_msi_next_event;
 | 
						evt->set_next_event = hpet_msi_next_event;
 | 
				
			||||||
	evt->shift = 32;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * The period is a femto seconds value. We need to calculate the
 | 
					 | 
				
			||||||
	 * scaled math multiplication factor for nanosecond to hpet tick
 | 
					 | 
				
			||||||
	 * conversion.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	hpet_freq = FSEC_PER_SEC;
 | 
					 | 
				
			||||||
	do_div(hpet_freq, hpet_period);
 | 
					 | 
				
			||||||
	evt->mult = div_sc((unsigned long) hpet_freq,
 | 
					 | 
				
			||||||
				      NSEC_PER_SEC, evt->shift);
 | 
					 | 
				
			||||||
	/* Calculate the max delta */
 | 
					 | 
				
			||||||
	evt->max_delta_ns = clockevent_delta2ns(0x7FFFFFFF, evt);
 | 
					 | 
				
			||||||
	/* 5 usec minimum reprogramming delta. */
 | 
					 | 
				
			||||||
	evt->min_delta_ns = 5000;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	evt->cpumask = cpumask_of(hdev->cpu);
 | 
						evt->cpumask = cpumask_of(hdev->cpu);
 | 
				
			||||||
	clockevents_register_device(evt);
 | 
					
 | 
				
			||||||
 | 
						clockevents_config_and_register(evt, hpet_freq, HPET_MIN_PROG_DELTA,
 | 
				
			||||||
 | 
										0x7FFFFFFF);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef CONFIG_HPET
 | 
					#ifdef CONFIG_HPET
 | 
				
			||||||
| 
						 | 
					@ -792,7 +760,6 @@ static struct clocksource clocksource_hpet = {
 | 
				
			||||||
static int hpet_clocksource_register(void)
 | 
					static int hpet_clocksource_register(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u64 start, now;
 | 
						u64 start, now;
 | 
				
			||||||
	u64 hpet_freq;
 | 
					 | 
				
			||||||
	cycle_t t1;
 | 
						cycle_t t1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Start the counter */
 | 
						/* Start the counter */
 | 
				
			||||||
| 
						 | 
					@ -819,24 +786,7 @@ static int hpet_clocksource_register(void)
 | 
				
			||||||
		return -ENODEV;
 | 
							return -ENODEV;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
					 | 
				
			||||||
	 * The definition of mult is (include/linux/clocksource.h)
 | 
					 | 
				
			||||||
	 * mult/2^shift = ns/cyc and hpet_period is in units of fsec/cyc
 | 
					 | 
				
			||||||
	 * so we first need to convert hpet_period to ns/cyc units:
 | 
					 | 
				
			||||||
	 *  mult/2^shift = ns/cyc = hpet_period/10^6
 | 
					 | 
				
			||||||
	 *  mult = (hpet_period * 2^shift)/10^6
 | 
					 | 
				
			||||||
	 *  mult = (hpet_period << shift)/FSEC_PER_NSEC
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Need to convert hpet_period (fsec/cyc) to cyc/sec:
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * cyc/sec = FSEC_PER_SEC/hpet_period(fsec/cyc)
 | 
					 | 
				
			||||||
	 * cyc/sec = (FSEC_PER_NSEC * NSEC_PER_SEC)/hpet_period
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	hpet_freq = FSEC_PER_SEC;
 | 
					 | 
				
			||||||
	do_div(hpet_freq, hpet_period);
 | 
					 | 
				
			||||||
	clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 | 
						clocksource_register_hz(&clocksource_hpet, (u32)hpet_freq);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -845,7 +795,9 @@ static int hpet_clocksource_register(void)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int __init hpet_enable(void)
 | 
					int __init hpet_enable(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						unsigned long hpet_period;
 | 
				
			||||||
	unsigned int id;
 | 
						unsigned int id;
 | 
				
			||||||
 | 
						u64 freq;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!is_hpet_capable())
 | 
						if (!is_hpet_capable())
 | 
				
			||||||
| 
						 | 
					@ -883,6 +835,14 @@ int __init hpet_enable(void)
 | 
				
			||||||
	if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
 | 
						if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
 | 
				
			||||||
		goto out_nohpet;
 | 
							goto out_nohpet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * The period is a femto seconds value. Convert it to a
 | 
				
			||||||
 | 
						 * frequency.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						freq = FSEC_PER_SEC;
 | 
				
			||||||
 | 
						do_div(freq, hpet_period);
 | 
				
			||||||
 | 
						hpet_freq = freq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Read the HPET ID register to retrieve the IRQ routing
 | 
						 * Read the HPET ID register to retrieve the IRQ routing
 | 
				
			||||||
	 * information and the number of channels
 | 
						 * information and the number of channels
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue