Update of /cvsroot/linux-vax/kernel-2.4/arch/mips/philips/nino In directory usw-pr-cvs1:/tmp/cvs-serv20728/mips/philips/nino Added Files: Makefile int-handler.S irq.c kgdb.c power.c prom.c reset.c rtc.c setup.c time.c Log Message: synch 2.4.15 commit 39 --- NEW FILE --- # # Makefile for the Philips Nino specific parts of the kernel # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # .S.s: $(CPP) $(AFLAGS) $< -o $@ .S.o: $(CC) $(AFLAGS) -c $< -o $@ O_TARGET := nino.o all: nino.o obj-y := int-handler.o setup.o irq.o time.o reset.o rtc.o prom.o power.o int-handler.o: int-handler.S obj-$(CONFIG_REMOTE_DEBUG) += kgdb.o obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o ramdisk.o: $(MAKE) -C ramdisk mv ramdisk/ramdisk.o ramdisk.o clean: rm -f *.o include $(TOPDIR)/Rules.make --- NEW FILE --- /* * linux/arch/mips/philips/nino/int-handler.S * * Copyright (C) 1999 Harald Koerfgen * Copyright (C) 2000 Jim Pick (ji...@ji...) * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Interrupt handler for Philips Nino. */ #include <asm/asm.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> #include <asm/tx3912.h> .data .globl HighPriVect HighPriVect: .word spurious # Reserved .word io_posnegint0 # IOPOSINT(0) or IONEGINT(0) .word spurious # CHIDMACNTINT .word spurious # TELDMACNTINT .word spurious # SNDDMACNTINT .word spurious # Reserved .word io_negint56 # IONEGINT(6) or IONEGINT(5) .word spurious # Reserved .word io_posint56 # IOPOSINT(6) or IOPOSINT(5) .word spurious # Reserved .word spurious # UARTBRXINT .word uarta_rx # UARTARXINT .word spurious # Reserved .word periodic_timer # PERINT .word spurious # ALARMINT .word spurious # POSPWROKINT or NEGPWROKINT /* * Here is the entry point to handle all interrupts. */ .text .set noreorder .align 5 NESTED(nino_handle_int, PT_SIZE, ra) .set noat SAVE_ALL CLI .set at /* * Get pending Interrupts */ mfc0 t0, CP0_CAUSE # Get pending interrupts andi t2, t0, IE_IRQ4 # IRQ4 (high priority) bne t2, IE_IRQ4, low_priority nop /* * Ok, we've got a high priority interrupt (a.k.a. an external interrupt). * Read Interrupt Status Register 6 to get vector. */ high_priority: lui t0, %hi(IntStatus6) lw t1, %lo(IntStatus6)(t0) andi t1, INT6_INTVECT la t2, HighPriVect addu t1, t1, t2 lw t2, 0(t1) jr t2 nop /* * Ok, we've got one of over a hundred other interupts. */ low_priority: lui t0, %hi(IntStatus1) lw t1, %lo(IntStatus1)(t0) j handle_it li a0, 20 /* * We don't currently handle spurious interrupts. */ spurious: j spurious_interrupt nop /* * We have the IRQ number, dispatch to the real handler. */ handle_it: jal do_IRQ move a1,sp j ret_from_irq nop /************************************ * High priority interrupt mappings * ************************************/ /* * Periodic timer - IRQ 0 */ periodic_timer: j handle_it li a0, 0 /* * UARTA RX - IRQ 3 */ uarta_rx: j handle_it li a0, 3 /* * GPIO Pin 0 transition - IRQ 10 */ io_posnegint0: j handle_it li a0, 10 /* * GPIO Pin 5 or 6 transition (0-to-1) - IRQ 11 */ io_posint56: j handle_it li a0, 11 /* * GPIO Pin 5 or 6 transition (1-to-0) - IRQ 12 */ io_negint56: j handle_it li a0, 12 END(nino_handle_int) --- NEW FILE --- /* * linux/arch/mips/philips/nino/irq.c * * Copyright (C) 1992 Linus Torvalds * Copyright (C) 1999 Harald Koerfgen * Copyright (C) 2000 Pavel Machek (pa...@su...) * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Generic interrupt handler for Philips Nino. */ #include <linux/errno.h> #include <linux/init.h> #include <linux/kernel_stat.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/types.h> #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/timex.h> #include <linux/slab.h> #include <linux/random.h> #include <asm/bitops.h> #include <asm/bootinfo.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/mipsregs.h> #include <asm/system.h> #include <asm/tx3912.h> unsigned long spurious_count = 0; irq_cpustat_t irq_stat [NR_CPUS]; static inline void mask_irq(unsigned int irq_nr) { switch (irq_nr) { case 0: /* Periodic Timer Interrupt */ IntClear5 = INT5_PERIODICINT; IntClear6 = INT6_PERIODICINT; IntEnable6 &= ~INT6_PERIODICINT; break; case 3: /* Serial port receive interrupt */ break; case 2: /* Serial port transmit interrupt */ break; default: printk( "Attempt to mask unknown IRQ %d?\n", irq_nr ); } } static inline void unmask_irq(unsigned int irq_nr) { switch (irq_nr) { case 0: IntEnable6 |= INT6_PERIODICINT; break; case 3: /* Serial port receive interrupt */ break; case 2: /* Serial port transmit interrupt */ break; default: printk( "Attempt to unmask unknown IRQ %d?\n", irq_nr ); } } void disable_irq(unsigned int irq_nr) { unsigned long flags; save_and_cli(flags); mask_irq(irq_nr); restore_flags(flags); } void enable_irq(unsigned int irq_nr) { unsigned long flags; save_and_cli(flags); unmask_irq(irq_nr); restore_flags(flags); } /* * Pointers to the low-level handlers: first the general ones, then the * fast ones, then the bad ones. */ extern void interrupt(void); static struct irqaction *irq_action[NR_IRQS] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; int get_irq_list(char *buf) { int i, len = 0; struct irqaction *action; for (i = 0; i < NR_IRQS; i++) { action = irq_action[i]; if (!action) continue; len += sprintf(buf + len, "%2d: %8d %c %s", i, kstat.irqs[0][i], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); for (action = action->next; action; action = action->next) { len += sprintf(buf + len, ",%s %s", (action->flags & SA_INTERRUPT) ? " +" : "", action->name); } len += sprintf(buf + len, "\n"); } return len; } atomic_t __mips_bh_counter; /* * do_IRQ handles IRQ's that have been installed without the * SA_INTERRUPT flag: it uses the full signal-handling return * and runs with other interrupts enabled. All relatively slow * IRQ's should use this format: notably the keyboard/timer * routines. */ asmlinkage void do_IRQ(int irq, struct pt_regs *regs) { struct irqaction *action; int do_random, cpu; if (irq == 20) { if (IntStatus2 & 0xfffff00) { if (IntStatus2 & 0x0f000000) return do_IRQ(2, regs); } } cpu = smp_processor_id(); irq_enter(cpu, irq); kstat.irqs[cpu][irq]++; if (irq == 20) { printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", IntStatus1, IntStatus2, IntStatus3, IntStatus4, IntStatus5 ); printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", IntEnable1, IntEnable2, IntEnable3, IntEnable4, IntEnable5 ); } mask_irq(irq); action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) __sti(); do_random = 0; do { do_random |= action->flags; action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (do_random & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); unmask_irq(irq); __cli(); } else { IntClear1 = ~0; IntClear3 = ~0; IntClear4 = ~0; IntClear5 = ~0; unmask_irq(irq); } irq_exit(cpu, irq); /* unmasking and bottom half handling is done magically for us. */ } /* * Idea is to put all interrupts * in a single table and differenciate them just by number. */ int setup_nino_irq(int irq, struct irqaction *new) { int shared = 0; struct irqaction *old, **p; unsigned long flags; p = irq_action + irq; if ((old = *p) != NULL) { /* Can't share interrupts unless both agree to */ if (!(old->flags & new->flags & SA_SHIRQ)) return -EBUSY; /* Can't share interrupts unless both are same type */ if ((old->flags ^ new->flags) & SA_INTERRUPT) return -EBUSY; /* add new interrupt at end of irq queue */ do { p = &old->next; old = *p; } while (old); shared = 1; } if (new->flags & SA_SAMPLE_RANDOM) rand_initialize_irq(irq); save_and_cli(flags); *p = new; if (!shared) { unmask_irq(irq); } restore_flags(flags); return 0; } int request_irq(unsigned int irq, void (*handler) (int, void *, struct pt_regs *), unsigned long irqflags, const char *devname, void *dev_id) { int retval; struct irqaction *action; if (irq >= NR_IRQS) return -EINVAL; if (!handler) return -EINVAL; action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); if (!action) return -ENOMEM; action->handler = handler; action->flags = irqflags; action->mask = 0; action->name = devname; action->next = NULL; action->dev_id = dev_id; retval = setup_nino_irq(irq, action); if (retval) kfree(action); return retval; } void free_irq(unsigned int irq, void *dev_id) { struct irqaction *action, **p; unsigned long flags; if (irq >= NR_IRQS) { printk(KERN_CRIT __FUNCTION__ ": trying to free IRQ%d\n", irq); return; } for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { if (action->dev_id != dev_id) continue; /* Found it - now free it */ save_and_cli(flags); *p = action->next; if (!irq[irq_action]) mask_irq(irq); restore_flags(flags); kfree(action); return; } printk(KERN_CRIT __FUNCTION__ ": trying to free free IRQ%d\n", irq); } unsigned long probe_irq_on(void) { /* TODO */ return 0; } int probe_irq_off(unsigned long irqs) { /* TODO */ return 0; } void __init init_IRQ(void) { irq_setup(); } --- NEW FILE --- /* * linux/arch/mips/philips/nino/kgdb.c * * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Kernel debugging on the Philips Nino. */ #include <asm/system.h> #include <asm/tx3912.h> static int remoteDebugInitialized = 0; void debugInit(void) { /* * If low-level debugging (before GDB or console operational) is * configured, then we do not need to re-initialize the UART. */ #ifndef CONFIG_DEBUG_LL earlyInitUartPR31700(); #endif } char getDebugChar(void) { char buf; unsigned long int2, flags; if (!remoteDebugInitialized) { debugInit(); remoteDebugInitialized = 1; } save_and_cli(flags); int2 = IntEnable2; IntEnable2 = 0; while(!(UartA_Ctrl1 & UART_RX_HOLD_FULL)); buf = UartA_Data; IntEnable2 = int2; restore_flags(flags); return buf; } int putDebugChar(char c) { int i; unsigned long int2; if (!remoteDebugInitialized) { debugInit(); remoteDebugInitialized = 1; } int2 = IntEnable2; IntEnable2 &= ~(INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY); for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < 10000); i++); IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; UartA_Data = c; for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < 10000); i++); IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; IntEnable2 = int2; return 1; } --- NEW FILE --- /* * linux/arch/mips/philips/nino/power.c * * Copyright (C) 2000 Jim Pick <ji...@ji...> * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Power management routines on the Philips Nino. */ #include <asm/tx3912.h> void nino_wait(void) { /* We stop the CPU to conserve power */ PowerControl |= PWR_STOPCPU; /* * We wait until an interrupt happens... */ /* We resume here */ PowerControl &= ~PWR_STOPCPU; /* Give ourselves a little delay */ __asm__ __volatile__( "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t"); } --- NEW FILE --- /* * linux/arch/mips/philips/nino/prom.c * * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Early initialization code for the Philips Nino. */ #include <linux/config.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> #include <asm/bootinfo.h> #include <asm/addrspace.h> #include <asm/page.h> char arcs_cmdline[COMMAND_LINE_SIZE]; #ifdef CONFIG_FB_TX3912 extern u_long tx3912fb_paddr; extern u_long tx3912fb_vaddr; extern u_long tx3912fb_size; #endif /* Do basic initialization */ void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) { u_long free_end, mem_size; u_int i; /* * collect args and prepare cmd_line */ for (i = 1; i < argc; i++) { strcat(arcs_cmdline, argv[i]); if (i < (argc - 1)) strcat(arcs_cmdline, " "); } mips_machgroup = MACH_GROUP_PHILIPS; mips_machtype = MACH_PHILIPS_NINO; #ifdef CONFIG_NINO_4MB mem_size = 4 << 20; #elif CONFIG_NINO_8MB mem_size = 8 << 20; #elif CONFIG_NINO_16MB mem_size = 16 << 20; #endif #ifdef CONFIG_FB_TX3912 /* * The LCD controller requires that the framebuffer * start address fall within a 1MB segment and is * aligned on a 16 byte boundary. The way to assure * this is to place the framebuffer at the end of * memory and mark it as reserved. */ free_end = (mem_size - tx3912fb_size) & PAGE_MASK; add_memory_region(0, free_end, BOOT_MEM_RAM); add_memory_region(free_end, (mem_size - free_end), BOOT_MEM_RESERVED); /* * Calculate physical and virtual addresses for * the beginning of the framebuffer. */ tx3912fb_paddr = PHYSADDR(free_end); tx3912fb_vaddr = KSEG1ADDR(free_end); #else add_memory_region(0, mem_size, BOOT_MEM_RAM); #endif } void __init prom_free_prom_memory (void) { } --- NEW FILE --- /* * linux/arch/mips/philips/nino/reset.c * * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Generic restart, halt and power off functions for Philips Nino. */ #include <linux/init.h> #include <asm/reboot.h> void (*reset_vector)(void) = (void (*)(void)) 0xBFC00000; void nino_machine_restart(char *command) { reset_vector(); } void nino_machine_halt(void) { reset_vector(); } void nino_machine_power_off(void) { reset_vector(); } void __init setup_nino_reset_vectors(void) { _machine_restart = nino_machine_restart; _machine_halt = nino_machine_halt; _machine_power_off = nino_machine_power_off; } --- NEW FILE --- /* * linux/arch/mips/philips/nino/rtc.c * * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Functions to access RTC on the Philips Nino. */ #include <linux/spinlock.h> #include <linux/mc146818rtc.h> static unsigned char nino_rtc_read_data(unsigned long addr) { return 0; } static void nino_rtc_write_data(unsigned char data, unsigned long addr) { } static int nino_rtc_bcd_mode(void) { return 0; } struct rtc_ops nino_rtc_ops = { &nino_rtc_read_data, &nino_rtc_write_data, &nino_rtc_bcd_mode }; --- NEW FILE --- /* * linux/arch/mips/philips/nino/setup.c * * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Interrupt and exception initialization for Philips Nino. */ #include <linux/console.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/mc146818rtc.h> #include <linux/sched.h> #include <asm/addrspace.h> #include <asm/gdb-stub.h> #include <asm/irq.h> #include <asm/wbflush.h> #include <asm/tx3912.h> extern struct rtc_ops nino_rtc_ops; extern void nino_wait(void); extern void setup_nino_reset_vectors(void); extern asmlinkage void nino_handle_int(void); extern int setup_nino_irq(int, struct irqaction *); void (*board_time_init) (struct irqaction * irq); #ifdef CONFIG_REMOTE_DEBUG extern void set_debug_traps(void); extern void breakpoint(void); static int remote_debug = 0; #endif static void __init nino_irq_setup(void) { unsigned int tmp; /* Turn all interrupts off */ IntEnable1 = 0; IntEnable2 = 0; IntEnable3 = 0; IntEnable4 = 0; IntEnable5 = 0; IntEnable6 = 0; /* Clear all interrupts */ IntClear1 = 0xffffffff; IntClear2 = 0xffffffff; IntClear3 = 0xffffffff; IntClear4 = 0xffffffff; IntClear5 = 0xffffffff; IntClear6 = 0xffffffff; /* * Enable only the interrupts for the UART and negative * edge (1-to-0) triggered multi-function I/O pins. */ change_cp0_status(ST0_BEV, 0); tmp = read_32bit_cp0_register(CP0_STATUS); change_cp0_status(ST0_IM, tmp | IE_IRQ2 | IE_IRQ4); /* Register the global interrupt handler */ set_except_vector(0, nino_handle_int); #ifdef CONFIG_REMOTE_DEBUG if (remote_debug) { set_debug_traps(); breakpoint(); } #endif } static __init void nino_time_init(struct irqaction *irq) { unsigned int scratch = 0; /* * Enable periodic interrupts */ setup_nino_irq(0, irq); RTCperiodTimer = PER_TIMER_COUNT; RTCtimerControl = TIM_ENPERTIMER; IntEnable5 |= INT5_PERIODICINT; scratch = inl(TX3912_CLK_CTRL_BASE); scratch |= TX3912_CLK_CTRL_ENTIMERCLK; outl(scratch, TX3912_CLK_CTRL_BASE); /* Enable all interrupts */ IntEnable6 |= INT6_GLOBALEN | INT6_PERIODICINT; } void __init nino_setup(void) { irq_setup = nino_irq_setup; board_time_init = nino_time_init; /* Base address to use for PC type I/O accesses */ mips_io_port_base = KSEG1ADDR(0xB0C00000); setup_nino_reset_vectors(); /* Function called during process idle (cpu_idle) */ cpu_wait = nino_wait; #ifdef CONFIG_FB conswitchp = &dummy_con; #endif #ifdef CONFIG_REMOTE_DEBUG remote_debug = 1; #endif rtc_ops = &nino_rtc_ops; } --- NEW FILE --- /* * linux/arch/mips/philips/nino/time.c * * Copyright (C) 1999 Harald Koerfgen * Copyright (C) 2000 Pavel Machek (pa...@su...) * Copyright (C) 2001 Steven J. Hill (sj...@re...) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Time handling functinos for Philips Nino. */ #include <linux/errno.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/param.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/interrupt.h> #include <linux/timex.h> #include <linux/delay.h> #include <asm/tx3912.h> extern volatile unsigned long wall_jiffies; extern rwlock_t xtime_lock; static struct timeval xbase; #define USECS_PER_JIFFY (1000000/HZ) /* * Poll the Interrupt Status Registers */ #undef POLL_STATUS static unsigned long do_gettimeoffset(void) { /* * This is a kludge */ return 0; } static void inline readRTC(unsigned long *high, unsigned long *low) { /* read twice, and keep reading till we find two * the same pairs. This is needed in case the RTC * was updating its registers and we read a old * High but a new Low. */ do { *high = RTChigh & RTC_HIGHMASK; *low = RTClow; } while (*high != (RTChigh & RTC_HIGHMASK) || RTClow!=*low); } /* * This version of gettimeofday has near millisecond resolution. */ void do_gettimeofday(struct timeval *tv) { unsigned long flags; unsigned long high, low; read_lock_irqsave(&xtime_lock, flags); // 40 bit RTC, driven by 32khz source: // +-----------+-----------------------------------------+ // | HHHH.HHHH | LLLL.LLLL.LLLL.LLLL.LMMM.MMMM.MMMM.MMMM | // +-----------+-----------------------------------------+ readRTC(&high,&low); tv->tv_sec = (high << 17) | (low >> 15); tv->tv_usec = (low % 32768) * 1953 / 64; tv->tv_sec += xbase.tv_sec; tv->tv_usec += xbase.tv_usec; tv->tv_usec += do_gettimeoffset(); /* * xtime is atomically updated in timer_bh. lost_ticks is * nonzero if the timer bottom half hasnt executed yet. */ if (jiffies - wall_jiffies) tv->tv_usec += USECS_PER_JIFFY; read_unlock_irqrestore(&xtime_lock, flags); if (tv->tv_usec >= 1000000) { tv->tv_usec -= 1000000; tv->tv_sec++; } } void do_settimeofday(struct timeval *tv) { write_lock_irq(&xtime_lock); /* This is revolting. We need to set the xtime.tv_usec * correctly. However, the value in this location is * is value at the last tick. * Discover what correction gettimeofday * would have done, and then undo it! */ tv->tv_usec -= do_gettimeoffset(); if (tv->tv_usec < 0) { tv->tv_usec += 1000000; tv->tv_sec--; } /* reset RTC to 0 (real time is xbase + RTC) */ xbase = *tv; RTCtimerControl |= TIM_RTCCLEAR; RTCtimerControl &= ~TIM_RTCCLEAR; RTCalarmHigh = RTCalarmLow = ~0UL; xtime = *tv; time_state = TIME_BAD; time_maxerror = MAXPHASE; time_esterror = MAXPHASE; write_unlock_irq(&xtime_lock); } static int set_rtc_mmss(unsigned long nowtime) { int retval = 0; return retval; } /* last time the cmos clock got updated */ static long last_rtc_update = 0; /* * timer_interrupt() needs to keep up the real-time clock, * as well as call the "do_timer()" routine every clocktick */ int do_write = 1; static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { #ifdef POLL_STATUS static unsigned long old_IntStatus1 = 0; static unsigned long old_IntStatus3 = 0; static unsigned long old_IntStatus4 = 0; static unsigned long old_IntStatus5 = 0; static int counter = 0; int i; new_spircv = SPIData & 0xff; if ((old_spircv != new_spircv) && (new_spircv != 0xff)) { printk( "SPIData changed: %x\n", new_spircv ); } old_spircv = new_spircv; if (do_write) SPIData = 0; #endif if (!user_mode(regs)) { if (prof_buffer && current->pid) { extern int _stext; unsigned long pc = regs->cp0_epc; pc -= (unsigned long) &_stext; pc >>= prof_shift; /* * Dont ignore out-of-bounds pc values silently, * put them into the last histogram slot, so if * present, they will show up as a sharp peak. */ if (pc > prof_len - 1) pc = prof_len - 1; atomic_inc((atomic_t *) & prof_buffer[pc]); } } /* * aaaand... action! */ do_timer(regs); /* * If we have an externally syncronized Linux clock, then update * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be * called as close as possible to 500 ms before the new second starts. */ if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && xtime.tv_usec > 500000 - (tick >> 1) && xtime.tv_usec < 500000 + (tick >> 1)) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ } } static struct irqaction irq0 = {timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; void (*board_time_init) (struct irqaction * irq); int __init time_init(void) { struct timeval starttime; starttime.tv_sec = mktime(2000, 1, 1, 0, 0, 0); starttime.tv_usec = 0; do_settimeofday(&starttime); board_time_init(&irq0); return 0; } |