Subject: Splitting sa1111 support codes.
To: None <port-arm@netbsd.org, port-hpcarm@netbsd.org>
From: None <bsh@netbsd.org>
List: port-arm
Date: 04/25/2003 18:48:32
Hi,

  I want to modify some files under sys/arch/arm/sa11x0 as in
following patch, so that common codes can be shared cleanly among
hpcarm and other platforms that have SA1111 companion chip.

  In the patch, I do:

     + extract #ifdef hpcarm parts from sa1111.c and sa11x1_pcic.c,
       leaving platform independent codes.
     + add files under sys/arch/{hpcarm,evbarm} for platform dependent
       part, for sa1111 attach routine and PCMCIA power control, etc.

  I've tested the patch on an evbarm platform.  I also checked
JORNADA720 kernel compiles ok with the change, but don't know it
really works as I don't have jornada.  The kernel is available as
ftp://ftp.grotto.jp/pub/netbsd/netbsd-JORNADA720.  Could someone
please try it?

  I'd also appreciate any comments on the patch.

TIA.

--
bsh.

diff -N --exclude=CVS -ru current/src/sys/arch/arm/sa11x0/sa1111.c new/src/sys/arch/arm/sa11x0/sa1111.c
--- current/src/sys/arch/arm/sa11x0/sa1111.c	Thu Oct 10 15:29:16 2002
+++ new/src/sys/arch/arm/sa11x0/sa1111.c	Fri Apr 18 18:03:16 2003
@@ -38,7 +38,6 @@
 
 /*
  * TODO:
- *   - separate machine specific attach code
  *   - introduce bus abstraction to support SA1101
  */
 
@@ -63,38 +62,26 @@
 #include <arm/sa11x0/sa1111_reg.h>
 #include <arm/sa11x0/sa1111_var.h>
 
-static	int	sacc_probe(struct device *, struct cfdata *, void *);
-static	void	sacc_attach(struct device *, struct device *, void *);
-static	int	sa1111_search(struct device *, struct cfdata *, void *);
+#include "locators.h"
+
 static	int	sa1111_print(void *, const char *);
 
 static void	sacc_intr_calculatemasks(struct sacc_softc *);
 static void	sacc_intr_setpolarity(sacc_chipset_tag_t *, int , int);
 int		sacc_intr(void *);
 
-#ifndef hpcarm
+#if !defined(__HAVE_GENERIC_SOFT_INTERRUPTS)
 void *softintr_establish(int, int (*)(void *), void *);
 void softintr_schedule(void *);
 #endif
 
-#ifdef hpcarm
-struct platid_data sacc_platid_table[] = {
-	{ &platid_mask_MACH_HP_JORNADA_720, (void *)1 },
-	{ &platid_mask_MACH_HP_JORNADA_720JP, (void *)1 },
-	{ NULL, NULL }
-};
-#endif
-
-CFATTACH_DECL(sacc, sizeof(struct sacc_softc),
-    sacc_probe, sacc_attach, NULL, NULL);
-
 #ifdef INTR_DEBUG
 #define DPRINTF(arg)	printf arg
 #else
 #define DPRINTF(arg)
 #endif
 
-static int
+int
 sacc_probe(parent, match, aux)
 	struct device *parent;
 	struct cfdata *match;
@@ -116,76 +103,25 @@
 	return (1);
 }
 
