Module Name:    src
Committed By:   nisimura
Date:           Fri Feb 10 09:17:49 UTC 2012

Modified Files:
        src/sys/arch/arm/s3c2xx0: s3c24x0_clk.c

Log Message:
- use a correct bit mask to pick SRCPND register indication.
- reading timer#4 possibly returns value '0'.  Having the
  '0' and a timer reload interrupt results in a too large
  number, meaning the next get_timecounter() call will
  return a smaller one than the previous, effectively kill
  things.  Handle this case.

ping(8) now shows better precisions.  Fixes from Paul Fleischer.

Ok by releng.


To generate a diff of this commit:
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/arm/s3c2xx0/s3c24x0_clk.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/s3c2xx0/s3c24x0_clk.c
diff -u src/sys/arch/arm/s3c2xx0/s3c24x0_clk.c:1.13 src/sys/arch/arm/s3c2xx0/s3c24x0_clk.c:1.14
--- src/sys/arch/arm/s3c2xx0/s3c24x0_clk.c:1.13	Tue Feb  7 09:06:05 2012
+++ src/sys/arch/arm/s3c2xx0/s3c24x0_clk.c	Fri Feb 10 09:17:49 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: s3c24x0_clk.c,v 1.13 2012/02/07 09:06:05 nisimura Exp $ */
+/*	$NetBSD: s3c24x0_clk.c,v 1.14 2012/02/10 09:17:49 nisimura Exp $ */
 
 /*
  * Copyright (c) 2003  Genetec corporation.  All rights reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: s3c24x0_clk.c,v 1.13 2012/02/07 09:06:05 nisimura Exp $");
+__KERNEL_RCSID(0, "$NetBSD: s3c24x0_clk.c,v 1.14 2012/02/10 09:17:49 nisimura Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -53,9 +53,9 @@ __KERNEL_RCSID(0, "$NetBSD: s3c24x0_clk.
 
 #define TIMER_FREQUENCY(pclk) ((pclk)/16) /* divider=1/16 */
 
-static unsigned int timer4_reload_value;
-static unsigned int timer4_prescaler;
-static unsigned int timer4_mseccount;
+static uint32_t timer4_reload_value;
+static uint32_t timer4_prescaler;
+static uint32_t timer4_mseccount;
 
 #define usec_to_counter(t)	\
 	((timer4_mseccount*(t))/1000)
@@ -68,7 +68,7 @@ static u_int	s3c24x0_get_timecount(struc
 static struct timecounter s3c24x0_timecounter = {
 	s3c24x0_get_timecount,	/* get_timecount */
 	0,			/* no poll_pps */
-	0xfff,			/* counter_mask */
+	0xffffffff,		/* counter_mask */
 	0,			/* frequency */
 	"s3c24x0",		/* name */
 	100,			/* quality */
@@ -83,21 +83,22 @@ s3c24x0_get_timecount(struct timecounter
 {
 	struct s3c24x0_softc *sc = (struct s3c24x0_softc *) s3c2xx0_softc;
 	int save, int_pend0, int_pend1, count;
+	int int_pend;
 
 	save = disable_interrupts(I32_bit);
 
  again:
-	int_pend0 = S3C24X0_INT_TIMER4 &
-	    bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_intctl_ioh,
+	int_pend = bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_intctl_ioh,
 		INTCTL_SRCPND);
+	int_pend0 = (1<<S3C24X0_INT_TIMER4) & int_pend;
 	count = bus_space_read_2(sc->sc_sx.sc_iot, sc->sc_timer_ioh,
 	    TIMER_TCNTO(4));
 	
 	for (;;) {
 
-		int_pend1 = S3C24X0_INT_TIMER4 &
-		    bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_intctl_ioh,
-			INTCTL_SRCPND);
+		int_pend1 = bus_space_read_4(sc->sc_sx.sc_iot,
+			sc->sc_sx.sc_intctl_ioh, INTCTL_SRCPND);
+		int_pend1 &= (1<<S3C24X0_INT_TIMER4);
 		if( int_pend0 == int_pend1 )
 			break;
 
@@ -122,11 +123,10 @@ s3c24x0_get_timecount(struct timecounter
 
 	restore_interrupts(save);
 
-	if (int_pend1) {
+	if (int_pend1 && count > 0) {
 		count -= timer4_reload_value;
 	}
 
-	//printf("delta: %u\n", (s3c24x0_base - count));
 	return s3c24x0_base - count;
 }
 
@@ -250,7 +250,7 @@ cpu_initclocks(void)
 	calc_time_constant(h);
 
 	timer4_prescaler = prescaler;
-	timer4_reload_value = TIMER_FREQUENCY(pclk) / hz / prescaler;
+	timer4_reload_value = (TIMER_FREQUENCY(pclk) / hz / prescaler) - 1;
 	timer4_mseccount = TIMER_FREQUENCY(pclk)/timer4_prescaler/1000 ;
 
 	bus_space_write_4(iot, ioh, TIMER_TCNTB(4),

Reply via email to