/* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ static void __init kick_start_clock(void) { struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; unsigned char sec; int i, count; prom_printf("CLOCK: Clock was stopped. Kick start "); spin_lock_irq(&mostek_lock); /* 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; spin_unlock_irq(&mostek_lock); /* Delay to allow the clock oscillator to start. */ sec = MSTK_REG_SEC(regs); for (i = 0; i < 3; i++) { while (sec == MSTK_REG_SEC(regs)) for (count = 0; count < 100000; count++) /* nothing */ ; prom_printf("."); sec = regs->sec; } prom_printf("\n"); spin_lock_irq(&mostek_lock); /* Turn off kick start and set a "valid" time and date. */ regs->creg |= MSTK_CREG_WRITE; regs->hour &= ~MSTK_KICK_START; MSTK_SET_REG_SEC(regs,0); MSTK_SET_REG_MIN(regs,0); MSTK_SET_REG_HOUR(regs,0); MSTK_SET_REG_DOW(regs,5); 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; spin_unlock_irq(&mostek_lock); /* Ensure the kick start bit is off. If it isn't, turn it off. */ while (regs->hour & MSTK_KICK_START) { prom_printf("CLOCK: Kick start still on!\n"); spin_lock_irq(&mostek_lock); regs->creg |= MSTK_CREG_WRITE; regs->hour &= ~MSTK_KICK_START; regs->creg &= ~MSTK_CREG_WRITE; spin_unlock_irq(&mostek_lock); } prom_printf("CLOCK: Kick start procedure successful.\n"); }
/* Retrieve the current date and time from the real time clock. */ static void get_rtc_time(struct rtc_time *t) { void __iomem *regs = mstk48t02_regs; u8 tmp; spin_lock_irq(&mostek_lock); tmp = mostek_read(regs + MOSTEK_CREG); tmp |= MSTK_CREG_READ; mostek_write(regs + MOSTEK_CREG, tmp); t->sec = MSTK_REG_SEC(regs); t->min = MSTK_REG_MIN(regs); t->hour = MSTK_REG_HOUR(regs); t->dow = MSTK_REG_DOW(regs); t->dom = MSTK_REG_DOM(regs); t->month = MSTK_REG_MONTH(regs); t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); tmp = mostek_read(regs + MOSTEK_CREG); tmp &= ~MSTK_CREG_READ; mostek_write(regs + MOSTEK_CREG, tmp); spin_unlock_irq(&mostek_lock); }
/* Retrieve the current date and time from the real time clock. */ void get_rtc_time(struct rtc_time *t) { unsigned long regs = mstk48t02_regs; unsigned long flags; u8 tmp; save_flags(flags); cli(); tmp = mostek_read(regs + MOSTEK_CREG); tmp |= MSTK_CREG_READ; mostek_write(regs + MOSTEK_CREG, tmp); t->sec = MSTK_REG_SEC(regs); t->min = MSTK_REG_MIN(regs); t->hour = MSTK_REG_HOUR(regs); t->dow = MSTK_REG_DOW(regs); t->dom = MSTK_REG_DOM(regs); t->month = MSTK_REG_MONTH(regs); t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); tmp = mostek_read(regs + MOSTEK_CREG); tmp &= ~MSTK_CREG_READ; mostek_write(regs + MOSTEK_CREG, tmp); restore_flags(flags); }
void __init sbus_time_init(void) { unsigned int year, mon, day, hour, min, sec; struct mostek48t02 *mregs; #ifdef CONFIG_SUN4 int temp; struct intersil *iregs; #endif BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); btfixup(); if (ARCH_SUN4) sun4_clock_probe(); else clock_probe(); sparc_init_timers(timer_interrupt); #ifdef CONFIG_SUN4 if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { #endif mregs = (struct mostek48t02 *)mstk48t02_regs; if(!mregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } spin_lock_irq(&mostek_lock); 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_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); mregs->creg &= ~MSTK_CREG_READ; spin_unlock_irq(&mostek_lock); #ifdef CONFIG_SUN4 } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { /* initialise the intersil on sun4 */ iregs=intersil_clock; if(!iregs) { prom_printf("Something wrong, clock regs not mapped yet.\n"); prom_halt(); } intersil_intr(intersil_clock,INTERSIL_INT_100HZ); disable_pil_irq(10); intersil_stop(iregs); intersil_read_intr(intersil_clock, temp); temp = iregs->clk.int_csec; sec = iregs->clk.int_sec; min = iregs->clk.int_min; hour = iregs->clk.int_hour; day = iregs->clk.int_day; mon = iregs->clk.int_month; year = MSTK_CVT_YEAR(iregs->clk.int_year); enable_pil_irq(10); intersil_start(iregs); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec); printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec); } #endif /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */ local_irq_enable(); }