Annotation of sys/dev/pci/sdhc_pci.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sdhc_pci.c,v 1.5 2006/07/19 20:58:45 fgsch Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
! 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/device.h>
! 21: #include <sys/systm.h>
! 22: #include <sys/malloc.h>
! 23:
! 24: #include <dev/pci/pcivar.h>
! 25: #include <dev/pci/pcidevs.h>
! 26: #include <dev/sdmmc/sdhcreg.h>
! 27: #include <dev/sdmmc/sdhcvar.h>
! 28: #include <dev/sdmmc/sdmmcvar.h>
! 29:
! 30: /*
! 31: * 8-bit PCI configuration register that tells us how many slots there
! 32: * are and which BAR entry corresponds to the first slot.
! 33: */
! 34: #define SDHC_PCI_CONF_SLOT_INFO 0x40
! 35: #define SDHC_PCI_NUM_SLOTS(info) ((((info) >> 4) & 0x7) + 1)
! 36: #define SDHC_PCI_FIRST_BAR(info) ((info) & 0x7)
! 37:
! 38: /* TI specific register */
! 39: #define SDHC_PCI_GENERAL_CTL 0x4c
! 40: #define MMC_SD_DIS 0x02
! 41:
! 42: struct sdhc_pci_softc {
! 43: struct sdhc_softc sc;
! 44: void *sc_ih;
! 45: };
! 46:
! 47: int sdhc_pci_match(struct device *, void *, void *);
! 48: void sdhc_pci_attach(struct device *, struct device *, void *);
! 49: void sdhc_takecontroller(struct pci_attach_args *);
! 50:
! 51: struct cfattach sdhc_pci_ca = {
! 52: sizeof(struct sdhc_pci_softc), sdhc_pci_match, sdhc_pci_attach
! 53: };
! 54:
! 55: int
! 56: sdhc_pci_match(struct device *parent, void *match, void *aux)
! 57: {
! 58: struct pci_attach_args *pa = aux;
! 59:
! 60: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SYSTEM &&
! 61: PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SYSTEM_SDHC)
! 62: return 1;
! 63:
! 64: return 0;
! 65: }
! 66:
! 67: void
! 68: sdhc_pci_attach(struct device *parent, struct device *self, void *aux)
! 69: {
! 70: struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)self;
! 71: struct pci_attach_args *pa = aux;
! 72: pci_intr_handle_t ih;
! 73: char const *intrstr;
! 74: int slotinfo;
! 75: int nslots;
! 76: int usedma;
! 77: int reg;
! 78: bus_space_tag_t iot;
! 79: bus_space_handle_t ioh;
! 80: bus_size_t size;
! 81:
! 82: /* Some TI controllers needs special treatment. */
! 83: if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI &&
! 84: PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TI_PCI7XX1_SD &&
! 85: pa->pa_function == 4)
! 86: sdhc_takecontroller(pa);
! 87:
! 88: if (pci_intr_map(pa, &ih)) {
! 89: printf(": can't map interrupt\n");
! 90: return;
! 91: }
! 92:
! 93: intrstr = pci_intr_string(pa->pa_pc, ih);
! 94: sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC,
! 95: sdhc_intr, sc, sc->sc.sc_dev.dv_xname);
! 96: if (sc->sc_ih == NULL) {
! 97: printf(": can't establish interrupt\n");
! 98: return;
! 99: }
! 100: printf(": %s\n", intrstr);
! 101:
! 102: /* Enable use of DMA if supported by the interface. */
! 103: usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA;
! 104:
! 105: /*
! 106: * Map and attach all hosts supported by the host controller.
! 107: */
! 108: slotinfo = pci_conf_read(pa->pa_pc, pa->pa_tag,
! 109: SDHC_PCI_CONF_SLOT_INFO);
! 110: nslots = SDHC_PCI_NUM_SLOTS(slotinfo);
! 111:
! 112: /* Allocate an array big enough to hold all the possible hosts */
! 113: MALLOC(sc->sc.sc_host, struct sdhc_host **,
! 114: sizeof(struct sdhc_host *) * nslots, M_DEVBUF, M_WAITOK);
! 115:
! 116: /* XXX: handle 64-bit BARs */
! 117: for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) *
! 118: sizeof(u_int32_t);
! 119: reg < SDHC_PCI_BAR_END && nslots > 0;
! 120: reg += sizeof(u_int32_t), nslots--) {
! 121:
! 122: if (pci_mem_find(pa->pa_pc, pa->pa_tag, reg,
! 123: NULL, NULL, NULL) != 0)
! 124: continue;
! 125:
! 126: if (pci_mapreg_map(pa, reg, PCI_MAPREG_TYPE_MEM, 0,
! 127: &iot, &ioh, NULL, &size, 0)) {
! 128: printf("%s at 0x%x: can't map registers\n",
! 129: sc->sc.sc_dev.dv_xname, reg);
! 130: continue;
! 131: }
! 132:
! 133: if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma) != 0)
! 134: /* XXX: sc->sc_host leak */
! 135: printf("%s at 0x%x: can't initialize host\n",
! 136: sc->sc.sc_dev.dv_xname, reg);
! 137: }
! 138:
! 139: /*
! 140: * Establish power and shutdown hooks.
! 141: */
! 142: (void)powerhook_establish(sdhc_power, &sc->sc);
! 143: (void)shutdownhook_establish(sdhc_shutdown, &sc->sc);
! 144: }
! 145:
! 146: void
! 147: sdhc_takecontroller(struct pci_attach_args *pa)
! 148: {
! 149: pcitag_t tag;
! 150: pcireg_t id, reg;
! 151:
! 152: /* Look at func 3 for the flash device */
! 153: tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device, 3);
! 154: id = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
! 155: if (PCI_PRODUCT(id) != PCI_PRODUCT_TI_PCI7XX1_FLASH)
! 156: return;
! 157:
! 158: /*
! 159: * Disable MMC/SD on the flash media controller so the
! 160: * SD host takes over.
! 161: */
! 162: reg = pci_conf_read(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL);
! 163: reg |= MMC_SD_DIS;
! 164: pci_conf_write(pa->pa_pc, tag, SDHC_PCI_GENERAL_CTL, reg);
! 165: }
CVSweb