diff options
Diffstat (limited to 'arch/sparc/kernel/pcic.c')
-rw-r--r-- | arch/sparc/kernel/pcic.c | 48 |
1 files changed, 26 insertions, 22 deletions
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index 6edec801e46a..118a3f5806a8 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c | |||
@@ -703,31 +703,28 @@ static void pcic_clear_clock_irq(void) | |||
703 | pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT); | 703 | pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT); |
704 | } | 704 | } |
705 | 705 | ||
706 | static irqreturn_t pcic_timer_handler (int irq, void *h) | 706 | /* CPU frequency is 100 MHz, timer increments every 4 CPU clocks */ |
707 | #define USECS_PER_JIFFY (1000000 / HZ) | ||
708 | #define TICK_TIMER_LIMIT ((100 * 1000000 / 4) / HZ) | ||
709 | |||
710 | static unsigned int pcic_cycles_offset(void) | ||
707 | { | 711 | { |
708 | pcic_clear_clock_irq(); | 712 | u32 value, count; |
709 | xtime_update(1); | ||
710 | #ifndef CONFIG_SMP | ||
711 | update_process_times(user_mode(get_irq_regs())); | ||
712 | #endif | ||
713 | return IRQ_HANDLED; | ||
714 | } | ||
715 | 713 | ||
716 | #define USECS_PER_JIFFY 10000 /* We have 100HZ "standard" timer for sparc */ | 714 | value = readl(pcic0.pcic_regs + PCI_SYS_COUNTER); |
717 | #define TICK_TIMER_LIMIT ((100*1000000/4)/100) | 715 | count = value & ~PCI_SYS_COUNTER_OVERFLOW; |
718 | 716 | ||
719 | u32 pci_gettimeoffset(void) | 717 | if (value & PCI_SYS_COUNTER_OVERFLOW) |
720 | { | 718 | count += TICK_TIMER_LIMIT; |
721 | /* | 719 | /* |
722 | * We divide all by 100 | 720 | * We divide all by HZ |
723 | * to have microsecond resolution and to avoid overflow | 721 | * to have microsecond resolution and to avoid overflow |
724 | */ | 722 | */ |
725 | unsigned long count = | 723 | count = ((count / HZ) * USECS_PER_JIFFY) / (TICK_TIMER_LIMIT / HZ); |
726 | readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW; | ||
727 | count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100); | ||
728 | return count * 1000; | ||
729 | } | ||
730 | 724 | ||
725 | /* Coordinate with the fact that timer_cs rate is 2MHz */ | ||
726 | return count * 2; | ||
727 | } | ||
731 | 728 | ||
732 | void __init pci_time_init(void) | 729 | void __init pci_time_init(void) |
733 | { | 730 | { |
@@ -736,9 +733,16 @@ void __init pci_time_init(void) | |||
736 | int timer_irq, irq; | 733 | int timer_irq, irq; |
737 | int err; | 734 | int err; |
738 | 735 | ||
739 | do_arch_gettimeoffset = pci_gettimeoffset; | 736 | #ifndef CONFIG_SMP |
740 | 737 | /* | |
741 | btfixup(); | 738 | * It's in SBUS dimension, because timer_cs is in this dimension. |
739 | * We take into account this in pcic_cycles_offset() | ||
740 | */ | ||
741 | timer_cs_period = SBUS_CLOCK_RATE / HZ; | ||
742 | sparc_config.features |= FEAT_L10_CLOCKEVENT; | ||
743 | #endif | ||
744 | sparc_config.features |= FEAT_L10_CLOCKSOURCE; | ||
745 | sparc_config.get_cycles_offset = pcic_cycles_offset; | ||
742 | 746 | ||
743 | writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT); | 747 | writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT); |
744 | /* PROM should set appropriate irq */ | 748 | /* PROM should set appropriate irq */ |
@@ -747,7 +751,7 @@ void __init pci_time_init(void) | |||
747 | writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), | 751 | writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), |
748 | pcic->pcic_regs+PCI_COUNTER_IRQ); | 752 | pcic->pcic_regs+PCI_COUNTER_IRQ); |
749 | irq = pcic_build_device_irq(NULL, timer_irq); | 753 | irq = pcic_build_device_irq(NULL, timer_irq); |
750 | err = request_irq(irq, pcic_timer_handler, | 754 | err = request_irq(irq, timer_interrupt, |
751 | IRQF_TIMER, "timer", NULL); | 755 | IRQF_TIMER, "timer", NULL); |
752 | if (err) { | 756 | if (err) { |
753 | prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); | 757 | prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); |