Subject: Re: hardclock(9) for cobalt
To: None <port-cobalt@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-cobalt
Date: 08/22/2004 02:17:08
In article <20040817.110641.74750627.kiyohara@kk.iij4u.or.jp>
kiyohara@kk.iij4u.or.jp wrote:

 :
> The former is performed. ;-)

I rewrite your patch a bit:

- rename timer_enable() to timer_start()
- no need to make timer_disable() global
- set and pass timer_cookie for an arg for timer_start() and timer_read()
  (so that struct gttmr_core is not needed)
- declare timer_*() functions in cpu.h rather than autoconf.h
- use address passed via mainbus_attach_args for GT64111 base address
- I'm not sure gt64111reg.h and gt64111var.h are acceptable for MI part yet,
  put them in MD as dev/gtreg.h and dev/gtvar.h for now
- put more register definitions in gtreg.h
etc.

> > >   1. attach gt
> > >   2.   attach gttmr
> > >   3.   disable timer0
> > >   4.   set func pointers
> > >   5. clear INTR_CAUSE register
> > 
> > Looks good. Maybe 5. could be done by calling a special
> > function in gt.c.
> 
> Is doing by gt_attach() useless?
> 
> However, now, gt(4) is not very well. Should gt(4) also be corrected?

Umm...
Well, now I wonder if it's really better to attach the timer in GT64111.

It may be simpler to map whole region of GT64111 and to initialize
all registers in gt_attach() rather than to have separate gttimer
device attachment. I'll rethink how this should be implemented.

In article <20040818.040347.74752442.kiyohara@kk.iij4u.or.jp>
kiyohara@kk.iij4u.or.jp wrote:q

> Is it better to all also write the configuration register of GT64111 ?

If it is confirmed that all other registers are initialized properly
by the firmware, we don't have to reset them again in the device
attachment.
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp


Index: cobalt/clock.c
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/cobalt/clock.c,v
retrieving revision 1.7
diff -u -r1.7 clock.c
--- cobalt/clock.c	5 Jul 2004 07:28:45 -0000	1.7
+++ cobalt/clock.c	21 Aug 2004 16:50:39 -0000
@@ -34,6 +34,8 @@
 #include <sys/kernel.h>
 #include <sys/device.h>
 
+#include <machine/cpu.h>
+
 #include <dev/clock_subr.h>
 
 #include <dev/ic/mc146818reg.h>
@@ -47,6 +49,9 @@
 cpu_initclocks()
 {
 
+	/* start timer */
+	(*timer_start)(timer_cookie);
+
 	return;
 }
 
Index: cobalt/machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/cobalt/machdep.c,v
retrieving revision 1.51
diff -u -r1.51 machdep.c
--- cobalt/machdep.c	2 Apr 2004 23:18:09 -0000	1.51
+++ cobalt/machdep.c	21 Aug 2004 16:50:39 -0000
@@ -69,6 +69,8 @@
 
 #include <dev/cons.h>
 
+#include <cobalt/dev/gtreg.h>
+
 #ifdef KGDB
 #include <sys/kgdb.h>
 #endif
@@ -121,7 +123,9 @@
 extern caddr_t esym;
 extern struct user *proc0paddr;
 
-
+void (*timer_start)(void *);
+uint32_t (*timer_read)(void *);
+void *timer_cookie;
 
 /*
  * Do all the stuff that locore normally does before calling main().
@@ -365,7 +369,7 @@
 
 	*tvp = time;
 
-	counter0 = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(0x14000850);
+	counter0 = (*timer_read)(timer_cookie);
 
 	/*
 	 * XXX
@@ -453,10 +457,11 @@
 	uvmexp.intrs++;
 
 	if (ipending & MIPS_INT_MASK_0) {
+		/* XXX */
 		volatile u_int32_t *irq_src =
-				(u_int32_t *)MIPS_PHYS_TO_KSEG1(0x14000c18);
+		    (u_int32_t *)MIPS_PHYS_TO_KSEG1(0x14000000 + GT_INTR_CAUSE);
 
