Example #1
0
/* TLB operations. */
void local_flush_tlb_all(void)
{
	unsigned long flags;
	unsigned long old_ctx;
	int entry;

#ifdef DEBUG_TLB
	printk("[tlball]");
#endif

	save_and_cli(flags);
	old_ctx = (get_entryhi() & 0xfc0);
	write_32bit_cp0_register(CP0_ENTRYLO0, 0);
#ifdef CONFIG_CPU_TX39XX
	entry = r3k_have_wired_reg ? get_wired() : 8;
#else
	entry = 8;
#endif
	for (; entry < mips_cpu.tlbsize; entry++) {
		write_32bit_cp0_register(CP0_INDEX, entry << 8);
		write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12));
		__asm__ __volatile__("tlbwi");
	}
	set_entryhi(old_ctx);
	restore_flags(flags);
}
Example #2
0
void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 ){
	write_32bit_cp0_register(CP0_ENTRYLO0, low0);
	write_32bit_cp0_register(CP0_PAGEMASK, pagemask);
	write_32bit_cp0_register(CP0_ENTRYLO1, low1);
	write_32bit_cp0_register(CP0_ENTRYHI, hi);
	write_32bit_cp0_register(CP0_INDEX, index);
	tlb_write_indexed();
}
Example #3
0
static inline void r49_flush_cache_all_d32i32(void)
{
    unsigned long flags, config;

    __save_and_cli(flags);
    blast_dcache32_wayLSB();
    /* disable icache (set ICE#) */
    config = read_32bit_cp0_register(CP0_CONFIG);
    write_32bit_cp0_register(CP0_CONFIG, config|TX49_CONF_IC);
    blast_icache32_wayLSB();
    write_32bit_cp0_register(CP0_CONFIG, config);
    __restore_flags(flags);
}
Example #4
0
static void __inline__ enable_all(void)
{
	unsigned long int_status;
	int_status = read_32bit_cp0_register(CP0_STATUS);
	int_status |= 0x1;
	write_32bit_cp0_register(CP0_STATUS, int_status);
}
Example #5
0
static void disable_rt2880_cp_int(unsigned int IP_X)
{
	unsigned long int_status;
	int_status = read_32bit_cp0_register(CP0_STATUS);
	int_status = int_status & ~(IP_X);
	write_32bit_cp0_register(CP0_STATUS, int_status);
}
Example #6
0
/*
 * Probe whether cpu has config register by trying to play with
 * alternate cache bit and see whether it matters.
 * It's used by cpu_probe to distinguish between R3000A and R3081.
 */
static inline int cpu_has_confreg(void)
{
#ifdef CONFIG_CPU_R3000
	extern unsigned long r3k_cache_size(unsigned long);
	unsigned long size1, size2; 
	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);

	size1 = r3k_cache_size(ST0_ISC);
	write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC);
	size2 = r3k_cache_size(ST0_ISC);
	write_32bit_cp0_register(CP0_CONF, cfg);
	return size1 != size2;
#else
	return 0;