-static void
-sacc_attach(parent, self, aux)
-	struct device *parent;
-	struct device *self;
-	void *aux;
-{
-	int i, gpiopin;
-	u_int32_t skid;
-	struct sacc_softc *sc = (struct sacc_softc *)self;
-	struct sa11x0_softc *psc = (struct sa11x0_softc *)parent;
-	struct sa11x0_attach_args *sa = aux;
-#ifdef hpcarm
-	struct platid_data *p;
-#endif
-
-	printf("\n");
-
-	sc->sc_iot = sa->sa_iot;
-	sc->sc_piot = psc->sc_iot;
-	sc->sc_gpioh = psc->sc_gpioh;
-#ifdef hpcarm
-	if ((p = platid_search_data(&platid, sacc_platid_table)) == NULL)
-		return;
-
-	gpiopin = (int) p->data;
-#else
-	gpiopin = sa->sa_gpio;
-#endif
-	sc->sc_gpiomask = 1 << gpiopin;
 
-	if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0,
-			  &sc->sc_ioh)) {
-		printf("%s: unable to map registers\n", sc->sc_dev.dv_xname);
-		return;
-	}
-
-	skid = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCSBI_SKID);
-
-	printf("%s: SA1111 rev %d.%d\n", sc->sc_dev.dv_xname,
-	       (skid & 0xf0) >> 3, skid & 0xf);
-
-	for(i = 0; i < SACCIC_LEN; i++)
-		sc->sc_intrhand[i] = NULL;
-
-	/* initialize SA1111 interrupt controller */
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN0, 0);
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN1, 0);
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTTSTSEL, 0);
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
-			  SACCIC_INTSTATCLR0, 0xffffffff);
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
-			  SACCIC_INTSTATCLR1, 0xffffffff);
-
-	/* connect to SA1110's GPIO intr */
-	sa11x0_intr_establish(0, gpiopin, 1, IPL_SERIAL, sacc_intr, sc);
-
-	/*
-	 *  Attach each devices
-	 */
-	config_search(sa1111_search, self, NULL);
-}
-
-static int
+int
 sa1111_search(parent, cf, aux)
 	struct device *parent;
 	struct cfdata *cf;
 	void *aux;
 {
-        if (config_match(parent, cf, NULL) > 0)
-                config_attach(parent, cf, NULL, sa1111_print);
+	struct sa1111_attach_args aa;
+
+	aa.sa_addr = cf->cf_loc[SACCCF_ADDR];
+	aa.sa_size = cf->cf_loc[SACCCF_SIZE];
+	aa.sa_intr = cf->cf_loc[SACCCF_INTR];
+#if 0
+	aa.sa_membase = cf->cf_loc[SACCCF_MEMBASE];
+	aa.sa_memsize = cf->cf_loc[SACCCF_MEMSIZE];
+#endif
+
+        if (config_match(parent, cf, &aa) > 0)
+                config_attach(parent, cf, &aa, sa1111_print);
 
         return 0;
 }
@@ -198,54 +134,6 @@
 	return (UNCONF);
 }
 
-int
-sacc_intr(arg)
-	void *arg;
-{
-	int i;
-	u_int32_t mask;
-	struct sacc_intrvec intstat;
-	struct sacc_softc *sc = arg;
-#ifdef hpcarm
-	struct sacc_intrhand *ih;
-#endif
-
-	intstat.lo =
-	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTSTATCLR0);
-	intstat.hi =
-	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTSTATCLR1);
-	DPRINTF(("sacc_intr_dispatch: %x %x\n", intstat.lo, intstat.hi));
-
-	/* clear SA1110's GPIO intr status */
-	bus_space_write_4(sc->sc_piot, sc->sc_gpioh,
-			  SAGPIO_EDR, sc->sc_gpiomask);
-
-	for(i = 0, mask = 1; i < 32; i++, mask <<= 1)
-		if (intstat.lo & mask) {
-			/*
-			 * Clear intr status before calling intr handlers.
-			 * This cause stray interrupts, but clearing
-			 * after calling intr handlers cause intr lossage.
-			 */
-			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
-					  SACCIC_INTSTATCLR0, 1 << i);
-
-#ifdef hpcarm
-			for(ih = sc->sc_intrhand[i]; ih; ih = ih->ih_next)
-				softintr_schedule(ih->ih_soft);
-#endif
-		}
-	for(i = 0, mask = 1; i < SACCIC_LEN - 32; i++, mask <<= 1)
-		if (intstat.hi & mask) {
-			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
-					  SACCIC_INTSTATCLR1, 1 << i);
-#ifdef hpcarm
-			for(ih = sc->sc_intrhand[i + 32]; ih; ih = ih->ih_next)
-				softintr_schedule(ih->ih_soft);
-#endif
-		}
-	return 1;
-}
 
 void *
 sacc_intr_establish(ic, irq, type, level, ih_fun, ih_arg)
@@ -276,7 +164,15 @@
 		panic("sacc_intr_establish: type must be unique");
 
 	/* install intr handler */
-#ifdef hpcarm
+#if defined(__HAVE_GENERIC_SOFT_INTERRUPTS)
+	/* map interrupt level to appropriate softinterrupt level */
+	if (level >= IPL_SOFTSERIAL)
+		level = IPL_SOFTSERIAL;
+	else if(level >= IPL_SOFTNET)
+		level = IPL_SOFTNET;
+	ih->ih_soft = softintr_establish(level, (void (*)(void *)) ih_fun,
+					 ih_arg);
+#else	/* hpcarm */
 	ih->ih_soft = softintr_establish(level, (void (*)(void *)) ih_fun,
 					 ih_arg);
 #endif
