patch-2.4.20 linux-2.4.20/arch/mips/sibyte/sb1250/time.c
Next file: linux-2.4.20/arch/mips/sibyte/swarm/Makefile
Previous file: linux-2.4.20/arch/mips/sibyte/sb1250/smp.c
Back to the patch index
Back to the overall index
- Lines: 96
- Date:
Thu Nov 28 15:53:10 2002
- Orig file:
linux-2.4.19/arch/mips/sibyte/sb1250/time.c
- Orig date:
Fri Aug 2 17:39:43 2002
diff -urN linux-2.4.19/arch/mips/sibyte/sb1250/time.c linux-2.4.20/arch/mips/sibyte/sb1250/time.c
@@ -10,17 +10,17 @@
* 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.
*/
-/*
+/*
* These are routines to set up and handle interrupts from the
* sb1250 general purpose timer 0. We're using the timer as a
* system clock, so we set it up to run at 100 Hz. On every
- * interrupt, we update our idea of what the time of day is,
+ * interrupt, we update our idea of what the time of day is,
* then call do_timer() in the architecture-independent kernel
* code to do general bookkeeping (e.g. update jiffies, run
* bottom halves, etc.)
@@ -29,6 +29,7 @@
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
+#include <linux/kernel_stat.h>
#include <asm/irq.h>
#include <asm/ptrace.h>
@@ -46,6 +47,8 @@
#define IMR_IP3_VAL K_INT_MAP_I1
#define IMR_IP4_VAL K_INT_MAP_I2
+extern int sb1250_steal_irq(int irq);
+
void sb1250_time_init(void)
{
int cpu = smp_processor_id();
@@ -55,11 +58,16 @@
BUG();
}
+ if (!cpu) {
+ /* Use our own gettimeoffset() routine */
+ do_gettimeoffset = sb1250_gettimeoffset;
+ }
+
sb1250_mask_irq(cpu, K_INT_TIMER_0 + cpu);
-
+
/* Map the timer interrupt to ip[4] of this cpu */
- out64(IMR_IP4_VAL, KSEG1 + A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE)
- + ((K_INT_TIMER_0 + cpu)<<3));
+ out64(IMR_IP4_VAL, KSEG1 + A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE)
+ + ((K_INT_TIMER_0 + cpu)<<3));
/* the general purpose timer ticks at 1 Mhz independent if the rest of the system */
/* Disable the timer and set up the count */
@@ -77,6 +85,7 @@
KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
sb1250_unmask_irq(cpu, K_INT_TIMER_0 + cpu);
+ sb1250_steal_irq(K_INT_TIMER_0 + cpu);
/*
* This interrupt is "special" in that it doesn't use the request_irq
* way to hook the irq line. The timer interrupt is initialized early
@@ -91,9 +100,10 @@
{
int cpu = smp_processor_id();
+ kstat.irqs[cpu][K_INT_TIMER_0+cpu]++;
/* Reset the timer */
out64(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS,
- KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
+ KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG));
/*
* CPU 0 handles the global timer interrupt job
@@ -107,3 +117,17 @@
*/
ll_local_timer_interrupt(0, regs);
}
+
+/*
+ * We use our own do_gettimeoffset() instead of the generic one,
+ * because the generic one does not work for SMP case.
+ * In addition, since we use general timer 0 for system time,
+ * we can get accurate intra-jiffy offset without calibration.
+ */
+unsigned long sb1250_gettimeoffset(void)
+{
+ unsigned long count =
+ in64(KSEG1 + A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT));
+
+ return 1000000/HZ - count;
+ }
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)