#endif
}
Example #7
0
void ev64120_setup(void)
{
	unsigned int i, j;

	//printk(KERN_INFO "ev64120_setup\n");

	_machine_restart = galileo_machine_restart;
	_machine_halt = galileo_machine_halt;
	_machine_power_off = galileo_machine_power_off;

	rtc_ops = &galileo_rtc_ops;

	board_time_init = galileo_time_init;
	set_io_port_base(KSEG1);

#ifdef CONFIG_L2_L3_CACHE
#error "external cache not implemented yet"
	config_register = read_32bit_cp0_register(CP0_CONFIG);
	printk("\n\n\nchecking second level cache cp0_config = %08lx\n",
	       config_register);
	if (config_register & CONF_SC) {	// second/third level cache available
		config_register = config_register & (1 << 12);
		write_32bit_cp0_register(CP0_CONFIG, config_register);
		printk
		    ("\n\n\nchecking second level cache cp0_config = %08lx\n",
		     config_register);
	}
#endif

}
Example #8
0
void default_exept_handle(unsigned int *sp, unsigned int arg)
{
//	printf("Exception %d\n", arg);
//	printf("CAUSE=%08x EPC=%08x\n", read_c0_cause(), read_c0_epc());
//	printf("SP= %08x\n", sp);
//	printf("AT= %08x  ra= %08x  fp= %08x  gp= %08x\n",sp[27],sp[0],sp[1],sp[2]);
//  printf("t9= %08x  t8= %08x  s7= %08x  S6= %08x\n",sp[3],sp[4],sp[5],sp[6]);
//  printf("s5= %08x  s4= %08x  s3= %08x  s2= %08x\n",sp[7],sp[8],sp[9],sp[10]);
//  printf("s1= %08x  s0= %08x  t7= %08x  t6= %08x\n",sp[11],sp[12],sp[13],sp[14]);
//  printf("t5= %08x  t4= %08x  t3= %08x  t2= %08x\n",sp[15],sp[16],sp[17],sp[18]);
//  printf("t1= %08x  t0= %08x  a3= %08x  a2= %08x\n",sp[19],sp[20],sp[21],sp[22]);
//  printf("a1= %08x  a0= %08x  v1= %08x  v0= %08x\n",sp[23],sp[24],sp[25], sp[26]);
//	printf("\n");
//  printf("c_except_handler: while(1)");
//  printf("\n");

//	while(1);

	__except_sp = sp;
	__except_arg = arg;
	__except_cause = read_c0_cause();
	__except_epc = read_c0_epc();

	write_32bit_cp0_register(CP0_EPC, _except_idle);
	__asm__ __volatile__("eret\n\t");
}
Example #9
0
static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask)
{
	unsigned long status = read_32bit_cp0_register(CP0_STATUS);
	status &= ~((clr_mask & 0xFF) << 8);
	status |=   (set_mask & 0xFF) << 8;
	write_32bit_cp0_register(CP0_STATUS, status);
}
Example #10
0
void vr4122_restart(char *command)
{
	change_cp0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL));
	change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
	flush_cache_all();
	write_32bit_cp0_register(CP0_WIRED, 0);
	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}
Example #11
0
__initfunc(void time_init(void))
{
	unsigned int epoch, year, mon, day, hour, min, sec;
	int i;

	/* The Linux interpretation of the CMOS clock register contents:
	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
	 * RTC registers show the second which has precisely just started.
	 * Let's hope other operating systems interpret the RTC the same way.
	 */
	/* read RTC exactly on falling edge of update flag */
	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
			break;
	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
			break;
	do { /* Isn't this overkill ? UIP above should guarantee consistency */
		sec = CMOS_READ(RTC_SECONDS);
		min = CMOS_READ(RTC_MINUTES);
		hour = CMOS_READ(RTC_HOURS);
		day = CMOS_READ(RTC_DAY_OF_MONTH);
		mon = CMOS_READ(RTC_MONTH);
		year = CMOS_READ(RTC_YEAR);
	} while (sec != CMOS_READ(RTC_SECONDS));
	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
	  {
	    BCD_TO_BIN(sec);
	    BCD_TO_BIN(min);
	    BCD_TO_BIN(hour);
	    BCD_TO_BIN(day);
	    BCD_TO_BIN(mon);
	    BCD_TO_BIN(year);
	  }

	/* Attempt to guess the epoch.  This is the same heuristic as in rtc.c so
	   no stupid things will happen to timekeeping.  Who knows, maybe Ultrix
  	   also uses 1952 as epoch ...  */
	if (year > 10 && year < 44) {
		epoch = 1980;
	} else if (year < 96) {
		epoch = 1952;
	}
	year += epoch;

	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
	xtime.tv_usec = 0;

	init_cycle_counter();

	if (cyclecounter_available) {
		write_32bit_cp0_register(CP0_COUNT, 0);
		do_gettimeoffset = do_fast_gettimeoffset;
		irq0.handler = r4k_timer_interrupt;
	}

	board_time_init(&irq0);
}
Example #12
0
inline unsigned int
clear_cp0_status(unsigned int clear)
{
    unsigned int res;

    res = read_32bit_cp0_register(CP0_STATUS);
    res &= ~clear;
    write_32bit_cp0_register(CP0_STATUS, res);
}
Example #13
0
static void disable_rt2880_irq(unsigned int irq)
{
	unsigned long int_status;
	int_status = read_32bit_cp0_register(CP0_STATUS);

	if ( irq == 3)
		int_status = int_status & ~(CAUSEF_IP5);	
	write_32bit_cp0_register(CP0_STATUS, int_status);
}
Example #14
0
int start_secondary(void *unused)
{
	prom_init_secondary();
	write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23);
	current_pgd[smp_processor_id()] = init_mm.pgd;
	printk("Slave cpu booted successfully\n");
	atomic_inc(&cpus_booted);
	cpu_idle();
	return 0;
}
Example #15
0
/*
 * Get the FPU Implementation/Revision.
 */
