summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r--arch/sparc64/kernel/time.c162
1 files changed, 92 insertions, 70 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
index 0b72e6e0b..60d5e4a5f 100644
--- a/arch/sparc64/kernel/time.c
+++ b/arch/sparc64/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.20 1999/03/15 22:13:40 davem Exp $
+/* $Id: time.c,v 1.22 1999/08/30 10:01:22 davem Exp $
* time.c: UltraSparc timer and TOD clock support.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -33,9 +33,9 @@
extern rwlock_t xtime_lock;
-struct mostek48t02 *mstk48t02_regs = 0;
-static struct mostek48t08 *mstk48t08_regs = 0;
-static struct mostek48t59 *mstk48t59_regs = 0;
+unsigned long mstk48t02_regs = 0UL;
+static unsigned long mstk48t08_regs = 0UL;
+static unsigned long mstk48t59_regs = 0UL;
static int set_rtc_mmss(unsigned long);
@@ -47,7 +47,7 @@ static int set_rtc_mmss(unsigned long);
*/
unsigned long timer_tick_offset;
static unsigned long timer_tick_compare;
-static unsigned long timer_ticks_per_usec;
+static unsigned long timer_ticks_per_usec_quotient;
static __inline__ void timer_check_rtc(void)
{
@@ -146,17 +146,25 @@ static inline unsigned long mktime(unsigned int year, unsigned int mon,
/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
static void __init kick_start_clock(void)
{
- register struct mostek48t02 *regs = mstk48t02_regs;
- unsigned char sec;
+ unsigned long regs = mstk48t02_regs;
+ u8 sec, tmp;
int i, count;
prom_printf("CLOCK: Clock was stopped. Kick start ");
/* Turn on the kick start bit to start the oscillator. */
- regs->creg |= MSTK_CREG_WRITE;
- regs->sec &= ~MSTK_STOP;
- regs->hour |= MSTK_KICK_START;
- regs->creg &= ~MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+ tmp = mostek_read(regs + MOSTEK_SEC);
+ tmp &= ~MSTK_STOP;
+ mostek_write(regs + MOSTEK_SEC, tmp);
+ tmp = mostek_read(regs + MOSTEK_HOUR);
+ tmp |= MSTK_KICK_START;
+ mostek_write(regs + MOSTEK_HOUR, tmp);
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
/* Delay to allow the clock oscillator to start. */
sec = MSTK_REG_SEC(regs);
@@ -165,13 +173,17 @@ static void __init kick_start_clock(void)
for (count = 0; count < 100000; count++)
/* nothing */ ;
prom_printf(".");
- sec = regs->sec;
+ sec = MSTK_REG_SEC(regs);
}
prom_printf("\n");
/* Turn off kick start and set a "valid" time and date. */
- regs->creg |= MSTK_CREG_WRITE;
- regs->hour &= ~MSTK_KICK_START;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+ tmp = mostek_read(regs + MOSTEK_HOUR);
+ tmp &= ~MSTK_KICK_START;
+ mostek_write(regs + MOSTEK_HOUR, tmp);
MSTK_SET_REG_SEC(regs,0);
MSTK_SET_REG_MIN(regs,0);
MSTK_SET_REG_HOUR(regs,0);
@@ -179,14 +191,24 @@ static void __init kick_start_clock(void)
MSTK_SET_REG_DOM(regs,1);
MSTK_SET_REG_MONTH(regs,8);
MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO);
- regs->creg &= ~MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
/* Ensure the kick start bit is off. If it isn't, turn it off. */
- while (regs->hour & MSTK_KICK_START) {
+ while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) {
prom_printf("CLOCK: Kick start still on!\n");
- regs->creg |= MSTK_CREG_WRITE;
- regs->hour &= ~MSTK_KICK_START;
- regs->creg &= ~MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+
+ tmp = mostek_read(regs + MOSTEK_HOUR);
+ tmp &= ~MSTK_KICK_START;
+ mostek_write(regs + MOSTEK_HOUR, tmp);
+
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
}
prom_printf("CLOCK: Kick start procedure successful.\n");
@@ -195,13 +217,13 @@ static void __init kick_start_clock(void)
/* Return nonzero if the clock chip battery is low. */
static int __init has_low_battery(void)
{
- register struct mostek48t02 *regs = mstk48t02_regs;
- unsigned char data1, data2;
+ unsigned long regs = mstk48t02_regs;
+ u8 data1, data2;
- data1 = regs->eeprom[0]; /* Read some data. */
- regs->eeprom[0] = ~data1; /* Write back the complement. */
- data2 = regs->eeprom[0]; /* Read back the complement. */
- regs->eeprom[0] = data1; /* Restore the original value. */
+ data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */
+ mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */
+ data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */
+ mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */
return (data1 == data2); /* Was the write blocked? */
}
@@ -211,17 +233,20 @@ static int __init has_low_battery(void)
static void __init set_system_time(void)
{
unsigned int year, mon, day, hour, min, sec;
- struct mostek48t02 *mregs;
+ unsigned long mregs = mstk48t02_regs;
+ u8 tmp;
do_get_fast_time = do_gettimeofday;
- mregs = mstk48t02_regs;
if(!mregs) {
prom_printf("Something wrong, clock regs not mapped yet.\n");
prom_halt();
}
- mregs->creg |= MSTK_CREG_READ;
+ tmp = mostek_read(mregs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_READ;
+ mostek_write(mregs + MOSTEK_CREG, tmp);
+
sec = MSTK_REG_SEC(mregs);
min = MSTK_REG_MIN(mregs);
hour = MSTK_REG_HOUR(mregs);
@@ -230,7 +255,10 @@ static void __init set_system_time(void)
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;
+
+ tmp = mostek_read(mregs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_READ;
+ mostek_write(mregs + MOSTEK_CREG, tmp);
}
void __init clock_probe(void)
@@ -315,19 +343,8 @@ void __init clock_probe(void)
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;
+ mstk48t59_regs = edev->resource[0].start;
+ mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
break;
}
#endif
@@ -338,22 +355,16 @@ void __init clock_probe(void)
}
if(model[5] == '0' && model[6] == '2') {
- mstk48t02_regs = (struct mostek48t02 *)
- sparc_alloc_io(clk_reg[0].phys_addr,
- (void *) 0, sizeof(*mstk48t02_regs),
- "clock", clk_reg[0].which_io, 0x0);
+ mstk48t02_regs = (((u64)clk_reg[0].phys_addr) |
+ (((u64)clk_reg[0].which_io)<<32UL));
} else if(model[5] == '0' && model[6] == '8') {
- mstk48t08_regs = (struct mostek48t08 *)
- sparc_alloc_io(clk_reg[0].phys_addr,
- (void *) 0, sizeof(*mstk48t08_regs),
- "clock", clk_reg[0].which_io, 0x0);
- mstk48t02_regs = &mstk48t08_regs->regs;
+ mstk48t08_regs = (((u64)clk_reg[0].phys_addr) |
+ (((u64)clk_reg[0].which_io)<<32UL));
+ mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02;
} else {
- mstk48t59_regs = (struct mostek48t59 *)
- sparc_alloc_io(clk_reg[0].phys_addr,
- (void *) 0, sizeof(*mstk48t59_regs),
- "clock", clk_reg[0].which_io, 0x0);
- mstk48t02_regs = &mstk48t59_regs->regs;
+ mstk48t59_regs = (((u64)clk_reg[0].phys_addr) |
+ (((u64)clk_reg[0].which_io)<<32UL));
+ mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
}
break;
}
@@ -363,7 +374,7 @@ void __init clock_probe(void)
prom_printf("NVRAM: Low battery voltage!\n");
/* Kick start the clock if it is completely stopped. */
- if (mstk48t02_regs->sec & MSTK_STOP)
+ if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
kick_start_clock();
set_system_time();
@@ -392,7 +403,7 @@ void __init time_init(void)
init_timers(timer_interrupt, &clock);
timer_tick_offset = clock / HZ;
- timer_ticks_per_usec = clock / 1000000;
+ timer_ticks_per_usec_quotient = ((1UL<<32) / (clock / 1000020));
}
static __inline__ unsigned long do_gettimeoffset(void)
@@ -408,7 +419,7 @@ static __inline__ unsigned long do_gettimeoffset(void)
: "r" (timer_tick_offset), "r" (timer_tick_compare)
: "g1", "g2");
- return ticks / timer_ticks_per_usec;
+ return (ticks * timer_ticks_per_usec_quotient) >> 32UL;
}
/* This need not obtain the xtime_lock as it is coded in
@@ -431,24 +442,22 @@ void do_gettimeofday(struct timeval *tv)
or %g2, %lo(xtime), %g2
or %g1, %lo(timer_tick_compare), %g1
1: ldda [%g2] 0x24, %o4
- membar #LoadLoad | #MemIssue
rd %tick, %o1
ldx [%g1], %g7
- membar #LoadLoad | #MemIssue
ldda [%g2] 0x24, %o2
- membar #LoadLoad
xor %o4, %o2, %o2
xor %o5, %o3, %o3
orcc %o2, %o3, %g0
bne,pn %xcc, 1b
sethi %hi(lost_ticks), %o2
- sethi %hi(timer_ticks_per_usec), %o3
+ sethi %hi(timer_ticks_per_usec_quotient), %o3
ldx [%o2 + %lo(lost_ticks)], %o2
add %g3, %o1, %o1
- ldx [%o3 + %lo(timer_ticks_per_usec)], %o3
+ ldx [%o3 + %lo(timer_ticks_per_usec_quotient)], %o3
sub %o1, %g7, %o1
+ mulx %o3, %o1, %o1
brz,pt %o2, 1f
- udivx %o1, %o3, %o1
+ srlx %o1, 32, %o1
sethi %hi(10000), %g2
or %g2, %lo(10000), %g2
add %o1, %g2, %o1
@@ -487,16 +496,23 @@ void do_settimeofday(struct timeval *tv)
static int set_rtc_mmss(unsigned long nowtime)
{
int real_seconds, real_minutes, mostek_minutes;
- struct mostek48t02 *regs = mstk48t02_regs;
+ unsigned long regs = mstk48t02_regs;
+ u8 tmp;
/* Not having a register set can lead to trouble. */
if (!regs)
return -1;
/* Read the current RTC minutes. */
- regs->creg |= MSTK_CREG_READ;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_READ;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+
mostek_minutes = MSTK_REG_MIN(regs);
- regs->creg &= ~MSTK_CREG_READ;
+
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_READ;
+ mostek_write(regs + MOSTEK_CREG, tmp);
/*
* since we're only adjusting minutes and seconds,
@@ -511,10 +527,16 @@ static int set_rtc_mmss(unsigned long nowtime)
real_minutes %= 60;
if (abs(real_minutes - mostek_minutes) < 30) {
- regs->creg |= MSTK_CREG_WRITE;
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp |= MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
+
MSTK_SET_REG_SEC(regs,real_seconds);
MSTK_SET_REG_MIN(regs,real_minutes);
- regs->creg &= ~MSTK_CREG_WRITE;
+
+ tmp = mostek_read(regs + MOSTEK_CREG);
+ tmp &= ~MSTK_CREG_WRITE;
+ mostek_write(regs + MOSTEK_CREG, tmp);
} else
return -1;