diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
commit | 545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch) | |
tree | e9ce4bc598d06374bda906f18365984bf22a526a /arch/sparc64/kernel/time.c | |
parent | 4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (diff) |
Merge with Linux 2.1.55. More bugfixes and goodies from my private
CVS archive.
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r-- | arch/sparc64/kernel/time.c | 162 |
1 files changed, 108 insertions, 54 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index df6a1c05e..8b0152231 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -1,4 +1,4 @@ -/* $Id: time.c,v 1.5 1997/07/23 11:32:06 davem Exp $ +/* $Id: time.c,v 1.12 1997/08/22 20:12:13 davem Exp $ * time.c: UltraSparc timer and TOD clock support. * * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu) @@ -8,6 +8,7 @@ * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) */ +#include <linux/config.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> @@ -17,12 +18,17 @@ #include <linux/interrupt.h> #include <linux/timex.h> #include <linux/init.h> +#include <linux/ioport.h> #include <asm/oplib.h> #include <asm/mostek.h> #include <asm/timer.h> #include <asm/irq.h> #include <asm/io.h> +#include <asm/sbus.h> +#include <asm/fhc.h> +#include <asm/pbm.h> +#include <asm/ebus.h> struct mostek48t02 *mstk48t02_regs = 0; struct mostek48t08 *mstk48t08_regs = 0; @@ -155,33 +161,55 @@ static int has_low_battery(void) /* Probe for the real time clock chip. */ -__initfunc(static void clock_probe(void)) +__initfunc(static void set_system_time(void)) { - struct linux_prom_registers clk_reg[2]; - char model[128]; - int node, sbusnd, err; - - /* XXX HACK HACK HACK, delete me soon */ - struct linux_prom_ranges XXX_sbus_ranges[PROMREG_MAX]; - int XXX_sbus_nranges; + unsigned int year, mon, day, hour, min, sec; + struct mostek48t02 *mregs; - node = prom_getchild(prom_root_node); - sbusnd = prom_searchsiblings(node, "sbus"); - node = prom_getchild(sbusnd); + do_get_fast_time = do_gettimeofday; - if(node == 0 || node == -1) { - prom_printf("clock_probe: Serious problem can't find sbus PROM node.\n"); + mregs = mstk48t02_regs; + if(!mregs) { + prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); + } + + mregs->creg |= MSTK_CREG_READ; + sec = MSTK_REG_SEC(mregs); + min = MSTK_REG_MIN(mregs); + hour = MSTK_REG_HOUR(mregs); + day = MSTK_REG_DOM(mregs); + mon = MSTK_REG_MONTH(mregs); + year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_usec = 0; + mregs->creg &= ~MSTK_CREG_READ; +} + +__initfunc(void clock_probe(void)) +{ + struct linux_prom_registers clk_reg[2]; + char model[128]; + int node, busnd = -1, err; + + if(central_bus != NULL) { + busnd = central_bus->child->prom_node; + } +#ifdef CONFIG_PCI + else if (ebus_chain != NULL) { + busnd = ebus_chain->prom_node; + } +#endif + else { + busnd = SBus_chain->prom_node; } - /* XXX FIX ME */ - err = prom_getproperty(sbusnd, "ranges", (char *) XXX_sbus_ranges, - sizeof(XXX_sbus_ranges)); - if(err == -1) { - prom_printf("clock_probe: Cannot get XXX sbus ranges\n"); + if(busnd == -1) { + prom_printf("clock_probe: problem, cannot find bus to search.\n"); prom_halt(); } - XXX_sbus_nranges = (err / sizeof(struct linux_prom_ranges)); + + node = prom_getchild(busnd); while(1) { prom_getstring(node, "model", model, sizeof(model)); @@ -199,12 +227,48 @@ __initfunc(static void clock_probe(void)) err = prom_getproperty(node, "reg", (char *)clk_reg, sizeof(clk_reg)); if(err == -1) { - prom_printf("clock_probe: Cannot make Mostek\n"); + prom_printf("clock_probe: Cannot get Mostek reg property\n"); prom_halt(); } - /* XXX fix me badly */ - prom_adjust_regs(clk_reg, 1, XXX_sbus_ranges, XXX_sbus_nranges); + if(central_bus) { + prom_apply_fhc_ranges(central_bus->child, clk_reg, 1); + prom_apply_central_ranges(central_bus, clk_reg, 1); + } +#ifdef CONFIG_PCI + else if (ebus_chain) { + struct linux_ebus_device *edev; + + for_each_ebusdev(edev, ebus_chain) + if (edev->prom_node == node) + break; + if (!edev) { + prom_printf("%s: Mostek not probed by EBUS\n", + __FUNCTION__); + prom_halt(); + } + + if (check_region(edev->base_address[0], + sizeof(struct mostek48t59))) { + prom_printf("%s: Can't get region %lx, %d\n", + __FUNCTION__, edev->base_address[0], + sizeof(struct mostek48t59)); + prom_halt(); + } + request_region(edev->base_address[0], + sizeof(struct mostek48t59), "clock"); + + mstk48t59_regs = (struct mostek48t59 *) + edev->base_address[0]; + mstk48t02_regs = &mstk48t59_regs->regs; + break; + } +#endif + else { + prom_adjust_regs(clk_reg, 1, + SBus_chain->sbus_ranges, + SBus_chain->num_sbus_ranges); + } if(model[5] == '0' && model[6] == '2') { mstk48t02_regs = (struct mostek48t02 *) @@ -234,6 +298,8 @@ __initfunc(static void clock_probe(void)) /* Kick start the clock if it is completely stopped. */ if (mstk48t02_regs->sec & MSTK_STOP) kick_start_clock(); + + set_system_time(); } #ifndef BCD_TO_BIN @@ -246,29 +312,10 @@ __initfunc(static void clock_probe(void)) __initfunc(void time_init(void)) { - unsigned int year, mon, day, hour, min, sec; - struct mostek48t02 *mregs; - - do_get_fast_time = do_gettimeofday; - - clock_probe(); - - mregs = mstk48t02_regs; - if(!mregs) { - prom_printf("Something wrong, clock regs not mapped yet.\n"); - prom_halt(); - } - - mregs->creg |= MSTK_CREG_READ; - sec = MSTK_REG_SEC(mregs); - min = MSTK_REG_MIN(mregs); - hour = MSTK_REG_HOUR(mregs); - day = MSTK_REG_DOM(mregs); - mon = MSTK_REG_MONTH(mregs); - year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_usec = 0; - mregs->creg &= ~MSTK_CREG_READ; + /* clock_probe() is now done at end of sbus_init on sparc64 + * so that both sbus and fhc bus information is probed and + * available. + */ } extern void init_timers(void (*func)(int, void *, struct pt_regs *)); @@ -301,22 +348,29 @@ void do_gettimeofday(struct timeval *tv) /* Load doubles must be used on xtime so that what we get * is guarenteed to be atomic, this is why we can run this * with interrupts on full blast. Don't touch this... -DaveM + * + * Note with time_t changes to the timeval type, I must now use + * nucleus atomic quad 128-bit loads. */ __asm__ __volatile__(" sethi %hi(linux_timers), %o1 sethi %hi(xtime), %g2 ldx [%o1 + %lo(linux_timers)], %g3 -1: ldd [%g2 + %lo(xtime)], %o4 + or %g2, %lo(xtime), %g2 +1: ldda [%g2] 0x24, %o4 + membar #LoadLoad | #MemIssue ldx [%g3], %o1 - ldd [%g2 + %lo(xtime)], %o2 + membar #LoadLoad | #MemIssue + ldda [%g2] 0x24, %o2 + membar #LoadLoad xor %o4, %o2, %o2 xor %o5, %o3, %o3 orcc %o2, %o3, %g0 - bne,pn %icc, 1b + bne,pn %xcc, 1b cmp %o1, 0 bge,pt %icc, 1f sethi %hi(tick), %o3 - ld [%o3 + %lo(tick)], %o3 + ldx [%o3 + %lo(tick)], %o3 sethi %hi(0x1fffff), %o2 or %o2, %lo(0x1fffff), %o2 add %o5, %o3, %o5 @@ -325,12 +379,12 @@ void do_gettimeofday(struct timeval *tv) sethi %hi(1000000), %o2 or %o2, %lo(1000000), %o2 cmp %o5, %o2 - bl,a,pn %icc, 1f - st %o4, [%o0 + 0x0] + bl,a,pn %xcc, 1f + stx %o4, [%o0 + 0x0] add %o4, 0x1, %o4 sub %o5, %o2, %o5 - st %o4, [%o0 + 0x0] -1: st %o5, [%o0 + 0x4]"); + stx %o4, [%o0 + 0x0] +1: stx %o5, [%o0 + 0x8]"); } void do_settimeofday(struct timeval *tv) |