static inline unsigned long cpu_get_fpu_id(void)
{
	unsigned long tmp, fpu_id;

	tmp = read_32bit_cp0_register(CP0_STATUS);
	__enable_fpu();
	fpu_id = read_32bit_cp1_register(CP1_REVISION);
	write_32bit_cp0_register(CP0_STATUS, tmp);
	return fpu_id;
}
Example #16
0
void c_except_handler(unsigned int *sp, unsigned int except_num)
{
    if(g_pExcept_info[except_num].except_handle == 0)
        default_exept_handle(sp, except_num);

    g_pExcept_info[except_num].except_handle((unsigned int)sp);

	write_32bit_cp0_register(CP0_EPC, g_pExcept_info[except_num].ra);
	__asm__ __volatile__("eret\n\t");
}
Example #17
0
void  setup_arch(void)
{
	unsigned long s;
        s = read_32bit_cp0_register(CP0_STATUS);
        s |= ST0_BEV;
        s ^= ST0_BEV;
        //s |= IE_IRQ0 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4  | IE_IRQ5;	//wei del
        s |= IE_IRQ0 | IE_IRQ1|IE_IRQ2 | IE_IRQ3 | IE_IRQ4  | IE_IRQ5; //wei add, david teach for use timer IRQ 3
	write_32bit_cp0_register(CP0_STATUS, s);        
	return ;
}
Example #18
0
void au1000_restart(char *command)
{
	/* Set all integrated peripherals to disabled states */
	u32 prid = read_32bit_cp0_register(CP0_PRID);

	printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n");
	switch (prid & 0xFF000000)
	{
	case 0x00000000: /* Au1000 */
		outl(0x02, 0xb0000010); /* ac97_enable */
		outl(0x08, 0xb017fffc); /* usbh_enable - early errata */
		asm("sync");
		outl(0x00, 0xb017fffc); /* usbh_enable */
		outl(0x00, 0xb0200058); /* usbd_enable */
		outl(0x00, 0xb0300040); /* ir_enable */
		outl(0x00, 0xb0520000); /* macen0 */
		outl(0x00, 0xb0520004); /* macen1 */
		outl(0x00, 0xb1000008); /* i2s_enable  */
		outl(0x00, 0xb1100100); /* uart0_enable */
		outl(0x00, 0xb1200100); /* uart1_enable */
		outl(0x00, 0xb1300100); /* uart2_enable */
		outl(0x00, 0xb1400100); /* uart3_enable */
		outl(0x02, 0xb1600100); /* ssi0_enable */
		outl(0x02, 0xb1680100); /* ssi1_enable */
		outl(0x00, 0xb1900020); /* sys_freqctrl0 */
		outl(0x00, 0xb1900024); /* sys_freqctrl1 */
		outl(0x00, 0xb1900028); /* sys_clksrc */
		outl(0x00, 0xb1900100); /* sys_pininputen */
		break;
	case 0x01000000: /* Au1500 */
		outl(0x02, 0xb0000010); /* ac97_enable */
		outl(0x08, 0xb017fffc); /* usbh_enable - early errata */
		asm("sync");
		outl(0x00, 0xb017fffc); /* usbh_enable */
		outl(0x00, 0xb0200058); /* usbd_enable */
		outl(0x00, 0xb1520000); /* macen0 */
		outl(0x00, 0xb1520004); /* macen1 */
		outl(0x00, 0xb1100100); /* uart0_enable */
		outl(0x00, 0xb1400100); /* uart3_enable */
		outl(0x00, 0xb1900020); /* sys_freqctrl0 */
		outl(0x00, 0xb1900024); /* sys_freqctrl1 */
		outl(0x00, 0xb1900028); /* sys_clksrc */
		outl(0x00, 0xb1900100); /* sys_pininputen */

	default:
		break;
	}

	set_cp0_status((ST0_BEV | ST0_ERL));
	set_cp0_config(CONF_CM_UNCACHED);
	flush_cache_all();
	write_32bit_cp0_register(CP0_WIRED, 0);
	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}