-		if (*irq_src & 0x00000100) {
+		if (*irq_src & T0EXP) {
 			*irq_src = 0;
 
 			cf.pc = pc;
Index: cobalt/mainbus.c
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/cobalt/mainbus.c,v
retrieving revision 1.8
diff -u -r1.8 mainbus.c
--- cobalt/mainbus.c	12 Sep 2003 14:59:13 -0000	1.8
+++ cobalt/mainbus.c	21 Aug 2004 16:50:39 -0000
@@ -106,7 +106,7 @@
 		return QUIET;
 
 	if (ma->ma_addr != MAINBUSCF_ADDR_DEFAULT)
-		aprint_normal(" addr 0x%lx", ma->ma_addr);
+		aprint_normal(" addr 0x%x", ma->ma_addr);
 	if (ma->ma_level != MAINBUSCF_LEVEL_DEFAULT)
 		aprint_normal(" level %d", ma->ma_level);
 
Index: conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/conf/GENERIC,v
retrieving revision 1.61
diff -u -r1.61 GENERIC
--- conf/GENERIC	15 Jul 2004 03:53:46 -0000	1.61
+++ conf/GENERIC	21 Aug 2004 16:50:39 -0000
@@ -151,6 +151,7 @@
 panel0 		at mainbus? addr 0x1f000000
 
 gt0 		at mainbus? addr 0x14000000
+gttimer0	at gt0
 
 pci* 		at gt0
 pchb* 		at pci? dev ? function ?
Index: conf/files.cobalt
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/conf/files.cobalt,v
retrieving revision 1.19
diff -u -r1.19 files.cobalt
--- conf/files.cobalt	17 Oct 2003 18:20:10 -0000	1.19
+++ conf/files.cobalt	21 Aug 2004 16:50:39 -0000
@@ -19,10 +19,15 @@
 attach panel at mainbus
 file arch/cobalt/dev/panel.c		panel
 
-device gt: pcibus
+define gt {}
+device gt: gt, pcibus
 attach gt at mainbus
 file arch/cobalt/dev/gt.c		gt
 
+device gttimer
+attach gttimer at gt
+file arch/cobalt/dev/gttimer.c		gttimer
+
 file arch/cobalt/cobalt/autoconf.c
 file arch/cobalt/cobalt/bus.c
 file arch/cobalt/cobalt/clock.c
Index: dev/gt.c
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/dev/gt.c,v
retrieving revision 1.9
diff -u -r1.9 gt.c
--- dev/gt.c	15 Jul 2003 01:29:23 -0000	1.9
+++ dev/gt.c	21 Aug 2004 16:50:39 -0000
@@ -43,14 +43,21 @@
 #include <sys/types.h>
 #include <sys/device.h>
 
+#include <machine/autoconf.h>
 #include <machine/intr.h>
 #include <machine/bus.h>
 
 #include <dev/pci/pcivar.h>
+
+#include <cobalt/dev/gtreg.h>
+#include <cobalt/dev/gtvar.h>
+
 #include "pci.h"
 
 struct gt_softc {
 	struct device	sc_dev;
+
+	uint32_t	sc_addr;
 };
 
 static int	gt_match(struct device *, struct cfdata *, void *);
@@ -60,6 +67,12 @@
 CFATTACH_DECL(gt, sizeof(struct gt_softc),
     gt_match, gt_attach, NULL, NULL);
 
+/* XXX */
+#define GT_READ_REG(sc, reg)	\
+    *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1((sc)->sc_addr + (reg))
+#define GT_WRITE_REG(sc, reg, val)	\
+    *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1((sc)->sc_addr + (reg)) = (val)
+
 static int
 gt_match(parent, match, aux)
 	struct device *parent;
@@ -75,14 +88,32 @@
 	struct device *self;
 	void *aux;
 {
+	struct mainbus_attach_args *ma = aux;
+	struct gt_softc *sc = (void *)self;
+	struct gt_attach_args ga;
+#if NPCI > 0
 	struct pcibus_attach_args pba;
+#endif
 
 	printf("\n");
 
-	/* XXX */
-	*((volatile u_int32_t *)0xb4000c00) =
-		(*((volatile u_int32_t *)0xb4000c00) & ~0x6) | 0x2;
+	sc->sc_addr = ma->ma_addr;
 
+	/*
+	 * timer0 is working at the time of BIOS. It might be got blocked
+	 * and timer interruption may already have generated it. A timer0
+	 * interruption must be cleared.
+	 */
+	ga.ga_name = "gttimer";
+	ga.ga_bst = ma->ma_iot;
+	ga.ga_base = sc->sc_addr;
+	config_found(self, &ga, gt_print);
+	GT_WRITE_REG(sc, GT_INTR_CAUSE,
+	    GT_READ_REG(sc, GT_INTR_CAUSE) & ~T0EXP);
+
+	/* XXX */
+	GT_WRITE_REG(sc, GT_PCI_COMMAND,
+	    (GT_READ_REG(sc, GT_PCI_COMMAND) & ~PCI_SYNCMODE) | PCI_PCLK_HIGH);
 #if NPCI > 0
 	pba.pba_busname = "pci";
 	pba.pba_dmat = &pci_bus_dma_tag;
@@ -94,7 +125,6 @@
 		PCI_FLAGS_MRL_OKAY | /*PCI_FLAGS_MRM_OKAY|*/ PCI_FLAGS_MWI_OKAY;
 	config_found(self, &pba, gt_print);
 #endif
-	return;
 }
 
 static int
Index: include/autoconf.h
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/include/autoconf.h,v
retrieving revision 1.2
diff -u -r1.2 autoconf.h
--- include/autoconf.h	5 May 2000 03:27:22 -0000	1.2
+++ include/autoconf.h	21 Aug 2004 16:50:39 -0000
@@ -29,7 +29,7 @@
 
 struct mainbus_attach_args {
 	char		*ma_name;
-	unsigned long	ma_addr;
+	uint32_t	ma_addr;
 	bus_space_tag_t	ma_iot;
 	bus_space_handle_t ma_ioh;
 	int		ma_level;
Index: include/cpu.h
===================================================================
RCS file: /cvsroot/src/sys/arch/cobalt/include/cpu.h,v
retrieving revision 1.10
diff -u -r1.10 cpu.h
--- include/cpu.h	4 Sep 2001 06:23:16 -0000	1.10
+++ include/cpu.h	21 Aug 2004 16:50:39 -0000
@@ -1,3 +1,11 @@
 /*	$NetBSD: cpu.h,v 1.10 2001/09/04 06:23:16 simonb Exp $	*/
 
 #include <mips/cpu.h>
+
+#ifdef _KERNEL
+#ifndef _LOCORE
+extern void (*timer_start)(void *);
+extern uint32_t (*timer_read)(void *);
+extern void *timer_cookie;
+#endif /* _LOCORE */
+#endif /* _KERNEL */
--- /dev/null	2004-08-22 01:45:17.000000000 +0900
+++ dev/gtreg.h	2004-08-22 01:14:08.000000000 +0900
@@ -0,0 +1,88 @@
+/* $NetBSD$ */
+/*
+ * Copyright (c) 2003
+ *     KIYOHARA Takashi.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define GT_TIMER_COUNT		0x850
+#define  TIMER_COUNT_REGSIZE	16
+#define  TIMER_COUNT_T0		0x0	/* offsets from GT_TIMER_COUNT */
+#define  TIMER_COUNT_T1		0x4
+#define  TIMER_COUNT_T2		0x8
+#define  TIMER_COUNT_T3		0xc
+
+
+#define GT_TIMER_CTRL		0x864
+#define  TIMER_CTRL_REGSIZE	4
+#define  ENTC0			0x01
+#define  TCSEL0			0x02
+#define  ENTC1			0x04
+#define  TCSEL1			0x08
+#define  ENTC2			0x10
+#define  TCSEL2			0x20
+#define  ENTC3			0x40
+#define  TCSEL3			0x80
+
+#define GT_PCI_COMMAND		0xc00
+#define  PCI_BYTESWAP		0x00000001
+#define  PCI_SYNCMODE		0x00000006
+#define  PCI_PCLK_LOW		0x00000000
+#define  PCI_PCLK_HIGH		0x00000002
+#define  PCI_PCLK_SYNC		0x00000004
+
+#define GT_INTR_CAUSE		0xc18
+#define  INTSUM			0x00000001
+#define  MEMOUT			0x00000002
+#define  DMAOUT			0x00000004
+#define  MASTEROUT		0x00000008
+#define  DMA0COMP		0x00000010
+#define  DMA1COMP		0x00000020
+#define  DMA2COMP		0x00000040
+#define  DMA3COMP		0x00000080
+#define  T0EXP			0x00000100
+#define  T1EXP			0x00000200
+#define  T2EXP			0x00000400
+#define  T3EXP			0x00000800
+#define  MASRDERR		0x00001000
+#define  SLVWRERR		0x00002000
+#define  MASWRERR		0x00004000
+#define  SLVRDERR		0x00008000
+#define  ADDRERR		0x00010000
+#define  MEMERR			0x00020000
+#define  MASABORT		0x00040000
+#define  TARABORT		0x00080000
+#define  RETRYCTR		0x00100000
+#define  MASTER_INT0		0x00200000
+#define  MASTER_INT1		0x00400000
+#define  MASTER_INT2		0x00800000
+#define  MASTER_INT3		0x01000000
+#define  MASTER_INT4		0x02000000
+#define  PCI_INT0		0x04000000
+#define  PCI_INT1		0x08000000
+#define  PCI_INT2		0x10000000
+#define  PCI_INT3		0x20000000
+#define  MASTER_INTSUM		0x40000000
+#define  PCI_INTSUM		0x80000000
+
+#define GT_MASTER_MASK		0xc1c
+#define GT_PCI_MASK		0xc24
--- /dev/null	2004-08-22 01:45:17.000000000 +0900
+++ dev/gtvar.h	2004-08-22 00:04:57.000000000 +0900
@@ -0,0 +1,31 @@
+/* $NetBSD$ */
+/*
+ * Copyright (c) 2003
+ *     KIYOHARA Takashi.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+struct gt_attach_args {
+	char *ga_name;			/* device name */
+	bus_space_tag_t	ga_bst;		/* bus space tag */
+	uint32_t ga_base;		/* base address */
+};
--- /dev/null	2004-08-22 01:45:17.000000000 +0900
+++ dev/gttimer.c	2004-08-22 01:43:35.000000000 +0900
@@ -0,0 +1,113 @@
+/* $NetBSD$ */
+/*
+ * Copyright (c) 2003
+ *     KIYOHARA Takashi.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+#include <machine/autoconf.h>
+#include <machine/bus.h>
+
+#include <cobalt/dev/gtreg.h>
+#include <cobalt/dev/gtvar.h>
+
+#define TIMER0_INIT_VALUE	500000
+
+struct gttimer_softc {
+	struct device sc_dev;
+
+	bus_space_tag_t sc_bst;
+	bus_space_handle_t sc_tmrh;
+	bus_space_handle_t sc_tmrch;
+};
+
+static int gttimer_match(struct device *, struct cfdata *, void *);
+static void gttimer_attach(struct device *, struct device *, void *);
+void timer0_start(void *);
+uint32_t timer0_read(void *);
+
+CFATTACH_DECL(gttimer, sizeof(struct gttimer_softc),
+    gttimer_match, gttimer_attach, NULL, NULL);
+
+void
+timer0_start(void *cookie)
+{
+	struct gttimer_softc *sc = cookie;
+
+	bus_space_write_4(sc->sc_bst, sc->sc_tmrh,
+	    TIMER_COUNT_T0, TIMER0_INIT_VALUE);
+	bus_space_write_4(sc->sc_bst, sc->sc_tmrch,
+	    0, bus_space_read_4(sc->sc_bst, sc->sc_tmrch, 0) | ENTC0);
+}
+
+uint32_t
+timer0_read(void *cookie)
+{
+	struct gttimer_softc *sc = cookie;
+
+	return bus_space_read_4(sc->sc_bst, sc->sc_tmrh, TIMER_COUNT_T0);
+}
+
+static int
+gttimer_match(struct device *parent, struct cfdata *match, void *aux)
+{
+	char **name = aux;
+
+	if (strcmp(*name, "gttimer") == 0)
+		return 1;
+	return 0;
+}
+
+static void
+gttimer_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct gttimer_softc *sc = (void *)self;
+	struct gt_attach_args *ga = aux;
+
+	sc->sc_bst = ga->ga_bst;
+	if (bus_space_map(sc->sc_bst, ga->ga_base + GT_TIMER_COUNT,
+	    TIMER_COUNT_REGSIZE, 0, &sc->sc_tmrh)) {
+		printf(": unable to map registers\n");
+		return;
+	}
+	if (bus_space_map(sc->sc_bst, ga->ga_base + GT_TIMER_CTRL,
+	    TIMER_CTRL_REGSIZE, 0, &sc->sc_tmrch)) {
+		printf(": unable to map control register\n");
+		bus_space_unmap(sc->sc_bst, sc->sc_tmrch, 16);
+		return;
+	}
+
+	printf(": 32/24bit-wide timer/counter on GT-64111\n");
+
+	/* stop timer0 */
+	bus_space_write_4(sc->sc_bst, sc->sc_tmrch, 0,
+	    bus_space_read_4(sc->sc_bst, sc->sc_tmrch, 0) & ~ENTC0);
+
+	timer_start = timer0_start;
+	timer_read = timer0_read;
+	timer_cookie = sc;
+}