diff -N --exclude=CVS -ru current/src/sys/arch/arm/sa11x0/sa1111_var.h new/src/sys/arch/arm/sa11x0/sa1111_var.h
--- current/src/sys/arch/arm/sa11x0/sa1111_var.h	Wed Apr 23 11:05:47 2003
+++ new/src/sys/arch/arm/sa11x0/sa1111_var.h	Wed Apr 23 12:14:09 2003
@@ -78,5 +78,7 @@
 void *sacc_intr_establish(sacc_chipset_tag_t *, int, int, int,
 			  int (*)(void *), void *);
 void sacc_intr_disestablish(sacc_chipset_tag_t *, void *);
+int	sacc_probe(struct device *, struct cfdata *, void *);
+int	sa1111_search(struct device *, struct cfdata *, void *);
 
 #endif /* _SA1111_VAR_H */
diff -N --exclude=CVS -ru current/src/sys/arch/arm/sa11x0/sa11x1_pcic.c new/src/sys/arch/arm/sa11x0/sa11x1_pcic.c
--- current/src/sys/arch/arm/sa11x0/sa11x1_pcic.c	Thu Oct 10 15:29:17 2002
+++ new/src/sys/arch/arm/sa11x0/sa11x1_pcic.c	Sat Mar  8 01:37:34 2003
@@ -47,10 +47,6 @@
 #include <sys/malloc.h>
 
 #include <machine/bus.h>
-#ifdef hpcarm
-#include <machine/platid.h>
-#include <machine/platid_mask.h>
-#endif
 
 #include <dev/pcmcia/pcmciachip.h>
 #include <dev/pcmcia/pcmciavar.h>
@@ -60,108 +56,37 @@
 #include <arm/sa11x0/sa1111_var.h>
 #include <arm/sa11x0/sa11x1_pcicreg.h>
 #include <arm/sa11x0/sa11xx_pcicvar.h>
+#include <arm/sa11x0/sa11x1_pcicvar.h>
 
 #include "sacpcic.h"
 
-static	int	sacpcic_match(struct device *, struct cfdata *, void *);
-static	void	sacpcic_attach(struct device *, struct device *, void *);
-static	int	sacpcic_print(void *, const char *);
-static	int	sacpcic_submatch(struct device *, struct cfdata *, void *);
-
-static	int	sacpcic_read(struct sapcic_socket *, int);
-static	void	sacpcic_write(struct sapcic_socket *, int, int);
-static	void	sacpcic_set_power(struct sapcic_socket *, int);
-static	void	sacpcic_clear_intr(int);
-static	void	*sacpcic_intr_establish(struct sapcic_socket *, int,
-				       int (*)(void *), void *);
-static	void	sacpcic_intr_disestablish(struct sapcic_socket *, void *);
-
-struct sacpcic_softc {
-	struct sapcic_softc sc_pc;
-	bus_space_handle_t sc_ioh;
-	
-	struct sapcic_socket sc_socket[2];
-};
-
-static struct sapcic_tag sacpcic_functions = {
-	sacpcic_read,
-	sacpcic_write,
-	sacpcic_set_power,
-	sacpcic_clear_intr,
-	sacpcic_intr_establish,
-	sacpcic_intr_disestablish
-};
-
-#ifdef hpcarm
-static int j720_power_capability[] = {
-	SAPCIC_POWER_5V | SAPCIC_POWER_3V, SAPCIC_POWER_3V
-};
-
-static struct platid_data sacpcic_platid_table[] = {
-	{ &platid_mask_MACH_HP_JORNADA_720, j720_power_capability },
-	{ &platid_mask_MACH_HP_JORNADA_720JP, j720_power_capability },
-	{ NULL, NULL }
-};
-#endif
-
-CFATTACH_DECL(sacpcic, sizeof(struct sacpcic_softc),
-    sacpcic_match, sacpcic_attach, NULL, NULL);
+static int	sacpcic_print(void *, const char *);
+static int	sacpcic_submatch(struct device *, struct cfdata *, void *);
 
-static int
-sacpcic_match(parent, cf, aux)
-	struct device *parent;
-	struct cfdata *cf;
-	void *aux;
-{
-	return (1);
-}
 
