diff options
Diffstat (limited to 'arch/sparc/kernel/pcic.c')
| -rw-r--r-- | arch/sparc/kernel/pcic.c | 55 | 
1 files changed, 29 insertions, 26 deletions
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index fcc148effaa..ded3f6090c3 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c @@ -703,31 +703,28 @@ static void pcic_clear_clock_irq(void)  	pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT);  } -static irqreturn_t pcic_timer_handler (int irq, void *h) +/* CPU frequency is 100 MHz, timer increments every 4 CPU clocks */ +#define USECS_PER_JIFFY  (1000000 / HZ) +#define TICK_TIMER_LIMIT ((100 * 1000000 / 4) / HZ) + +static unsigned int pcic_cycles_offset(void)  { -	pcic_clear_clock_irq(); -	xtime_update(1); -#ifndef CONFIG_SMP -	update_process_times(user_mode(get_irq_regs())); -#endif -	return IRQ_HANDLED; -} +	u32 value, count; -#define USECS_PER_JIFFY  10000  /* We have 100HZ "standard" timer for sparc */ -#define TICK_TIMER_LIMIT ((100*1000000/4)/100) +	value = readl(pcic0.pcic_regs + PCI_SYS_COUNTER); +	count = value & ~PCI_SYS_COUNTER_OVERFLOW; -u32 pci_gettimeoffset(void) -{ +	if (value & PCI_SYS_COUNTER_OVERFLOW) +		count += TICK_TIMER_LIMIT;  	/* -	 * We divide all by 100 +	 * We divide all by HZ  	 * to have microsecond resolution and to avoid overflow  	 */ -	unsigned long count = -	    readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; -	count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100); -	return count * 1000; -} +	count = ((count / HZ) * USECS_PER_JIFFY) / (TICK_TIMER_LIMIT / HZ); +	/* Coordinate with the sparc_config.clock_rate setting */ +	return count * 2; +}  void __init pci_time_init(void)  { @@ -736,9 +733,16 @@ void __init pci_time_init(void)  	int timer_irq, irq;  	int err; -	do_arch_gettimeoffset = pci_gettimeoffset; - -	btfixup(); +#ifndef CONFIG_SMP +	/* +	 * The clock_rate is in SBUS dimension. +	 * We take into account this in pcic_cycles_offset() +	 */ +	sparc_config.clock_rate = SBUS_CLOCK_RATE / HZ; +	sparc_config.features |= FEAT_L10_CLOCKEVENT; +#endif +	sparc_config.features |= FEAT_L10_CLOCKSOURCE; +	sparc_config.get_cycles_offset = pcic_cycles_offset;  	writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);  	/* PROM should set appropriate irq */ @@ -747,7 +751,7 @@ void __init pci_time_init(void)  	writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),  		pcic->pcic_regs+PCI_COUNTER_IRQ);  	irq = pcic_build_device_irq(NULL, timer_irq); -	err = request_irq(irq, pcic_timer_handler, +	err = request_irq(irq, timer_interrupt,  			  IRQF_TIMER, "timer", NULL);  	if (err) {  		prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); @@ -875,10 +879,9 @@ static void pcic_load_profile_irq(int cpu, unsigned int limit)  void __init sun4m_pci_init_IRQ(void)  { -	sparc_irq_config.build_device_irq = pcic_build_device_irq; - -	BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); -	BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); +	sparc_config.build_device_irq = pcic_build_device_irq; +	sparc_config.clear_clock_irq  = pcic_clear_clock_irq; +	sparc_config.load_profile_irq = pcic_load_profile_irq;  }  int pcibios_assign_resource(struct pci_dev *pdev, int resource)  |