1241600Sgonzo/*-
2241600Sgonzo * Copyright (c) 2008 Alexander Motin <mav@FreeBSD.org>
3241600Sgonzo * All rights reserved.
4241600Sgonzo *
5241600Sgonzo * Redistribution and use in source and binary forms, with or without
6241600Sgonzo * modification, are permitted provided that the following conditions
7241600Sgonzo * are met:
8241600Sgonzo * 1. Redistributions of source code must retain the above copyright
9241600Sgonzo *    notice, this list of conditions and the following disclaimer.
10241600Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
11241600Sgonzo *    notice, this list of conditions and the following disclaimer in the
12241600Sgonzo *    documentation and/or other materials provided with the distribution.
13241600Sgonzo *
14241600Sgonzo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15241600Sgonzo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16241600Sgonzo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17241600Sgonzo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18241600Sgonzo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19241600Sgonzo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20241600Sgonzo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21241600Sgonzo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22241600Sgonzo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23241600Sgonzo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24241600Sgonzo */
25241600Sgonzo
26241600Sgonzo#include <sys/cdefs.h>
27241600Sgonzo__FBSDID("$FreeBSD: stable/11/sys/dev/sdhci/sdhci_pci.c 343504 2019-01-27 19:04:28Z marius $");
28241600Sgonzo
29241600Sgonzo#include <sys/param.h>
30241600Sgonzo#include <sys/systm.h>
31241600Sgonzo#include <sys/bus.h>
32241600Sgonzo#include <sys/kernel.h>
33241600Sgonzo#include <sys/lock.h>
34241600Sgonzo#include <sys/module.h>
35241600Sgonzo#include <sys/mutex.h>
36241600Sgonzo#include <sys/resource.h>
37241600Sgonzo#include <sys/rman.h>
38241600Sgonzo#include <sys/sysctl.h>
39241600Sgonzo#include <sys/taskqueue.h>
40241600Sgonzo
41241600Sgonzo#include <dev/pci/pcireg.h>
42241600Sgonzo#include <dev/pci/pcivar.h>
43241600Sgonzo
44241600Sgonzo#include <machine/bus.h>
45241600Sgonzo#include <machine/resource.h>
46241600Sgonzo
47241600Sgonzo#include <dev/mmc/bridge.h>
48241600Sgonzo
49318197Smarius#include <dev/sdhci/sdhci.h>
50318197Smarius
51241600Sgonzo#include "mmcbr_if.h"
52241600Sgonzo#include "sdhci_if.h"
53241600Sgonzo
54241600Sgonzo/*
55241600Sgonzo * PCI registers
56241600Sgonzo */
57318197Smarius#define	PCI_SDHCI_IFPIO			0x00
58318197Smarius#define	PCI_SDHCI_IFDMA			0x01
59318197Smarius#define	PCI_SDHCI_IFVENDOR		0x02
60241600Sgonzo
61318197Smarius#define	PCI_SLOT_INFO			0x40	/* 8 bits */
62318197Smarius#define	PCI_SLOT_INFO_SLOTS(x)		(((x >> 4) & 7) + 1)
63318197Smarius#define	PCI_SLOT_INFO_FIRST_BAR(x)	((x) & 7)
64241600Sgonzo
65241600Sgonzo/*
66241600Sgonzo * RICOH specific PCI registers
67241600Sgonzo */
68241600Sgonzo#define	SDHC_PCI_MODE_KEY		0xf9
69241600Sgonzo#define	SDHC_PCI_MODE			0x150
70312399Smarius#define	SDHC_PCI_MODE_SD20		0x10
71241600Sgonzo#define	SDHC_PCI_BASE_FREQ_KEY		0xfc
72241600Sgonzo#define	SDHC_PCI_BASE_FREQ		0xe1
73241600Sgonzo
74241600Sgonzostatic const struct sdhci_device {
75241600Sgonzo	uint32_t	model;
76241600Sgonzo	uint16_t	subvendor;
77270885Smarius	const char	*desc;
78241600Sgonzo	u_int		quirks;
79241600Sgonzo} sdhci_devices[] = {
80318197Smarius	{ 0x08221180,	0xffff,	"RICOH R5C822 SD",
81241600Sgonzo	    SDHCI_QUIRK_FORCE_DMA },
82318197Smarius	{ 0xe8221180,	0xffff,	"RICOH R5CE822 SD",
83276469Smarius	    SDHCI_QUIRK_FORCE_DMA |
84276469Smarius	    SDHCI_QUIRK_LOWER_FREQUENCY },
85318197Smarius	{ 0xe8231180,	0xffff,	"RICOH R5CE823 SD",
86241600Sgonzo	    SDHCI_QUIRK_LOWER_FREQUENCY },
87318197Smarius	{ 0x8034104c,	0xffff, "TI XX21/XX11 SD",
88241600Sgonzo	    SDHCI_QUIRK_FORCE_DMA },
89318197Smarius	{ 0x05501524,	0xffff, "ENE CB712 SD",
90241600Sgonzo	    SDHCI_QUIRK_BROKEN_TIMINGS },
91318197Smarius	{ 0x05511524,	0xffff, "ENE CB712 SD 2",
92241600Sgonzo	    SDHCI_QUIRK_BROKEN_TIMINGS },
93318197Smarius	{ 0x07501524,	0xffff, "ENE CB714 SD",
94241600Sgonzo	    SDHCI_QUIRK_RESET_ON_IOS |
95241600Sgonzo	    SDHCI_QUIRK_BROKEN_TIMINGS },
96318197Smarius	{ 0x07511524,	0xffff, "ENE CB714 SD 2",
97241600Sgonzo	    SDHCI_QUIRK_RESET_ON_IOS |
98241600Sgonzo	    SDHCI_QUIRK_BROKEN_TIMINGS },
99318197Smarius	{ 0x410111ab,	0xffff, "Marvell CaFe SD",
100241600Sgonzo	    SDHCI_QUIRK_INCR_TIMEOUT_CONTROL },
101318197Smarius	{ 0x2381197B,	0xffff,	"JMicron JMB38X SD",
102241600Sgonzo	    SDHCI_QUIRK_32BIT_DMA_SIZE |
103241600Sgonzo	    SDHCI_QUIRK_RESET_AFTER_REQUEST },
104289359Sadrian	{ 0x16bc14e4,	0xffff,	"Broadcom BCM577xx SDXC/MMC Card Reader",
105289359Sadrian	    SDHCI_QUIRK_BCM577XX_400KHZ_CLKSRC },
106312399Smarius	{ 0x0f148086,	0xffff,	"Intel Bay Trail eMMC 4.5 Controller",
107333767Smarius	    /* DDR52 is supported but affected by the VLI54 erratum */
108318197Smarius	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
109318494Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
110318494Smarius	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
111318494Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN},
112318197Smarius	{ 0x0f158086,	0xffff,	"Intel Bay Trail SDXC Controller",
113318494Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
114318494Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
115312399Smarius	{ 0x0f508086,	0xffff,	"Intel Bay Trail eMMC 4.5 Controller",
116333767Smarius	    /* DDR52 is supported but affected by the VLI54 erratum */
117318197Smarius	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
118318494Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
119318494Smarius	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
120318494Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
121331032Smarius	{ 0x19db8086,	0xffff,	"Intel Denverton eMMC 5.0 Controller",
122331032Smarius	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
123331032Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
124331032Smarius	    SDHCI_QUIRK_MMC_DDR52 |
125331032Smarius	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
126331032Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
127312399Smarius	{ 0x22948086,	0xffff,	"Intel Braswell eMMC 4.5.1 Controller",
128312399Smarius	    SDHCI_QUIRK_DATA_TIMEOUT_1MHZ |
129318197Smarius	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
130318494Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
131318494Smarius	    SDHCI_QUIRK_MMC_DDR52 |
132318494Smarius	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
133318494Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
134318197Smarius	{ 0x22968086,	0xffff,	"Intel Braswell SDXC Controller",
135318494Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
136318494Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
137318197Smarius	{ 0x5aca8086,	0xffff,	"Intel Apollo Lake SDXC Controller",
138318496Smarius	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
139318494Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
140318494Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
141312399Smarius	{ 0x5acc8086,	0xffff,	"Intel Apollo Lake eMMC 5.0 Controller",
142318496Smarius	    SDHCI_QUIRK_BROKEN_DMA |	/* APL18 erratum */
143318197Smarius	    SDHCI_QUIRK_INTEL_POWER_UP_RESET |
144318494Smarius	    SDHCI_QUIRK_WAIT_WHILE_BUSY |
145318494Smarius	    SDHCI_QUIRK_MMC_DDR52 |
146318494Smarius	    SDHCI_QUIRK_CAPS_BIT63_FOR_MMC_HS400 |
147318494Smarius	    SDHCI_QUIRK_PRESET_VALUE_BROKEN },
148241600Sgonzo	{ 0,		0xffff,	NULL,
149241600Sgonzo	    0 }
150241600Sgonzo};
151241600Sgonzo
152241600Sgonzostruct sdhci_pci_softc {
153241600Sgonzo	u_int		quirks;		/* Chip specific quirks */
154241600Sgonzo	struct resource *irq_res;	/* IRQ resource */
155318197Smarius	void		*intrhand;	/* Interrupt handle */
156241600Sgonzo
157241600Sgonzo	int		num_slots;	/* Number of slots on this controller */
158241600Sgonzo	struct sdhci_slot slots[6];
159241600Sgonzo	struct resource	*mem_res[6];	/* Memory resource */
160312399Smarius	uint8_t		cfg_freq;	/* Saved frequency */
161312399Smarius	uint8_t		cfg_mode;	/* Saved mode */
162241600Sgonzo};
163241600Sgonzo
164270885Smariusstatic int sdhci_enable_msi = 1;
165270885SmariusSYSCTL_INT(_hw_sdhci, OID_AUTO, enable_msi, CTLFLAG_RDTUN, &sdhci_enable_msi,
166270885Smarius    0, "Enable MSI interrupts");
167241600Sgonzo
168241600Sgonzostatic uint8_t
169318197Smariussdhci_pci_read_1(device_t dev, struct sdhci_slot *slot __unused, bus_size_t off)
170241600Sgonzo{
171241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
172241600Sgonzo
173241600Sgonzo	bus_barrier(sc->mem_res[slot->num], 0, 0xFF,
174241600Sgonzo	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
175241600Sgonzo	return bus_read_1(sc->mem_res[slot->num], off);
176241600Sgonzo}
177241600Sgonzo
178241600Sgonzostatic void
179318197Smariussdhci_pci_write_1(device_t dev, struct sdhci_slot *slot __unused,
180318197Smarius    bus_size_t off, uint8_t val)
181241600Sgonzo{
182241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
183241600Sgonzo
184241600Sgonzo	bus_barrier(sc->mem_res[slot->num], 0, 0xFF,
185241600Sgonzo	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
186241600Sgonzo	bus_write_1(sc->mem_res[slot->num], off, val);
187241600Sgonzo}
188241600Sgonzo
189241600Sgonzostatic uint16_t
190318197Smariussdhci_pci_read_2(device_t dev, struct sdhci_slot *slot __unused, bus_size_t off)
191241600Sgonzo{
192241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
193241600Sgonzo
194241600Sgonzo	bus_barrier(sc->mem_res[slot->num], 0, 0xFF,
195241600Sgonzo	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
196241600Sgonzo	return bus_read_2(sc->mem_res[slot->num], off);
197241600Sgonzo}
198241600Sgonzo
199241600Sgonzostatic void
200318197Smariussdhci_pci_write_2(device_t dev, struct sdhci_slot *slot __unused,
201318197Smarius    bus_size_t off, uint16_t val)
202241600Sgonzo{
203241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
204241600Sgonzo
205241600Sgonzo	bus_barrier(sc->mem_res[slot->num], 0, 0xFF,
206241600Sgonzo	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
207241600Sgonzo	bus_write_2(sc->mem_res[slot->num], off, val);
208241600Sgonzo}
209241600Sgonzo
210241600Sgonzostatic uint32_t
211318197Smariussdhci_pci_read_4(device_t dev, struct sdhci_slot *slot __unused, bus_size_t off)
212241600Sgonzo{
213241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
214241600Sgonzo
215241600Sgonzo	bus_barrier(sc->mem_res[slot->num], 0, 0xFF,
216241600Sgonzo	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
217241600Sgonzo	return bus_read_4(sc->mem_res[slot->num], off);
218241600Sgonzo}
219241600Sgonzo
220241600Sgonzostatic void
221318197Smariussdhci_pci_write_4(device_t dev, struct sdhci_slot *slot __unused,
222318197Smarius    bus_size_t off, uint32_t val)
223241600Sgonzo{
224241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
225241600Sgonzo
226241600Sgonzo	bus_barrier(sc->mem_res[slot->num], 0, 0xFF,
227241600Sgonzo	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
228241600Sgonzo	bus_write_4(sc->mem_res[slot->num], off, val);
229241600Sgonzo}
230241600Sgonzo
231241600Sgonzostatic void
232318197Smariussdhci_pci_read_multi_4(device_t dev, struct sdhci_slot *slot __unused,
233241600Sgonzo    bus_size_t off, uint32_t *data, bus_size_t count)
234241600Sgonzo{
235241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
236241600Sgonzo
237241600Sgonzo	bus_read_multi_stream_4(sc->mem_res[slot->num], off, data, count);
238241600Sgonzo}
239241600Sgonzo
240241600Sgonzostatic void
241318197Smariussdhci_pci_write_multi_4(device_t dev, struct sdhci_slot *slot __unused,
242241600Sgonzo    bus_size_t off, uint32_t *data, bus_size_t count)
243241600Sgonzo{
244241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
245241600Sgonzo
246241600Sgonzo	bus_write_multi_stream_4(sc->mem_res[slot->num], off, data, count);
247241600Sgonzo}
248241600Sgonzo
249241600Sgonzostatic void sdhci_pci_intr(void *arg);
250241600Sgonzo
251241600Sgonzostatic void
252241600Sgonzosdhci_lower_frequency(device_t dev)
253241600Sgonzo{
254276469Smarius	struct sdhci_pci_softc *sc = device_get_softc(dev);
255241600Sgonzo
256276469Smarius	/*
257276469Smarius	 * Enable SD2.0 mode.
258276469Smarius	 * NB: for RICOH R5CE823, this changes the PCI device ID to 0xe822.
259276469Smarius	 */
260241600Sgonzo	pci_write_config(dev, SDHC_PCI_MODE_KEY, 0xfc, 1);
261276469Smarius	sc->cfg_mode = pci_read_config(dev, SDHC_PCI_MODE, 1);
262241600Sgonzo	pci_write_config(dev, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20, 1);
263241600Sgonzo	pci_write_config(dev, SDHC_PCI_MODE_KEY, 0x00, 1);
264241600Sgonzo
265241600Sgonzo	/*
266241600Sgonzo	 * Some SD/MMC cards don't work with the default base
267276469Smarius	 * clock frequency of 200 MHz.  Lower it to 50 MHz.
268241600Sgonzo	 */
269241600Sgonzo	pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x01, 1);
270276469Smarius	sc->cfg_freq = pci_read_config(dev, SDHC_PCI_BASE_FREQ, 1);
271241600Sgonzo	pci_write_config(dev, SDHC_PCI_BASE_FREQ, 50, 1);
272241600Sgonzo	pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x00, 1);
273241600Sgonzo}
274241600Sgonzo
275276469Smariusstatic void
276276469Smariussdhci_restore_frequency(device_t dev)
277276469Smarius{
278276469Smarius	struct sdhci_pci_softc *sc = device_get_softc(dev);
279276469Smarius
280276469Smarius	/* Restore mode. */
281276469Smarius	pci_write_config(dev, SDHC_PCI_MODE_KEY, 0xfc, 1);
282276469Smarius	pci_write_config(dev, SDHC_PCI_MODE, sc->cfg_mode, 1);
283276469Smarius	pci_write_config(dev, SDHC_PCI_MODE_KEY, 0x00, 1);
284276469Smarius
285276469Smarius	/* Restore frequency. */
286276469Smarius	pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x01, 1);
287276469Smarius	pci_write_config(dev, SDHC_PCI_BASE_FREQ, sc->cfg_freq, 1);
288276469Smarius	pci_write_config(dev, SDHC_PCI_BASE_FREQ_KEY, 0x00, 1);
289276469Smarius}
290276469Smarius
291241600Sgonzostatic int
292241600Sgonzosdhci_pci_probe(device_t dev)
293241600Sgonzo{
294241600Sgonzo	uint32_t model;
295241600Sgonzo	uint16_t subvendor;
296241600Sgonzo	uint8_t class, subclass;
297241600Sgonzo	int i, result;
298270885Smarius
299241600Sgonzo	model = (uint32_t)pci_get_device(dev) << 16;
300241600Sgonzo	model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff;
301241600Sgonzo	subvendor = pci_get_subvendor(dev);
302241600Sgonzo	class = pci_get_class(dev);
303241600Sgonzo	subclass = pci_get_subclass(dev);
304270885Smarius
305241600Sgonzo	result = ENXIO;
306241600Sgonzo	for (i = 0; sdhci_devices[i].model != 0; i++) {
307241600Sgonzo		if (sdhci_devices[i].model == model &&
308241600Sgonzo		    (sdhci_devices[i].subvendor == 0xffff ||
309241600Sgonzo		    sdhci_devices[i].subvendor == subvendor)) {
310241600Sgonzo			device_set_desc(dev, sdhci_devices[i].desc);
311241600Sgonzo			result = BUS_PROBE_DEFAULT;
312241600Sgonzo			break;
313241600Sgonzo		}
314241600Sgonzo	}
315241600Sgonzo	if (result == ENXIO && class == PCIC_BASEPERIPH &&
316241600Sgonzo	    subclass == PCIS_BASEPERIPH_SDHC) {
317241600Sgonzo		device_set_desc(dev, "Generic SD HCI");
318241600Sgonzo		result = BUS_PROBE_GENERIC;
319241600Sgonzo	}
320270885Smarius
321241600Sgonzo	return (result);
322241600Sgonzo}
323241600Sgonzo
324241600Sgonzostatic int
325241600Sgonzosdhci_pci_attach(device_t dev)
326241600Sgonzo{
327241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
328318197Smarius	struct sdhci_slot *slot;
329241600Sgonzo	uint32_t model;
330241600Sgonzo	uint16_t subvendor;
331270885Smarius	int bar, err, rid, slots, i;
332241600Sgonzo
333241600Sgonzo	model = (uint32_t)pci_get_device(dev) << 16;
334241600Sgonzo	model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff;
335241600Sgonzo	subvendor = pci_get_subvendor(dev);
336241600Sgonzo	/* Apply chip specific quirks. */
337241600Sgonzo	for (i = 0; sdhci_devices[i].model != 0; i++) {
338241600Sgonzo		if (sdhci_devices[i].model == model &&
339241600Sgonzo		    (sdhci_devices[i].subvendor == 0xffff ||
340241600Sgonzo		    sdhci_devices[i].subvendor == subvendor)) {
341241600Sgonzo			sc->quirks = sdhci_devices[i].quirks;
342241600Sgonzo			break;
343241600Sgonzo		}
344241600Sgonzo	}
345318494Smarius	sc->quirks &= ~sdhci_quirk_clear;
346318494Smarius	sc->quirks |= sdhci_quirk_set;
347318496Smarius
348241600Sgonzo	/* Some controllers need to be bumped into the right mode. */
349241600Sgonzo	if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY)
350241600Sgonzo		sdhci_lower_frequency(dev);
351241600Sgonzo	/* Read slots info from PCI registers. */
352241600Sgonzo	slots = pci_read_config(dev, PCI_SLOT_INFO, 1);
353241600Sgonzo	bar = PCI_SLOT_INFO_FIRST_BAR(slots);
354241600Sgonzo	slots = PCI_SLOT_INFO_SLOTS(slots);
355241600Sgonzo	if (slots > 6 || bar > 5) {
356241600Sgonzo		device_printf(dev, "Incorrect slots information (%d, %d).\n",
357241600Sgonzo		    slots, bar);
358241600Sgonzo		return (EINVAL);
359241600Sgonzo	}
360241600Sgonzo	/* Allocate IRQ. */
361270885Smarius	i = 1;
362270885Smarius	rid = 0;
363270885Smarius	if (sdhci_enable_msi != 0 && pci_alloc_msi(dev, &i) == 0)
364270885Smarius		rid = 1;
365270885Smarius	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
366270885Smarius		RF_ACTIVE | (rid != 0 ? 0 : RF_SHAREABLE));
367241600Sgonzo	if (sc->irq_res == NULL) {
368241600Sgonzo		device_printf(dev, "Can't allocate IRQ\n");
369270885Smarius		pci_release_msi(dev);
370241600Sgonzo		return (ENOMEM);
371241600Sgonzo	}
372241600Sgonzo	/* Scan all slots. */
373241600Sgonzo	for (i = 0; i < slots; i++) {
374318197Smarius		slot = &sc->slots[sc->num_slots];
375241600Sgonzo
376241600Sgonzo		/* Allocate memory. */
377270885Smarius		rid = PCIR_BAR(bar + i);
378296135Sjhibbits		sc->mem_res[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
379296135Sjhibbits		    &rid, RF_ACTIVE);
380241600Sgonzo		if (sc->mem_res[i] == NULL) {
381318197Smarius			device_printf(dev,
382318197Smarius			    "Can't allocate memory for slot %d\n", i);
383241600Sgonzo			continue;
384241600Sgonzo		}
385318197Smarius
386289359Sadrian		slot->quirks = sc->quirks;
387241600Sgonzo
388241600Sgonzo		if (sdhci_init_slot(dev, slot, i) != 0)
389241600Sgonzo			continue;
390241600Sgonzo
391241600Sgonzo		sc->num_slots++;
392241600Sgonzo	}
393241600Sgonzo	device_printf(dev, "%d slot(s) allocated\n", sc->num_slots);
394241600Sgonzo	/* Activate the interrupt */
395241600Sgonzo	err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
396241600Sgonzo	    NULL, sdhci_pci_intr, sc, &sc->intrhand);
397241600Sgonzo	if (err)
398241600Sgonzo		device_printf(dev, "Can't setup IRQ\n");
399241600Sgonzo	pci_enable_busmaster(dev);
400241600Sgonzo	/* Process cards detection. */
401318197Smarius	for (i = 0; i < sc->num_slots; i++)
402318197Smarius		sdhci_start_slot(&sc->slots[i]);
403241600Sgonzo
404241600Sgonzo	return (0);
405241600Sgonzo}
406241600Sgonzo
407241600Sgonzostatic int
408241600Sgonzosdhci_pci_detach(device_t dev)
409241600Sgonzo{
410241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
411241600Sgonzo	int i;
412241600Sgonzo
413241600Sgonzo	bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
414241600Sgonzo	bus_release_resource(dev, SYS_RES_IRQ,
415270885Smarius	    rman_get_rid(sc->irq_res), sc->irq_res);
416270885Smarius	pci_release_msi(dev);
417241600Sgonzo
418241600Sgonzo	for (i = 0; i < sc->num_slots; i++) {
419318197Smarius		sdhci_cleanup_slot(&sc->slots[i]);
420241600Sgonzo		bus_release_resource(dev, SYS_RES_MEMORY,
421270885Smarius		    rman_get_rid(sc->mem_res[i]), sc->mem_res[i]);
422241600Sgonzo	}
423276469Smarius	if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY)
424276469Smarius		sdhci_restore_frequency(dev);
425241600Sgonzo	return (0);
426241600Sgonzo}
427241600Sgonzo
428241600Sgonzostatic int
429276469Smariussdhci_pci_shutdown(device_t dev)
430276469Smarius{
431276469Smarius	struct sdhci_pci_softc *sc = device_get_softc(dev);
432276469Smarius
433276469Smarius	if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY)
434276469Smarius		sdhci_restore_frequency(dev);
435276469Smarius	return (0);
436276469Smarius}
437276469Smarius
438276469Smariusstatic int
439241600Sgonzosdhci_pci_suspend(device_t dev)
440241600Sgonzo{
441241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
442241600Sgonzo	int i, err;
443241600Sgonzo
444241600Sgonzo	err = bus_generic_suspend(dev);
445241600Sgonzo	if (err)
446241600Sgonzo		return (err);
447241600Sgonzo	for (i = 0; i < sc->num_slots; i++)
448270885Smarius		sdhci_generic_suspend(&sc->slots[i]);
449241600Sgonzo	return (0);
450241600Sgonzo}
451241600Sgonzo
452241600Sgonzostatic int
453241600Sgonzosdhci_pci_resume(device_t dev)
454241600Sgonzo{
455241600Sgonzo	struct sdhci_pci_softc *sc = device_get_softc(dev);
456299414Strasz	int i, err;
457241600Sgonzo
458241600Sgonzo	for (i = 0; i < sc->num_slots; i++)
459241600Sgonzo		sdhci_generic_resume(&sc->slots[i]);
460299414Strasz	err = bus_generic_resume(dev);
461299414Strasz	if (err)
462299414Strasz		return (err);
463299414Strasz	if (sc->quirks & SDHCI_QUIRK_LOWER_FREQUENCY)
464299414Strasz		sdhci_lower_frequency(dev);
465299414Strasz	return (0);
466241600Sgonzo}
467241600Sgonzo
468241600Sgonzostatic void
469241600Sgonzosdhci_pci_intr(void *arg)
470241600Sgonzo{
471241600Sgonzo	struct sdhci_pci_softc *sc = (struct sdhci_pci_softc *)arg;
472241600Sgonzo	int i;
473241600Sgonzo
474318197Smarius	for (i = 0; i < sc->num_slots; i++)
475318197Smarius		sdhci_generic_intr(&sc->slots[i]);
476241600Sgonzo}
477241600Sgonzo
478241600Sgonzostatic device_method_t sdhci_methods[] = {
479241600Sgonzo	/* device_if */
480318197Smarius	DEVMETHOD(device_probe,		sdhci_pci_probe),
481318197Smarius	DEVMETHOD(device_attach,	sdhci_pci_attach),
482318197Smarius	DEVMETHOD(device_detach,	sdhci_pci_detach),
483318197Smarius	DEVMETHOD(device_shutdown,	sdhci_pci_shutdown),
484318197Smarius	DEVMETHOD(device_suspend,	sdhci_pci_suspend),
485318197Smarius	DEVMETHOD(device_resume,	sdhci_pci_resume),
486241600Sgonzo
487241600Sgonzo	/* Bus interface */
488241600Sgonzo	DEVMETHOD(bus_read_ivar,	sdhci_generic_read_ivar),
489241600Sgonzo	DEVMETHOD(bus_write_ivar,	sdhci_generic_write_ivar),
490241600Sgonzo
491241600Sgonzo	/* mmcbr_if */
492318197Smarius	DEVMETHOD(mmcbr_update_ios,	sdhci_generic_update_ios),
493318494Smarius	DEVMETHOD(mmcbr_switch_vccq,	sdhci_generic_switch_vccq),
494322119Smarius	DEVMETHOD(mmcbr_tune,		sdhci_generic_tune),
495322119Smarius	DEVMETHOD(mmcbr_retune,		sdhci_generic_retune),
496318197Smarius	DEVMETHOD(mmcbr_request,	sdhci_generic_request),
497318197Smarius	DEVMETHOD(mmcbr_get_ro,		sdhci_generic_get_ro),
498312399Smarius	DEVMETHOD(mmcbr_acquire_host,   sdhci_generic_acquire_host),
499312399Smarius	DEVMETHOD(mmcbr_release_host,   sdhci_generic_release_host),
500241600Sgonzo
501318494Smarius	/* SDHCI accessors */
502241600Sgonzo	DEVMETHOD(sdhci_read_1,		sdhci_pci_read_1),
503241600Sgonzo	DEVMETHOD(sdhci_read_2,		sdhci_pci_read_2),
504241600Sgonzo	DEVMETHOD(sdhci_read_4,		sdhci_pci_read_4),
505241600Sgonzo	DEVMETHOD(sdhci_read_multi_4,	sdhci_pci_read_multi_4),
506241600Sgonzo	DEVMETHOD(sdhci_write_1,	sdhci_pci_write_1),
507241600Sgonzo	DEVMETHOD(sdhci_write_2,	sdhci_pci_write_2),
508241600Sgonzo	DEVMETHOD(sdhci_write_4,	sdhci_pci_write_4),
509241600Sgonzo	DEVMETHOD(sdhci_write_multi_4,	sdhci_pci_write_multi_4),
510318494Smarius	DEVMETHOD(sdhci_set_uhs_timing,	sdhci_generic_set_uhs_timing),
511241600Sgonzo
512246128Ssbz	DEVMETHOD_END
513241600Sgonzo};
514241600Sgonzo
515241600Sgonzostatic driver_t sdhci_pci_driver = {
516241600Sgonzo	"sdhci_pci",
517241600Sgonzo	sdhci_methods,
518241600Sgonzo	sizeof(struct sdhci_pci_softc),
519241600Sgonzo};
520241600Sgonzostatic devclass_t sdhci_pci_devclass;
521241600Sgonzo
522270885SmariusDRIVER_MODULE(sdhci_pci, pci, sdhci_pci_driver, sdhci_pci_devclass, NULL,
523270885Smarius    NULL);
524343504SmariusSDHCI_DEPEND(sdhci_pci);
525318197SmariusMMC_DECLARE_BRIDGE(sdhci_pci);
526