-static void
-sacpcic_attach(parent, self, aux)
-	struct device *parent;
-	struct device *self;
-	void *aux;
+void
+sacpcic_attach_common(struct sacc_softc *psc, struct sacpcic_softc *sc,
+    void *aux, void (* socket_setup_hook)(struct sapcic_socket *))
 {
 	int i;
-#ifdef hpcarm
-	int *ip;
-#endif
 	struct pcmciabus_attach_args paa;
-	struct sacpcic_softc *sc = (struct sacpcic_softc *)self;
-	struct sacc_softc *psc = (struct sacc_softc *)parent;
-#ifdef hpcarm
-	struct platid_data *p;
-#endif
 
 	printf("\n");
 
 	sc->sc_pc.sc_iot = psc->sc_iot;
 	sc->sc_ioh = psc->sc_ioh;
-#ifdef hpcarm
-	p = platid_search_data(&platid, sacpcic_platid_table);
-#endif
 
 	for(i = 0; i < 2; i++) {
 		sc->sc_socket[i].sc = (struct sapcic_softc *)sc;
 		sc->sc_socket[i].socket = i;
 		sc->sc_socket[i].pcictag_cookie = psc;
-		sc->sc_socket[i].pcictag = &sacpcic_functions;
+		sc->sc_socket[i].pcictag = NULL;
 		sc->sc_socket[i].event_thread = NULL;
 		sc->sc_socket[i].event = 0;
 		sc->sc_socket[i].laststatus = SAPCIC_CARD_INVALID;
 		sc->sc_socket[i].shutdown = 0;
 
-#ifdef hpcarm
-		if (p == NULL) {
-			sc->sc_socket[i].power_capability = SAPCIC_POWER_5V;
-		} else {
-			ip = (int *)p->data;
-			sc->sc_socket[i].power_capability = ip[i];
-		}
-#else
-		/* XXX */
-		sc->sc_socket[i].power_capability = SAPCIC_POWER_5V;
-#endif
+		socket_setup_hook(&sc->sc_socket[i]);
 
 		paa.paa_busname = "pcmcia";
 		paa.pct = (pcmcia_chipset_tag_t)&sa11x0_pcmcia_functions;
@@ -188,7 +113,7 @@
 	}
 }
 
-static int
+int
 sacpcic_print(aux, name)
 	void *aux;
 	const char *name;
@@ -196,20 +121,15 @@
 	return (UNCONF);
 }
 
-static int
-sacpcic_submatch(parent, cf, aux)
-	struct device *parent;
-	struct cfdata *cf;
-	void *aux;
+int
+sacpcic_submatch(struct device *parent, struct cfdata *cf, void *aux)
 {
 	return config_match(parent, cf, aux);
 }
 
 
-static int
-sacpcic_read(so, reg)
-	struct sapcic_socket *so;
-	int reg;
+int
+sacpcic_read(struct sapcic_socket *so, int reg)
 {
 	int cr, bit;
 	struct sacpcic_softc *sc = (struct sacpcic_softc *)so->sc;
@@ -241,11 +161,8 @@
 	}
 }
 
-static void
-sacpcic_write(so, reg, arg)
-	struct sapcic_socket *so;
-	int reg;
-	int arg;
+void
+sacpcic_write(struct sapcic_socket *so, int reg, int arg)
 {
 	int s, oldvalue, newvalue, mask;
 	struct sacpcic_softc *sc = (struct sacpcic_softc *)so->sc;
@@ -296,55 +213,13 @@
 	splx(s);
 }
 		
-static void
-sacpcic_set_power(so, arg)
-	struct sapcic_socket *so;
-	int arg;
-{
-	/* XXX this should go to dev/jornada720.c */
-	int newval, oldval, s;
-	struct sacc_softc *sc = so->pcictag_cookie;
-
-	/* XXX this isn't well confirmed. DANGER DANGER */
-	switch (arg) {
-	case SAPCIC_POWER_OFF:
-		newval = 0;
-		break;
-	case SAPCIC_POWER_3V:
-		newval = 2;
-		break;
-	case SAPCIC_POWER_5V:
-		newval = 1;
-		break;
-	default:
-		panic("sacpcic_set_power: bogus arg");
-	}
-
-	s = splbio();
-	oldval = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
-				  SACCGPIOA_DVR);
-	switch (so->socket) {
-	case 0:
-		newval = newval | (oldval & 0xc);
-		break;
-	case 1:
-		newval = (newval << 2) | (oldval & 3);
-		break;
-	default:
-		splx(s);
-		panic("sacpcic_set_power");
-	}
-	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCGPIOA_DVR, newval);
-	splx(s);
-}
-
-static void
+void
 sacpcic_clear_intr(arg)
 {
 	/* sacc_intr_dispatch takes care of intr status */
 }
 
-static void *
+void *
 sacpcic_intr_establish(so, level, ih_fun, ih_arg)
 	struct sapcic_socket *so;
 	int level;
