xref: /openbsd-src/sys/dev/sdmmc/sdhc.c (revision 8ab765f84d4769bbeb688bacea2d9caee85a211e)
1*8ab765f8Shastings /*	$OpenBSD: sdhc.c,v 1.78 2024/10/19 21:10:03 hastings Exp $	*/
2aae4fe77Suwe 
3aae4fe77Suwe /*
4aae4fe77Suwe  * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
5aae4fe77Suwe  *
6aae4fe77Suwe  * Permission to use, copy, modify, and distribute this software for any
7aae4fe77Suwe  * purpose with or without fee is hereby granted, provided that the above
8aae4fe77Suwe  * copyright notice and this permission notice appear in all copies.
9aae4fe77Suwe  *
10aae4fe77Suwe  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11aae4fe77Suwe  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12aae4fe77Suwe  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13aae4fe77Suwe  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14aae4fe77Suwe  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15aae4fe77Suwe  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16aae4fe77Suwe  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17aae4fe77Suwe  */
18aae4fe77Suwe 
19aae4fe77Suwe /*
20aae4fe77Suwe  * SD Host Controller driver based on the SD Host Controller Standard
215e422abeSjsg  * Simplified Specification Version 1.00 (www.sdcard.org).
22aae4fe77Suwe  */
23aae4fe77Suwe 
24aae4fe77Suwe #include <sys/param.h>
25aae4fe77Suwe #include <sys/device.h>
26aae4fe77Suwe #include <sys/kernel.h>
27aae4fe77Suwe #include <sys/malloc.h>
28c2deed7fSkettenis #include <sys/proc.h>
29aae4fe77Suwe #include <sys/systm.h>
303f3abf14Scheloha #include <sys/time.h>
31aae4fe77Suwe 
32aae4fe77Suwe #include <dev/sdmmc/sdhcreg.h>
33aae4fe77Suwe #include <dev/sdmmc/sdhcvar.h>
34aae4fe77Suwe #include <dev/sdmmc/sdmmcchip.h>
35aae4fe77Suwe #include <dev/sdmmc/sdmmcreg.h>
36aae4fe77Suwe #include <dev/sdmmc/sdmmcvar.h>
37402f30eeSpatrick #include <dev/sdmmc/sdmmc_ioreg.h>
38aae4fe77Suwe 
393f3abf14Scheloha /* Timeouts in seconds */
403f3abf14Scheloha #define SDHC_COMMAND_TIMEOUT	1
413f3abf14Scheloha #define SDHC_BUFFER_TIMEOUT	1
423f3abf14Scheloha #define SDHC_TRANSFER_TIMEOUT	1
433f3abf14Scheloha #define SDHC_DMA_TIMEOUT	3
44aae4fe77Suwe 
45aae4fe77Suwe struct sdhc_host {
46aae4fe77Suwe 	struct sdhc_softc *sc;		/* host controller device */
47aae4fe77Suwe 	struct device *sdmmc;		/* generic SD/MMC device */
48aae4fe77Suwe 	bus_space_tag_t iot;		/* host register set tag */
49aae4fe77Suwe 	bus_space_handle_t ioh;		/* host register set handle */
50445e328eSkettenis 	u_int16_t version;		/* specification version */
51aae4fe77Suwe 	u_int clkbase;			/* base clock frequency in KHz */
52aae4fe77Suwe 	int maxblklen;			/* maximum block length */
53aae4fe77Suwe 	int flags;			/* flags for this host */
54aae4fe77Suwe 	u_int32_t ocr;			/* OCR value from capabilities */
55f50f4931Suwe 	u_int8_t regs[14];		/* host controller state */
56a6fd99a7Suwe 	u_int16_t intr_status;		/* soft interrupt status */
57a6fd99a7Suwe 	u_int16_t intr_error_status;	/* soft error status */
58c6293583Skettenis 
59c6293583Skettenis 	bus_dmamap_t adma_map;
60c6293583Skettenis 	bus_dma_segment_t adma_segs[1];
61c6293583Skettenis 	caddr_t adma2;
6204b7fce9Skettenis 
6304b7fce9Skettenis 	uint16_t block_size;
6404b7fce9Skettenis 	uint16_t block_count;
6504b7fce9Skettenis 	uint16_t transfer_mode;
66aae4fe77Suwe };
67aae4fe77Suwe 
68aae4fe77Suwe /* flag values */
69aae4fe77Suwe #define SHF_USE_DMA		0x0001
70b60bffefSpatrick #define SHF_USE_DMA64		0x0002
7104b7fce9Skettenis #define SHF_USE_32BIT_ACCESS	0x0004
72aae4fe77Suwe 
73aae4fe77Suwe #define HREAD1(hp, reg)							\
7404b7fce9Skettenis 	(sdhc_read_1((hp), (reg)))
75aae4fe77Suwe #define HREAD2(hp, reg)							\
7604b7fce9Skettenis 	(sdhc_read_2((hp), (reg)))
77aae4fe77Suwe #define HREAD4(hp, reg)							\
78aae4fe77Suwe 	(bus_space_read_4((hp)->iot, (hp)->ioh, (reg)))
79aae4fe77Suwe #define HWRITE1(hp, reg, val)						\
8004b7fce9Skettenis 	sdhc_write_1((hp), (reg), (val))
81aae4fe77Suwe #define HWRITE2(hp, reg, val)						\
8204b7fce9Skettenis 	sdhc_write_2((hp), (reg), (val))
83aae4fe77Suwe #define HWRITE4(hp, reg, val)						\
84aae4fe77Suwe 	bus_space_write_4((hp)->iot, (hp)->ioh, (reg), (val))
85aae4fe77Suwe #define HCLR1(hp, reg, bits)						\
86aae4fe77Suwe 	HWRITE1((hp), (reg), HREAD1((hp), (reg)) & ~(bits))
87aae4fe77Suwe #define HCLR2(hp, reg, bits)						\
88aae4fe77Suwe 	HWRITE2((hp), (reg), HREAD2((hp), (reg)) & ~(bits))
89aae4fe77Suwe #define HSET1(hp, reg, bits)						\
90aae4fe77Suwe 	HWRITE1((hp), (reg), HREAD1((hp), (reg)) | (bits))
91aae4fe77Suwe #define HSET2(hp, reg, bits)						\
92aae4fe77Suwe 	HWRITE2((hp), (reg), HREAD2((hp), (reg)) | (bits))
93aae4fe77Suwe 
94aae4fe77Suwe int	sdhc_host_reset(sdmmc_chipset_handle_t);
95aae4fe77Suwe u_int32_t sdhc_host_ocr(sdmmc_chipset_handle_t);
96aae4fe77Suwe int	sdhc_host_maxblklen(sdmmc_chipset_handle_t);
97aae4fe77Suwe int	sdhc_card_detect(sdmmc_chipset_handle_t);
98aae4fe77Suwe int	sdhc_bus_power(sdmmc_chipset_handle_t, u_int32_t);
99820e06f1Skettenis int	sdhc_bus_clock(sdmmc_chipset_handle_t, int, int);
100b140af5cSkettenis int	sdhc_bus_width(sdmmc_chipset_handle_t, int);
101b979651fSuwe void	sdhc_card_intr_mask(sdmmc_chipset_handle_t, int);
102b979651fSuwe void	sdhc_card_intr_ack(sdmmc_chipset_handle_t);
103820e06f1Skettenis int	sdhc_signal_voltage(sdmmc_chipset_handle_t, int);
104a6fd99a7Suwe void	sdhc_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
105aae4fe77Suwe int	sdhc_start_command(struct sdhc_host *, struct sdmmc_command *);
106a6fd99a7Suwe int	sdhc_wait_state(struct sdhc_host *, u_int32_t, u_int32_t);
1075842cfcdSfgsch int	sdhc_soft_reset(struct sdhc_host *, int);
108f3036462Sjmatthew int	sdhc_wait_intr_cold(struct sdhc_host *, int, int);
109a6fd99a7Suwe int	sdhc_wait_intr(struct sdhc_host *, int, int);
110a6fd99a7Suwe void	sdhc_transfer_data(struct sdhc_host *, struct sdmmc_command *);
111aae4fe77Suwe void	sdhc_read_data(struct sdhc_host *, u_char *, int);
112aae4fe77Suwe void	sdhc_write_data(struct sdhc_host *, u_char *, int);
113f3036462Sjmatthew int	sdhc_hibernate_init(sdmmc_chipset_handle_t, void *);
114aae4fe77Suwe 
115aae4fe77Suwe #ifdef SDHC_DEBUG
11637539bbbSuwe int sdhcdebug = 0;
11737539bbbSuwe #define DPRINTF(n,s)	do { if ((n) <= sdhcdebug) printf s; } while (0)
118aae4fe77Suwe void	sdhc_dump_regs(struct sdhc_host *);
119aae4fe77Suwe #else
12037539bbbSuwe #define DPRINTF(n,s)	do {} while(0)
121aae4fe77Suwe #endif
122aae4fe77Suwe 
123aae4fe77Suwe struct sdmmc_chip_functions sdhc_functions = {
124a62fc20aSkettenis 	.host_reset = sdhc_host_reset,
125a62fc20aSkettenis 	.host_ocr = sdhc_host_ocr,
126a62fc20aSkettenis 	.host_maxblklen = sdhc_host_maxblklen,
127a62fc20aSkettenis 	.card_detect = sdhc_card_detect,
128a62fc20aSkettenis 	.bus_power = sdhc_bus_power,
129a62fc20aSkettenis 	.bus_clock = sdhc_bus_clock,
130a62fc20aSkettenis 	.bus_width = sdhc_bus_width,
131a62fc20aSkettenis 	.exec_command = sdhc_exec_command,
132a62fc20aSkettenis 	.card_intr_mask = sdhc_card_intr_mask,
133a62fc20aSkettenis 	.card_intr_ack = sdhc_card_intr_ack,
134a62fc20aSkettenis 	.signal_voltage = sdhc_signal_voltage,
135a62fc20aSkettenis 	.hibernate_init = sdhc_hibernate_init,
136aae4fe77Suwe };
137aae4fe77Suwe 
138aae4fe77Suwe struct cfdriver sdhc_cd = {
139aae4fe77Suwe 	NULL, "sdhc", DV_DULL
140aae4fe77Suwe };
141aae4fe77Suwe 
142aae4fe77Suwe /*
14304b7fce9Skettenis  * Some controllers live on a bus that only allows 32-bit
14404b7fce9Skettenis  * transactions.  In that case we use a RMW cycle for 8-bit and 16-bit
14504b7fce9Skettenis  * register writes.  However that doesn't work for the Transfer Mode
14604b7fce9Skettenis  * register as this register lives in the same 32-bit word as the
14704b7fce9Skettenis  * Command register and writing the Command register triggers SD
14804b7fce9Skettenis  * command generation.  We avoid this issue by using a shadow variable
14904b7fce9Skettenis  * for the Transfer Mode register that we write out when we write the
15004b7fce9Skettenis  * Command register.
15104b7fce9Skettenis  *
152b3af768dSjsg  * The Arasan controller integrated on the Broadcom SoCs
15304b7fce9Skettenis  * used in the Raspberry Pi has an interesting bug where writing the
15404b7fce9Skettenis  * same 32-bit register twice doesn't work.  This means that we lose
15504b7fce9Skettenis  * writes to the Block Sine and/or Block Count register.  We work
15604b7fce9Skettenis  * around that issue by using shadow variables as well.
15704b7fce9Skettenis  */
15804b7fce9Skettenis 
15904b7fce9Skettenis uint8_t
16004b7fce9Skettenis sdhc_read_1(struct sdhc_host *hp, bus_size_t offset)
16104b7fce9Skettenis {
16204b7fce9Skettenis 	uint32_t reg;
16304b7fce9Skettenis 
16404b7fce9Skettenis 	if (hp->flags & SHF_USE_32BIT_ACCESS) {
16504b7fce9Skettenis 		reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~3);
16604b7fce9Skettenis 		return (reg >> ((offset & 3) * 8)) & 0xff;
16704b7fce9Skettenis 	}
16804b7fce9Skettenis 
16904b7fce9Skettenis 	return bus_space_read_1(hp->iot, hp->ioh, offset);
17004b7fce9Skettenis }
17104b7fce9Skettenis 
17204b7fce9Skettenis uint16_t
17304b7fce9Skettenis sdhc_read_2(struct sdhc_host *hp, bus_size_t offset)
17404b7fce9Skettenis {
17504b7fce9Skettenis 	uint32_t reg;
17604b7fce9Skettenis 
17704b7fce9Skettenis 	if (hp->flags & SHF_USE_32BIT_ACCESS) {
17804b7fce9Skettenis 		reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~2);
17904b7fce9Skettenis 		return (reg >> ((offset & 2) * 8)) & 0xffff;
18004b7fce9Skettenis 	}
18104b7fce9Skettenis 
18204b7fce9Skettenis 	return bus_space_read_2(hp->iot, hp->ioh, offset);
18304b7fce9Skettenis }
18404b7fce9Skettenis 
18504b7fce9Skettenis void
18604b7fce9Skettenis sdhc_write_1(struct sdhc_host *hp, bus_size_t offset, uint8_t value)
18704b7fce9Skettenis {
18804b7fce9Skettenis 	uint32_t reg;
18904b7fce9Skettenis 
19004b7fce9Skettenis 	if (hp->flags & SHF_USE_32BIT_ACCESS) {
19104b7fce9Skettenis 		reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~3);
19204b7fce9Skettenis 		reg &= ~(0xff << ((offset & 3) * 8));
19304b7fce9Skettenis 		reg |= (value << ((offset & 3) * 8));
19404b7fce9Skettenis 		bus_space_write_4(hp->iot, hp->ioh, offset & ~3, reg);
19504b7fce9Skettenis 		return;
19604b7fce9Skettenis 	}
19704b7fce9Skettenis 
19804b7fce9Skettenis 	bus_space_write_1(hp->iot, hp->ioh, offset, value);
19904b7fce9Skettenis }
20004b7fce9Skettenis 
20104b7fce9Skettenis void
20204b7fce9Skettenis sdhc_write_2(struct sdhc_host *hp, bus_size_t offset, uint16_t value)
20304b7fce9Skettenis {
20404b7fce9Skettenis 	uint32_t reg;
20504b7fce9Skettenis 
20604b7fce9Skettenis 	if (hp->flags & SHF_USE_32BIT_ACCESS) {
20704b7fce9Skettenis 		switch (offset) {
20804b7fce9Skettenis 		case SDHC_BLOCK_SIZE:
20904b7fce9Skettenis 			hp->block_size = value;
21004b7fce9Skettenis 			return;
21104b7fce9Skettenis 		case SDHC_BLOCK_COUNT:
21204b7fce9Skettenis 			hp->block_count = value;
21304b7fce9Skettenis 			return;
21404b7fce9Skettenis 		case SDHC_TRANSFER_MODE:
21504b7fce9Skettenis 			hp->transfer_mode = value;
21604b7fce9Skettenis 			return;
21704b7fce9Skettenis 		case SDHC_COMMAND:
21804b7fce9Skettenis 			bus_space_write_4(hp->iot, hp->ioh, SDHC_BLOCK_SIZE,
21904b7fce9Skettenis 			    (hp->block_count << 16) | hp->block_size);
22004b7fce9Skettenis 			bus_space_write_4(hp->iot, hp->ioh, SDHC_TRANSFER_MODE,
22104b7fce9Skettenis 			    (value << 16) | hp->transfer_mode);
22204b7fce9Skettenis 			return;
22304b7fce9Skettenis 		}
22404b7fce9Skettenis 
22504b7fce9Skettenis 		reg = bus_space_read_4(hp->iot, hp->ioh, offset & ~2);
22604b7fce9Skettenis 		reg &= ~(0xffff << ((offset & 2) * 8));
22704b7fce9Skettenis 		reg |= (value << ((offset & 2) * 8));
22804b7fce9Skettenis 		bus_space_write_4(hp->iot, hp->ioh, offset & ~2, reg);
22904b7fce9Skettenis 		return;
23004b7fce9Skettenis 	}
23104b7fce9Skettenis 
23204b7fce9Skettenis 	bus_space_write_2(hp->iot, hp->ioh, offset, value);
23304b7fce9Skettenis }
23404b7fce9Skettenis 
23504b7fce9Skettenis /*
236aae4fe77Suwe  * Called by attachment driver.  For each SD card slot there is one SD
237aae4fe77Suwe  * host controller standard register set. (1.3)
238aae4fe77Suwe  */
239aae4fe77Suwe int
240aae4fe77Suwe sdhc_host_found(struct sdhc_softc *sc, bus_space_tag_t iot,
241bfa5fdb5Spatrick     bus_space_handle_t ioh, bus_size_t iosize, int usedma, uint64_t capmask,
242bfa5fdb5Spatrick     uint64_t capset)
243aae4fe77Suwe {
244aae4fe77Suwe 	struct sdmmcbus_attach_args saa;
245aae4fe77Suwe 	struct sdhc_host *hp;
246bfa5fdb5Spatrick 	uint32_t caps;
2474e9dcb19Skettenis 	int major, minor;
248c538fe19Sfgsch 	int error = 1;
249445e328eSkettenis 	int max_clock;
250aae4fe77Suwe 
251aae4fe77Suwe 	/* Allocate one more host structure. */
252aae4fe77Suwe 	sc->sc_nhosts++;
2532b585ff0Skrw 	hp = malloc(sizeof(*hp), M_DEVBUF, M_WAITOK | M_ZERO);
25481aa4bdcSfgsch 	sc->sc_host[sc->sc_nhosts - 1] = hp;
255aae4fe77Suwe 
25604b7fce9Skettenis 	if (ISSET(sc->sc_flags, SDHC_F_32BIT_ACCESS))
25704b7fce9Skettenis 		SET(hp->flags, SHF_USE_32BIT_ACCESS);
25804b7fce9Skettenis 
259aae4fe77Suwe 	/* Fill in the new host structure. */
260aae4fe77Suwe 	hp->sc = sc;
261aae4fe77Suwe 	hp->iot = iot;
262aae4fe77Suwe 	hp->ioh = ioh;
263aae4fe77Suwe 
264445e328eSkettenis 	/* Store specification version. */
26504b7fce9Skettenis 	hp->version = HREAD2(hp, SDHC_HOST_CTL_VERSION);
266445e328eSkettenis 
267aae4fe77Suwe 	/*
268aae4fe77Suwe 	 * Reset the host controller and enable interrupts.
269aae4fe77Suwe 	 */
270861ce88aSuwe 	(void)sdhc_host_reset(hp);
271aae4fe77Suwe 
272aae4fe77Suwe 	/* Determine host capabilities. */
273aae4fe77Suwe 	caps = HREAD4(hp, SDHC_CAPABILITIES);
274bfa5fdb5Spatrick 	caps &= ~capmask;
275bfa5fdb5Spatrick 	caps |= capset;
276aae4fe77Suwe 
277aae4fe77Suwe 	/* Use DMA if the host system and the controller support it. */
278b60bffefSpatrick 	if (usedma && ISSET(caps, SDHC_ADMA2_SUPP)) {
279aae4fe77Suwe 		SET(hp->flags, SHF_USE_DMA);
280b60bffefSpatrick 		if (ISSET(caps, SDHC_64BIT_DMA_SUPP))
281b60bffefSpatrick 			SET(hp->flags, SHF_USE_DMA64);
282b60bffefSpatrick 	}
283aae4fe77Suwe 
284aae4fe77Suwe 	/*
285aae4fe77Suwe 	 * Determine the base clock frequency. (2.2.24)
286aae4fe77Suwe 	 */
287445e328eSkettenis 	if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
288445e328eSkettenis 		/* SDHC 3.0 supports 10-255 MHz. */
289445e328eSkettenis 		max_clock = 255000;
290445e328eSkettenis 		if (SDHC_BASE_FREQ_KHZ_V3(caps) != 0)
291445e328eSkettenis 			hp->clkbase = SDHC_BASE_FREQ_KHZ_V3(caps);
292445e328eSkettenis 	} else {
293445e328eSkettenis 		/* SDHC 1.0/2.0 supports only 10-63 MHz. */
294445e328eSkettenis 		max_clock = 63000;
295aae4fe77Suwe 		if (SDHC_BASE_FREQ_KHZ(caps) != 0)
296aae4fe77Suwe 			hp->clkbase = SDHC_BASE_FREQ_KHZ(caps);
297445e328eSkettenis 	}
298aae4fe77Suwe 	if (hp->clkbase == 0) {
2997b2b2895Skettenis 		/* Make sure we can clock down to 400 kHz. */
3007b2b2895Skettenis 		max_clock = 400 * SDHC_SDCLK_DIV_MAX_V3;
3017b2b2895Skettenis 		hp->clkbase = sc->sc_clkbase;
3027b2b2895Skettenis 	}
3037b2b2895Skettenis 	if (hp->clkbase == 0) {
304aae4fe77Suwe 		/* The attachment driver must tell us. */
305aae4fe77Suwe 		printf("%s: base clock frequency unknown\n",
306aae4fe77Suwe 		    sc->sc_dev.dv_xname);
307aae4fe77Suwe 		goto err;
308445e328eSkettenis 	} else if (hp->clkbase < 10000 || hp->clkbase > max_clock) {
309aae4fe77Suwe 		printf("%s: base clock frequency out of range: %u MHz\n",
310db9033feSfgsch 		    sc->sc_dev.dv_xname, hp->clkbase / 1000);
311aae4fe77Suwe 		goto err;
312aae4fe77Suwe 	}
313aae4fe77Suwe 
3144e9dcb19Skettenis 	switch (SDHC_SPEC_VERSION(hp->version)) {
3154e9dcb19Skettenis 	case SDHC_SPEC_VERS_4_10:
3164e9dcb19Skettenis 		major = 4, minor = 10;
3174e9dcb19Skettenis 		break;
3184e9dcb19Skettenis 	case SDHC_SPEC_VERS_4_20:
3194e9dcb19Skettenis 		major = 4, minor = 20;
3204e9dcb19Skettenis 		break;
3214e9dcb19Skettenis 	default:
3224e9dcb19Skettenis 		major = SDHC_SPEC_VERSION(hp->version) + 1, minor = 0;
3234e9dcb19Skettenis 		break;
3244e9dcb19Skettenis 	}
3254e9dcb19Skettenis 
3264e9dcb19Skettenis 	printf("%s: SDHC %d.%02d, %d MHz base clock\n", DEVNAME(sc),
3274e9dcb19Skettenis 	    major, minor, hp->clkbase / 1000);
328e8385f59Skettenis 
329aae4fe77Suwe 	/*
330aae4fe77Suwe 	 * XXX Set the data timeout counter value according to
331aae4fe77Suwe 	 * capabilities. (2.2.15)
332aae4fe77Suwe 	 */
333aae4fe77Suwe 
334aae4fe77Suwe 	/*
335aae4fe77Suwe 	 * Determine SD bus voltage levels supported by the controller.
336aae4fe77Suwe 	 */
337aae4fe77Suwe 	if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V))
338b676d50fSkettenis 		SET(hp->ocr, MMC_OCR_1_65V_1_95V);
339aae4fe77Suwe 	if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_0V))
340aae4fe77Suwe 		SET(hp->ocr, MMC_OCR_2_9V_3_0V | MMC_OCR_3_0V_3_1V);
341aae4fe77Suwe 	if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_3V))
342aae4fe77Suwe 		SET(hp->ocr, MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V);
343aae4fe77Suwe 
344aae4fe77Suwe 	/*
345aae4fe77Suwe 	 * Determine the maximum block length supported by the host
346aae4fe77Suwe 	 * controller. (2.2.24)
347aae4fe77Suwe 	 */
348aae4fe77Suwe 	switch((caps >> SDHC_MAX_BLK_LEN_SHIFT) & SDHC_MAX_BLK_LEN_MASK) {
349aae4fe77Suwe 	case SDHC_MAX_BLK_LEN_512:
350aae4fe77Suwe 		hp->maxblklen = 512;
351aae4fe77Suwe 		break;
352aae4fe77Suwe 	case SDHC_MAX_BLK_LEN_1024:
353aae4fe77Suwe 		hp->maxblklen = 1024;
354aae4fe77Suwe 		break;
355aae4fe77Suwe 	case SDHC_MAX_BLK_LEN_2048:
356aae4fe77Suwe 		hp->maxblklen = 2048;
357aae4fe77Suwe 		break;
358aae4fe77Suwe 	default:
359aae4fe77Suwe 		hp->maxblklen = 1;
360aae4fe77Suwe 		break;
361aae4fe77Suwe 	}
362aae4fe77Suwe 
363c6293583Skettenis 	if (ISSET(hp->flags, SHF_USE_DMA)) {
364c6293583Skettenis 		int rseg;
365c6293583Skettenis 
366c6293583Skettenis 		/* Allocate ADMA2 descriptor memory */
367c6293583Skettenis 		error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
368c6293583Skettenis 		    PAGE_SIZE, hp->adma_segs, 1, &rseg,
369c6293583Skettenis 		    BUS_DMA_WAITOK | BUS_DMA_ZERO);
370c6293583Skettenis 		if (error)
371c6293583Skettenis 			goto adma_done;
372c6293583Skettenis 		error = bus_dmamem_map(sc->sc_dmat, hp->adma_segs, rseg,
37312393d97Skettenis 		    PAGE_SIZE, &hp->adma2, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
374c6293583Skettenis 		if (error) {
375c6293583Skettenis 			bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg);
376c6293583Skettenis 			goto adma_done;
377c6293583Skettenis 		}
378c6293583Skettenis 		error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
379c6293583Skettenis 		    0, BUS_DMA_WAITOK, &hp->adma_map);
380c6293583Skettenis 		if (error) {
381c6293583Skettenis 			bus_dmamem_unmap(sc->sc_dmat, hp->adma2, PAGE_SIZE);
382c6293583Skettenis 			bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg);
383c6293583Skettenis 			goto adma_done;
384c6293583Skettenis 		}
385c6293583Skettenis 		error = bus_dmamap_load(sc->sc_dmat, hp->adma_map,
386c6293583Skettenis 		    hp->adma2, PAGE_SIZE, NULL,
387c6293583Skettenis 		    BUS_DMA_WAITOK | BUS_DMA_WRITE);
388c6293583Skettenis 		if (error) {
389c6293583Skettenis 			bus_dmamap_destroy(sc->sc_dmat, hp->adma_map);
390c6293583Skettenis 			bus_dmamem_unmap(sc->sc_dmat, hp->adma2, PAGE_SIZE);
391c6293583Skettenis 			bus_dmamem_free(sc->sc_dmat, hp->adma_segs, rseg);
392c6293583Skettenis 			goto adma_done;
393c6293583Skettenis 		}
394c6293583Skettenis 
395c6293583Skettenis 	adma_done:
396c6293583Skettenis 		if (error) {
397c6293583Skettenis 			printf("%s: can't allocate DMA descriptor table\n",
398c6293583Skettenis 			    DEVNAME(hp->sc));
399c6293583Skettenis 			CLR(hp->flags, SHF_USE_DMA);
400c6293583Skettenis 		}
401c6293583Skettenis 	}
402c6293583Skettenis 
403aae4fe77Suwe 	/*
404aae4fe77Suwe 	 * Attach the generic SD/MMC bus driver.  (The bus driver must
405aae4fe77Suwe 	 * not invoke any chipset functions before it is attached.)
406aae4fe77Suwe 	 */
407aae4fe77Suwe 	bzero(&saa, sizeof(saa));
408aae4fe77Suwe 	saa.saa_busname = "sdmmc";
409aae4fe77Suwe 	saa.sct = &sdhc_functions;
410aae4fe77Suwe 	saa.sch = hp;
411b140af5cSkettenis 	saa.caps = SMC_CAPS_4BIT_MODE;
412c6293583Skettenis 	saa.dmat = sc->sc_dmat;
413834ff46cSdlg 	saa.dma_boundary = sc->sc_dma_boundary;
414c6293583Skettenis 	if (ISSET(hp->flags, SHF_USE_DMA))
415c6293583Skettenis 		saa.caps |= SMC_CAPS_DMA;
416aae4fe77Suwe 
417829e5ee2Skettenis 	if (ISSET(caps, SDHC_HIGH_SPEED_SUPP))
418829e5ee2Skettenis 		saa.caps |= SMC_CAPS_SD_HIGHSPEED;
419829e5ee2Skettenis 	if (ISSET(caps, SDHC_HIGH_SPEED_SUPP))
420829e5ee2Skettenis 		saa.caps |= SMC_CAPS_MMC_HIGHSPEED;
421829e5ee2Skettenis 
42282aad119Skettenis 	if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
423820e06f1Skettenis 		uint32_t caps2 = HREAD4(hp, SDHC_CAPABILITIES2);
424bfa5fdb5Spatrick 		caps2 &= ~(capmask >> 32);
425bfa5fdb5Spatrick 		caps2 |= capset >> 32;
426820e06f1Skettenis 
42782aad119Skettenis 		if (ISSET(caps, SDHC_8BIT_MODE_SUPP))
42882aad119Skettenis 			saa.caps |= SMC_CAPS_8BIT_MODE;
429820e06f1Skettenis 
430820e06f1Skettenis 		if (ISSET(caps2, SDHC_DDR50_SUPP))
431820e06f1Skettenis 			saa.caps |= SMC_CAPS_MMC_DDR52;
43282aad119Skettenis 	}
43382aad119Skettenis 
434fd406f4dSstsp 	if (ISSET(sc->sc_flags, SDHC_F_NONREMOVABLE))
435fd406f4dSstsp 		saa.caps |= SMC_CAPS_NONREMOVABLE;
436fd406f4dSstsp 
437aae4fe77Suwe 	hp->sdmmc = config_found(&sc->sc_dev, &saa, NULL);
438aae4fe77Suwe 	if (hp->sdmmc == NULL) {
439c538fe19Sfgsch 		error = 0;
440aae4fe77Suwe 		goto err;
441aae4fe77Suwe 	}
442aae4fe77Suwe 
443aae4fe77Suwe 	return 0;
444aae4fe77Suwe 
445aae4fe77Suwe err:
44687985770Sderaadt 	free(hp, M_DEVBUF, sizeof *hp);
44781aa4bdcSfgsch 	sc->sc_host[sc->sc_nhosts - 1] = NULL;
448aae4fe77Suwe 	sc->sc_nhosts--;
449c538fe19Sfgsch 	return (error);
450aae4fe77Suwe }
451aae4fe77Suwe 
4522c6678e4Sderaadt int
4532c6678e4Sderaadt sdhc_activate(struct device *self, int act)
454aae4fe77Suwe {
4552c6678e4Sderaadt 	struct sdhc_softc *sc = (struct sdhc_softc *)self;
456f50f4931Suwe 	struct sdhc_host *hp;
457b7fbe345Sderaadt 	int n, i, rv = 0;
458aae4fe77Suwe 
4592c6678e4Sderaadt 	switch (act) {
4602c6678e4Sderaadt 	case DVACT_SUSPEND:
46100c76a70Sderaadt 		rv = config_activate_children(self, act);
462f50f4931Suwe 
463f50f4931Suwe 		/* Save the host controller state. */
464f50f4931Suwe 		for (n = 0; n < sc->sc_nhosts; n++) {
46581aa4bdcSfgsch 			hp = sc->sc_host[n];
466f50f4931Suwe 			for (i = 0; i < sizeof hp->regs; i++)
467f50f4931Suwe 				hp->regs[i] = HREAD1(hp, i);
468f50f4931Suwe 		}
469aae4fe77Suwe 		break;
4702c6678e4Sderaadt 	case DVACT_RESUME:
471f50f4931Suwe 		/* Restore the host controller state. */
472f50f4931Suwe 		for (n = 0; n < sc->sc_nhosts; n++) {
47381aa4bdcSfgsch 			hp = sc->sc_host[n];
474861ce88aSuwe 			(void)sdhc_host_reset(hp);
475f50f4931Suwe 			for (i = 0; i < sizeof hp->regs; i++)
476f50f4931Suwe 				HWRITE1(hp, i, hp->regs[i]);
477f50f4931Suwe 		}
478b7fbe345Sderaadt 		rv = config_activate_children(self, act);
479aae4fe77Suwe 		break;
48037ecb596Sderaadt 	case DVACT_POWERDOWN:
48137ecb596Sderaadt 		rv = config_activate_children(self, act);
48237ecb596Sderaadt 		sdhc_shutdown(self);
48337ecb596Sderaadt 		break;
48437ecb596Sderaadt 	default:
48537ecb596Sderaadt 		rv = config_activate_children(self, act);
48637ecb596Sderaadt 		break;
487aae4fe77Suwe 	}
488b7fbe345Sderaadt 	return (rv);
4892c6678e4Sderaadt }
4902c6678e4Sderaadt 
491aae4fe77Suwe /*
492aae4fe77Suwe  * Shutdown hook established by or called from attachment driver.
493aae4fe77Suwe  */
494aae4fe77Suwe void
495aae4fe77Suwe sdhc_shutdown(void *arg)
496aae4fe77Suwe {
497aae4fe77Suwe 	struct sdhc_softc *sc = arg;
498aae4fe77Suwe 	struct sdhc_host *hp;
499aae4fe77Suwe 	int i;
500aae4fe77Suwe 
501aae4fe77Suwe 	/* XXX chip locks up if we don't disable it before reboot. */
502aae4fe77Suwe 	for (i = 0; i < sc->sc_nhosts; i++) {
50381aa4bdcSfgsch 		hp = sc->sc_host[i];
504861ce88aSuwe 		(void)sdhc_host_reset(hp);
505aae4fe77Suwe 	}
506aae4fe77Suwe }
507aae4fe77Suwe 
508aae4fe77Suwe /*
509aae4fe77Suwe  * Reset the host controller.  Called during initialization, when
510861ce88aSuwe  * cards are removed, upon resume, and during error recovery.
511aae4fe77Suwe  */
512aae4fe77Suwe int
513aae4fe77Suwe sdhc_host_reset(sdmmc_chipset_handle_t sch)
514aae4fe77Suwe {
515aae4fe77Suwe 	struct sdhc_host *hp = sch;
516aae4fe77Suwe 	u_int16_t imask;
5175842cfcdSfgsch 	int error;
518aae4fe77Suwe 	int s;
519aae4fe77Suwe 
520aae4fe77Suwe 	s = splsdmmc();
521aae4fe77Suwe 
522aae4fe77Suwe 	/* Disable all interrupts. */
523aae4fe77Suwe 	HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, 0);
524aae4fe77Suwe 
525aae4fe77Suwe 	/*
526861ce88aSuwe 	 * Reset the entire host controller and wait up to 100ms for
527861ce88aSuwe 	 * the controller to clear the reset bit.
528aae4fe77Suwe 	 */
529f2fcfe5eSkrw 	if ((error = sdhc_soft_reset(hp, SDHC_RESET_ALL)) != 0) {
530f2fcfe5eSkrw 		splx(s);
5315842cfcdSfgsch 		return (error);
532f2fcfe5eSkrw 	}
533aae4fe77Suwe 
534aae4fe77Suwe 	/* Set data timeout counter value to max for now. */
535aae4fe77Suwe 	HWRITE1(hp, SDHC_TIMEOUT_CTL, SDHC_TIMEOUT_MAX);
536aae4fe77Suwe 
537aae4fe77Suwe 	/* Enable interrupts. */
538aae4fe77Suwe 	imask = SDHC_CARD_REMOVAL | SDHC_CARD_INSERTION |
539aae4fe77Suwe 	    SDHC_BUFFER_READ_READY | SDHC_BUFFER_WRITE_READY |
540aae4fe77Suwe 	    SDHC_DMA_INTERRUPT | SDHC_BLOCK_GAP_EVENT |
541b979651fSuwe 	    SDHC_TRANSFER_COMPLETE | SDHC_COMMAND_COMPLETE;
542393d192eSuwe 
543aae4fe77Suwe 	HWRITE2(hp, SDHC_NINTR_STATUS_EN, imask);
544aae4fe77Suwe 	HWRITE2(hp, SDHC_EINTR_STATUS_EN, SDHC_EINTR_STATUS_MASK);
545aae4fe77Suwe 	HWRITE2(hp, SDHC_NINTR_SIGNAL_EN, imask);
546aae4fe77Suwe 	HWRITE2(hp, SDHC_EINTR_SIGNAL_EN, SDHC_EINTR_SIGNAL_MASK);
547aae4fe77Suwe 
548aae4fe77Suwe 	splx(s);
549861ce88aSuwe 	return 0;
550aae4fe77Suwe }
551aae4fe77Suwe 
552aae4fe77Suwe u_int32_t
553aae4fe77Suwe sdhc_host_ocr(sdmmc_chipset_handle_t sch)
554aae4fe77Suwe {
555aae4fe77Suwe 	struct sdhc_host *hp = sch;
556aae4fe77Suwe 	return hp->ocr;
557aae4fe77Suwe }
558aae4fe77Suwe 
559aae4fe77Suwe int
560aae4fe77Suwe sdhc_host_maxblklen(sdmmc_chipset_handle_t sch)
561aae4fe77Suwe {
562aae4fe77Suwe 	struct sdhc_host *hp = sch;
563aae4fe77Suwe 	return hp->maxblklen;
564aae4fe77Suwe }
565aae4fe77Suwe 
566aae4fe77Suwe /*
567aae4fe77Suwe  * Return non-zero if the card is currently inserted.
568aae4fe77Suwe  */
569aae4fe77Suwe int
570aae4fe77Suwe sdhc_card_detect(sdmmc_chipset_handle_t sch)
571aae4fe77Suwe {
572aae4fe77Suwe 	struct sdhc_host *hp = sch;
57388a093b3Skettenis 
57488a093b3Skettenis 	if (hp->sc->sc_card_detect)
57588a093b3Skettenis 		return hp->sc->sc_card_detect(hp->sc);
57688a093b3Skettenis 
577aae4fe77Suwe 	return ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CARD_INSERTED) ?
578aae4fe77Suwe 	    1 : 0;
579aae4fe77Suwe }
580aae4fe77Suwe 
581aae4fe77Suwe /*
582aae4fe77Suwe  * Set or change SD bus voltage and enable or disable SD bus power.
583aae4fe77Suwe  * Return zero on success.
584aae4fe77Suwe  */
585aae4fe77Suwe int
586aae4fe77Suwe sdhc_bus_power(sdmmc_chipset_handle_t sch, u_int32_t ocr)
587aae4fe77Suwe {
588aae4fe77Suwe 	struct sdhc_host *hp = sch;
589aae4fe77Suwe 	u_int8_t vdd;
590aae4fe77Suwe 	int s;
591aae4fe77Suwe 
592aae4fe77Suwe 	s = splsdmmc();
593aae4fe77Suwe 
594aae4fe77Suwe 	/* If power is disabled, reset the host and return now. */
595aae4fe77Suwe 	if (ocr == 0) {
596*8ab765f8Shastings 		HWRITE1(hp, SDHC_POWER_CTL, 0);
597aae4fe77Suwe 		splx(s);
598861ce88aSuwe 		(void)sdhc_host_reset(hp);
599aae4fe77Suwe 		return 0;
600aae4fe77Suwe 	}
601aae4fe77Suwe 
602aae4fe77Suwe 	/*
603aae4fe77Suwe 	 * Select the maximum voltage according to capabilities.
604aae4fe77Suwe 	 */
605aae4fe77Suwe 	ocr &= hp->ocr;
606aae4fe77Suwe 	if (ISSET(ocr, MMC_OCR_3_2V_3_3V|MMC_OCR_3_3V_3_4V))
607aae4fe77Suwe 		vdd = SDHC_VOLTAGE_3_3V;
608aae4fe77Suwe 	else if (ISSET(ocr, MMC_OCR_2_9V_3_0V|MMC_OCR_3_0V_3_1V))
609aae4fe77Suwe 		vdd = SDHC_VOLTAGE_3_0V;
610b676d50fSkettenis 	else if (ISSET(ocr, MMC_OCR_1_65V_1_95V))
611aae4fe77Suwe 		vdd = SDHC_VOLTAGE_1_8V;
612aae4fe77Suwe 	else {
613aae4fe77Suwe 		/* Unsupported voltage level requested. */
614aae4fe77Suwe 		splx(s);
615aae4fe77Suwe 		return EINVAL;
616aae4fe77Suwe 	}
617aae4fe77Suwe 
618aae4fe77Suwe 	/*
619*8ab765f8Shastings 	 * Return if no change to powered bus voltage.
620*8ab765f8Shastings 	 */
621*8ab765f8Shastings 	if (HREAD1(hp, SDHC_POWER_CTL) ==
622*8ab765f8Shastings 	    ((vdd << SDHC_VOLTAGE_SHIFT) | SDHC_BUS_POWER)) {
623*8ab765f8Shastings 		splx(s);
624*8ab765f8Shastings 		return 0;
625*8ab765f8Shastings 	}
626*8ab765f8Shastings 
627*8ab765f8Shastings 	/*
628*8ab765f8Shastings 	 * Disable bus power before voltage change.
629*8ab765f8Shastings 	 */
630*8ab765f8Shastings 	if (!(hp->sc->sc_flags & SDHC_F_NOPWR0))
631*8ab765f8Shastings 		HWRITE1(hp, SDHC_POWER_CTL, 0);
632*8ab765f8Shastings 
633*8ab765f8Shastings 	/*
634aae4fe77Suwe 	 * Enable bus power.  Wait at least 1 ms (or 74 clocks) plus
635aae4fe77Suwe 	 * voltage ramp until power rises.
636aae4fe77Suwe 	 */
637aae4fe77Suwe 	HWRITE1(hp, SDHC_POWER_CTL, (vdd << SDHC_VOLTAGE_SHIFT) |
638aae4fe77Suwe 	    SDHC_BUS_POWER);
639aae4fe77Suwe 	sdmmc_delay(10000);
640aae4fe77Suwe 
641aae4fe77Suwe 	/*
642aae4fe77Suwe 	 * The host system may not power the bus due to battery low,
643aae4fe77Suwe 	 * etc.  In that case, the host controller should clear the
644aae4fe77Suwe 	 * bus power bit.
645aae4fe77Suwe 	 */
646aae4fe77Suwe 	if (!ISSET(HREAD1(hp, SDHC_POWER_CTL), SDHC_BUS_POWER)) {
647aae4fe77Suwe 		splx(s);
648aae4fe77Suwe 		return ENXIO;
649aae4fe77Suwe 	}
650aae4fe77Suwe 
651aae4fe77Suwe 	splx(s);
652aae4fe77Suwe 	return 0;
653aae4fe77Suwe }
654aae4fe77Suwe 
655aae4fe77Suwe /*
656aae4fe77Suwe  * Return the smallest possible base clock frequency divisor value
657aae4fe77Suwe  * for the CLOCK_CTL register to produce `freq' (KHz).
658aae4fe77Suwe  */
659aae4fe77Suwe static int
660aae4fe77Suwe sdhc_clock_divisor(struct sdhc_host *hp, u_int freq)
661aae4fe77Suwe {
662aae4fe77Suwe 	int div;
663aae4fe77Suwe 
664e7a76d17Spatrick 	if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
665e7a76d17Spatrick 		if (hp->clkbase <= freq)
666e7a76d17Spatrick 			return 0;
667445e328eSkettenis 
668e7a76d17Spatrick 		for (div = 2; div <= SDHC_SDCLK_DIV_MAX_V3; div += 2)
669aae4fe77Suwe 			if ((hp->clkbase / div) <= freq)
670aae4fe77Suwe 				return (div / 2);
671e7a76d17Spatrick 	} else {
672e7a76d17Spatrick 		for (div = 1; div <= SDHC_SDCLK_DIV_MAX; div *= 2)
673e7a76d17Spatrick 			if ((hp->clkbase / div) <= freq)
674e7a76d17Spatrick 				return (div / 2);
675e7a76d17Spatrick 	}
676e7a76d17Spatrick 
677aae4fe77Suwe 	/* No divisor found. */
678aae4fe77Suwe 	return -1;
679aae4fe77Suwe }
680aae4fe77Suwe 
681aae4fe77Suwe /*
682aae4fe77Suwe  * Set or change SDCLK frequency or disable the SD clock.
683aae4fe77Suwe  * Return zero on success.
684aae4fe77Suwe  */
685aae4fe77Suwe int
686820e06f1Skettenis sdhc_bus_clock(sdmmc_chipset_handle_t sch, int freq, int timing)
687aae4fe77Suwe {
688aae4fe77Suwe 	struct sdhc_host *hp = sch;
689d03761f2Smglocker 	struct sdhc_softc *sc = hp->sc;
690aae4fe77Suwe 	int s;
691aae4fe77Suwe 	int div;
692445e328eSkettenis 	int sdclk;
693aae4fe77Suwe 	int timo;
694aae4fe77Suwe 	int error = 0;
695aae4fe77Suwe 
696aae4fe77Suwe 	s = splsdmmc();
697aae4fe77Suwe 
698fa1cdcb1Spatrick 	if (hp->sc->sc_bus_clock_pre)
699fa1cdcb1Spatrick 		hp->sc->sc_bus_clock_pre(hp->sc, freq, timing);
700fa1cdcb1Spatrick 
701aae4fe77Suwe #ifdef DIAGNOSTIC
702aae4fe77Suwe 	/* Must not stop the clock if commands are in progress. */
703aae4fe77Suwe 	if (ISSET(HREAD4(hp, SDHC_PRESENT_STATE), SDHC_CMD_INHIBIT_MASK) &&
704aae4fe77Suwe 	    sdhc_card_detect(hp))
705aae4fe77Suwe 		printf("sdhc_sdclk_frequency_select: command in progress\n");
706aae4fe77Suwe #endif
707aae4fe77Suwe 
708aae4fe77Suwe 	/*
709aae4fe77Suwe 	 * Stop SD clock before changing the frequency.
710aae4fe77Suwe 	 */
711aae4fe77Suwe 	HWRITE2(hp, SDHC_CLOCK_CTL, 0);
712aae4fe77Suwe 	if (freq == SDMMC_SDCLK_OFF)
713aae4fe77Suwe 		goto ret;
714aae4fe77Suwe 
715d03761f2Smglocker 	if (!ISSET(sc->sc_flags, SDHC_F_NO_HS_BIT)) {
716820e06f1Skettenis 		if (timing == SDMMC_TIMING_LEGACY)
717820e06f1Skettenis 			HCLR1(hp, SDHC_HOST_CTL, SDHC_HIGH_SPEED);
718820e06f1Skettenis 		else
719820e06f1Skettenis 			HSET1(hp, SDHC_HOST_CTL, SDHC_HIGH_SPEED);
720d03761f2Smglocker 	}
721820e06f1Skettenis 
722820e06f1Skettenis 	if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
723820e06f1Skettenis 		switch (timing) {
724820e06f1Skettenis 		case SDMMC_TIMING_MMC_DDR52:
725820e06f1Skettenis 			HCLR2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_MASK);
726820e06f1Skettenis 			HSET2(hp, SDHC_HOST_CTL2, SDHC_UHS_MODE_SELECT_DDR50);
727820e06f1Skettenis 			break;
728820e06f1Skettenis 		}
729820e06f1Skettenis 	}
730820e06f1Skettenis 
731aae4fe77Suwe 	/*
732aae4fe77Suwe 	 * Set the minimum base clock frequency divisor.
733aae4fe77Suwe 	 */
734aae4fe77Suwe 	if ((div = sdhc_clock_divisor(hp, freq)) < 0) {
735aae4fe77Suwe 		/* Invalid base clock frequency or `freq' value. */
736aae4fe77Suwe 		error = EINVAL;
737aae4fe77Suwe 		goto ret;
738aae4fe77Suwe 	}
739445e328eSkettenis 	if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3)
740445e328eSkettenis 		sdclk = SDHC_SDCLK_DIV_V3(div);
741445e328eSkettenis 	else
742445e328eSkettenis 		sdclk = SDHC_SDCLK_DIV(div);
743445e328eSkettenis 	HWRITE2(hp, SDHC_CLOCK_CTL, sdclk);
744aae4fe77Suwe 
745aae4fe77Suwe 	/*
746aae4fe77Suwe 	 * Start internal clock.  Wait 10ms for stabilization.
747aae4fe77Suwe 	 */
748aae4fe77Suwe 	HSET2(hp, SDHC_CLOCK_CTL, SDHC_INTCLK_ENABLE);
749aae4fe77Suwe 	for (timo = 1000; timo > 0; timo--) {
750aae4fe77Suwe 		if (ISSET(HREAD2(hp, SDHC_CLOCK_CTL), SDHC_INTCLK_STABLE))
751aae4fe77Suwe 			break;
752aae4fe77Suwe 		sdmmc_delay(10);
753aae4fe77Suwe 	}
754aae4fe77Suwe 	if (timo == 0) {
755aae4fe77Suwe 		error = ETIMEDOUT;
756aae4fe77Suwe 		goto ret;
757aae4fe77Suwe 	}
758aae4fe77Suwe 
759aae4fe77Suwe 	/*
760aae4fe77Suwe 	 * Enable SD clock.
761aae4fe77Suwe 	 */
762aae4fe77Suwe 	HSET2(hp, SDHC_CLOCK_CTL, SDHC_SDCLK_ENABLE);
763aae4fe77Suwe 
764fa1cdcb1Spatrick 	if (hp->sc->sc_bus_clock_post)
765fa1cdcb1Spatrick 		hp->sc->sc_bus_clock_post(hp->sc, freq, timing);
766fa1cdcb1Spatrick 
767aae4fe77Suwe ret:
768aae4fe77Suwe 	splx(s);
769aae4fe77Suwe 	return error;
770aae4fe77Suwe }
771aae4fe77Suwe 
772b140af5cSkettenis int
773b140af5cSkettenis sdhc_bus_width(sdmmc_chipset_handle_t sch, int width)
774b140af5cSkettenis {
775b140af5cSkettenis 	struct sdhc_host *hp = (struct sdhc_host *)sch;
776b140af5cSkettenis 	int reg;
777b140af5cSkettenis 	int s;
778b140af5cSkettenis 
779b140af5cSkettenis 	if (width != 1 && width != 4 && width != 8)
780820e06f1Skettenis 		return EINVAL;
781b140af5cSkettenis 
782b140af5cSkettenis 	s = splsdmmc();
783b140af5cSkettenis 
784b140af5cSkettenis 	reg = HREAD1(hp, SDHC_HOST_CTL);
785b140af5cSkettenis 	reg &= ~SDHC_4BIT_MODE;
786b140af5cSkettenis 	if (SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3) {
787b140af5cSkettenis 		reg &= ~SDHC_8BIT_MODE;
788b140af5cSkettenis 	}
789b140af5cSkettenis 	if (width == 4) {
790b140af5cSkettenis 		reg |= SDHC_4BIT_MODE;
791b140af5cSkettenis 	} else if (width == 8) {
792b140af5cSkettenis 		KASSERT(SDHC_SPEC_VERSION(hp->version) >= SDHC_SPEC_V3);
793b140af5cSkettenis 		reg |= SDHC_8BIT_MODE;
794b140af5cSkettenis 	}
795b140af5cSkettenis 	HWRITE1(hp, SDHC_HOST_CTL, reg);
796b140af5cSkettenis 
797b140af5cSkettenis 	splx(s);
798b140af5cSkettenis 
799b140af5cSkettenis 	return 0;
800b140af5cSkettenis }
801b140af5cSkettenis 
802b979651fSuwe void
803b979651fSuwe sdhc_card_intr_mask(sdmmc_chipset_handle_t sch, int enable)
804b979651fSuwe {
805b979651fSuwe 	struct sdhc_host *hp = sch;
806b979651fSuwe 
807b979651fSuwe 	if (enable) {
808b979651fSuwe 		HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
809b979651fSuwe 		HSET2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
810b979651fSuwe 	} else {
811b979651fSuwe 		HCLR2(hp, SDHC_NINTR_SIGNAL_EN, SDHC_CARD_INTERRUPT);
812b979651fSuwe 		HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
813b979651fSuwe 	}
814b979651fSuwe }
815b979651fSuwe 
816b979651fSuwe void
817b979651fSuwe sdhc_card_intr_ack(sdmmc_chipset_handle_t sch)
818b979651fSuwe {
819b979651fSuwe 	struct sdhc_host *hp = sch;
820b979651fSuwe 
821b979651fSuwe 	HSET2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
822b979651fSuwe }
823aae4fe77Suwe 
824aae4fe77Suwe int
825820e06f1Skettenis sdhc_signal_voltage(sdmmc_chipset_handle_t sch, int signal_voltage)
826820e06f1Skettenis {
827820e06f1Skettenis 	struct sdhc_host *hp = sch;
828820e06f1Skettenis 
829c2deed7fSkettenis 	if (hp->sc->sc_signal_voltage)
830c2deed7fSkettenis 		return hp->sc->sc_signal_voltage(hp->sc, signal_voltage);
831c2deed7fSkettenis 
832820e06f1Skettenis 	if (SDHC_SPEC_VERSION(hp->version) < SDHC_SPEC_V3)
833820e06f1Skettenis 		return EINVAL;
834820e06f1Skettenis 
835820e06f1Skettenis 	switch (signal_voltage) {
836820e06f1Skettenis 	case SDMMC_SIGNAL_VOLTAGE_180:
837820e06f1Skettenis 		HSET2(hp, SDHC_HOST_CTL2, SDHC_1_8V_SIGNAL_EN);
838820e06f1Skettenis 		break;
839820e06f1Skettenis 	case SDMMC_SIGNAL_VOLTAGE_330:
840820e06f1Skettenis 		HCLR2(hp, SDHC_HOST_CTL2, SDHC_1_8V_SIGNAL_EN);
841820e06f1Skettenis 		break;
842820e06f1Skettenis 	default:
843820e06f1Skettenis 		return EINVAL;
844820e06f1Skettenis 	}
845820e06f1Skettenis 
846820e06f1Skettenis 	/* Regulator output shall be stable within 5 ms. */
847820e06f1Skettenis 	sdmmc_delay(5000);
848820e06f1Skettenis 
849820e06f1Skettenis 	/* Host controller clears this bit if 1.8V signalling fails. */
850820e06f1Skettenis 	if (signal_voltage == SDMMC_SIGNAL_VOLTAGE_180 &&
851679ad45bSpatrick 	    !ISSET(HREAD2(hp, SDHC_HOST_CTL2), SDHC_1_8V_SIGNAL_EN))
852820e06f1Skettenis 		return EIO;
853820e06f1Skettenis 
854820e06f1Skettenis 	return 0;
855820e06f1Skettenis }
856820e06f1Skettenis 
857820e06f1Skettenis int
858aae4fe77Suwe sdhc_wait_state(struct sdhc_host *hp, u_int32_t mask, u_int32_t value)
859aae4fe77Suwe {
860aae4fe77Suwe 	u_int32_t state;
861aae4fe77Suwe 	int timeout;
862aae4fe77Suwe 
863aae4fe77Suwe 	for (timeout = 10; timeout > 0; timeout--) {
864aae4fe77Suwe 		if (((state = HREAD4(hp, SDHC_PRESENT_STATE)) & mask)
865aae4fe77Suwe 		    == value)
866aae4fe77Suwe 			return 0;
867aae4fe77Suwe 		sdmmc_delay(10000);
868aae4fe77Suwe 	}
869a93f47f6Sjasper 	DPRINTF(0,("%s: timeout waiting for %x (state=%b)\n", DEVNAME(hp->sc),
870aae4fe77Suwe 	    value, state, SDHC_PRESENT_STATE_BITS));
871aae4fe77Suwe 	return ETIMEDOUT;
872aae4fe77Suwe }
873aae4fe77Suwe 
874a6fd99a7Suwe void
875a6fd99a7Suwe sdhc_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
876a6fd99a7Suwe {
877a6fd99a7Suwe 	struct sdhc_host *hp = sch;
878a6fd99a7Suwe 	int error;
879a6fd99a7Suwe 
880a6fd99a7Suwe 	/*
881a6fd99a7Suwe 	 * Start the MMC command, or mark `cmd' as failed and return.
882a6fd99a7Suwe 	 */
883a6fd99a7Suwe 	error = sdhc_start_command(hp, cmd);
884a6fd99a7Suwe 	if (error != 0) {
885a6fd99a7Suwe 		cmd->c_error = error;
886a6fd99a7Suwe 		SET(cmd->c_flags, SCF_ITSDONE);
887a6fd99a7Suwe 		return;
888a6fd99a7Suwe 	}
889a6fd99a7Suwe 
890a6fd99a7Suwe 	/*
891a6fd99a7Suwe 	 * Wait until the command phase is done, or until the command
892a6fd99a7Suwe 	 * is marked done for any other reason.
893a6fd99a7Suwe 	 */
894a6fd99a7Suwe 	if (!sdhc_wait_intr(hp, SDHC_COMMAND_COMPLETE,
895a6fd99a7Suwe 	    SDHC_COMMAND_TIMEOUT)) {
896a6fd99a7Suwe 		cmd->c_error = ETIMEDOUT;
897a6fd99a7Suwe 		SET(cmd->c_flags, SCF_ITSDONE);
898a6fd99a7Suwe 		return;
899a6fd99a7Suwe 	}
900a6fd99a7Suwe 
901a6fd99a7Suwe 	/*
902a6fd99a7Suwe 	 * The host controller removes bits [0:7] from the response
903a6fd99a7Suwe 	 * data (CRC) and we pass the data up unchanged to the bus
904a6fd99a7Suwe 	 * driver (without padding).
905a6fd99a7Suwe 	 */
906a6fd99a7Suwe 	if (cmd->c_error == 0 && ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
907a6fd99a7Suwe 		if (ISSET(cmd->c_flags, SCF_RSP_136)) {
908a6fd99a7Suwe 			u_char *p = (u_char *)cmd->c_resp;
909a6fd99a7Suwe 			int i;
910a6fd99a7Suwe 
911a6fd99a7Suwe 			for (i = 0; i < 15; i++)
912a6fd99a7Suwe 				*p++ = HREAD1(hp, SDHC_RESPONSE + i);
913a6fd99a7Suwe 		} else
914a6fd99a7Suwe 			cmd->c_resp[0] = HREAD4(hp, SDHC_RESPONSE);
915a6fd99a7Suwe 	}
916a6fd99a7Suwe 
917a6fd99a7Suwe 	/*
918a6fd99a7Suwe 	 * If the command has data to transfer in any direction,
919a6fd99a7Suwe 	 * execute the transfer now.
920a6fd99a7Suwe 	 */
921a6fd99a7Suwe 	if (cmd->c_error == 0 && cmd->c_data != NULL)
922a6fd99a7Suwe 		sdhc_transfer_data(hp, cmd);
923a6fd99a7Suwe 
924a6fd99a7Suwe 	/* Turn off the LED. */
925a6fd99a7Suwe 	HCLR1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
926a6fd99a7Suwe 
92737539bbbSuwe 	DPRINTF(1,("%s: cmd %u done (flags=%#x error=%d)\n",
928a93f47f6Sjasper 	    DEVNAME(hp->sc), cmd->c_opcode, cmd->c_flags, cmd->c_error));
929a6fd99a7Suwe 	SET(cmd->c_flags, SCF_ITSDONE);
930a6fd99a7Suwe }
931a6fd99a7Suwe 
932aae4fe77Suwe int
933aae4fe77Suwe sdhc_start_command(struct sdhc_host *hp, struct sdmmc_command *cmd)
934aae4fe77Suwe {
935b60bffefSpatrick 	struct sdhc_adma2_descriptor32 *desc32 = (void *)hp->adma2;
936b60bffefSpatrick 	struct sdhc_adma2_descriptor64 *desc64 = (void *)hp->adma2;
937c6293583Skettenis 	struct sdhc_softc *sc = hp->sc;
938aae4fe77Suwe 	u_int16_t blksize = 0;
939aae4fe77Suwe 	u_int16_t blkcount = 0;
940aae4fe77Suwe 	u_int16_t mode;
941aae4fe77Suwe 	u_int16_t command;
942aae4fe77Suwe 	int error;
943c6293583Skettenis 	int seg;
944aae4fe77Suwe 	int s;
945aae4fe77Suwe 
9461dd2d335Sians 	DPRINTF(1,("%s: start cmd %u arg=%#x data=%p dlen=%d flags=%#x\n",
9471dd2d335Sians 	    DEVNAME(hp->sc), cmd->c_opcode, cmd->c_arg, cmd->c_data,
9481dd2d335Sians 	    cmd->c_datalen, cmd->c_flags));
949aae4fe77Suwe 
950aae4fe77Suwe 	/*
951aae4fe77Suwe 	 * The maximum block length for commands should be the minimum
952aae4fe77Suwe 	 * of the host buffer size and the card buffer size. (1.7.2)
953aae4fe77Suwe 	 */
954aae4fe77Suwe 
955aae4fe77Suwe 	/* Fragment the data into proper blocks. */
956aae4fe77Suwe 	if (cmd->c_datalen > 0) {
957393d192eSuwe 		blksize = MIN(cmd->c_datalen, cmd->c_blklen);
958aae4fe77Suwe 		blkcount = cmd->c_datalen / blksize;
959aae4fe77Suwe 		if (cmd->c_datalen % blksize > 0) {
960aae4fe77Suwe 			/* XXX: Split this command. (1.7.4) */
961aae4fe77Suwe 			printf("%s: data not a multiple of %d bytes\n",
962a93f47f6Sjasper 			    DEVNAME(hp->sc), blksize);
963aae4fe77Suwe 			return EINVAL;
964aae4fe77Suwe 		}
965aae4fe77Suwe 	}
966aae4fe77Suwe 
967aae4fe77Suwe 	/* Check limit imposed by 9-bit block count. (1.7.2) */
968aae4fe77Suwe 	if (blkcount > SDHC_BLOCK_COUNT_MAX) {
969a93f47f6Sjasper 		printf("%s: too much data\n", DEVNAME(hp->sc));
970aae4fe77Suwe 		return EINVAL;
971aae4fe77Suwe 	}
972aae4fe77Suwe 
973aae4fe77Suwe 	/* Prepare transfer mode register value. (2.2.5) */
974aae4fe77Suwe 	mode = 0;
975aae4fe77Suwe 	if (ISSET(cmd->c_flags, SCF_CMD_READ))
976aae4fe77Suwe 		mode |= SDHC_READ_MODE;
977aae4fe77Suwe 	if (blkcount > 0) {
978aae4fe77Suwe 		mode |= SDHC_BLOCK_COUNT_ENABLE;
979aae4fe77Suwe 		if (blkcount > 1) {
980aae4fe77Suwe 			mode |= SDHC_MULTI_BLOCK_MODE;
981402f30eeSpatrick 			if (cmd->c_opcode != SD_IO_RW_EXTENDED)
982aae4fe77Suwe 				mode |= SDHC_AUTO_CMD12_ENABLE;
983aae4fe77Suwe 		}
984aae4fe77Suwe 	}
985c6293583Skettenis 	if (cmd->c_dmamap && cmd->c_datalen > 0 &&
986c6293583Skettenis 	    ISSET(hp->flags, SHF_USE_DMA))
987aae4fe77Suwe 		mode |= SDHC_DMA_ENABLE;
988aae4fe77Suwe 
989aae4fe77Suwe 	/*
990aae4fe77Suwe 	 * Prepare command register value. (2.2.6)
991aae4fe77Suwe 	 */
992aae4fe77Suwe 	command = (cmd->c_opcode & SDHC_COMMAND_INDEX_MASK) <<
993aae4fe77Suwe 	    SDHC_COMMAND_INDEX_SHIFT;
994aae4fe77Suwe 
995aae4fe77Suwe 	if (ISSET(cmd->c_flags, SCF_RSP_CRC))
996aae4fe77Suwe 		command |= SDHC_CRC_CHECK_ENABLE;
997aae4fe77Suwe 	if (ISSET(cmd->c_flags, SCF_RSP_IDX))
998aae4fe77Suwe 		command |= SDHC_INDEX_CHECK_ENABLE;
999aae4fe77Suwe 	if (cmd->c_data != NULL)
1000aae4fe77Suwe 		command |= SDHC_DATA_PRESENT_SELECT;
1001aae4fe77Suwe 
1002aae4fe77Suwe 	if (!ISSET(cmd->c_flags, SCF_RSP_PRESENT))
1003aae4fe77Suwe 		command |= SDHC_NO_RESPONSE;
1004aae4fe77Suwe 	else if (ISSET(cmd->c_flags, SCF_RSP_136))
1005aae4fe77Suwe 		command |= SDHC_RESP_LEN_136;
1006aae4fe77Suwe 	else if (ISSET(cmd->c_flags, SCF_RSP_BSY))
1007aae4fe77Suwe 		command |= SDHC_RESP_LEN_48_CHK_BUSY;
1008aae4fe77Suwe 	else
1009aae4fe77Suwe 		command |= SDHC_RESP_LEN_48;
1010aae4fe77Suwe 
1011aae4fe77Suwe 	/* Wait until command and data inhibit bits are clear. (1.5) */
1012aae4fe77Suwe 	if ((error = sdhc_wait_state(hp, SDHC_CMD_INHIBIT_MASK, 0)) != 0)
1013aae4fe77Suwe 		return error;
1014aae4fe77Suwe 
1015aae4fe77Suwe 	s = splsdmmc();
1016aae4fe77Suwe 
1017aae4fe77Suwe 	/* Alert the user not to remove the card. */
1018aae4fe77Suwe 	HSET1(hp, SDHC_HOST_CTL, SDHC_LED_ON);
1019aae4fe77Suwe 
1020c6293583Skettenis 	/* Set DMA start address if SHF_USE_DMA is set. */
1021c6293583Skettenis 	if (cmd->c_dmamap && ISSET(hp->flags, SHF_USE_DMA)) {
1022c6293583Skettenis 		for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
1023c6293583Skettenis 			bus_addr_t paddr =
1024c6293583Skettenis 			    cmd->c_dmamap->dm_segs[seg].ds_addr;
1025c6293583Skettenis 			uint16_t len =
1026c6293583Skettenis 			    cmd->c_dmamap->dm_segs[seg].ds_len == 65536 ?
1027c6293583Skettenis 			    0 : cmd->c_dmamap->dm_segs[seg].ds_len;
1028c6293583Skettenis 			uint16_t attr;
1029c6293583Skettenis 
1030c6293583Skettenis 			attr = SDHC_ADMA2_VALID | SDHC_ADMA2_ACT_TRANS;
1031c6293583Skettenis 			if (seg == cmd->c_dmamap->dm_nsegs - 1)
1032c6293583Skettenis 				attr |= SDHC_ADMA2_END;
1033c6293583Skettenis 
1034b60bffefSpatrick 			if (ISSET(hp->flags, SHF_USE_DMA64)) {
1035b60bffefSpatrick 				desc64[seg].attribute = htole16(attr);
1036b60bffefSpatrick 				desc64[seg].length = htole16(len);
1037b60bffefSpatrick 				desc64[seg].address_lo =
1038b60bffefSpatrick 				    htole32((uint64_t)paddr & 0xffffffff);
1039b60bffefSpatrick 				desc64[seg].address_hi =
1040b60bffefSpatrick 				    htole32((uint64_t)paddr >> 32);
1041b60bffefSpatrick 			} else {
1042b60bffefSpatrick 				desc32[seg].attribute = htole16(attr);
1043b60bffefSpatrick 				desc32[seg].length = htole16(len);
1044b60bffefSpatrick 				desc32[seg].address = htole32(paddr);
1045b60bffefSpatrick 			}
1046c6293583Skettenis 		}
1047c6293583Skettenis 
1048b60bffefSpatrick 		if (ISSET(hp->flags, SHF_USE_DMA64))
1049b60bffefSpatrick 			desc64[cmd->c_dmamap->dm_nsegs].attribute = htole16(0);
1050b60bffefSpatrick 		else
1051b60bffefSpatrick 			desc32[cmd->c_dmamap->dm_nsegs].attribute = htole16(0);
1052c6293583Skettenis 
1053c6293583Skettenis 		bus_dmamap_sync(sc->sc_dmat, hp->adma_map, 0, PAGE_SIZE,
1054c6293583Skettenis 		    BUS_DMASYNC_PREWRITE);
1055c6293583Skettenis 
1056c6293583Skettenis 		HCLR1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT);
1057b60bffefSpatrick 		if (ISSET(hp->flags, SHF_USE_DMA64))
1058b60bffefSpatrick 			HSET1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT_ADMA64);
1059b60bffefSpatrick 		else
1060b60bffefSpatrick 			HSET1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT_ADMA32);
1061c6293583Skettenis 
1062c6293583Skettenis 		HWRITE4(hp, SDHC_ADMA_SYSTEM_ADDR,
1063c6293583Skettenis 		    hp->adma_map->dm_segs[0].ds_addr);
1064cb39577eSpatrick 	} else
1065cb39577eSpatrick 		HCLR1(hp, SDHC_HOST_CTL, SDHC_DMA_SELECT);
1066aae4fe77Suwe 
106737539bbbSuwe 	DPRINTF(1,("%s: cmd=%#x mode=%#x blksize=%d blkcount=%d\n",
1068a93f47f6Sjasper 	    DEVNAME(hp->sc), command, mode, blksize, blkcount));
1069f6697933Sfgsch 
1070d80c3592Spatrick 	/* We're starting a new command, reset state. */
1071d80c3592Spatrick 	hp->intr_status = 0;
1072d80c3592Spatrick 
1073aae4fe77Suwe 	/*
1074aae4fe77Suwe 	 * Start a CPU data transfer.  Writing to the high order byte
1075aae4fe77Suwe 	 * of the SDHC_COMMAND register triggers the SD command. (1.5)
1076aae4fe77Suwe 	 */
1077393d192eSuwe 	HWRITE2(hp, SDHC_TRANSFER_MODE, mode);
1078aae4fe77Suwe 	HWRITE2(hp, SDHC_BLOCK_SIZE, blksize);
1079aae4fe77Suwe 	HWRITE2(hp, SDHC_BLOCK_COUNT, blkcount);
1080aae4fe77Suwe 	HWRITE4(hp, SDHC_ARGUMENT, cmd->c_arg);
1081aae4fe77Suwe 	HWRITE2(hp, SDHC_COMMAND, command);
1082aae4fe77Suwe 
1083aae4fe77Suwe 	splx(s);
1084aae4fe77Suwe 	return 0;
1085aae4fe77Suwe }
1086aae4fe77Suwe 
1087aae4fe77Suwe void
1088a6fd99a7Suwe sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd)
1089aae4fe77Suwe {
109012393d97Skettenis 	struct sdhc_softc *sc = hp->sc;
1091aae4fe77Suwe 	u_char *datap = cmd->c_data;
1092aae4fe77Suwe 	int i, datalen;
1093aae4fe77Suwe 	int mask;
1094aae4fe77Suwe 	int error;
1095aae4fe77Suwe 
1096c6293583Skettenis 	if (cmd->c_dmamap) {
1097c6293583Skettenis 		int status;
1098c6293583Skettenis 
1099c6293583Skettenis 		error = 0;
1100c6293583Skettenis 		for (;;) {
1101c6293583Skettenis 			status = sdhc_wait_intr(hp,
1102c6293583Skettenis 			    SDHC_DMA_INTERRUPT|SDHC_TRANSFER_COMPLETE,
1103c6293583Skettenis 			    SDHC_DMA_TIMEOUT);
1104c6293583Skettenis 			if (status & SDHC_TRANSFER_COMPLETE)
1105c6293583Skettenis 				break;
1106c6293583Skettenis 			if (!status) {
1107c6293583Skettenis 				error = ETIMEDOUT;
1108c6293583Skettenis 				break;
1109c6293583Skettenis 			}
1110c6293583Skettenis 		}
1111c6293583Skettenis 
111212393d97Skettenis 		bus_dmamap_sync(sc->sc_dmat, hp->adma_map, 0, PAGE_SIZE,
111312393d97Skettenis 		    BUS_DMASYNC_POSTWRITE);
1114c6293583Skettenis 		goto done;
1115c6293583Skettenis 	}
1116c6293583Skettenis 
1117aae4fe77Suwe 	mask = ISSET(cmd->c_flags, SCF_CMD_READ) ?
1118aae4fe77Suwe 	    SDHC_BUFFER_READ_ENABLE : SDHC_BUFFER_WRITE_ENABLE;
1119aae4fe77Suwe 	error = 0;
1120aae4fe77Suwe 	datalen = cmd->c_datalen;
1121aae4fe77Suwe 
1122a93f47f6Sjasper 	DPRINTF(1,("%s: resp=%#x datalen=%d\n", DEVNAME(hp->sc),
1123a6fd99a7Suwe 	    MMC_R1(cmd->c_resp), datalen));
1124aae4fe77Suwe 
1125393d192eSuwe #ifdef SDHC_DEBUG
1126393d192eSuwe 	/* XXX I forgot why I wanted to know when this happens :-( */
1127393d192eSuwe 	if ((cmd->c_opcode == 52 || cmd->c_opcode == 53) &&
1128393d192eSuwe 	    ISSET(MMC_R1(cmd->c_resp), 0xcb00))
1129393d192eSuwe 		printf("%s: CMD52/53 error response flags %#x\n",
1130a93f47f6Sjasper 		    DEVNAME(hp->sc), MMC_R1(cmd->c_resp) & 0xff00);
1131393d192eSuwe #endif
1132393d192eSuwe 
1133a6fd99a7Suwe 	while (datalen > 0) {
1134a6fd99a7Suwe 		if (!sdhc_wait_intr(hp, SDHC_BUFFER_READ_READY|
1135a6fd99a7Suwe 		    SDHC_BUFFER_WRITE_READY, SDHC_BUFFER_TIMEOUT)) {
1136a6fd99a7Suwe 			error = ETIMEDOUT;
1137a6fd99a7Suwe 			break;
1138a6fd99a7Suwe 		}
1139a6fd99a7Suwe 
1140a6fd99a7Suwe 		if ((error = sdhc_wait_state(hp, mask, mask)) != 0)
1141aae4fe77Suwe 			break;
1142aae4fe77Suwe 
1143aae4fe77Suwe 		i = MIN(datalen, cmd->c_blklen);
1144aae4fe77Suwe 		if (ISSET(cmd->c_flags, SCF_CMD_READ))
1145aae4fe77Suwe 			sdhc_read_data(hp, datap, i);
1146aae4fe77Suwe 		else
1147aae4fe77Suwe 			sdhc_write_data(hp, datap, i);
1148aae4fe77Suwe 
1149aae4fe77Suwe 		datap += i;
1150aae4fe77Suwe 		datalen -= i;
1151aae4fe77Suwe 	}
1152aae4fe77Suwe 
1153a6fd99a7Suwe 	if (error == 0 && !sdhc_wait_intr(hp, SDHC_TRANSFER_COMPLETE,
1154a6fd99a7Suwe 	    SDHC_TRANSFER_TIMEOUT))
1155a6fd99a7Suwe 		error = ETIMEDOUT;
1156aae4fe77Suwe 
1157c6293583Skettenis done:
1158a6fd99a7Suwe 	if (error != 0)
1159aae4fe77Suwe 		cmd->c_error = error;
1160a6fd99a7Suwe 	SET(cmd->c_flags, SCF_ITSDONE);
1161aae4fe77Suwe 
116237539bbbSuwe 	DPRINTF(1,("%s: data transfer done (error=%d)\n",
1163a93f47f6Sjasper 	    DEVNAME(hp->sc), cmd->c_error));
1164aae4fe77Suwe }
1165aae4fe77Suwe 
1166aae4fe77Suwe void
1167aae4fe77Suwe sdhc_read_data(struct sdhc_host *hp, u_char *datap, int datalen)
1168aae4fe77Suwe {
1169393d192eSuwe 	while (datalen > 3) {
1170393d192eSuwe 		*(u_int32_t *)datap = HREAD4(hp, SDHC_DATA);
11718371700fSmiod 		datap += 4;
1172aae4fe77Suwe 		datalen -= 4;
1173aae4fe77Suwe 	}
1174393d192eSuwe 	if (datalen > 0) {
1175393d192eSuwe 		u_int32_t rv = HREAD4(hp, SDHC_DATA);
1176393d192eSuwe 		do {
1177393d192eSuwe 			*datap++ = rv & 0xff;
1178393d192eSuwe 			rv = rv >> 8;
1179393d192eSuwe 		} while (--datalen > 0);
1180aae4fe77Suwe 	}
1181aae4fe77Suwe }
1182aae4fe77Suwe 
1183aae4fe77Suwe void
1184aae4fe77Suwe sdhc_write_data(struct sdhc_host *hp, u_char *datap, int datalen)
1185aae4fe77Suwe {
1186393d192eSuwe 	while (datalen > 3) {
1187393d192eSuwe 		DPRINTF(3,("%08x\n", *(u_int32_t *)datap));
1188ab8fb65aSgrange 		HWRITE4(hp, SDHC_DATA, *((u_int32_t *)datap));
1189ab8fb65aSgrange 		datap += 4;
1190aae4fe77Suwe 		datalen -= 4;
1191aae4fe77Suwe 	}
1192393d192eSuwe 	if (datalen > 0) {
1193393d192eSuwe 		u_int32_t rv = *datap++;
1194393d192eSuwe 		if (datalen > 1)
1195393d192eSuwe 			rv |= *datap++ << 8;
1196393d192eSuwe 		if (datalen > 2)
1197393d192eSuwe 			rv |= *datap++ << 16;
1198393d192eSuwe 		DPRINTF(3,("rv %08x\n", rv));
1199393d192eSuwe 		HWRITE4(hp, SDHC_DATA, rv);
1200aae4fe77Suwe 	}
1201aae4fe77Suwe }
1202aae4fe77Suwe 
1203a6fd99a7Suwe /* Prepare for another command. */
12045842cfcdSfgsch int
12055842cfcdSfgsch sdhc_soft_reset(struct sdhc_host *hp, int mask)
1206aae4fe77Suwe {
12075842cfcdSfgsch 	int timo;
12085842cfcdSfgsch 
1209a93f47f6Sjasper 	DPRINTF(1,("%s: software reset reg=%#x\n", DEVNAME(hp->sc), mask));
12105842cfcdSfgsch 
12115842cfcdSfgsch 	HWRITE1(hp, SDHC_SOFTWARE_RESET, mask);
12125842cfcdSfgsch 	for (timo = 10; timo > 0; timo--) {
12135842cfcdSfgsch 		if (!ISSET(HREAD1(hp, SDHC_SOFTWARE_RESET), mask))
12145842cfcdSfgsch 			break;
1215a6fd99a7Suwe 		sdmmc_delay(10000);
121669c67381Sclaudio 		HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
1217a6fd99a7Suwe 	}
12185842cfcdSfgsch 	if (timo == 0) {
1219a93f47f6Sjasper 		DPRINTF(1,("%s: timeout reg=%#x\n", DEVNAME(hp->sc),
12205842cfcdSfgsch 		    HREAD1(hp, SDHC_SOFTWARE_RESET)));
12215842cfcdSfgsch 		HWRITE1(hp, SDHC_SOFTWARE_RESET, 0);
12225842cfcdSfgsch 		return (ETIMEDOUT);
12235842cfcdSfgsch 	}
12245842cfcdSfgsch 
12255842cfcdSfgsch 	return (0);
12265842cfcdSfgsch }
1227a6fd99a7Suwe 
1228a6fd99a7Suwe int
12293f3abf14Scheloha sdhc_wait_intr_cold(struct sdhc_host *hp, int mask, int secs)
1230f3036462Sjmatthew {
12313f3abf14Scheloha 	int status, usecs;
1232f3036462Sjmatthew 
1233f3036462Sjmatthew 	mask |= SDHC_ERROR_INTERRUPT;
12343f3abf14Scheloha 	usecs = secs * 1000000;
1235f3036462Sjmatthew 	status = hp->intr_status;
1236f3036462Sjmatthew 	while ((status & mask) == 0) {
1237f3036462Sjmatthew 
1238f3036462Sjmatthew 		status = HREAD2(hp, SDHC_NINTR_STATUS);
1239f3036462Sjmatthew 		if (ISSET(status, SDHC_NINTR_STATUS_MASK)) {
1240f3036462Sjmatthew 			HWRITE2(hp, SDHC_NINTR_STATUS, status);
1241f3036462Sjmatthew 			if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
1242f3036462Sjmatthew 				uint16_t error;
1243f3036462Sjmatthew 				error = HREAD2(hp, SDHC_EINTR_STATUS);
1244f3036462Sjmatthew 				HWRITE2(hp, SDHC_EINTR_STATUS, error);
1245f3036462Sjmatthew 				hp->intr_status |= status;
1246f3036462Sjmatthew 
1247f3036462Sjmatthew 				if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR|
1248f3036462Sjmatthew 				    SDHC_DATA_TIMEOUT_ERROR))
1249f3036462Sjmatthew 					break;
1250f3036462Sjmatthew 			}
1251f3036462Sjmatthew 
1252f3036462Sjmatthew 			if (ISSET(status, SDHC_BUFFER_READ_READY |
1253f3036462Sjmatthew 			    SDHC_BUFFER_WRITE_READY | SDHC_COMMAND_COMPLETE |
1254f3036462Sjmatthew 			    SDHC_TRANSFER_COMPLETE)) {
1255f3036462Sjmatthew 				hp->intr_status |= status;
1256f3036462Sjmatthew 				break;
1257f3036462Sjmatthew 			}
1258f3036462Sjmatthew 
1259f3036462Sjmatthew 			if (ISSET(status, SDHC_CARD_INTERRUPT)) {
1260f3036462Sjmatthew 				HSET2(hp, SDHC_NINTR_STATUS_EN,
1261f3036462Sjmatthew 				    SDHC_CARD_INTERRUPT);
1262f3036462Sjmatthew 			}
1263f3036462Sjmatthew 
1264f3036462Sjmatthew 			continue;
1265f3036462Sjmatthew 		}
1266f3036462Sjmatthew 
1267f3036462Sjmatthew 		delay(1);
12683f3abf14Scheloha 		if (usecs-- == 0) {
1269f3036462Sjmatthew 			status |= SDHC_ERROR_INTERRUPT;
1270f3036462Sjmatthew 			break;
1271f3036462Sjmatthew 		}
1272f3036462Sjmatthew 	}
1273f3036462Sjmatthew 
1274f3036462Sjmatthew 	hp->intr_status &= ~(status & mask);
1275f3036462Sjmatthew 	return (status & mask);
1276f3036462Sjmatthew }
1277f3036462Sjmatthew 
1278f3036462Sjmatthew int
12793f3abf14Scheloha sdhc_wait_intr(struct sdhc_host *hp, int mask, int secs)
1280a6fd99a7Suwe {
1281a6fd99a7Suwe 	int status;
1282aae4fe77Suwe 	int s;
1283aae4fe77Suwe 
1284f3036462Sjmatthew 	if (cold)
12853f3abf14Scheloha 		return (sdhc_wait_intr_cold(hp, mask, secs));
1286f3036462Sjmatthew 
1287a6fd99a7Suwe 	mask |= SDHC_ERROR_INTERRUPT;
1288aae4fe77Suwe 
1289aae4fe77Suwe 	s = splsdmmc();
1290a6fd99a7Suwe 	status = hp->intr_status & mask;
1291a6fd99a7Suwe 	while (status == 0) {
12923f3abf14Scheloha 		if (tsleep_nsec(&hp->intr_status, PWAIT, "hcintr",
12933f3abf14Scheloha 		    SEC_TO_NSEC(secs)) == EWOULDBLOCK) {
1294a6fd99a7Suwe 			status |= SDHC_ERROR_INTERRUPT;
1295a6fd99a7Suwe 			break;
1296aae4fe77Suwe 		}
1297a6fd99a7Suwe 		status = hp->intr_status & mask;
1298a6fd99a7Suwe 	}
1299a6fd99a7Suwe 	hp->intr_status &= ~status;
1300a6fd99a7Suwe 
1301a93f47f6Sjasper 	DPRINTF(2,("%s: intr status %#x error %#x\n", DEVNAME(hp->sc), status,
1302a6fd99a7Suwe 	    hp->intr_error_status));
1303a6fd99a7Suwe 
1304a6fd99a7Suwe 	/* Command timeout has higher priority than command complete. */
1305a6fd99a7Suwe 	if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
1306a6fd99a7Suwe 		hp->intr_error_status = 0;
13075842cfcdSfgsch 		(void)sdhc_soft_reset(hp, SDHC_RESET_DAT|SDHC_RESET_CMD);
1308a6fd99a7Suwe 		status = 0;
1309a6fd99a7Suwe 	}
1310a6fd99a7Suwe 
1311aae4fe77Suwe 	splx(s);
1312a6fd99a7Suwe 	return status;
1313aae4fe77Suwe }
1314aae4fe77Suwe 
1315aae4fe77Suwe /*
1316aae4fe77Suwe  * Established by attachment driver at interrupt priority IPL_SDMMC.
1317aae4fe77Suwe  */
1318aae4fe77Suwe int
1319aae4fe77Suwe sdhc_intr(void *arg)
1320aae4fe77Suwe {
1321aae4fe77Suwe 	struct sdhc_softc *sc = arg;
1322aae4fe77Suwe 	int host;
1323a6fd99a7Suwe 	int done = 0;
1324aae4fe77Suwe 
1325aae4fe77Suwe 	/* We got an interrupt, but we don't know from which slot. */
1326aae4fe77Suwe 	for (host = 0; host < sc->sc_nhosts; host++) {
132781aa4bdcSfgsch 		struct sdhc_host *hp = sc->sc_host[host];
1328aae4fe77Suwe 		u_int16_t status;
1329aae4fe77Suwe 
1330aae4fe77Suwe 		if (hp == NULL)
1331aae4fe77Suwe 			continue;
1332aae4fe77Suwe 
133356ce46e4Suwe 		/* Find out which interrupts are pending. */
1334aae4fe77Suwe 		status = HREAD2(hp, SDHC_NINTR_STATUS);
133556ce46e4Suwe 		if (!ISSET(status, SDHC_NINTR_STATUS_MASK))
133656ce46e4Suwe 			continue; /* no interrupt for us */
133756ce46e4Suwe 
133856ce46e4Suwe 		/* Acknowledge the interrupts we are about to handle. */
1339a6fd99a7Suwe 		HWRITE2(hp, SDHC_NINTR_STATUS, status);
1340a93f47f6Sjasper 		DPRINTF(2,("%s: interrupt status=%b\n", DEVNAME(hp->sc),
1341a6fd99a7Suwe 		    status, SDHC_NINTR_STATUS_BITS));
1342a6fd99a7Suwe 
1343a6fd99a7Suwe 		/* Claim this interrupt. */
1344a6fd99a7Suwe 		done = 1;
1345aae4fe77Suwe 
1346aae4fe77Suwe 		/*
1347a6fd99a7Suwe 		 * Service error interrupts.
1348aae4fe77Suwe 		 */
1349aae4fe77Suwe 		if (ISSET(status, SDHC_ERROR_INTERRUPT)) {
1350aae4fe77Suwe 			u_int16_t error;
1351aae4fe77Suwe 
1352a6fd99a7Suwe 			/* Acknowledge error interrupts. */
1353aae4fe77Suwe 			error = HREAD2(hp, SDHC_EINTR_STATUS);
1354aae4fe77Suwe 			HWRITE2(hp, SDHC_EINTR_STATUS, error);
135537539bbbSuwe 			DPRINTF(2,("%s: error interrupt, status=%b\n",
1356a93f47f6Sjasper 			    DEVNAME(hp->sc), error, SDHC_EINTR_STATUS_BITS));
1357aae4fe77Suwe 
1358aae4fe77Suwe 			if (ISSET(error, SDHC_CMD_TIMEOUT_ERROR|
1359a6fd99a7Suwe 			    SDHC_DATA_TIMEOUT_ERROR)) {
1360a6fd99a7Suwe 				hp->intr_error_status |= error;
1361a6fd99a7Suwe 				hp->intr_status |= status;
1362a6fd99a7Suwe 				wakeup(&hp->intr_status);
1363aae4fe77Suwe 			}
1364aae4fe77Suwe 		}
1365aae4fe77Suwe 
1366a6fd99a7Suwe 		/*
1367a6fd99a7Suwe 		 * Wake up the sdmmc event thread to scan for cards.
1368a6fd99a7Suwe 		 */
1369a6fd99a7Suwe 		if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION))
1370a6fd99a7Suwe 			sdmmc_needs_discover(hp->sdmmc);
1371a6fd99a7Suwe 
1372a6fd99a7Suwe 		/*
1373a6fd99a7Suwe 		 * Wake up the blocking process to service command
1374a6fd99a7Suwe 		 * related interrupt(s).
1375a6fd99a7Suwe 		 */
1376a6fd99a7Suwe 		if (ISSET(status, SDHC_BUFFER_READ_READY|
1377a6fd99a7Suwe 		    SDHC_BUFFER_WRITE_READY|SDHC_COMMAND_COMPLETE|
1378a6fd99a7Suwe 		    SDHC_TRANSFER_COMPLETE)) {
1379a6fd99a7Suwe 			hp->intr_status |= status;
1380a6fd99a7Suwe 			wakeup(&hp->intr_status);
1381a6fd99a7Suwe 		}
1382a6fd99a7Suwe 
1383a6fd99a7Suwe 		/*
1384a6fd99a7Suwe 		 * Service SD card interrupts.
1385a6fd99a7Suwe 		 */
1386aae4fe77Suwe 		if (ISSET(status, SDHC_CARD_INTERRUPT)) {
1387a93f47f6Sjasper 			DPRINTF(0,("%s: card interrupt\n", DEVNAME(hp->sc)));
1388aae4fe77Suwe 			HCLR2(hp, SDHC_NINTR_STATUS_EN, SDHC_CARD_INTERRUPT);
1389b979651fSuwe 			sdmmc_card_intr(hp->sdmmc);
1390aae4fe77Suwe 		}
1391aae4fe77Suwe 	}
1392aae4fe77Suwe 	return done;
1393aae4fe77Suwe }
1394aae4fe77Suwe 
1395c6076839Skettenis void
1396c6076839Skettenis sdhc_needs_discover(struct sdhc_softc *sc)
1397c6076839Skettenis {
1398c6076839Skettenis 	int host;
1399c6076839Skettenis 
1400c6076839Skettenis 	for (host = 0; host < sc->sc_nhosts; host++)
1401c6076839Skettenis 		sdmmc_needs_discover(sc->sc_host[host]->sdmmc);
1402c6076839Skettenis }
1403c6076839Skettenis 
1404aae4fe77Suwe #ifdef SDHC_DEBUG
1405aae4fe77Suwe void
1406aae4fe77Suwe sdhc_dump_regs(struct sdhc_host *hp)
1407aae4fe77Suwe {
1408aae4fe77Suwe 	printf("0x%02x PRESENT_STATE:    %b\n", SDHC_PRESENT_STATE,
1409aae4fe77Suwe 	    HREAD4(hp, SDHC_PRESENT_STATE), SDHC_PRESENT_STATE_BITS);
1410aae4fe77Suwe 	printf("0x%02x POWER_CTL:        %x\n", SDHC_POWER_CTL,
1411aae4fe77Suwe 	    HREAD1(hp, SDHC_POWER_CTL));
1412aae4fe77Suwe 	printf("0x%02x NINTR_STATUS:     %x\n", SDHC_NINTR_STATUS,
1413aae4fe77Suwe 	    HREAD2(hp, SDHC_NINTR_STATUS));
1414aae4fe77Suwe 	printf("0x%02x EINTR_STATUS:     %x\n", SDHC_EINTR_STATUS,
1415aae4fe77Suwe 	    HREAD2(hp, SDHC_EINTR_STATUS));
1416aae4fe77Suwe 	printf("0x%02x NINTR_STATUS_EN:  %x\n", SDHC_NINTR_STATUS_EN,
1417aae4fe77Suwe 	    HREAD2(hp, SDHC_NINTR_STATUS_EN));
1418aae4fe77Suwe 	printf("0x%02x EINTR_STATUS_EN:  %x\n", SDHC_EINTR_STATUS_EN,
1419aae4fe77Suwe 	    HREAD2(hp, SDHC_EINTR_STATUS_EN));
1420aae4fe77Suwe 	printf("0x%02x NINTR_SIGNAL_EN:  %x\n", SDHC_NINTR_SIGNAL_EN,
1421aae4fe77Suwe 	    HREAD2(hp, SDHC_NINTR_SIGNAL_EN));
1422aae4fe77Suwe 	printf("0x%02x EINTR_SIGNAL_EN:  %x\n", SDHC_EINTR_SIGNAL_EN,
1423aae4fe77Suwe 	    HREAD2(hp, SDHC_EINTR_SIGNAL_EN));
1424aae4fe77Suwe 	printf("0x%02x CAPABILITIES:     %x\n", SDHC_CAPABILITIES,
1425aae4fe77Suwe 	    HREAD4(hp, SDHC_CAPABILITIES));
1426aae4fe77Suwe 	printf("0x%02x MAX_CAPABILITIES: %x\n", SDHC_MAX_CAPABILITIES,
1427aae4fe77Suwe 	    HREAD4(hp, SDHC_MAX_CAPABILITIES));
1428aae4fe77Suwe }
1429aae4fe77Suwe #endif
1430f3036462Sjmatthew 
1431f3036462Sjmatthew int
1432f3036462Sjmatthew sdhc_hibernate_init(sdmmc_chipset_handle_t sch, void *fake_softc)
1433f3036462Sjmatthew {
1434f3036462Sjmatthew 	struct sdhc_host *hp, *fhp;
1435f3036462Sjmatthew 	fhp = fake_softc;
1436f3036462Sjmatthew 	hp = sch;
1437f3036462Sjmatthew 	*fhp = *hp;
1438f3036462Sjmatthew 
1439f3036462Sjmatthew 	return (0);
1440f3036462Sjmatthew }
1441