Example #19
0
static void r49_flush_cache_range_d16i32(struct mm_struct *mm,
        unsigned long start,
        unsigned long end)
{
    if (mm->context != 0) {
        unsigned long flags, config;

#ifdef DEBUG_CACHE
        printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end);
#endif
        __save_and_cli(flags);
        blast_dcache16_wayLSB();
        /* disable icache (set ICE#) */
        config = read_32bit_cp0_register(CP0_CONFIG);
        write_32bit_cp0_register(CP0_CONFIG, config|TX49_CONF_IC);
        blast_icache32_wayLSB();
        write_32bit_cp0_register(CP0_CONFIG, config);
        __restore_flags(flags);
    }
}
Example #20
0
void __init mips_timer_setup(struct irqaction *irq)
{
	/* we are using the cpu counter for timer interrupts */
	irq->handler = no_action;     /* we use our own handler */
	setup_irq(MIPS_CPU_TIMER_IRQ, irq);

        /* to generate the first timer interrupt */
	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
	write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
	set_cp0_status(ALLINTS);
}
Example #21
0
void ps2_be_board_handler(struct pt_regs *regs)
{
	u_int sr, paddr;

	sr = read_32bit_cp0_register(CP0_STATUS);
	paddr = read_32bit_cp0_register($23);			/* BadPAddr */
	force_sig(SIGBUS, current);
	show_regs(regs);
	printk("paddr : %08x\n", paddr);
	write_32bit_cp0_register(CP0_STATUS, sr & ~(1 << 12));  /* clear BM */
}
Example #22
0
File: time.c Project: nhanh0/hah
void __init time_init(void)
{
        unsigned int est_freq;

	printk("calculating r4koff... ");
	r4k_offset = cal_r4koff();
	printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset);

	//est_freq = 2*r4k_offset*HZ;	
	est_freq = r4k_offset*HZ;	
	est_freq += 5000;    /* round */
	est_freq -= est_freq%10000;
	printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, 
	       (est_freq%1000000)*100/1000000);
	set_au1000_speed(est_freq);
	set_au1000_lcd_clock(); // program the LCD clock
	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);

	write_32bit_cp0_register(CP0_COMPARE, r4k_cur);

	/* no RTC on the pb1000 */
	xtime.tv_sec = 0;
	xtime.tv_usec = 0;

#ifdef CONFIG_PM
	/*
	 * setup counter 0, since it keeps ticking after a
	 * 'wait' instruction has been executed. The CP0 timer and
	 * counter 1 do NOT continue running after 'wait'
	 *
	 * It's too early to call request_irq() here, so we handle
	 * counter 0 interrupt as a special irq and it doesn't show
	 * up under /proc/interrupts.
	 */
	while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
	writel(0, SYS_TOYWRITE);
	while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);

	writel(readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK);
	writel(~0, SYS_WAKESRC);
	au_sync();
	while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);

	/* setup match20 to interrupt once every 10ms */
	last_pc0 = last_match20 = readl(SYS_TOYREAD);
	writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
	au_sync();
	while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
	startup_match20_interrupt();