@@ -358,7 +233,7 @@
 				    IST_EDGE_FALL, level, ih_fun, ih_arg));
 }
 
-static void
+void
 sacpcic_intr_disestablish(so, ih)
 	struct sapcic_socket *so;
 	void *ih;
diff -N --exclude=CVS -ru current/src/sys/arch/arm/sa11x0/sa11x1_pcicvar.h new/src/sys/arch/arm/sa11x0/sa11x1_pcicvar.h
--- current/src/sys/arch/arm/sa11x0/sa11x1_pcicvar.h	Thu Jan  1 09:00:00 1970
+++ new/src/sys/arch/arm/sa11x0/sa11x1_pcicvar.h	Sat Mar  8 01:37:34 2003
@@ -0,0 +1,60 @@
+/*	$NetBSD$ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the NetBSD
+ *	Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#ifndef _SA11X1_PCICVAR_H_
+#define _SA11X1_PCICVAR_H_
+
+struct sacpcic_softc {
+	struct sapcic_softc sc_pc;
+	bus_space_handle_t sc_ioh;
+	
+	struct sapcic_socket sc_socket[2];
+};
+
+void	sacpcic_attach_common(struct sacc_softc *, struct sacpcic_softc *,
+	    void *, void (*)(struct sapcic_socket *));
+
+int	sacpcic_read(struct sapcic_socket *, int);
+void	sacpcic_write(struct sapcic_socket *, int, int);
+void	sacpcic_set_power(struct sapcic_socket *, int);
+void	sacpcic_clear_intr(int);
+void	*sacpcic_intr_establish(struct sapcic_socket *, int,
+				       int (*)(void *), void *);
+void	sacpcic_intr_disestablish(struct sapcic_socket *, void *);
+
+#endif /* _SA11X1_PCICVAR_H_ */
diff -N --exclude=CVS -ru current/src/sys/arch/evbarm/conf/files.lubbock new/src/sys/arch/evbarm/conf/files.lubbock
--- current/src/sys/arch/evbarm/conf/files.lubbock	Thu Dec 19 22:55:36 2002
+++ new/src/sys/arch/evbarm/conf/files.lubbock	Sat Mar  8 01:38:10 2003
@@ -48,8 +48,9 @@
 
 device	sacpcic: pcmciabus
 attach	sacpcic at sacc
-file	arch/arm/sa11x0/sa11x1_pcic.c	sacpcic needs-flag
-file	arch/arm/sa11x0/sa11xx_pcic.c	sacpcic
+file	arch/arm/sa11x0/sa11x1_pcic.c     	sacpcic needs-flag
+file	arch/arm/sa11x0/sa11xx_pcic.c      	sacpcic
+file	arch/evbarm/lubbock/lubbock_pcic.c	sacpcic
 
 
 # LCD frame buffer
diff -N --exclude=CVS -ru current/src/sys/arch/hpcarm/conf/files.hpcarm new/src/sys/arch/hpcarm/conf/files.hpcarm
--- current/src/sys/arch/hpcarm/conf/files.hpcarm	Fri Nov  8 03:35:41 2002
+++ new/src/sys/arch/hpcarm/conf/files.hpcarm	Fri Apr 18 18:06:26 2003
@@ -34,6 +34,12 @@
 # Include hpcarm/StrongARM config definitions.
 include "arch/arm/conf/files.sa11x0"
 
+# SA11[01]1 companion chips
+file	arch/hpcarm/dev/sacc_hpcarm.c		sacc
+
+# platform dependent part of PCMCIA support.
+file	arch/hpcarm/dev/j720pcic.c	sacpcic
+
 # XXX iPAQ Virtual bus
 device	ipaqbus {}
 attach	ipaqbus at saip
