diff -Nru up/arch/mips/kernel/time.c.orig up/arch/mips/kernel/time.c --- up/arch/mips/kernel/time.c.orig Sun Nov 11 22:03:57 2001 +++ up/arch/mips/kernel/time.c Fri Jan 25 10:41:58 2002 @@ -39,6 +39,11 @@ extern volatile unsigned long wall_jiffies; /* + * whether we emulate local_timer_interrupts for SMP machines. + */ +int emulate_local_timer_interrupt; + +/* * By default we provide the null RTC ops */ static unsigned long null_rtc_get_time(void) @@ -283,6 +288,42 @@ /* + * local_timer_interrupt() does profiling and process accounting + * on a per-CPU basis. + * + * In UP mode, it is invoked from the (global) timer_interrupt. + * + * In SMP mode, it might invoked by per-CPU timer interrupt, or + * a broadcasted inter-processor interrupt which itself is triggered + * by the global timer interrupt. + */ +void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if(!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long pc = regs->cp0_epc; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } + } + +#if defined(CONFIG_SMP) + /* in UP mode, update_process_times() is invoked by do_timer() */ + update_process_times(user_mode(regs)); +#endif +} + +/* * high-level timer interrupt service routines. This function * is set as irqaction->handler and is invoked through do_IRQ. */ @@ -309,24 +350,6 @@ } - if(!user_mode(regs)) { - if (prof_buffer && current->pid) { - extern int _stext; - unsigned long pc = regs->cp0_epc; - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - /* - * Dont ignore out-of-bounds pc values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len-1) - pc = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[pc]); - } - } - /* * call the generic timer interrupt handling */ @@ -359,6 +382,31 @@ if (!jiffies) { timerhi = timerlo = 0; } + +#if !defined(CONFIG_SMP) + /* + * In UP mode, we call local_timer_interrupt() to do profiling + * and process accouting. + * + * In SMP mode, local_timer_interrupt() is invoked by appropriate + * low-level local timer interrupt handler. + */ + local_timer_interrupt(0, NULL, regs); + +#else /* CONFIG_SMP */ + + if (emulate_local_timer_interrupt) { + /* + * this is the place where we send out inter-process + * interrupts and let each CPU do its own profiling + * and process accouting. + * + * Obviously we need to call local_timer_interrupt() for + * the current CPU too. + */ + panic("Not implemented yet!!!"); + } +#endif /* CONFIG_SMP */ } asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) @@ -377,6 +425,21 @@ do_softirq(); } +asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + irq_enter(cpu, irq); + kstat.irqs[cpu][irq]++; + + /* we keep interrupt disabled all the time */ + local_timer_interrupt(irq, NULL, regs); + + irq_exit(cpu, irq); + + if (softirq_pending(cpu)) + do_softirq(); +} /* * time_init() - it does the following things. diff -Nru up/arch/mips/sibyte/sb1250/time.c.orig up/arch/mips/sibyte/sb1250/time.c --- up/arch/mips/sibyte/sb1250/time.c.orig Mon Dec 17 11:03:22 2001 +++ up/arch/mips/sibyte/sb1250/time.c Fri Jan 25 10:41:58 2002 @@ -33,6 +33,8 @@ #include #include #include +#include + #include #include #include @@ -40,10 +42,6 @@ #include -void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); - - - #define IMR_IP2_VAL K_INT_MAP_I0 #define IMR_IP3_VAL K_INT_MAP_I1 #define IMR_IP4_VAL K_INT_MAP_I2 @@ -87,10 +85,6 @@ */ } -extern int set_rtc_mmss(unsigned long nowtime); -extern rwlock_t xtime_lock; -static long last_rtc_update = 0; - void sb1250_timer_interrupt(struct pt_regs *regs) { int cpu = smp_processor_id(); @@ -100,37 +94,14 @@ KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); /* - * Need to do some stuff here with xtime, too, but that looks like - * it should be architecture independent...does it really belong here? + * CPU 0 handles the global timer interrupt job */ - if (!cpu) { - do_timer(regs); - - read_lock(&xtime_lock); - if ((time_status & STA_UNSYNC) == 0 - && xtime.tv_sec > last_rtc_update + 660 - && xtime.tv_usec >= 500000 - (tick >> 1) - && xtime.tv_usec <= 500000 + (tick >> 1)) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* do it again in 60 s */ - last_rtc_update = xtime.tv_sec - 600; - } - read_unlock(&xtime_lock); + if (cpu == 0) { + ll_timer_interrupt(0, regs); } -#ifdef CONFIG_SMP /* - * We need to make like a normal interrupt -- otherwise timer - * interrupts ignore the global interrupt lock, which would be - * a Bad Thing. + * every CPU should do profiling and process accouting */ - irq_enter(cpu, 0); - update_process_times(user_mode(regs)); - irq_exit(cpu, 0); - - if (softirq_pending(cpu)) - do_softirq(); -#endif /* CONFIG_SMP */ + ll_local_timer_interrupt(0, regs); } diff -Nru up/arch/mips/sibyte/swarm/time.c.orig up/arch/mips/sibyte/swarm/time.c --- up/arch/mips/sibyte/swarm/time.c.orig Thu Jan 24 16:25:51 2002 +++ up/arch/mips/sibyte/swarm/time.c Fri Jan 25 10:43:07 2002 @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Broadcom Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Time routines for the swarm board. We pass all the hard stuff - * through to the sb1250 handling code. Only thing we really keep - * track of here is what time of day we think it is. And we don't - * really even do a good job of that... - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -extern rwlock_t xtime_lock; - -/* Xicor 1241 definitions */ - -/* - * Register bits - */ - -#define X1241REG_SR_BAT 0x80 /* currently on battery power */ -#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */ -#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */ -#define X1241REG_SR_RTCF 0x01 /* clock failed */ -#define X1241REG_BL_BP2 0x80 /* block protect 2 */ -#define X1241REG_BL_BP1 0x40 /* block protect 1 */ -#define X1241REG_BL_BP0 0x20 /* block protect 0 */ -#define X1241REG_BL_WD1 0x10 -#define X1241REG_BL_WD0 0x08 -#define X1241REG_HR_MIL 0x80 /* military time format */ - -/* - * Register numbers - */ - -#define X1241REG_BL 0x10 /* block protect bits */ -#define X1241REG_INT 0x11 /* */ -#define X1241REG_SC 0x30 /* Seconds */ -#define X1241REG_MN 0x31 /* Minutes */ -#define X1241REG_HR 0x32 /* Hours */ -#define X1241REG_DT 0x33 /* Day of month */ -#define X1241REG_MO 0x34 /* Month */ -#define X1241REG_YR 0x35 /* Year */ -#define X1241REG_DW 0x36 /* Day of Week */ -#define X1241REG_Y2K 0x37 /* Year 2K */ -#define X1241REG_SR 0x3F /* Status register */ - -#define X1241_CCR_ADDRESS 0x6F - -#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) - -static int xicor_read(uint8_t addr) -{ - while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) - ; - - out64((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD)); - out64((addr & 0xff), SMB_CSR(R_SMB_DATA)); - out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE), SMB_CSR(R_SMB_START)); - - while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) - ; - - out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE), SMB_CSR(R_SMB_START)); - - while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) - ; - - if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { - /* Clear error bit by writing a 1 */ - out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); - return -1; - } - - return (in64(SMB_CSR(R_SMB_DATA)) & 0xff); -} - -static int xicor_write(uint8_t addr, int b) -{ - while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) - ; - - out64(addr, SMB_CSR(R_SMB_CMD)); - out64((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA)); - out64(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE, - SMB_CSR(R_SMB_START)); - - while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) - ; - - if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { - /* Clear error bit by writing a 1 */ - out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); - return -1; - } else { - return 0; - } -} - -#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) -#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) - -/* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you'll only notice that after reboot! - */ -int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - - cmos_minutes = xicor_read(X1241REG_MN); - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - /* unlock writes to the CCR */ - xicor_write(X1241REG_SR, X1241REG_SR_WEL); - xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); - - if (abs(real_minutes - cmos_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - xicor_write(X1241REG_SC, real_seconds); - xicor_write(X1241REG_MN, real_minutes); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - xicor_write(X1241REG_SR, 0); - - printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds); - - return retval; -} - -static unsigned long __init get_swarm_time(void) -{ - unsigned int year, mon, day, hour, min, sec, y2k; - - sec = xicor_read(X1241REG_SC); - min = xicor_read(X1241REG_MN); - hour = xicor_read(X1241REG_HR); - - if (hour & X1241REG_HR_MIL) { - hour &= 0x3f; - } else { - if (hour & 0x20) - hour = (hour & 0xf) + 0x12; - } - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - - day = xicor_read(X1241REG_DT); - mon = xicor_read(X1241REG_MO); - year = xicor_read(X1241REG_YR); - y2k = xicor_read(X1241REG_Y2K); - - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - BCD_TO_BIN(y2k); - - year += (y2k * 100); - - return mktime(year, mon, day, hour, min, sec); -} - -/* - * Bring up the timer at 100 Hz. - */ -void __init swarm_time_init(void) -{ - unsigned int flags; - int status; - - /* Set up the scd general purpose timer 0 to cpu 0 */ - sb1250_time_init(); - - /* Establish communication with the Xicor 1241 RTC */ - /* XXXKW how do I share the SMBus with the I2C subsystem? */ - - out64(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ)); - out64(0, SMB_CSR(R_SMB_CONTROL)); - - if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) { - printk("x1241: couldn't detect on SWARM SMBus 1\n"); - } else { - if (status & X1241REG_SR_RTCF) - printk("x1241: battery failed -- time is probably wrong\n"); - write_lock_irqsave (&xtime_lock, flags); - xtime.tv_sec = get_swarm_time(); - xtime.tv_usec = 0; - write_unlock_irqrestore(&xtime_lock, flags); - } -} diff -Nru up/arch/mips/sibyte/swarm/Makefile.orig up/arch/mips/sibyte/swarm/Makefile --- up/arch/mips/sibyte/swarm/Makefile.orig Mon Nov 19 02:22:15 2001 +++ up/arch/mips/sibyte/swarm/Makefile Fri Jan 25 10:42:06 2002 @@ -7,7 +7,7 @@ all: sbswarm.a -OBJS-y = setup.o cmdline.o rtc.o time.o memory.o cfe_api.o +OBJS-y = setup.o cmdline.o memory.o cfe_api.o rtc_xicor1241.o OBJS-$(CONFIG_SMP) += smp.o diff -Nru up/arch/mips/sibyte/swarm/setup.c.orig up/arch/mips/sibyte/swarm/setup.c --- up/arch/mips/sibyte/swarm/setup.c.orig Fri Jan 25 10:30:16 2002 +++ up/arch/mips/sibyte/swarm/setup.c Fri Jan 25 10:47:58 2002 @@ -21,12 +21,12 @@ */ #include -#include #include #include #include #include #include + #include #include #include @@ -225,14 +225,31 @@ { } -extern void swarm_time_init(void); +void __init swarm_timer_setup(struct irqaction *irq) +{ + /* + * we don't set up irqaction, because we will deliver timer + * interrupts through low-level (direct) meachanism. + */ + + /* We only need to setup the generic timer */ + sb1250_time_init(); +} + +extern int xicor_set_time(unsigned long); +extern unsigned int xicor_get_time(void); void __init swarm_setup(void) { extern int panic_timeout; - rtc_ops = &swarm_rtc_ops; - panic_timeout = 5; /* For debug. This should probably be raised later */ + panic_timeout = 5; /* For debug. */ + + board_timer_setup = swarm_timer_setup; + + rtc_get_time = xicor_get_time; + rtc_set_time = xicor_set_time; + _machine_restart = (void (*)(char *))swarm_linux_exit; _machine_halt = swarm_linux_exit; _machine_power_off = swarm_linux_exit; @@ -249,8 +266,6 @@ "board" #endif " runs\n"); - - board_time_init = swarm_time_init; #ifdef CONFIG_BLK_DEV_IDE_SWARM ide_ops = &swarm_ide_ops; diff -Nru up/arch/mips/sibyte/swarm/rtc.c.orig up/arch/mips/sibyte/swarm/rtc.c --- up/arch/mips/sibyte/swarm/rtc.c.orig Wed Nov 7 17:54:47 2001 +++ up/arch/mips/sibyte/swarm/rtc.c Fri Jan 25 10:42:06 2002 @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Broadcom Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - * Not really sure what is supposed to be here, yet - */ - -#include -#include - -static unsigned char swarm_rtc_read_data(unsigned long addr) -{ - return 0; -} - -static void swarm_rtc_write_data(unsigned char data, unsigned long addr) -{ -} - -static int swarm_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops swarm_rtc_ops = { - &swarm_rtc_read_data, - &swarm_rtc_write_data, - &swarm_rtc_bcd_mode -}; diff -Nru up/arch/mips/sibyte/swarm/rtc_xicor1241.c.orig up/arch/mips/sibyte/swarm/rtc_xicor1241.c --- up/arch/mips/sibyte/swarm/rtc_xicor1241.c.orig Fri Jan 25 10:42:06 2002 +++ up/arch/mips/sibyte/swarm/rtc_xicor1241.c Fri Jan 25 10:42:06 2002 @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * Copyright (C) 2002 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/* Xicor 1241 definitions */ + +/* + * Register bits + */ + +#define X1241REG_SR_BAT 0x80 /* currently on battery power */ +#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */ +#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */ +#define X1241REG_SR_RTCF 0x01 /* clock failed */ +#define X1241REG_BL_BP2 0x80 /* block protect 2 */ +#define X1241REG_BL_BP1 0x40 /* block protect 1 */ +#define X1241REG_BL_BP0 0x20 /* block protect 0 */ +#define X1241REG_BL_WD1 0x10 +#define X1241REG_BL_WD0 0x08 +#define X1241REG_HR_MIL 0x80 /* military time format */ + +/* + * Register numbers + */ + +#define X1241REG_BL 0x10 /* block protect bits */ +#define X1241REG_INT 0x11 /* */ +#define X1241REG_SC 0x30 /* Seconds */ +#define X1241REG_MN 0x31 /* Minutes */ +#define X1241REG_HR 0x32 /* Hours */ +#define X1241REG_DT 0x33 /* Day of month */ +#define X1241REG_MO 0x34 /* Month */ +#define X1241REG_YR 0x35 /* Year */ +#define X1241REG_DW 0x36 /* Day of Week */ +#define X1241REG_Y2K 0x37 /* Year 2K */ +#define X1241REG_SR 0x3F /* Status register */ + +#define X1241_CCR_ADDRESS 0x6F + +#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) + +static int xicor_read(uint8_t addr) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD)); + out64((addr & 0xff), SMB_CSR(R_SMB_DATA)); + out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } + + return (in64(SMB_CSR(R_SMB_DATA)) & 0xff); +} + +static int xicor_write(uint8_t addr, int b) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64(addr, SMB_CSR(R_SMB_CMD)); + out64((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA)); + out64(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE, + SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } else { + return 0; + } +} + +#define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10) +#define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10) + +int xicor_set_time(unsigned long t) +{ + struct rtc_time tm; + int tmp; + + to_tm(t, &tm); + + /* unlock writes to the CCR */ + xicor_write(X1241REG_SR, X1241REG_SR_WEL); + xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); + + /* trivial ones */ + BIN_TO_BCD(tm.tm_sec); + xicor_write(X1241REG_SC, tm.tm_sec); + + BIN_TO_BCD(tm.tm_min); + xicor_write(X1241REG_MN, tm.tm_min); + + BIN_TO_BCD(tm.tm_mday); + xicor_write(X1241REG_DT, tm.tm_mday); + + /* tm_mon starts from 0, *ick* */ + tm.tm_mon ++; + BIN_TO_BCD(tm.tm_mon); + xicor_write(X1241REG_MO, tm.tm_mon); + + /* year is split */ + tmp = tm.tm_year / 100; + tm.tm_year %= 100; + xicor_write(X1241REG_YR, tm.tm_year); + xicor_write(X1241REG_Y2K, tmp); + + /* hour is the most tricky one */ + tmp = xicor_read(X1241REG_HR); + if (tmp & X1241REG_HR_MIL) { + /* 24 hour format */ + BIN_TO_BCD(tm.tm_hour); + tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f); + } else { + /* 12 hour format, with 0x2 for pm */ + tmp = tmp & ~0x3f; + if (tm.tm_hour >= 12) { + tmp |= 0x20; + tm.tm_hour -= 12; + } + BIN_TO_BCD(tm.tm_hour); + tmp |= tm.tm_hour; + } + xicor_write(X1241REG_HR, tmp); + + xicor_write(X1241REG_SR, 0); + + return 0; +} + +unsigned long xicor_get_time(void) +{ + unsigned int year, mon, day, hour, min, sec, y2k; + + sec = xicor_read(X1241REG_SC); + min = xicor_read(X1241REG_MN); + hour = xicor_read(X1241REG_HR); + + if (hour & X1241REG_HR_MIL) { + hour &= 0x3f; + } else { + if (hour & 0x20) + hour = (hour & 0xf) + 0x12; + } + + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + + day = xicor_read(X1241REG_DT); + mon = xicor_read(X1241REG_MO); + year = xicor_read(X1241REG_YR); + y2k = xicor_read(X1241REG_Y2K); + + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + BCD_TO_BIN(y2k); + + year += (y2k * 100); + + return mktime(year, mon, day, hour, min, sec); +} + diff -Nru up/arch/mips/config.in.orig up/arch/mips/config.in --- up/arch/mips/config.in.orig Thu Jan 24 16:25:45 2002 +++ up/arch/mips/config.in Fri Jan 25 10:50:57 2002 @@ -94,6 +94,8 @@ if [ "$CONFIG_SIBYTE_SB1250" = "y" ]; then define_bool CONFIG_NEW_IRQ y + define_bool CONFIG_NEW_TIME_C y + define_bool CONFIG_DUMMY_KEYB y define_bool CONFIG_SWAP_IO_SPACE y fi @@ -284,10 +286,6 @@ define_bool CONFIG_NONCOHERENT_IO y define_bool CONFIG_PCI y #not yet define_bool CONFIG_PCI_AUTO y -fi - -if [ "$CONFIG_SIBYTE_SWARM" = "y" ]; then - define_bool CONFIG_NEW_TIME_C y fi if [ "$CONFIG_TOSHIBA_JMR3927" = "y" ]; then diff -Nru up/include/asm-mips/time.h.orig up/include/asm-mips/time.h --- up/include/asm-mips/time.h.orig Thu Jan 24 16:36:28 2002 +++ up/include/asm-mips/time.h Fri Jan 25 11:01:13 2002 @@ -1,5 +1,5 @@ /* - * Copyright 2001 MontaVista Software Inc. + * Copyright (C) 2001, 2002, MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * * include/asm-mips/time.h @@ -59,6 +59,12 @@ * the corresponding low-level timer interrupt routine. */ asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs); + +/* + * profiling and process accouting is done separately in local_timer_interrupt + */ +void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs); +asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs); /* * board specific routines required by time_init().