[BACK]Return to sdhc_pci.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

Annotation of sys/dev/pci/sdhc_pci.c, Revision 1.1.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