time.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:16k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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