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