diff options
Diffstat (limited to 'tools/updater/utils.c')
| -rw-r--r-- | tools/updater/utils.c | 148 | 
1 files changed, 148 insertions, 0 deletions
| diff --git a/tools/updater/utils.c b/tools/updater/utils.c new file mode 100644 index 000000000..e230e19f9 --- /dev/null +++ b/tools/updater/utils.c @@ -0,0 +1,148 @@ +#include <common.h> +#include <asm/processor.h> +#include <memio.h> +#include <linux/ctype.h> + +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) +{ +	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; + +    msr = get_msr(); +    set_msr (msr & ~MSR_EE); +    return ((msr & MSR_EE) != 0); +} + +u8 in8(u32 port) +{ +    return in_byte(port); +} + +void out8(u32 port, u8 val) +{ +    out_byte(port, val); +} + +unsigned long in32(u32 port) +{ +    return in_long(port); +} + +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ +        unsigned long result = 0,value; + +        if (*cp == '0') { +                cp++; +                if ((*cp == 'x') && isxdigit(cp[1])) { +                        base = 16; +                        cp++; +                } +                if (!base) { +                        base = 8; +                } +        } +        if (!base) { +                base = 10; +        } +        while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) +            ? toupper(*cp) : *cp)-'A'+10) < base) { +                result = result*base + value; +                cp++; +        } +        if (endp) +                *endp = (char *)cp; +        return result; +} + +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ +        if(*cp=='-') +                return -simple_strtoul(cp+1,endp,base); +        return simple_strtoul(cp,endp,base); +} + +static inline void +soft_restart(unsigned long addr) +{ +        /* SRR0 has system reset vector, SRR1 has default MSR value */ +        /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ + +        __asm__ __volatile__ ("mtspr    26, %0"         :: "r" (addr)); +        __asm__ __volatile__ ("li       4, (1 << 6)"    ::: "r4"); +        __asm__ __volatile__ ("mtspr    27, 4"); +        __asm__ __volatile__ ("rfi"); + +        while(1);       /* not reached */ +} + +void +do_reset (void) +{ +        ulong addr; +        /* flush and disable I/D cache */ +        __asm__ __volatile__ ("mfspr    3, 1008"        ::: "r3"); +        __asm__ __volatile__ ("ori      5, 5, 0xcc00"   ::: "r5"); +        __asm__ __volatile__ ("ori      4, 3, 0xc00"    ::: "r4"); +        __asm__ __volatile__ ("andc     5, 3, 5"        ::: "r5"); +        __asm__ __volatile__ ("sync"); +        __asm__ __volatile__ ("mtspr    1008, 4"); +        __asm__ __volatile__ ("isync"); +        __asm__ __volatile__ ("sync"); +        __asm__ __volatile__ ("mtspr    1008, 5"); +        __asm__ __volatile__ ("isync"); +        __asm__ __volatile__ ("sync"); + +#ifdef CFG_RESET_ADDRESS +        addr = CFG_RESET_ADDRESS; +#else +        /* +         * note: when CFG_MONITOR_BASE points to a RAM address, +         * CFG_MONITOR_BASE - sizeof (ulong) is usually a valid +         * address. Better pick an address known to be invalid on your +         * system and assign it to CFG_RESET_ADDRESS. +         */ +        addr = CFG_MONITOR_BASE - sizeof (ulong); +#endif +        soft_restart(addr); +        while(1);       /* not reached */ +} |