diff options
Diffstat (limited to 'roms/u-boot/arch/powerpc/lib/interrupts.c')
-rw-r--r-- | roms/u-boot/arch/powerpc/lib/interrupts.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/roms/u-boot/arch/powerpc/lib/interrupts.c b/roms/u-boot/arch/powerpc/lib/interrupts.c new file mode 100644 index 00000000..f7cf9157 --- /dev/null +++ b/roms/u-boot/arch/powerpc/lib/interrupts.c @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2003 + * Gleb Natapov <gnatapov@mrv.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/processor.h> +#include <watchdog.h> +#ifdef CONFIG_STATUS_LED +#include <status_led.h> +#endif + +#ifdef CONFIG_SHOW_ACTIVITY +void board_show_activity (ulong) __attribute__((weak, alias("__board_show_activity"))); + +void __board_show_activity (ulong dummy) +{ + return; +} +#endif /* CONFIG_SHOW_ACTIVITY */ + +#ifndef CONFIG_SYS_WATCHDOG_FREQ +#define CONFIG_SYS_WATCHDOG_FREQ (CONFIG_SYS_HZ / 2) +#endif + +extern int interrupt_init_cpu (unsigned *); +extern void timer_interrupt_cpu (struct pt_regs *); + +static unsigned decrementer_count; /* count value for 1e6/HZ microseconds */ + +static __inline__ unsigned long get_msr (void) +{ + unsigned long msr; + + asm volatile ("mfmsr %0":"=r" (msr):); + + return msr; +} + +static __inline__ void set_msr (unsigned long msr) +{ + asm volatile ("mtmsr %0"::"r" (msr)); +} + +static __inline__ unsigned long get_dec (void) +{ + unsigned long val; + + asm volatile ("mfdec %0":"=r" (val):); + + return val; +} + + +static __inline__ void set_dec (unsigned long val) +{ + if (val) + asm volatile ("mtdec %0"::"r" (val)); +} + + +void enable_interrupts (void) +{ + set_msr (get_msr () | MSR_EE); +} + +/* returns flag if MSR_EE was set before */ +int disable_interrupts (void) +{ + ulong msr = get_msr (); + + set_msr (msr & ~MSR_EE); + return ((msr & MSR_EE) != 0); +} + +int interrupt_init (void) +{ + int ret; + + /* call cpu specific function from $(CPU)/interrupts.c */ + ret = interrupt_init_cpu (&decrementer_count); + + if (ret) + return ret; + + set_dec (decrementer_count); + + set_msr (get_msr () | MSR_EE); + + return (0); +} + +static volatile ulong timestamp = 0; + +void timer_interrupt (struct pt_regs *regs) +{ + /* call cpu specific function from $(CPU)/interrupts.c */ + timer_interrupt_cpu (regs); + + /* Restore Decrementer Count */ + set_dec (decrementer_count); + + timestamp++; + +#if defined(CONFIG_WATCHDOG) || defined (CONFIG_HW_WATCHDOG) + if ((timestamp % (CONFIG_SYS_WATCHDOG_FREQ)) == 0) + WATCHDOG_RESET (); +#endif /* CONFIG_WATCHDOG || CONFIG_HW_WATCHDOG */ + +#ifdef CONFIG_STATUS_LED + status_led_tick (timestamp); +#endif /* CONFIG_STATUS_LED */ + +#ifdef CONFIG_SHOW_ACTIVITY + board_show_activity (timestamp); +#endif /* CONFIG_SHOW_ACTIVITY */ +} + +ulong get_timer (ulong base) +{ + return (timestamp - base); +} |