summaryrefslogtreecommitdiff
path: root/sys/arch/zaurus/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/zaurus/dev')
-rw-r--r--sys/arch/zaurus/dev/scoop_pcic.c252
-rw-r--r--sys/arch/zaurus/dev/zaurus_scoop.c18
-rw-r--r--sys/arch/zaurus/dev/zaurus_scoopreg.h53
3 files changed, 299 insertions, 24 deletions
diff --git a/sys/arch/zaurus/dev/scoop_pcic.c b/sys/arch/zaurus/dev/scoop_pcic.c
new file mode 100644
index 00000000000..b663fc567a4
--- /dev/null
+++ b/sys/arch/zaurus/dev/scoop_pcic.c
@@ -0,0 +1,252 @@
+/* $OpenBSD: scoop_pcic.c,v 1.1 2005/07/01 23:51:55 uwe Exp $ */
+
+/*
+ * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <uvm/uvm.h>
+
+#include <arch/arm/xscale/pxa2x0var.h>
+#include <arch/arm/xscale/pxapcicvar.h>
+
+#include <machine/zaurus_reg.h>
+#include <machine/zaurus_var.h>
+
+#include <zaurus/dev/zaurus_scoopreg.h>
+
+int scoop_pcic_match(struct device *, void *, void *);
+void scoop_pcic_attach(struct device *, struct device *, void *);
+void scoop_pcic_socket_setup(struct pxapcic_socket *);
+
+struct cfattach pxapcic_scoop_ca = {
+ sizeof(struct pxapcic_softc), scoop_pcic_match,
+ scoop_pcic_attach
+};
+
+u_int scoop_pcic_read(struct pxapcic_socket *, int);
+void scoop_pcic_write(struct pxapcic_socket *, int, u_int);
+void scoop_pcic_set_power(struct pxapcic_socket *, int);
+void scoop_pcic_clear_intr(struct pxapcic_socket *);
+
+struct pxapcic_tag scoop_pcic_functions = {
+ scoop_pcic_read,
+ scoop_pcic_write,
+ scoop_pcic_set_power,
+ scoop_pcic_clear_intr,
+ 0, /* intr_establish */
+ 0, /* intr_disestablish */
+ 0 /* intr_string */
+};
+
+int
+scoop_pcic_match(struct device *parent, void *cf, void *aux)
+{
+ return (ZAURUS_ISC860 || ZAURUS_ISC3000);
+}
+
+void
+scoop_pcic_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct pxapcic_softc *sc = (struct pxapcic_softc *)self;
+ struct pxaip_attach_args *pxa = aux;
+
+ sc->sc_iot = pxa->pxa_iot;
+
+ if (ZAURUS_ISC860) {
+ sc->sc_nslots = 1;
+ sc->sc_irqpin[0] = C860_CF0_IRQ;
+ sc->sc_irqcfpin[0] = C860_CF0_IRQ_PIN;
+ } else if (ZAURUS_ISC3000) {
+ sc->sc_nslots = 2;
+ sc->sc_irqpin[0] = C3000_CF0_IRQ;
+ sc->sc_irqcfpin[0] = C3000_CF0_IRQ_PIN;
+ sc->sc_irqpin[1] = C3000_CF1_IRQ;
+ sc->sc_irqcfpin[1] = C3000_CF1_IRQ_PIN;
+ }
+
+ pxapcic_attach(sc, &scoop_pcic_socket_setup);
+}
+
+void
+scoop_pcic_socket_setup(struct pxapcic_socket *so)
+{
+ struct pxapcic_softc *sc;
+ bus_addr_t pa;
+ bus_size_t size = SCOOP_SIZE;
+ bus_space_tag_t iot;
+ bus_space_handle_t scooph;
+ int error;
+
+ sc = so->sc;
+ iot = sc->sc_iot;
+
+ if (so->socket == 0)
+ pa = C3000_SCOOP0_BASE;
+ else if (so->socket == 1)
+ pa = C3000_SCOOP1_BASE;
+ else
+ panic("%s: invalid CF slot %d", sc->sc_dev.dv_xname,
+ so->socket);
+ error = bus_space_map(iot, trunc_page(pa), round_page(size),
+ 0, &scooph);
+ if (error)
+ panic("%s: failed to map memory %x for scoop",
+ sc->sc_dev.dv_xname, pa);
+ scooph += pa - trunc_page(pa);
+
+ bus_space_write_2(iot, scooph, SCOOP_IMR,
+ SCP_IMR_UNKN0 | SCP_IMR_UNKN1);
+
+ /* setup */
+ bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0100);
+ bus_space_write_2(iot, scooph, SCOOP_CDR, 0x0000);
+ bus_space_write_2(iot, scooph, SCOOP_CPR, 0x0000);
+ bus_space_write_2(iot, scooph, SCOOP_IMR, 0x0000);
+ bus_space_write_2(iot, scooph, SCOOP_IRM, 0x00ff);
+ bus_space_write_2(iot, scooph, SCOOP_ISR, 0x0000);
+ bus_space_write_2(iot, scooph, SCOOP_IRM, 0x0000);
+
+ /* C3000 */
+ if (so->socket == 1) {
+ bus_space_write_2(iot, scooph, SCOOP_CPR, 0x80c1);
+ bus_space_write_2(iot, scooph, SCOOP_IMR, 0x00c4);
+ bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0111);
+ } else {
+ bus_space_write_2(iot, scooph, SCOOP_CPR,
+ SCP_CPR_PWR|SCP_CPR_5V);
+ }
+
+ bus_space_write_2(iot, scooph, SCOOP_IMR, 0x00ce);
+ bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0111);
+
+ /* C3000 */
+ so->power_capability = PXAPCIC_POWER_3V;
+ if (so->socket == 0)
+ so->power_capability |= PXAPCIC_POWER_5V;
+
+ so->pcictag_cookie = (void *)scooph;
+ so->pcictag = &scoop_pcic_functions;
+}
+
+u_int
+scoop_pcic_read(struct pxapcic_socket *so, int reg)
+{
+ bus_space_tag_t iot = so->sc->sc_iot;
+ bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
+ u_int16_t csr;
+
+ csr = bus_space_read_2(iot, ioh, SCOOP_CSR);
+
+ switch (reg) {
+ case PXAPCIC_CARD_STATUS:
+ if (csr & SCP_CSR_MISSING)
+ return (PXAPCIC_CARD_INVALID);
+ else
+ return (PXAPCIC_CARD_VALID);
+
+ case PXAPCIC_CARD_READY:
+ return ((bus_space_read_2(iot, ioh, SCOOP_CSR) &
+ SCP_CSR_READY) != 0);
+
+ default:
+ panic("scoop_pcic_read: bogus register");
+ }
+}
+
+void
+scoop_pcic_write(struct pxapcic_socket *so, int reg, u_int val)
+{
+ bus_space_tag_t iot = so->sc->sc_iot;
+ bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
+ u_int16_t newval;
+ int s;
+
+ s = splhigh();
+
+ switch (reg) {
+ case PXAPCIC_CARD_POWER:
+ newval = bus_space_read_2(iot, ioh, SCOOP_CPR);
+ newval &= ~(SCP_CPR_PWR | SCP_CPR_3V | SCP_CPR_5V);
+
+ if (val == PXAPCIC_POWER_3V)
+ newval |= (SCP_CPR_PWR | SCP_CPR_3V);
+ else if (val == PXAPCIC_POWER_5V)
+ newval |= (SCP_CPR_PWR | SCP_CPR_5V);
+
+ bus_space_write_2(iot, ioh, SCOOP_CPR, newval);
+ break;
+
+ case PXAPCIC_CARD_RESET:
+ bus_space_write_2(iot, ioh, SCOOP_CCR,
+ val ? SCP_CCR_RESET : 0);
+ break;
+
+ default:
+ panic("scoop_pcic_write: bogus register");
+ }
+
+ splx(s);
+}
+
+void
+scoop_pcic_set_power(struct pxapcic_socket *so, int pwr)
+{
+ bus_space_tag_t iot = so->sc->sc_iot;
+ bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
+ u_int16_t reg;
+ int s;
+
+ s = splhigh();
+
+ switch (pwr) {
+ case PXAPCIC_POWER_OFF:
+#if 0
+ /* XXX does this disable power to both sockets? */
+ reg = bus_space_read_2(iot, ioh, SCOOP_GPWR);
+ bus_space_write_2(iot, ioh, SCOOP_GPWR,
+ reg & ~(1 << SCOOP0_CF_POWER_C3000));
+#endif
+ break;
+
+ case PXAPCIC_POWER_3V:
+ case PXAPCIC_POWER_5V:
+ /* XXX */
+ if (so->socket == 0) {
+ reg = bus_space_read_2(iot, ioh, SCOOP_GPWR);
+ bus_space_write_2(iot, ioh, SCOOP_GPWR,
+ reg | (1 << SCOOP0_CF_POWER_C3000));
+ }
+ break;
+
+ default:
+ splx(s);
+ panic("scoop_pcic_set_power: bogus power state");
+ }
+
+ splx(s);
+}
+
+void
+scoop_pcic_clear_intr(struct pxapcic_socket *so)
+{
+ bus_space_tag_t iot = so->sc->sc_iot;
+ bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
+
+ bus_space_write_2(iot, ioh, SCOOP_IRM, 0x00ff);
+ bus_space_write_2(iot, ioh, SCOOP_ISR, 0x0000);
+ bus_space_write_2(iot, ioh, SCOOP_IRM, 0x0000);
+}
diff --git a/sys/arch/zaurus/dev/zaurus_scoop.c b/sys/arch/zaurus/dev/zaurus_scoop.c
index 60347e5c1ad..197a74020d3 100644
--- a/sys/arch/zaurus/dev/zaurus_scoop.c
+++ b/sys/arch/zaurus/dev/zaurus_scoop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: zaurus_scoop.c,v 1.10 2005/05/23 22:44:57 pascoe Exp $ */
+/* $OpenBSD: zaurus_scoop.c,v 1.11 2005/07/01 23:51:55 uwe Exp $ */
/*
* Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
@@ -25,6 +25,9 @@
#include <arm/xscale/pxa2x0var.h>
+#include <machine/zaurus_reg.h>
+#include <machine/zaurus_var.h>
+
#include <zaurus/dev/zaurus_scoopreg.h>
#include <zaurus/dev/zaurus_scoopvar.h>
@@ -38,7 +41,7 @@ struct scoop_softc {
int scoopmatch(struct device *, void *, void *);
void scoopattach(struct device *, struct device *, void *);
-struct cfattach scoop_pxaip_ca = {
+struct cfattach scoop_ca = {
sizeof (struct scoop_softc), scoopmatch, scoopattach
};
@@ -57,10 +60,9 @@ scoopmatch(struct device *parent, void *match, void *aux)
struct cfdata *cf = match;
/*
- * Only the C3000 models (pxa270) are known to have two SCOOPs,
- * on other models we only find the first one.
+ * Only C3000-like models are known to have two SCOOPs.
*/
- if ((cputype & ~CPU_ID_XSCALE_COREREV_MASK) == CPU_ID_PXA27X)
+ if (ZAURUS_ISC3000)
return (cf->cf_unit < 2);
return (cf->cf_unit == 0);
@@ -79,9 +81,9 @@ scoopattach(struct device *parent, struct device *self, void *aux)
if (pxa->pxa_addr != -1)
addr = pxa->pxa_addr;
else if (sc->sc_dev.dv_unit == 0)
- addr = SCOOP0_BASE;
+ addr = C3000_SCOOP0_BASE;
else
- addr = SCOOP1_BASE;
+ addr = C3000_SCOOP1_BASE;
size = pxa->pxa_size < SCOOP_SIZE ? SCOOP_SIZE : pxa->pxa_size;
@@ -90,7 +92,7 @@ scoopattach(struct device *parent, struct device *self, void *aux)
return;
}
- printf(": Onboard Peripheral Controller\n");
+ printf(": PCMCIA/GPIO controller\n");
}
int
diff --git a/sys/arch/zaurus/dev/zaurus_scoopreg.h b/sys/arch/zaurus/dev/zaurus_scoopreg.h
index e430f99f9fd..c2aa000147a 100644
--- a/sys/arch/zaurus/dev/zaurus_scoopreg.h
+++ b/sys/arch/zaurus/dev/zaurus_scoopreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: zaurus_scoopreg.h,v 1.6 2005/03/08 23:29:06 uwe Exp $ */
+/* $OpenBSD: zaurus_scoopreg.h,v 1.7 2005/07/01 23:51:55 uwe Exp $ */
/*
* Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
@@ -16,22 +16,43 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#define SCOOP0_BASE 0x10800000
-#define SCOOP1_BASE 0x08800040
-#define SCOOP_SIZE 0x2c
+#define SCOOP_SIZE 0x2c
-#define SCOOP_MCR 0x00 /* (R/W) */
-#define SCOOP_CDR 0x04 /* (R?/W) */
-#define SCOOP_CSR 0x08 /* card status register (R) */
-#define SCOOP_CPR 0x0c /* card power register (R/W) */
-#define SCOOP_CCR 0x10 /* card configuration reg.? (R/W) */
-#define SCOOP_IRR 0x14 /* XXX for pcic: bit 0x4 role is? */
-#define SCOOP_IRM 0x14
-#define SCOOP_IMR 0x18 /* (R/W) */
-#define SCOOP_ISR 0x1c
-#define SCOOP_GPCR 0x20 /* GPIO pin direction (R/W) */
-#define SCOOP_GPWR 0x24 /* GPIO pin output level (R/W) */
-#define SCOOP_GPRR 0x28
+/* registers and values */
+
+#define SCOOP_MCR 0x00
+#define SCP_MCR_IOCARD 0x0010
+#define SCOOP_CDR 0x04 /* card detect register */
+#define SCP_CDR_DETECT 0x0002
+#define SCOOP_CSR 0x08 /* card status register */
+#define SCP_CSR_READY 0x0002
+#define SCP_CSR_MISSING 0x0004
+#define SCP_CSR_WPROT 0x0008
+#define SCP_CSR_BVD1 0x0010
+#define SCP_CSR_BVD2 0x0020
+#define SCP_CSR_3V 0x0040
+#define SCP_CSR_PWR 0x0080
+#define SCOOP_CPR 0x0c /* card power register */
+#define SCP_CPR_OFF 0x0000
+#define SCP_CPR_3V 0x0001
+#define SCP_CPR_5V 0x0002
+#define SCP_CPR_PWR 0x0080
+#define SCOOP_CCR 0x10 /* card control register */
+#define SCP_CCR_RESET 0x0080
+#define SCOOP_IRR 0x14 /* XXX for pcic: bit 0x4 role is? */
+#define SCOOP_IRM 0x14
+#define SCOOP_IMR 0x18
+#define SCP_IMR_READY 0x0002
+#define SCP_IMR_DETECT 0x0004
+#define SCP_IMR_WRPROT 0x0008
+#define SCP_IMR_STSCHG 0x0010
+#define SCP_IMR_BATWARN 0x0020
+#define SCP_IMR_UNKN0 0x0040
+#define SCP_IMR_UNKN1 0x0080
+#define SCOOP_ISR 0x1c
+#define SCOOP_GPCR 0x20 /* GPIO pin direction (R/W) */
+#define SCOOP_GPWR 0x24 /* GPIO pin output level (R/W) */
+#define SCOOP_GPRR 0x28 /* GPIO pin input level (R) */
/* GPIO bits */