root/dev/pci/sdhc_pci.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sdhc_pci_match
  2. sdhc_pci_attach
  3. sdhc_takecontroller

    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 }

/* [<][>][^][v][top][bottom][index][help] */