Annotation of sys/arch/zaurus/dev/scoop_pcic.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: scoop_pcic.c,v 1.1 2005/07/01 23:51:55 uwe Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/param.h>
! 20: #include <sys/systm.h>
! 21: #include <uvm/uvm.h>
! 22:
! 23: #include <arch/arm/xscale/pxa2x0var.h>
! 24: #include <arch/arm/xscale/pxapcicvar.h>
! 25:
! 26: #include <machine/zaurus_reg.h>
! 27: #include <machine/zaurus_var.h>
! 28:
! 29: #include <zaurus/dev/zaurus_scoopreg.h>
! 30:
! 31: int scoop_pcic_match(struct device *, void *, void *);
! 32: void scoop_pcic_attach(struct device *, struct device *, void *);
! 33: void scoop_pcic_socket_setup(struct pxapcic_socket *);
! 34:
! 35: struct cfattach pxapcic_scoop_ca = {
! 36: sizeof(struct pxapcic_softc), scoop_pcic_match,
! 37: scoop_pcic_attach
! 38: };
! 39:
! 40: u_int scoop_pcic_read(struct pxapcic_socket *, int);
! 41: void scoop_pcic_write(struct pxapcic_socket *, int, u_int);
! 42: void scoop_pcic_set_power(struct pxapcic_socket *, int);
! 43: void scoop_pcic_clear_intr(struct pxapcic_socket *);
! 44:
! 45: struct pxapcic_tag scoop_pcic_functions = {
! 46: scoop_pcic_read,
! 47: scoop_pcic_write,
! 48: scoop_pcic_set_power,
! 49: scoop_pcic_clear_intr,
! 50: 0, /* intr_establish */
! 51: 0, /* intr_disestablish */
! 52: 0 /* intr_string */
! 53: };
! 54:
! 55: int
! 56: scoop_pcic_match(struct device *parent, void *cf, void *aux)
! 57: {
! 58: return (ZAURUS_ISC860 || ZAURUS_ISC3000);
! 59: }
! 60:
! 61: void
! 62: scoop_pcic_attach(struct device *parent, struct device *self, void *aux)
! 63: {
! 64: struct pxapcic_softc *sc = (struct pxapcic_softc *)self;
! 65: struct pxaip_attach_args *pxa = aux;
! 66:
! 67: sc->sc_iot = pxa->pxa_iot;
! 68:
! 69: if (ZAURUS_ISC860) {
! 70: sc->sc_nslots = 1;
! 71: sc->sc_irqpin[0] = C860_CF0_IRQ;
! 72: sc->sc_irqcfpin[0] = C860_CF0_IRQ_PIN;
! 73: } else if (ZAURUS_ISC3000) {
! 74: sc->sc_nslots = 2;
! 75: sc->sc_irqpin[0] = C3000_CF0_IRQ;
! 76: sc->sc_irqcfpin[0] = C3000_CF0_IRQ_PIN;
! 77: sc->sc_irqpin[1] = C3000_CF1_IRQ;
! 78: sc->sc_irqcfpin[1] = C3000_CF1_IRQ_PIN;
! 79: }
! 80:
! 81: pxapcic_attach(sc, &scoop_pcic_socket_setup);
! 82: }
! 83:
! 84: void
! 85: scoop_pcic_socket_setup(struct pxapcic_socket *so)
! 86: {
! 87: struct pxapcic_softc *sc;
! 88: bus_addr_t pa;
! 89: bus_size_t size = SCOOP_SIZE;
! 90: bus_space_tag_t iot;
! 91: bus_space_handle_t scooph;
! 92: int error;
! 93:
! 94: sc = so->sc;
! 95: iot = sc->sc_iot;
! 96:
! 97: if (so->socket == 0)
! 98: pa = C3000_SCOOP0_BASE;
! 99: else if (so->socket == 1)
! 100: pa = C3000_SCOOP1_BASE;
! 101: else
! 102: panic("%s: invalid CF slot %d", sc->sc_dev.dv_xname,
! 103: so->socket);
! 104: error = bus_space_map(iot, trunc_page(pa), round_page(size),
! 105: 0, &scooph);
! 106: if (error)
! 107: panic("%s: failed to map memory %x for scoop",
! 108: sc->sc_dev.dv_xname, pa);
! 109: scooph += pa - trunc_page(pa);
! 110:
! 111: bus_space_write_2(iot, scooph, SCOOP_IMR,
! 112: SCP_IMR_UNKN0 | SCP_IMR_UNKN1);
! 113:
! 114: /* setup */
! 115: bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0100);
! 116: bus_space_write_2(iot, scooph, SCOOP_CDR, 0x0000);
! 117: bus_space_write_2(iot, scooph, SCOOP_CPR, 0x0000);
! 118: bus_space_write_2(iot, scooph, SCOOP_IMR, 0x0000);
! 119: bus_space_write_2(iot, scooph, SCOOP_IRM, 0x00ff);
! 120: bus_space_write_2(iot, scooph, SCOOP_ISR, 0x0000);
! 121: bus_space_write_2(iot, scooph, SCOOP_IRM, 0x0000);
! 122:
! 123: /* C3000 */
! 124: if (so->socket == 1) {
! 125: bus_space_write_2(iot, scooph, SCOOP_CPR, 0x80c1);
! 126: bus_space_write_2(iot, scooph, SCOOP_IMR, 0x00c4);
! 127: bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0111);
! 128: } else {
! 129: bus_space_write_2(iot, scooph, SCOOP_CPR,
! 130: SCP_CPR_PWR|SCP_CPR_5V);
! 131: }
! 132:
! 133: bus_space_write_2(iot, scooph, SCOOP_IMR, 0x00ce);
! 134: bus_space_write_2(iot, scooph, SCOOP_MCR, 0x0111);
! 135:
! 136: /* C3000 */
! 137: so->power_capability = PXAPCIC_POWER_3V;
! 138: if (so->socket == 0)
! 139: so->power_capability |= PXAPCIC_POWER_5V;
! 140:
! 141: so->pcictag_cookie = (void *)scooph;
! 142: so->pcictag = &scoop_pcic_functions;
! 143: }
! 144:
! 145: u_int
! 146: scoop_pcic_read(struct pxapcic_socket *so, int reg)
! 147: {
! 148: bus_space_tag_t iot = so->sc->sc_iot;
! 149: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
! 150: u_int16_t csr;
! 151:
! 152: csr = bus_space_read_2(iot, ioh, SCOOP_CSR);
! 153:
! 154: switch (reg) {
! 155: case PXAPCIC_CARD_STATUS:
! 156: if (csr & SCP_CSR_MISSING)
! 157: return (PXAPCIC_CARD_INVALID);
! 158: else
! 159: return (PXAPCIC_CARD_VALID);
! 160:
! 161: case PXAPCIC_CARD_READY:
! 162: return ((bus_space_read_2(iot, ioh, SCOOP_CSR) &
! 163: SCP_CSR_READY) != 0);
! 164:
! 165: default:
! 166: panic("scoop_pcic_read: bogus register");
! 167: }
! 168: }
! 169:
! 170: void
! 171: scoop_pcic_write(struct pxapcic_socket *so, int reg, u_int val)
! 172: {
! 173: bus_space_tag_t iot = so->sc->sc_iot;
! 174: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
! 175: u_int16_t newval;
! 176: int s;
! 177:
! 178: s = splhigh();
! 179:
! 180: switch (reg) {
! 181: case PXAPCIC_CARD_POWER:
! 182: newval = bus_space_read_2(iot, ioh, SCOOP_CPR);
! 183: newval &= ~(SCP_CPR_PWR | SCP_CPR_3V | SCP_CPR_5V);
! 184:
! 185: if (val == PXAPCIC_POWER_3V)
! 186: newval |= (SCP_CPR_PWR | SCP_CPR_3V);
! 187: else if (val == PXAPCIC_POWER_5V)
! 188: newval |= (SCP_CPR_PWR | SCP_CPR_5V);
! 189:
! 190: bus_space_write_2(iot, ioh, SCOOP_CPR, newval);
! 191: break;
! 192:
! 193: case PXAPCIC_CARD_RESET:
! 194: bus_space_write_2(iot, ioh, SCOOP_CCR,
! 195: val ? SCP_CCR_RESET : 0);
! 196: break;
! 197:
! 198: default:
! 199: panic("scoop_pcic_write: bogus register");
! 200: }
! 201:
! 202: splx(s);
! 203: }
! 204:
! 205: void
! 206: scoop_pcic_set_power(struct pxapcic_socket *so, int pwr)
! 207: {
! 208: bus_space_tag_t iot = so->sc->sc_iot;
! 209: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
! 210: u_int16_t reg;
! 211: int s;
! 212:
! 213: s = splhigh();
! 214:
! 215: switch (pwr) {
! 216: case PXAPCIC_POWER_OFF:
! 217: #if 0
! 218: /* XXX does this disable power to both sockets? */
! 219: reg = bus_space_read_2(iot, ioh, SCOOP_GPWR);
! 220: bus_space_write_2(iot, ioh, SCOOP_GPWR,
! 221: reg & ~(1 << SCOOP0_CF_POWER_C3000));
! 222: #endif
! 223: break;
! 224:
! 225: case PXAPCIC_POWER_3V:
! 226: case PXAPCIC_POWER_5V:
! 227: /* XXX */
! 228: if (so->socket == 0) {
! 229: reg = bus_space_read_2(iot, ioh, SCOOP_GPWR);
! 230: bus_space_write_2(iot, ioh, SCOOP_GPWR,
! 231: reg | (1 << SCOOP0_CF_POWER_C3000));
! 232: }
! 233: break;
! 234:
! 235: default:
! 236: splx(s);
! 237: panic("scoop_pcic_set_power: bogus power state");
! 238: }
! 239:
! 240: splx(s);
! 241: }
! 242:
! 243: void
! 244: scoop_pcic_clear_intr(struct pxapcic_socket *so)
! 245: {
! 246: bus_space_tag_t iot = so->sc->sc_iot;
! 247: bus_space_handle_t ioh = (bus_space_handle_t)so->pcictag_cookie;
! 248:
! 249: bus_space_write_2(iot, ioh, SCOOP_IRM, 0x00ff);
! 250: bus_space_write_2(iot, ioh, SCOOP_ISR, 0x0000);
! 251: bus_space_write_2(iot, ioh, SCOOP_IRM, 0x0000);
! 252: }
CVSweb