sdhc_pci.c revision 1.10 1 /* $NetBSD: sdhc_pci.c,v 1.10 2012/12/20 14:41:35 jakllsch Exp $ */
2 /* $OpenBSD: sdhc_pci.c,v 1.7 2007/10/30 18:13:45 chl Exp $ */
3
4 /*
5 * Copyright (c) 2006 Uwe Stuehler <uwe (at) openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: sdhc_pci.c,v 1.10 2012/12/20 14:41:35 jakllsch Exp $");
22
23 #ifdef _KERNEL_OPT
24 #include "opt_sdmmc.h"
25 #endif
26
27 #include <sys/param.h>
28 #include <sys/device.h>
29 #include <sys/systm.h>
30 #include <sys/malloc.h>
31 #include <sys/pmf.h>
32
33 #include <dev/pci/pcivar.h>
34 #include <dev/pci/pcidevs.h>
35
36 #include <dev/sdmmc/sdhcreg.h>
37 #include <dev/sdmmc/sdhcvar.h>
38 #include <dev/sdmmc/sdmmcvar.h>
39
40 /* PCI base address registers */
41 #define SDHC_PCI_BAR_START PCI_MAPREG_START
42 #define SDHC_PCI_BAR_END PCI_MAPREG_END
43
44 /* PCI interface classes */
45 #define SDHC_PCI_INTERFACE_NO_DMA 0x00
46 #define SDHC_PCI_INTERFACE_DMA 0x01
47 #define SDHC_PCI_INTERFACE_VENDOR 0x02
48
49 /*
50 * 8-bit PCI configuration register that tells us how many slots there
51 * are and which BAR entry corresponds to the first slot.
52 */
53 #define SDHC_PCI_CONF_SLOT_INFO 0x40
54 #define SDHC_PCI_NUM_SLOTS(info) ((((info) >> 4) & 0x7) + 1)
55 #define SDHC_PCI_FIRST_BAR(info) ((info) & 0x7)
56
57 struct sdhc_pci_softc {
58 struct sdhc_softc sc;
59 pci_chipset_tag_t sc_pc;
60 void *sc_ih;
61 };
62
63 static int sdhc_pci_match(device_t, cfdata_t, void *);
64 static void sdhc_pci_attach(device_t, device_t, void *);
65 static int sdhc_pci_detach(device_t, int);
66
67 CFATTACH_DECL_NEW(sdhc_pci, sizeof(struct sdhc_pci_softc),
68 sdhc_pci_match, sdhc_pci_attach, sdhc_pci_detach, NULL);
69
70 #ifdef SDHC_DEBUG
71 #define DPRINTF(s) printf s
72 #else
73 #define DPRINTF(s) /**/
74 #endif
75
76 static const struct sdhc_pci_quirk {
77 pci_vendor_id_t vendor;
78 pci_product_id_t product;
79 pci_vendor_id_t subvendor;
80 pci_product_id_t subproduct;
81 u_int function;
82
83 uint32_t flags;
84 #define SDHC_PCI_QUIRK_FORCE_DMA (1U << 0)
85 #define SDHC_PCI_QUIRK_TI_HACK (1U << 1)
86 #define SDHC_PCI_QUIRK_NO_PWR0 (1U << 2)
87 #define SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK (1U << 3)
88 } sdhc_pci_quirk_table[] = {
89 {
90 PCI_VENDOR_TI,
91 PCI_PRODUCT_TI_PCI72111SD,
92 0xffff,
93 0xffff,
94 4,
95 SDHC_PCI_QUIRK_TI_HACK
96 },
97
98 {
99 PCI_VENDOR_TI,
100 PCI_PRODUCT_TI_PCIXX12SD,
101 0xffff,
102 0xffff,
103 3,
104 SDHC_PCI_QUIRK_TI_HACK
105 },
106
107 {
108 PCI_VENDOR_ENE,
109 PCI_PRODUCT_ENE_CB712,
110 0xffff,
111 0xffff,
112 0,
113 SDHC_PCI_QUIRK_NO_PWR0
114 },
115
116 {
117 PCI_VENDOR_RICOH,
118 PCI_PRODUCT_RICOH_Rx5U823,
119 0xffff,
120 0xffff,
121 0,
122 SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK
123 },
124
125 {
126 PCI_VENDOR_RICOH,
127 PCI_PRODUCT_RICOH_Rx5C822,
128 0xffff,
129 0xffff,
130 ~0,
131 SDHC_PCI_QUIRK_FORCE_DMA
132 },
133
134 {
135 PCI_VENDOR_RICOH,
136 PCI_PRODUCT_RICOH_Rx5U822,
137 0xffff,
138 0xffff,
139 ~0,
140 SDHC_PCI_QUIRK_FORCE_DMA
141 },
142 };
143
144 static void sdhc_pci_quirk_ti_hack(struct pci_attach_args *);
145 static void sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *);
146
147 static uint32_t
148 sdhc_pci_lookup_quirk_flags(struct pci_attach_args *pa)
149 {
150 const struct sdhc_pci_quirk *q;
151 pcireg_t id;
152 pci_vendor_id_t vendor;
153 pci_product_id_t product;
154 int i;
155
156 for (i = 0; i < __arraycount(sdhc_pci_quirk_table); i++) {
157 q = &sdhc_pci_quirk_table[i];
158
159 if ((PCI_VENDOR(pa->pa_id) == q->vendor)
160 && (PCI_PRODUCT(pa->pa_id) == q->product)) {
161 if ((q->function != ~0)
162 && (pa->pa_function != q->function))
163 continue;
164
165 if ((q->subvendor == 0xffff)
166 && (q->subproduct == 0xffff))
167 return (q->flags);
168
169 id = pci_conf_read(pa->pa_pc, pa->pa_tag,
170 PCI_SUBSYS_ID_REG);
171 vendor = PCI_VENDOR(id);
172 product = PCI_PRODUCT(id);
173
174 if ((q->subvendor != 0xffff)
175 && (q->subproduct != 0xffff)) {
176 if ((vendor == q->subvendor)
177 && (product == q->subproduct))
178 return (q->flags);
179 } else if (q->subvendor != 0xffff) {
180 if (product == q->subproduct)
181 return (q->flags);
182 } else {
183 if (vendor == q->subvendor)
184 return (q->flags);
185 }
186 }
187 }
188 return (0);
189 }
190
191 static int
192 sdhc_pci_match(device_t parent, cfdata_t cf, void *aux)
193 {
194 struct pci_attach_args *pa = aux;
195
196 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SYSTEM &&
197 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SYSTEM_SDHC)
198 return (1);
199 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
200 (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_Rx5U822 ||
201 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_Rx5U823))
202 return (1);
203 return (0);
204 }
205
206 static void
207 sdhc_pci_attach(device_t parent, device_t self, void *aux)
208 {
209 struct sdhc_pci_softc *sc = device_private(self);
210 struct pci_attach_args *pa = (struct pci_attach_args *)aux;
211 pci_chipset_tag_t pc = pa->pa_pc;
212 pcitag_t tag = pa->pa_tag;
213 pci_intr_handle_t ih;
214 pcireg_t csr;
215 pcireg_t slotinfo;
216 char const *intrstr;
217 int nslots;
218 int reg;
219 int cnt;
220 bus_space_tag_t iot;
221 bus_space_handle_t ioh;
222 bus_size_t size;
223 uint32_t flags;
224
225 sc->sc.sc_dev = self;
226 sc->sc.sc_dmat = pa->pa_dmat;
227 sc->sc.sc_host = NULL;
228
229 sc->sc_pc = pc;
230
231 pci_aprint_devinfo(pa, NULL);
232
233 /* Some controllers needs special treatment. */
234 flags = sdhc_pci_lookup_quirk_flags(pa);
235 if (ISSET(flags, SDHC_PCI_QUIRK_TI_HACK))
236 sdhc_pci_quirk_ti_hack(pa);
237 if (ISSET(flags, SDHC_PCI_QUIRK_FORCE_DMA))
238 SET(sc->sc.sc_flags, SDHC_FLAG_FORCE_DMA);
239 if (ISSET(flags, SDHC_PCI_QUIRK_NO_PWR0))
240 SET(sc->sc.sc_flags, SDHC_FLAG_NO_PWR0);
241 if (ISSET(flags, SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK))
242 sdhc_pci_quirk_ricoh_lower_freq_hack(pa);
243
244 /*
245 * Map and attach all hosts supported by the host controller.
246 */
247 slotinfo = pci_conf_read(pc, tag, SDHC_PCI_CONF_SLOT_INFO);
248 nslots = SDHC_PCI_NUM_SLOTS(slotinfo);
249
250 /* Allocate an array big enough to hold all the possible hosts */
251 sc->sc.sc_host = malloc(sizeof(struct sdhc_host *) * nslots,
252 M_DEVBUF, M_NOWAIT | M_ZERO);
253 if (sc->sc.sc_host == NULL) {
254 aprint_error_dev(self, "couldn't alloc memory\n");
255 goto err;
256 }
257
258 /* Enable the device. */
259 csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
260 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
261 csr | PCI_COMMAND_MASTER_ENABLE);
262
263 /* Map and establish the interrupt. */
264 if (pci_intr_map(pa, &ih)) {
265 aprint_error_dev(self, "couldn't map interrupt\n");
266 goto err;
267 }
268
269 intrstr = pci_intr_string(pc, ih);
270 sc->sc_ih = pci_intr_establish(pc, ih, IPL_SDMMC, sdhc_intr, &sc->sc);
271 if (sc->sc_ih == NULL) {
272 aprint_error_dev(self, "couldn't establish interrupt\n");
273 goto err;
274 }
275 aprint_normal_dev(self, "interrupting at %s\n", intrstr);
276
277 /* Enable use of DMA if supported by the interface. */
278 if ((PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA))
279 SET(sc->sc.sc_flags, SDHC_FLAG_USE_DMA);
280
281 /* XXX: handle 64-bit BARs */
282 cnt = 0;
283 for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) *
284 sizeof(uint32_t);
285 reg < SDHC_PCI_BAR_END && nslots > 0;
286 reg += sizeof(uint32_t), nslots--) {
287 if (pci_mapreg_map(pa, reg, PCI_MAPREG_TYPE_MEM, 0,
288 &iot, &ioh, NULL, &size)) {
289 continue;
290 }
291
292 cnt++;
293 if (sdhc_host_found(&sc->sc, iot, ioh, size) != 0) {
294 /* XXX: sc->sc_host leak */
295 aprint_error_dev(self,
296 "couldn't initialize host (0x%x)\n", reg);
297 }
298 }
299 if (cnt == 0) {
300 aprint_error_dev(self, "couldn't map register\n");
301 goto err;
302 }
303
304 if (!pmf_device_register1(self, sdhc_suspend, sdhc_resume,
305 sdhc_shutdown)) {
306 aprint_error_dev(self, "couldn't establish powerhook\n");
307 }
308
309 return;
310
311 err:
312 if (sc->sc.sc_host != NULL) {
313 free(sc->sc.sc_host, M_DEVBUF);
314 sc->sc.sc_host = NULL;
315 }
316 }
317
318 static int
319 sdhc_pci_detach(device_t self, int flags)
320 {
321 struct sdhc_pci_softc * const sc = device_private(self);
322 int rv;
323
324 rv = sdhc_detach(&sc->sc, flags);
325 if (rv)
326 return rv;
327
328 if (sc->sc_ih != NULL) {
329 pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
330 sc->sc_ih = NULL;
331 }
332
333 if (sc->sc.sc_host != NULL) {
334 free(sc->sc.sc_host, M_DEVBUF);
335 sc->sc.sc_host = NULL;
336 }
337
338 return rv;
339 }
340
341 static void
342 sdhc_pci_conf_write(struct pci_attach_args *pa, int reg, uint8_t val)
343 {
344 pcireg_t r;
345
346 r = pci_conf_read(pa->pa_pc, pa->pa_tag, reg & ~0x3);
347 r &= ~(0xff << ((reg & 0x3) * 8));
348 r |= (val << ((reg & 0x3) * 8));
349 pci_conf_write(pa->pa_pc, pa->pa_tag, reg & ~0x3, r);
350 }
351
352 /* TI specific register */
353 #define SDHC_PCI_GENERAL_CTL 0x4c
354 #define MMC_SD_DIS 0x02
355
356 static void
357 sdhc_pci_quirk_ti_hack(struct pci_attach_args *pa)
358 {
359 pci_chipset_tag_t pc = pa->pa_pc;
360 pcitag_t tag;
361 pcireg_t id, reg;
362
363 /* Look at func - 1 for the flash device */
364 tag = pci_make_tag(pc, pa->pa_bus, pa->pa_device, pa->pa_function - 1);
365 id = pci_conf_read(pc, tag, PCI_ID_REG);
366 if (PCI_VENDOR(id) != PCI_VENDOR_TI) {
367 return;
368 }
369 switch (PCI_PRODUCT(id)) {
370 case PCI_PRODUCT_TI_PCI72111FM:
371 case PCI_PRODUCT_TI_PCIXX12FM:
372 break;
373 default:
374 return;
375 }
376
377 /*
378 * Disable MMC/SD on the flash media controller so the
379 * SD host takes over.
380 */
381 reg = pci_conf_read(pc, tag, SDHC_PCI_GENERAL_CTL);
382 reg |= MMC_SD_DIS;
383 pci_conf_write(pc, tag, SDHC_PCI_GENERAL_CTL, reg);
384 }
385
386 /* Ricoh specific register */
387 #define SDHC_PCI_MODE_KEY 0xf9
388 #define SDHC_PCI_MODE 0x150
389 #define SDHC_PCI_MODE_SD20 0x10
390 #define SDHC_PCI_BASE_FREQ_KEY 0xfc
391 #define SDHC_PCI_BASE_FREQ 0xe1
392
393 /* Some RICOH controllers need to be bumped into the right mode. */
394 static void
395 sdhc_pci_quirk_ricoh_lower_freq_hack(struct pci_attach_args *pa)
396 {
397
398 /* Enable SD2.0 mode. */
399 sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0xfc);
400 sdhc_pci_conf_write(pa, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20);
401 sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0x00);
402
403 /*
404 * Some SD/MMC cards don't work with the default base
405 * clock frequency of 200MHz. Lower it to 50Hz.
406 */
407 sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x01);
408 sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ, 50);
409 sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x00);
410 }
411