#endif

	//set_cp0_status(ALLINTS);
	au_sync();
}
Example #23
0
inline unsigned int
change_cp0_status(unsigned int change, unsigned int newvalue)
{
    unsigned int res;

    res = read_32bit_cp0_register(CP0_STATUS);
    res &= ~change;
    res |= (newvalue & change);
    write_32bit_cp0_register(CP0_STATUS, res);

    return res;
}
Example #24
0
asmlinkage void init_arch(int argc, char **argv, char **envp, int *prom_vec)
{
	unsigned int s;
	/* Disable coprocessors */
	s = read_32bit_cp0_register(CP0_STATUS);
	s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX);
	s |= ST0_CU0;
	write_32bit_cp0_register(CP0_STATUS, s);
	s = read_32bit_cp0_register(CP0_STATUS);

        start_kernel();
}
Example #25
0
void __init it8172_timer_setup(struct irqaction *irq)
{
	puts("timer_setup\n");
	put32(NR_IRQS);
	puts("");
        /* we are using the cpu counter for timer interrupts */
	setup_irq(MIPS_CPU_TIMER_IRQ, irq);

        /* to generate the first timer interrupt */
	r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset);
	write_32bit_cp0_register(CP0_COMPARE, r4k_cur);
	set_cp0_status(ALLINTS);
}
Example #26
0
void momenco_ocelot_restart(char *command)
{
	*(volatile char *) 0xbc000000 = 0x0f;

	/*
	 * Ouch, we're still alive ... This time we take the silver bullet ...
	 * ... and find that we leave the hardware in a state in which the
	 * kernel in the flush locks up somewhen during of after the PCI
	 * detection stuff.
	 */
	clear_cp0_status(ST0_BEV | ST0_ERL);
	change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED);
	flush_cache_all();
	write_32bit_cp0_register(CP0_WIRED, 0);
	__asm__ __volatile__("jr\t%0"::"r"(0xbfc00000));
}
Example #27
0
void
dump_tlb(int first, int last)
{
	int	i;
	unsigned int asid;
	unsigned long entryhi, entrylo0;

	asid = get_entryhi() & 0xfc0;

	for(i=first;i<=last;i++)
	{
		write_32bit_cp0_register(CP0_INDEX, i<<8);
		__asm__ __volatile__(
			".set\tnoreorder\n\t"
			"tlbr\n\t"
			"nop\n\t"
			".set\treorder");
		entryhi  = read_32bit_cp0_register(CP0_ENTRYHI);
		entrylo0 = read_32bit_cp0_register(CP0_ENTRYLO0);

		/* Unused entries have a virtual address of KSEG0.  */
		if ((entryhi & 0xffffe000) != 0x80000000
		    && (entryhi & 0xfc0) == asid) {
			/*
			 * Only print entries in use
			 */
			printk("Index: %2d ", i);

			printk("va=%08lx asid=%08lx"
			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
			       (entryhi & 0xffffe000),
			       entryhi & 0xfc0,
			       entrylo0 & PAGE_MASK,
			       (entrylo0 & (1 << 11)) ? 1 : 0,
			       (entrylo0 & (1 << 10)) ? 1 : 0,
			       (entrylo0 & (1 << 9)) ? 1 : 0,
			       (entrylo0 & (1 << 8)) ? 1 : 0);
		}
	}
	printk("\n");

	set_entryhi(asid);
}
Example #28
0
File: time.c Project: nhanh0/hah
/* 
 * Figure out the r4k offset, the amount to increment the compare
 * register for each time tick. 
 * Use the Programmable Counter 1 to do this.
 */
