1 /* $Id: time.c,v 1.59.2.1 2002/01/23 14:35:45 davem Exp $
2  * linux/arch/sparc/kernel/time.c
3  *
4  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5  * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
6  *
7  * Chris Davis (cdavis@cois.on.ca) 03/27/1998
8  * Added support for the intersil on the sun4/4200
9  *
10  * Gleb Raiko (rajko@mech.math.msu.su) 08/18/1998
11  * Support for MicroSPARC-IIep, PCI CPU.
12  *
13  * This file handles the Sparc specific time handling details.
14  *
15  * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
16  *		"A Kernel Model for Precision Timekeeping" by Dave Mills
17  */
18 #include <linux/config.h>
19 #include <linux/errno.h>
20 #include <linux/sched.h>
21 #include <linux/kernel.h>
22 #include <linux/param.h>
23 #include <linux/string.h>
24 #include <linux/mm.h>
25 #include <linux/interrupt.h>
26 #include <linux/timex.h>
27 #include <linux/init.h>
28 #include <linux/pci.h>
29 #include <linux/ioport.h>
30 
31 #include <asm/oplib.h>
32 #include <asm/segment.h>
33 #include <asm/timer.h>
34 #include <asm/mostek.h>
35 #include <asm/system.h>
36 #include <asm/irq.h>
37 #include <asm/io.h>
38 #include <asm/idprom.h>
39 #include <asm/machines.h>
40 #include <asm/sun4paddr.h>
41 #include <asm/page.h>
42 #include <asm/pcic.h>
43 
44 extern rwlock_t xtime_lock;
45 
46 enum sparc_clock_type sp_clock_typ;
47 spinlock_t mostek_lock = SPIN_LOCK_UNLOCKED;
48 unsigned long mstk48t02_regs = 0UL;
49 static struct mostek48t08 *mstk48t08_regs = 0;
50 static int set_rtc_mmss(unsigned long);
51 static void sbus_do_settimeofday(struct timeval *tv);
52 
53 #ifdef CONFIG_SUN4
54 struct intersil *intersil_clock;
55 #define intersil_cmd(intersil_reg, intsil_cmd) intersil_reg->int_cmd_reg = \
56 	(intsil_cmd)
57 
58 #define intersil_intr(intersil_reg, intsil_cmd) intersil_reg->int_intr_reg = \
59 	(intsil_cmd)
60 
61 #define intersil_start(intersil_reg) intersil_cmd(intersil_reg, \
62 	( INTERSIL_START | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\
63 	  INTERSIL_INTR_ENABLE))
64 
65 #define intersil_stop(intersil_reg) intersil_cmd(intersil_reg, \
66 	( INTERSIL_STOP | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\
67 	  INTERSIL_INTR_ENABLE))
68 
69 #define intersil_read_intr(intersil_reg, towhere) towhere = \
70 	intersil_reg->int_intr_reg
71 
72 #endif
73 
74 static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
75 
76 /* 32-bit Sparc specific profiling function. */
sparc_do_profile(unsigned long pc,unsigned long o7)77 void sparc_do_profile(unsigned long pc, unsigned long o7)
78 {
79 	if(prof_buffer && current->pid) {
80 		extern int _stext;
81 		extern int __copy_user_begin, __copy_user_end;
82 		extern int __atomic_begin, __atomic_end;
83 		extern int __bzero_begin, __bzero_end;
84 		extern int __bitops_begin, __bitops_end;
85 
86 		if ((pc >= (unsigned long) &__copy_user_begin &&
87 		     pc < (unsigned long) &__copy_user_end) ||
88 		    (pc >= (unsigned long) &__atomic_begin &&
89 		     pc < (unsigned long) &__atomic_end) ||
90 		    (pc >= (unsigned long) &__bzero_begin &&
91 		     pc < (unsigned long) &__bzero_end) ||
92 		    (pc >= (unsigned long) &__bitops_begin &&
93 		     pc < (unsigned long) &__bitops_end))
94 			pc = o7;
95 
96 		pc -= (unsigned long) &_stext;
97 		pc >>= prof_shift;
98 
99 		spin_lock(&ticker_lock);
100 		if(pc < prof_len)
101 			prof_buffer[pc]++;
102 		else
103 			prof_buffer[prof_len - 1]++;
104 		spin_unlock(&ticker_lock);
105 	}
106 }
107 
108 __volatile__ unsigned int *master_l10_counter;
109 __volatile__ unsigned int *master_l10_limit;
110 
111 /*
112  * timer_interrupt() needs to keep up the real-time clock,
113  * as well as call the "do_timer()" routine every clocktick
114  */
timer_interrupt(int irq,void * dev_id,struct pt_regs * regs)115 void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
116 {
117 	/* last time the cmos clock got updated */
118 	static long last_rtc_update;
119 
120 #ifndef CONFIG_SMP
121 	if(!user_mode(regs))
122 		sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
123 #endif
124 
125 #ifdef CONFIG_SUN4
126 	if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) ||
127 	   (idprom->id_machtype == (SM_SUN4 | SM_4_110))) {
128 		int temp;
129         	intersil_read_intr(intersil_clock, temp);
130 		/* re-enable the irq */
131 		enable_pil_irq(10);
132 	}
133 #endif
134 	clear_clock_irq();
135 
136 	write_lock(&xtime_lock);
137 
138 	do_timer(regs);
139 
140 	/* Determine when to update the Mostek clock. */
141 	if ((time_status & STA_UNSYNC) == 0 &&
142 	    xtime.tv_sec > last_rtc_update + 660 &&
143 	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
144 	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
145 	  if (set_rtc_mmss(xtime.tv_sec) == 0)
146 	    last_rtc_update = xtime.tv_sec;
147 	  else
148 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
149 	}
150 	write_unlock(&xtime_lock);
151 }
152 
153 /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */
kick_start_clock(void)154 static void __init kick_start_clock(void)
155 {
156 	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
157 	unsigned char sec;
158 	int i, count;
159 
160 	prom_printf("CLOCK: Clock was stopped. Kick start ");
161 
162 	spin_lock_irq(&mostek_lock);
163 
164 	/* Turn on the kick start bit to start the oscillator. */
165 	regs->creg |= MSTK_CREG_WRITE;
166 	regs->sec &= ~MSTK_STOP;
167 	regs->hour |= MSTK_KICK_START;
168 	regs->creg &= ~MSTK_CREG_WRITE;
169 
170 	spin_unlock_irq(&mostek_lock);
171 
172 	/* Delay to allow the clock oscillator to start. */
173 	sec = MSTK_REG_SEC(regs);
174 	for (i = 0; i < 3; i++) {
175 		while (sec == MSTK_REG_SEC(regs))
176 			for (count = 0; count < 100000; count++)
177 				/* nothing */ ;
178 		prom_printf(".");
179 		sec = regs->sec;
180 	}
181 	prom_printf("\n");
182 
183 	spin_lock_irq(&mostek_lock);
184 
185 	/* Turn off kick start and set a "valid" time and date. */
186 	regs->creg |= MSTK_CREG_WRITE;
187 	regs->hour &= ~MSTK_KICK_START;
188 	MSTK_SET_REG_SEC(regs,0);
189 	MSTK_SET_REG_MIN(regs,0);
190 	MSTK_SET_REG_HOUR(regs,0);
191 	MSTK_SET_REG_DOW(regs,5);
192 	MSTK_SET_REG_DOM(regs,1);
193 	MSTK_SET_REG_MONTH(regs,8);
194 	MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO);
195 	regs->creg &= ~MSTK_CREG_WRITE;
196 
197 	spin_unlock_irq(&mostek_lock);
198 
199 	/* Ensure the kick start bit is off. If it isn't, turn it off. */
200 	while (regs->hour & MSTK_KICK_START) {
201 		prom_printf("CLOCK: Kick start still on!\n");
202 
203 		spin_lock_irq(&mostek_lock);
204 		regs->creg |= MSTK_CREG_WRITE;
205 		regs->hour &= ~MSTK_KICK_START;
206 		regs->creg &= ~MSTK_CREG_WRITE;
207 		spin_unlock_irq(&mostek_lock);
208 	}
209 
210 	prom_printf("CLOCK: Kick start procedure successful.\n");
211 }
212 
213 /* Return nonzero if the clock chip battery is low. */
has_low_battery(void)214 static __inline__ int has_low_battery(void)
215 {
216 	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
217 	unsigned char data1, data2;
218 
219 	spin_lock_irq(&mostek_lock);
220 	data1 = regs->eeprom[0];	/* Read some data. */
221 	regs->eeprom[0] = ~data1;	/* Write back the complement. */
222 	data2 = regs->eeprom[0];	/* Read back the complement. */
223 	regs->eeprom[0] = data1;	/* Restore the original value. */
224 	spin_unlock_irq(&mostek_lock);
225 
226 	return (data1 == data2);	/* Was the write blocked? */
227 }
228 
229 /* Probe for the real time clock chip on Sun4 */
sun4_clock_probe(void)230 static __inline__ void sun4_clock_probe(void)
231 {
232 #ifdef CONFIG_SUN4
233 	int temp;
234 	struct resource r;
235 
236 	memset(&r, 0, sizeof(r));
237 	if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) {
238 		sp_clock_typ = MSTK48T02;
239 		r.start = sun4_clock_physaddr;
240 		mstk48t02_regs = sbus_ioremap(&r, 0,
241 				       sizeof(struct mostek48t02), 0);
242 		mstk48t08_regs = 0;  /* To catch weirdness */
243 		intersil_clock = 0;  /* just in case */
244 
245 		/* Kick start the clock if it is completely stopped. */
246 		if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
247 			kick_start_clock();
248 	} else if( idprom->id_machtype == (SM_SUN4 | SM_4_260)) {
249 		/* intersil setup code */
250 		printk("Clock: INTERSIL at %8x ",sun4_clock_physaddr);
251 		sp_clock_typ = INTERSIL;
252 		r.start = sun4_clock_physaddr;
253 		intersil_clock = (struct intersil *)
254 		    sbus_ioremap(&r, 0, sizeof(*intersil_clock), "intersil");
255 		mstk48t02_regs = 0;  /* just be sure */
256 		mstk48t08_regs = 0;  /* ditto */
257 		/* initialise the clock */
258 
259 		intersil_intr(intersil_clock,INTERSIL_INT_100HZ);
260 
261 		intersil_start(intersil_clock);
262 
263 		intersil_read_intr(intersil_clock, temp);
264                 while (!(temp & 0x80))
265                         intersil_read_intr(intersil_clock, temp);
266 
267                 intersil_read_intr(intersil_clock, temp);
268                 while (!(temp & 0x80))
269                         intersil_read_intr(intersil_clock, temp);
270 
271 		intersil_stop(intersil_clock);
272 
273 	}
274 #endif
275 }
276 
277 /* Probe for the mostek real time clock chip. */
clock_probe(void)278 static __inline__ void clock_probe(void)
279 {
280 	struct linux_prom_registers clk_reg[2];
281 	char model[128];
282 	register int node, cpuunit, bootbus;
283 	struct resource r;
284 
285 	cpuunit = bootbus = 0;
286 	memset(&r, 0, sizeof(r));
287 
288 	/* Determine the correct starting PROM node for the probe. */
289 	node = prom_getchild(prom_root_node);
290 	switch (sparc_cpu_model) {
291 	case sun4c:
292 		break;
293 	case sun4m:
294 		node = prom_getchild(prom_searchsiblings(node, "obio"));
295 		break;
296 	case sun4d:
297 		node = prom_getchild(bootbus = prom_searchsiblings(prom_getchild(cpuunit = prom_searchsiblings(node, "cpu-unit")), "bootbus"));
298 		break;
299 	default:
300 		prom_printf("CLOCK: Unsupported architecture!\n");
301 		prom_halt();
302 	}
303 
304 	/* Find the PROM node describing the real time clock. */
305 	sp_clock_typ = MSTK_INVALID;
306 	node = prom_searchsiblings(node,"eeprom");
307 	if (!node) {
308 		prom_printf("CLOCK: No clock found!\n");
309 		prom_halt();
310 	}
311 
312 	/* Get the model name and setup everything up. */
313 	model[0] = '\0';
314 	prom_getstring(node, "model", model, sizeof(model));
315 	if (strcmp(model, "mk48t02") == 0) {
316 		sp_clock_typ = MSTK48T02;
317 		if (prom_getproperty(node, "reg", (char *) clk_reg, sizeof(clk_reg)) == -1) {
318 			prom_printf("clock_probe: FAILED!\n");
319 			prom_halt();
320 		}
321 		if (sparc_cpu_model == sun4d)
322 			prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1);
323 		else
324 			prom_apply_obio_ranges(clk_reg, 1);
325 		/* Map the clock register io area read-only */
326 		r.flags = clk_reg[0].which_io;
327 		r.start = clk_reg[0].phys_addr;
328 		mstk48t02_regs = sbus_ioremap(&r, 0,
329 		    sizeof(struct mostek48t02), "mk48t02");
330 		mstk48t08_regs = 0;  /* To catch weirdness */
331 	} else if (strcmp(model, "mk48t08") == 0) {
332 		sp_clock_typ = MSTK48T08;
333 		if(prom_getproperty(node, "reg", (char *) clk_reg,
334 				    sizeof(clk_reg)) == -1) {
335 			prom_printf("clock_probe: FAILED!\n");
336 			prom_halt();
337 		}
338 		if (sparc_cpu_model == sun4d)
339 			prom_apply_generic_ranges (bootbus, cpuunit, clk_reg, 1);
340 		else
341 			prom_apply_obio_ranges(clk_reg, 1);
342 		/* Map the clock register io area read-only */
343 		/* XXX r/o attribute is somewhere in r.flags */
344 		r.flags = clk_reg[0].which_io;
345 		r.start = clk_reg[0].phys_addr;
346 		mstk48t08_regs = (struct mostek48t08 *) sbus_ioremap(&r, 0,
347 		    sizeof(struct mostek48t08), "mk48t08");
348 
349 		mstk48t02_regs = (unsigned long)&mstk48t08_regs->regs;
350 	} else {
351 		prom_printf("CLOCK: Unknown model name '%s'\n",model);
352 		prom_halt();
353 	}
354 
355 	/* Report a low battery voltage condition. */
356 	if (has_low_battery())
357 		printk(KERN_CRIT "NVRAM: Low battery voltage!\n");
358 
359 	/* Kick start the clock if it is completely stopped. */
360 	if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP)
361 		kick_start_clock();
362 }
363 
sbus_time_init(void)364 void __init sbus_time_init(void)
365 {
366 	unsigned int year, mon, day, hour, min, sec;
367 	struct mostek48t02 *mregs;
368 
369 #ifdef CONFIG_SUN4
370 	int temp;
371 	struct intersil *iregs;
372 #endif
373 
374 	BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
375 	btfixup();
376 
377 	if (ARCH_SUN4)
378 		sun4_clock_probe();
379 	else
380 		clock_probe();
381 
382 	sparc_init_timers(timer_interrupt);
383 
384 #ifdef CONFIG_SUN4
385 	if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) {
386 #endif
387 	mregs = (struct mostek48t02 *)mstk48t02_regs;
388 	if(!mregs) {
389 		prom_printf("Something wrong, clock regs not mapped yet.\n");
390 		prom_halt();
391 	}
392 	spin_lock_irq(&mostek_lock);
393 	mregs->creg |= MSTK_CREG_READ;
394 	sec = MSTK_REG_SEC(mregs);
395 	min = MSTK_REG_MIN(mregs);
396 	hour = MSTK_REG_HOUR(mregs);
397 	day = MSTK_REG_DOM(mregs);
398 	mon = MSTK_REG_MONTH(mregs);
399 	year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
400 	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
401 	xtime.tv_usec = 0;
402 	mregs->creg &= ~MSTK_CREG_READ;
403 	spin_unlock_irq(&mostek_lock);
404 #ifdef CONFIG_SUN4
405 	} else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) {
406 		/* initialise the intersil on sun4 */
407 
408 		iregs=intersil_clock;
409 		if(!iregs) {
410 			prom_printf("Something wrong, clock regs not mapped yet.\n");
411 			prom_halt();
412 		}
413 
414 		intersil_intr(intersil_clock,INTERSIL_INT_100HZ);
415 		disable_pil_irq(10);
416 		intersil_stop(iregs);
417 		intersil_read_intr(intersil_clock, temp);
418 
419 		temp = iregs->clk.int_csec;
420 
421 		sec = iregs->clk.int_sec;
422 		min = iregs->clk.int_min;
423 		hour = iregs->clk.int_hour;
424 		day = iregs->clk.int_day;
425 		mon = iregs->clk.int_month;
426 		year = MSTK_CVT_YEAR(iregs->clk.int_year);
427 
428 		enable_pil_irq(10);
429 		intersil_start(iregs);
430 
431 		xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
432 		xtime.tv_usec = 0;
433 		printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec);
434 	}
435 #endif
436 
437 	/* Now that OBP ticker has been silenced, it is safe to enable IRQ. */
438 	__sti();
439 }
440 
time_init(void)441 void __init time_init(void)
442 {
443 #ifdef CONFIG_PCI
444 	extern void pci_time_init(void);
445 	if (pcic_present()) {
446 		pci_time_init();
447 		return;
448 	}
449 #endif
450 	sbus_time_init();
451 }
452 
do_gettimeoffset(void)453 extern __inline__ unsigned long do_gettimeoffset(void)
454 {
455 	struct tasklet_struct *t;
456 	unsigned long offset = 0;
457 	unsigned int count;
458 
459 	count = (*master_l10_counter >> 10) & 0x1fffff;
460 
461 	t = &bh_task_vec[TIMER_BH];
462 	if (test_bit(TASKLET_STATE_SCHED, &t->state))
463 		offset = 1000000;
464 
465 	return offset + count;
466 }
467 
468 /* This need not obtain the xtime_lock as it is coded in
469  * an implicitly SMP safe way already.
470  */
do_gettimeofday(struct timeval * tv)471 void do_gettimeofday(struct timeval *tv)
472 {
473 	/* Load doubles must be used on xtime so that what we get
474 	 * is guarenteed to be atomic, this is why we can run this
475 	 * with interrupts on full blast.  Don't touch this... -DaveM
476 	 */
477 	__asm__ __volatile__(
478 	"sethi	%hi(master_l10_counter), %o1\n\t"
479 	"ld	[%o1 + %lo(master_l10_counter)], %g3\n\t"
480 	"sethi	%hi(xtime), %g2\n"
481 	"1:\n\t"
482 	"ldd	[%g2 + %lo(xtime)], %o4\n\t"
483 	"ld	[%g3], %o1\n\t"
484 	"ldd	[%g2 + %lo(xtime)], %o2\n\t"
485 	"xor	%o4, %o2, %o2\n\t"
486 	"xor	%o5, %o3, %o3\n\t"
487 	"orcc	%o2, %o3, %g0\n\t"
488 	"bne	1b\n\t"
489 	" cmp	%o1, 0\n\t"
490 	"bge	1f\n\t"
491 	" srl	%o1, 0xa, %o1\n\t"
492 	"sethi	%hi(tick), %o3\n\t"
493 	"ld	[%o3 + %lo(tick)], %o3\n\t"
494 	"sethi	%hi(0x1fffff), %o2\n\t"
495 	"or	%o2, %lo(0x1fffff), %o2\n\t"
496 	"add	%o5, %o3, %o5\n\t"
497 	"and	%o1, %o2, %o1\n"
498 	"1:\n\t"
499 	"add	%o5, %o1, %o5\n\t"
500 	"sethi	%hi(1000000), %o2\n\t"
501 	"or	%o2, %lo(1000000), %o2\n\t"
502 	"cmp	%o5, %o2\n\t"
503 	"bl,a	1f\n\t"
504 	" st	%o4, [%o0 + 0x0]\n\t"
505 	"add	%o4, 0x1, %o4\n\t"
506 	"sub	%o5, %o2, %o5\n\t"
507 	"st	%o4, [%o0 + 0x0]\n"
508 	"1:\n\t"
509 	"st	%o5, [%o0 + 0x4]\n");
510 }
511 
do_settimeofday(struct timeval * tv)512 void do_settimeofday(struct timeval *tv)
513 {
514 	write_lock_irq(&xtime_lock);
515 	bus_do_settimeofday(tv);
516 	write_unlock_irq(&xtime_lock);
517 }
518 
sbus_do_settimeofday(struct timeval * tv)519 static void sbus_do_settimeofday(struct timeval *tv)
520 {
521 	tv->tv_usec -= do_gettimeoffset();
522 	if(tv->tv_usec < 0) {
523 		tv->tv_usec += 1000000;
524 		tv->tv_sec--;
525 	}
526 	xtime = *tv;
527 	time_adjust = 0;		/* stop active adjtime() */
528 	time_status |= STA_UNSYNC;
529 	time_maxerror = NTP_PHASE_LIMIT;
530 	time_esterror = NTP_PHASE_LIMIT;
531 }
532 
533 /*
534  * BUG: This routine does not handle hour overflow properly; it just
535  *      sets the minutes. Usually you won't notice until after reboot!
536  */
set_rtc_mmss(unsigned long nowtime)537 static int set_rtc_mmss(unsigned long nowtime)
538 {
539 	int real_seconds, real_minutes, mostek_minutes;
540 	struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs;
541 	unsigned long flags;
542 #ifdef CONFIG_SUN4
543 	struct intersil *iregs = intersil_clock;
544 	int temp;
545 #endif
546 
547 	/* Not having a register set can lead to trouble. */
548 	if (!regs) {
549 #ifdef CONFIG_SUN4
550 		if(!iregs)
551 		return -1;
552 	 	else {
553 			temp = iregs->clk.int_csec;
554 
555 			mostek_minutes = iregs->clk.int_min;
556 
557 			real_seconds = nowtime % 60;
558 			real_minutes = nowtime / 60;
559 			if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
560 				real_minutes += 30;	/* correct for half hour time zone */
561 			real_minutes %= 60;
562 
563 			if (abs(real_minutes - mostek_minutes) < 30) {
564 				intersil_stop(iregs);
565 				iregs->clk.int_sec=real_seconds;
566 				iregs->clk.int_min=real_minutes;
567 				intersil_start(iregs);
568 			} else {
569 				printk(KERN_WARNING
570 			       "set_rtc_mmss: can't update from %d to %d\n",
571 				       mostek_minutes, real_minutes);
572 				return -1;
573 			}
574 
575 			return 0;
576 		}
577 #endif
578 	}
579 
580 	spin_lock_irqsave(&mostek_lock, flags);
581 	/* Read the current RTC minutes. */
582 	regs->creg |= MSTK_CREG_READ;
583 	mostek_minutes = MSTK_REG_MIN(regs);
584 	regs->creg &= ~MSTK_CREG_READ;
585 
586 	/*
587 	 * since we're only adjusting minutes and seconds,
588 	 * don't interfere with hour overflow. This avoids
589 	 * messing with unknown time zones but requires your
590 	 * RTC not to be off by more than 15 minutes
591 	 */
592 	real_seconds = nowtime % 60;
593 	real_minutes = nowtime / 60;
594 	if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1)
595 		real_minutes += 30;	/* correct for half hour time zone */
596 	real_minutes %= 60;
597 
598 	if (abs(real_minutes - mostek_minutes) < 30) {
599 		regs->creg |= MSTK_CREG_WRITE;
600 		MSTK_SET_REG_SEC(regs,real_seconds);
601 		MSTK_SET_REG_MIN(regs,real_minutes);
602 		regs->creg &= ~MSTK_CREG_WRITE;
603 		spin_unlock_irqrestore(&mostek_lock, flags);
604 		return 0;
605 	} else {
606 		spin_unlock_irqrestore(&mostek_lock, flags);
607 		return -1;
608 	}
609 }
610