diff options
Diffstat (limited to 'sys/arch/zaurus/dev')
-rw-r--r-- | sys/arch/zaurus/dev/scoop_pcic.c | 252 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_scoop.c | 18 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_scoopreg.h | 53 |
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 */ |