unsigned long cal_r4koff(void)
{
	unsigned long count;
	unsigned long cpu_speed;
	unsigned long start, end;
	unsigned long counter;
	int trim_divide = 16;
	unsigned long flags;

	save_and_cli(flags);

	counter = inl(SYS_COUNTER_CNTRL);
	outl(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);

	while (inl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
	outl(trim_divide-1, SYS_RTCTRIM); /* RTC now ticks at 32.768/16 kHz */
	while (inl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);

	while (inl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
	outl (0, SYS_TOYWRITE);
	while (inl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);

	start = inl(SYS_RTCREAD);
	start += 2;
	/* wait for the beginning of a new tick */
	while (inl(SYS_RTCREAD) < start);

	/* Start r4k counter. */
	write_32bit_cp0_register(CP0_COUNT, 0);
	end = start + (32768 / trim_divide)/2; /* wait 0.5 seconds */

	while (end > inl(SYS_RTCREAD));

	count = read_32bit_cp0_register(CP0_COUNT);
	cpu_speed = count * 2;
	mips_counter_frequency = count;
	set_au1000_uart_baud_base(((cpu_speed) / 4) / 16);
	restore_flags(flags);
	return (cpu_speed / HZ);
}
Example #29
0
void __init arch_init_irq(void)
{
	int i;

	/*
	 * Mask out all interrupt by writing "1" to all bit position in
	 * the interrupt reset reg.
	 */
#if 1
	int mips_cp0_cause, mips_cp0_status;
        mips_cp0_cause = read_32bit_cp0_register(CP0_CAUSE);
        mips_cp0_status = read_32bit_cp0_register(CP0_STATUS);
        printk("cause = %x, status = %x\n", mips_cp0_cause, mips_cp0_status);
        mips_cp0_status= mips_cp0_status& ~(CAUSEF_IP0|CAUSEF_IP1|CAUSEF_IP2|CAUSEF_IP3|CAUSEF_IP4|CAUSEF_IP5|CAUSEF_IP6|CAUSEF_IP7);
        write_32bit_cp0_register(CP0_STATUS, mips_cp0_status);
#endif
	
	memset(irq_desc, 0, sizeof(irq_desc));

	for (i = 0; i <= SURFBOARDINT_END; i++) {
		set_irq_chip(i, &surfboard_irq_type);
	}

	/* Enable global interrupt bit */
//	surfboard_hw0_icregs->intDisable = 0xffffffff;
	surfboard_hw0_icregs->intEnable = M_SURFBOARD_GLOBAL_INT;

#ifdef CONFIG_RALINK_GPIO
	ralink_gpio_init_irq();
#endif

#ifdef CONFIG_KGDB
	if (remote_debug) {
		set_debug_traps();
		breakpoint();
	}
#endif
}
Example #30
0
static inline void 
r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
	unsigned int count;

	/*
	 * The cycle counter is only 32 bit which is good for about
	 * a minute at current count rates of upto 150MHz or so.
	 */
	count = read_32bit_cp0_register(CP0_COUNT);
	timerhi += (count < timerlo);	/* Wrap around */
	timerlo = count;

#ifdef CONFIG_SGI_IP22
	/* Since we don't get anything but r4k timer interrupts, we need to
	 * set this up so that we'll get one next time. Fortunately since we
	 * have timerhi/timerlo, we don't care so much if we miss one. So
	 * we need only ask for the next in r4k_interval counts. On other
	 * archs we have a real timer, so we don't want this.
	 */
	write_32bit_cp0_register (CP0_COMPARE, 
				  (unsigned long) (count + r4k_interval));
        kstat.irqs[0][irq]++;
#endif

	timer_interrupt(irq, dev_id, regs);

	if (!jiffies)
	{
		/*
		 * If jiffies has overflowed in this timer_interrupt we must
		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
		 * quotient calc still valid. -arca
		 */
		timerhi = timerlo = 0;
	}
}