diff -N --exclude=CVS -ru current/src/sys/arch/hpcarm/dev/j720pcic.c new/src/sys/arch/hpcarm/dev/j720pcic.c
--- current/src/sys/arch/hpcarm/dev/j720pcic.c	Thu Jan  1 09:00:00 1970
+++ new/src/sys/arch/hpcarm/dev/j720pcic.c	Sat Mar  8 01:40:30 2003
@@ -0,0 +1,163 @@
+/*      $NetBSD: sa11x1_pcic.c,v 1.7 2002/10/02 05:02:32 thorpej Exp $        */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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/systm.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+#include <machine/platid.h>
+#include <machine/platid_mask.h>
+
+#include <dev/pcmcia/pcmciachip.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <arm/sa11x0/sa11x0_reg.h>
+#include <arm/sa11x0/sa11x0_var.h>
+#include <arm/sa11x0/sa1111_reg.h>
+#include <arm/sa11x0/sa1111_var.h>
+#include <arm/sa11x0/sa11x1_pcicreg.h>
+#include <arm/sa11x0/sa11xx_pcicvar.h>
+#include <arm/sa11x0/sa11x1_pcicvar.h>
+
+#include "sacpcic.h"
+
+static	int	sacpcic_match(struct device *, struct cfdata *, void *);
+static	void	sacpcic_attach(struct device *, struct device *, void *);
+static	void	j720_set_power(struct sapcic_socket *so, int arg);
+
+static struct sapcic_tag j720_sacpcic_functions = {
+	sacpcic_read,
+	sacpcic_write,
+	j720_set_power,
+	sacpcic_clear_intr,
+	sacpcic_intr_establish,
+	sacpcic_intr_disestablish
+};
+
+static int j720_power_capability[] = {
+	SAPCIC_POWER_5V | SAPCIC_POWER_3V, SAPCIC_POWER_3V
+};
+
+static struct platid_data sacpcic_platid_table[] = {
+	{ &platid_mask_MACH_HP_JORNADA_720, j720_power_capability },
+	{ &platid_mask_MACH_HP_JORNADA_720JP, j720_power_capability },
+	{ NULL, NULL }
+};
+
+CFATTACH_DECL(sacpcic, sizeof(struct sacpcic_softc),
+    sacpcic_match, sacpcic_attach, NULL, NULL);
+
+static int
+sacpcic_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	return (1);
+}
+
+static void
+j720_socket_setup(struct sapcic_socket *sp)
+{
+	int *ip;
+	struct platid_data *p;
+	int socket = sp->socket;
+
+	p = platid_search_data(&platid, sacpcic_platid_table);
+
+	if (p == NULL) {
+		sp->power_capability = SAPCIC_POWER_5V;
+	} else {
+		ip = (int *)p->data;
+		sp->power_capability = ip[socket];
+	}
+
+	sp->pcictag = &j720_sacpcic_functions;
+}
+
+static void
+sacpcic_attach(struct device *parent, struct device *self, void *aux)
+{
+	sacpcic_attach_common((struct sacc_softc *)parent,
+	    (struct sacpcic_softc *)self, aux, j720_socket_setup);
+}
+
+static void
+j720_set_power(so, arg)
+	struct sapcic_socket *so;
+	int arg;
+{
+	int newval, oldval, s;
+	struct sacc_softc *sc = so->pcictag_cookie;
+
+	/* XXX this isn't well confirmed. DANGER DANGER */
+	switch (arg) {
+	case SAPCIC_POWER_OFF:
+		newval = 0;
+		break;
+	case SAPCIC_POWER_3V:
+		newval = 2;
+		break;
+	case SAPCIC_POWER_5V:
+		newval = 1;
+		break;
+	default:
+		panic("sacpcic_set_power: bogus arg");
+	}
+
+	s = splbio();
+	oldval = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
+				  SACCGPIOA_DVR);
+	switch (so->socket) {
+	case 0:
+		newval = newval | (oldval & 0xc);
+		break;
+	case 1:
+		newval = (newval << 2) | (oldval & 3);
+		break;
+	default:
+		splx(s);
+		panic("sacpcic_set_power");
+	}
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCGPIOA_DVR, newval);
+	splx(s);
+}
+
diff -N --exclude=CVS -ru current/src/sys/arch/hpcarm/dev/sacc_hpcarm.c new/src/sys/arch/hpcarm/dev/sacc_hpcarm.c
--- current/src/sys/arch/hpcarm/dev/sacc_hpcarm.c	Thu Jan  1 09:00:00 1970
+++ new/src/sys/arch/hpcarm/dev/sacc_hpcarm.c	Fri Apr 25 17:14:23 2003
@@ -0,0 +1,182 @@
+/*      $NetBSD: sa1111.c,v 1.9 2002/10/02 05:02:31 thorpej Exp $	*/
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+/*
+ * Platform dependent part for SA11[01]1 companion chip on hpcarm.
+ *
+ * TODO:
+ *   - introduce bus abstraction to support SA1101
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/uio.h>
+
+#include <machine/bus.h>
+#include <machine/platid.h>
+#include <machine/platid_mask.h>
+
+#include <arm/sa11x0/sa11x0_reg.h>
+#include <arm/sa11x0/sa11x0_var.h>
+#include <arm/sa11x0/sa11x0_gpioreg.h>
+#include <arm/sa11x0/sa1111_reg.h>
+#include <arm/sa11x0/sa1111_var.h>
+
+#include "locators.h"
+
+static	void	sacc_attach(struct device *, struct device *, void *);
+static int	sacc_intr(void *);
+
+struct platid_data sacc_platid_table[] = {
+	{ &platid_mask_MACH_HP_JORNADA_720, (void *)1 },
+	{ &platid_mask_MACH_HP_JORNADA_720JP, (void *)1 },
+	{ NULL, NULL }
+};
+
+CFATTACH_DECL(sacc, sizeof(struct sacc_softc),
+    sacc_probe, sacc_attach, NULL, NULL);
+
+#ifdef INTR_DEBUG
+#define DPRINTF(arg)	printf arg
+#else
+#define DPRINTF(arg)
+#endif
+
+static void
+sacc_attach(parent, self, aux)
+	struct device *parent;
+	struct device *self;
+	void *aux;
+{
+	int i, gpiopin;
+	u_int32_t skid;
+	struct sacc_softc *sc = (struct sacc_softc *)self;
+	struct sa11x0_softc *psc = (struct sa11x0_softc *)parent;
+	struct sa11x0_attach_args *sa = aux;
+	struct platid_data *p;
+
+	printf("\n");
+
+	sc->sc_iot = sa->sa_iot;
+	sc->sc_piot = psc->sc_iot;
+	sc->sc_gpioh = psc->sc_gpioh;
+	if ((p = platid_search_data(&platid, sacc_platid_table)) == NULL)
+		return;
+
+	gpiopin = (int) p->data;
+	sc->sc_gpiomask = 1 << gpiopin;
+
+	if (bus_space_map(sa->sa_iot, sa->sa_addr, sa->sa_size, 0,
+			  &sc->sc_ioh)) {
+		printf("%s: unable to map registers\n", sc->sc_dev.dv_xname);
+		return;
+	}
+
+	skid = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCSBI_SKID);
+
+	printf("%s: SA1111 rev %d.%d\n", sc->sc_dev.dv_xname,
+	       (skid & 0xf0) >> 3, skid & 0xf);
+
+	for(i = 0; i < SACCIC_LEN; i++)
+		sc->sc_intrhand[i] = NULL;
+
+	/* initialize SA1111 interrupt controller */
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN0, 0);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTEN1, 0);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTTSTSEL, 0);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+			  SACCIC_INTSTATCLR0, 0xffffffff);
+	bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+			  SACCIC_INTSTATCLR1, 0xffffffff);
+
+	/* connect to SA1110's GPIO intr */
+	sa11x0_intr_establish(0, gpiopin, 1, IPL_SERIAL, sacc_intr, sc);
+
+	/*
+	 *  Attach each devices
+	 */
+	config_search(sa1111_search, self, NULL);
+}
+
+static int
+sacc_intr(arg)
+	void *arg;
+{
+	int i;
+	u_int32_t mask;
+	struct sacc_intrvec intstat;
+	struct sacc_softc *sc = arg;
+	struct sacc_intrhand *ih;
+
+	intstat.lo =
+	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTSTATCLR0);
+	intstat.hi =
+	    bus_space_read_4(sc->sc_iot, sc->sc_ioh, SACCIC_INTSTATCLR1);
+	DPRINTF(("sacc_intr_dispatch: %x %x\n", intstat.lo, intstat.hi));
+
+	/* clear SA1110's GPIO intr status */
+	bus_space_write_4(sc->sc_piot, sc->sc_gpioh,
+			  SAGPIO_EDR, sc->sc_gpiomask);
+
+	for(i = 0, mask = 1; i < 32; i++, mask <<= 1)
+		if (intstat.lo & mask) {
+			/*
+			 * Clear intr status before calling intr handlers.
+			 * This cause stray interrupts, but clearing
+			 * after calling intr handlers cause intr lossage.
+			 */
+			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+					  SACCIC_INTSTATCLR0, 1 << i);
+
+			for(ih = sc->sc_intrhand[i]; ih; ih = ih->ih_next)
+				softintr_schedule(ih->ih_soft);
+		}
+	for(i = 0, mask = 1; i < SACCIC_LEN - 32; i++, mask <<= 1)
+		if (intstat.hi & mask) {
+			bus_space_write_4(sc->sc_iot, sc->sc_ioh,
+					  SACCIC_INTSTATCLR1, 1 << i);
+			for(ih = sc->sc_intrhand[i + 32]; ih; ih = ih->ih_next)
+				softintr_schedule(ih->ih_soft);
+		}
+	return 1;
+}
diff -N --exclude=CVS -ru current/src/sys/arch/evbarm/lubbock/lubbock_pcic.c new/src/sys/arch/evbarm/lubbock/lubbock_pcic.c
--- current/src/sys/arch/evbarm/lubbock/lubbock_pcic.c	Thu Jan  1 09:00:00 1970
+++ new/src/sys/arch/evbarm/lubbock/lubbock_pcic.c	Fri Apr 25 16:52:09 2003
@@ -0,0 +1,142 @@
+/*      $NetBSD$ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by IWAMOTO Toshihiro.
+ *
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *        This product includes software developed by the NetBSD
+ *        Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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/systm.h>
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/malloc.h>
+
+#include <machine/bus.h>
+
+#include <dev/pcmcia/pcmciachip.h>
+#include <dev/pcmcia/pcmciavar.h>
+#include <arm/sa11x0/sa11x0_reg.h>
+#include <arm/sa11x0/sa11x0_var.h>
+#include <arm/sa11x0/sa1111_reg.h>
+#include <arm/sa11x0/sa1111_var.h>
+#include <arm/sa11x0/sa11x1_pcicreg.h>
+#include <arm/sa11x0/sa11xx_pcicvar.h>
+#include <arm/sa11x0/sa11x1_pcicvar.h>
+
+#include <evbarm/lubbock/lubbock_reg.h>
+#include <evbarm/lubbock/lubbock_var.h>
+
+static	int	sacpcic_match(struct device *, struct cfdata *, void *);
+static	void	sacpcic_attach(struct device *, struct device *, void *);
+static	void	lubbock_set_power(struct sapcic_socket *so, int arg);
+static	void	lubbock_socket_setup(struct sapcic_socket *sp);
+
+static struct sapcic_tag lubbock_sacpcic_functions = {
+	sacpcic_read,
+	sacpcic_write,
+	lubbock_set_power,
+	sacpcic_clear_intr,
+	sacpcic_intr_establish,
+	sacpcic_intr_disestablish
+};
+
+CFATTACH_DECL(sacpcic, sizeof(struct sacpcic_softc),
+    sacpcic_match, sacpcic_attach, NULL, NULL);
+
+static int
+sacpcic_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+	return (1);
+}
+
+static void
+lubbock_socket_setup(struct sapcic_socket *sp)
+{
+	sp->power_capability = SAPCIC_POWER_5V | SAPCIC_POWER_3V;
+	sp->pcictag = &lubbock_sacpcic_functions;
+}
+
+static void
+sacpcic_attach(struct device *parent, struct device *self, void *aux)
+{
+	sacpcic_attach_common((struct sacc_softc *)parent,
+	    (struct sacpcic_softc *)self, aux, lubbock_socket_setup);
+}
+
+
+static void
+lubbock_set_power(struct sapcic_socket *so, int arg)
+{
+	struct sacc_softc *sc = so->pcictag_cookie;
+	struct obio_softc *bsc = (struct obio_softc *)sc->sc_dev.dv_parent;
+	int s;
+	uint16_t tmp;
+
+	static const uint8_t vval_socket0[] = {
+		/* for socket0 (pcmcia) */
+		0x00,		/* OFF */
+		0x08,		/* 3.3V */
+		0x05,		/* 5V */
+	};
+	static const uint16_t vval_socket1[] = {
+		/* for socket1 (CF) */
+		0x0000,		/* OFF */
+		0x8000,		/* 3.3V */
+		0x4000,		/* 5V */
+	};
+
+	if( arg < 0 || SAPCIC_POWER_5V < arg )
+		panic("sacpcic_set_power: bogus arg\n");
+			
+	switch( so->socket ){
+	case 0:
+		bus_space_write_4(sc->sc_iot, sc->sc_ioh, SACCGPIOA_DVR, 
+				  vval_socket0[arg]);
+		break;
+	case 1:
+		s = splhigh();
+		tmp = bus_space_read_2(bsc->sc_iot, bsc->sc_obioreg_ioh,
+		    LUBBOCK_MISCWR);
+		bus_space_write_2(bsc->sc_iot, bsc->sc_obioreg_ioh,
+		    LUBBOCK_MISCWR, (tmp & 0x3fff) | vval_socket1[arg] );
+		splx(s);
+		break;
+	default:
+		printf("unknown socket number: %d\n", so->socket);
+	}
+}