xref: /freebsd/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2018 Klaus P. Ohrhallinger <k@7he.at>
5  * All rights reserved.
6  *
7  * Based on bcm2835_sdhci.c:
8  * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  */
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 /*
37  * pin 48-53 - card slot
38  * pin 34-39 - radio module
39  *
40  * alt-0 - rubbish SDHCI  (0x7e202000) aka sdhost
41  * alt-3 - advanced SDHCI (0x7e300000) aka sdhci/mmc/sdio
42  *
43  * driving card slot with mmc:
44  *
45  * sdhost_pins {
46  *         brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>;
47  *         brcm,function = <0x7>;
48  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
49  *         phandle = <0x17>;
50  * };
51  * sdio_pins {
52  *         brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>;
53  *         brcm,function = <0x4>;
54  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
55  *         phandle = <0x18>;
56  * };
57  *
58  * driving card slot with sdhost:
59  *
60  * sdhost_pins {
61  *         brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>;
62  *         brcm,function = <0x4>;
63  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
64  *         phandle = <0x17>;
65  * };
66  * sdio_pins {
67  *         brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>;
68  *         brcm,function = <0x7>;
69  *         brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
70  *         phandle = <0x18>;
71  * };
72  *
73  */
74 
75 #include <sys/param.h>
76 #include <sys/systm.h>
77 #include <sys/kobj.h>
78 #include <sys/bus.h>
79 #include <sys/kernel.h>
80 #include <sys/lock.h>
81 #include <sys/malloc.h>
82 #include <sys/module.h>
83 #include <sys/mutex.h>
84 #include <sys/rman.h>
85 #include <sys/sysctl.h>
86 #include <sys/taskqueue.h>
87 #include <sys/gpio.h>
88 
89 #include <machine/bus.h>
90 
91 #include <dev/ofw/ofw_bus.h>
92 #include <dev/ofw/ofw_bus_subr.h>
93 
94 #include <dev/mmc/bridge.h>
95 #include <dev/mmc/mmcreg.h>
96 
97 #include <dev/sdhci/sdhci.h>
98 
99 #include "mmcbr_if.h"
100 #include "sdhci_if.h"
101 
102 #include "opt_mmccam.h"
103 
104 #include "bcm2835_dma.h"
105 #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
106 #include "bcm2835_vcbus.h"
107 
108 /* #define SDHOST_DEBUG */
109 
110 /* Registers */
111 #define HC_COMMAND		0x00	/* Command and flags */
112 #define HC_ARGUMENT		0x04
113 #define HC_TIMEOUTCOUNTER	0x08
114 #define HC_CLOCKDIVISOR		0x0c
115 #define HC_RESPONSE_0		0x10
116 #define HC_RESPONSE_1		0x14
117 #define HC_RESPONSE_2		0x18
118 #define HC_RESPONSE_3		0x1c
119 #define HC_HOSTSTATUS		0x20
120 #define HC_POWER		0x30
121 #define HC_DEBUG		0x34
122 #define HC_HOSTCONFIG		0x38
123 #define HC_BLOCKSIZE		0x3c
124 #define HC_DATAPORT		0x40
125 #define HC_BLOCKCOUNT		0x50
126 
127 /* Flags for HC_COMMAND register */
128 #define HC_CMD_ENABLE			0x8000
129 #define HC_CMD_FAILED			0x4000
130 #define HC_CMD_BUSY			0x0800
131 #define HC_CMD_RESPONSE_NONE		0x0400
132 #define HC_CMD_RESPONSE_LONG		0x0200
133 #define HC_CMD_WRITE			0x0080
134 #define HC_CMD_READ			0x0040
135 #define HC_CMD_COMMAND_MASK		0x003f
136 
137 #define HC_CLOCKDIVISOR_MAXVAL		0x07ff
138 
139 /* Flags for HC_HOSTSTATUS register */
140 #define HC_HSTST_HAVEDATA		0x0001
141 #define HC_HSTST_ERROR_FIFO		0x0008
142 #define HC_HSTST_ERROR_CRC7		0x0010
143 #define HC_HSTST_ERROR_CRC16		0x0020
144 #define HC_HSTST_TIMEOUT_CMD		0x0040
145 #define HC_HSTST_TIMEOUT_DATA		0x0080
146 #define HC_HSTST_INT_BLOCK		0x0200
147 #define HC_HSTST_INT_BUSY		0x0400
148 
149 #define HC_HSTST_RESET			0xffff
150 
151 #define HC_HSTST_MASK_ERROR_DATA	(HC_HSTST_ERROR_FIFO | \
152     HC_HSTST_ERROR_CRC7 | HC_HSTST_ERROR_CRC16 | HC_HSTST_TIMEOUT_DATA)
153 
154 #define HC_HSTST_MASK_ERROR_ALL		(HC_HSTST_MASK_ERROR_DATA | \
155     HC_HSTST_TIMEOUT_CMD)
156 
157 /* Flags for HC_HOSTCONFIG register */
158 #define HC_HSTCF_INTBUS_WIDE		0x0002
159 #define HC_HSTCF_EXTBUS_4BIT		0x0004
160 #define HC_HSTCF_SLOW_CARD		0x0008
161 #define HC_HSTCF_INT_DATA		0x0010
162 #define HC_HSTCF_INT_BLOCK		0x0100
163 #define HC_HSTCF_INT_BUSY		0x0400
164 
165 /* Flags for HC_DEBUG register */
166 #define HC_DBG_FIFO_THRESH_WRITE_SHIFT	9
167 #define HC_DBG_FIFO_THRESH_READ_SHIFT	14
168 #define HC_DBG_FIFO_THRESH_MASK		0x001f
169 
170 /* Settings */
171 #define HC_FIFO_SIZE		16
172 #define HC_FIFO_THRESH_READ	4
173 #define HC_FIFO_THRESH_WRITE	4
174 
175 #define HC_TIMEOUT_DEFAULT	0x00f00000
176 
177 #define	BCM2835_DEFAULT_SDHCI_FREQ	50
178 
179 static int bcm2835_sdhost_debug = 0;
180 
181 #ifdef SDHOST_DEBUG
182 
183 TUNABLE_INT("hw.bcm2835.sdhost.debug", &bcm2835_sdhost_debug);
184 SYSCTL_INT(_hw_sdhci, OID_AUTO, bcm2835_sdhost_debug, CTLFLAG_RWTUN,
185     &bcm2835_sdhost_debug, 0, "bcm2835-sdhost Debug level");
186 
187 #define dprintf(fmt, args...) \
188 	do { \
189 		if (bcm2835_sdhost_debug > 0) \
190 			printf(fmt,##args); \
191 	} while (0)
192 #else
193 
194 #define dprintf(fmt, args...)
195 
196 #endif /* ! SDHOST_DEBUG */
197 
198 static struct ofw_compat_data compat_data[] = {
199 	{"brcm,bcm2835-sdhost",		1},
200 	{NULL,				0}
201 };
202 
203 struct bcm_sdhost_softc {
204 	device_t		sc_dev;
205 	struct resource *	sc_mem_res;
206 	struct resource *	sc_irq_res;
207 	bus_space_tag_t		sc_bst;
208 	bus_space_handle_t	sc_bsh;
209 	void *			sc_intrhand;
210 	struct mmc_request *	sc_req;
211 	struct sdhci_slot	sc_slot;
212 
213 	struct mtx		mtx;
214 
215 	char			cmdbusy;
216 	char			mmc_app_cmd;
217 
218 	u_int32_t		sdhci_int_status;
219 	u_int32_t		sdhci_signal_enable;
220 	u_int32_t		sdhci_present_state;
221 	u_int32_t		sdhci_blocksize;
222 	u_int32_t		sdhci_blockcount;
223 
224 	u_int32_t		sdcard_rca;
225 };
226 
227 static int bcm_sdhost_probe(device_t);
228 static int bcm_sdhost_attach(device_t);
229 static int bcm_sdhost_detach(device_t);
230 static void bcm_sdhost_intr(void *);
231 
232 static int bcm_sdhost_get_ro(device_t, device_t);
233 
234 static inline uint32_t
235 RD4(struct bcm_sdhost_softc *sc, bus_size_t off)
236 {
237 	uint32_t val;
238 
239 	val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
240 
241 	return (val);
242 }
243 
244 static inline void
245 WR4(struct bcm_sdhost_softc *sc, bus_size_t off, uint32_t val)
246 {
247 
248 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
249 }
250 
251 #ifdef notyet
252 static inline uint16_t
253 RD2(struct bcm_sdhost_softc *sc, bus_size_t off)
254 {
255 	uint32_t val;
256 
257 	val = RD4(sc, off & ~3);
258 
259 	return ((val >> (off & 3)*8) & 0xffff);
260 }
261 #endif
262 
263 static inline uint8_t
264 RD1(struct bcm_sdhost_softc *sc, bus_size_t off)
265 {
266 	uint32_t val;
267 
268 	val = RD4(sc, off & ~3);
269 
270 	return ((val >> (off & 3)*8) & 0xff);
271 }
272 
273 static inline void
274 WR2(struct bcm_sdhost_softc *sc, bus_size_t off, uint16_t val)
275 {
276 	uint32_t val32;
277 
278 	val32 = RD4(sc, off & ~3);
279 	val32 &= ~(0xffff << (off & 3)*8);
280 	val32 |= (val << (off & 3)*8);
281 	WR4(sc, off & ~3, val32);
282 }
283 
284 static inline void
285 WR1(struct bcm_sdhost_softc *sc, bus_size_t off, uint8_t val)
286 {
287 	uint32_t val32;
288 
289 	val32 = RD4(sc, off & ~3);
290 	val32 &= ~(0xff << (off & 3)*8);
291 	val32 |= (val << (off & 3)*8);
292 	WR4(sc, off & ~3, val32);
293 }
294 
295 static void
296 bcm_sdhost_print_regs(struct bcm_sdhost_softc *sc, struct sdhci_slot *slot,
297     int line, int error)
298 {
299 
300 	if (bcm2835_sdhost_debug > 0 || error > 0) {
301 		printf("%s: sc=%p slot=%p\n",
302 		    __func__, sc, slot);
303 		printf("HC_COMMAND:        0x%08x\n",
304 		    RD4(sc, HC_COMMAND));
305 		printf("HC_ARGUMENT:       0x%08x\n",
306 		    RD4(sc, HC_ARGUMENT));
307 		printf("HC_TIMEOUTCOUNTER: 0x%08x\n",
308 		    RD4(sc, HC_TIMEOUTCOUNTER));
309 		printf("HC_CLOCKDIVISOR:   0x%08x\n",
310 		    RD4(sc, HC_CLOCKDIVISOR));
311 		printf("HC_RESPONSE_0:     0x%08x\n",
312 		    RD4(sc, HC_RESPONSE_0));
313 		printf("HC_RESPONSE_1:     0x%08x\n",
314 		    RD4(sc, HC_RESPONSE_1));
315 		printf("HC_RESPONSE_2:     0x%08x\n",
316 		    RD4(sc, HC_RESPONSE_2));
317 		printf("HC_RESPONSE_3:     0x%08x\n",
318 		    RD4(sc, HC_RESPONSE_3));
319 		printf("HC_HOSTSTATUS:     0x%08x\n",
320 		    RD4(sc, HC_HOSTSTATUS));
321 		printf("HC_POWER:          0x%08x\n",
322 		    RD4(sc, HC_POWER));
323 		printf("HC_DEBUG:          0x%08x\n",
324 		    RD4(sc, HC_DEBUG));
325 		printf("HC_HOSTCONFIG:     0x%08x\n",
326 		    RD4(sc, HC_HOSTCONFIG));
327 		printf("HC_BLOCKSIZE:      0x%08x\n",
328 		    RD4(sc, HC_BLOCKSIZE));
329 		printf("HC_BLOCKCOUNT:     0x%08x\n",
330 		    RD4(sc, HC_BLOCKCOUNT));
331 
332 	} else {
333 		/*
334 		printf("%04d | HC_COMMAND: 0x%08x HC_ARGUMENT: 0x%08x "
335 		    "HC_HOSTSTATUS: 0x%08x HC_HOSTCONFIG: 0x%08x\n",
336 		    line, RD4(sc, HC_COMMAND), RD4(sc, HC_ARGUMENT),
337 		    RD4(sc, HC_HOSTSTATUS), RD4(sc, HC_HOSTCONFIG));
338 		*/
339 	}
340 }
341 
342 static void
343 bcm_sdhost_reset(device_t dev, struct sdhci_slot *slot)
344 {
345 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
346 	u_int32_t dbg;
347 
348 	WR4(sc, HC_POWER, 0);
349 
350 	WR4(sc, HC_COMMAND, 0);
351 	WR4(sc, HC_ARGUMENT, 0);
352 	WR4(sc, HC_TIMEOUTCOUNTER, HC_TIMEOUT_DEFAULT);
353 	WR4(sc, HC_CLOCKDIVISOR, 0);
354 	WR4(sc, HC_HOSTSTATUS, HC_HSTST_RESET);
355 	WR4(sc, HC_HOSTCONFIG, 0);
356 	WR4(sc, HC_BLOCKSIZE, 0);
357 	WR4(sc, HC_BLOCKCOUNT, 0);
358 
359 	dbg = RD4(sc, HC_DEBUG);
360 	dbg &= ~( (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_READ_SHIFT) |
361 	          (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_WRITE_SHIFT) );
362 	dbg |= (HC_FIFO_THRESH_READ << HC_DBG_FIFO_THRESH_READ_SHIFT) |
363 	       (HC_FIFO_THRESH_WRITE << HC_DBG_FIFO_THRESH_WRITE_SHIFT);
364 	WR4(sc, HC_DEBUG, dbg);
365 
366 	DELAY(250000);
367 
368 	WR4(sc, HC_POWER, 1);
369 
370 	DELAY(250000);
371 
372 	sc->sdhci_present_state = SDHCI_CARD_PRESENT | SDHCI_CARD_STABLE |
373 		SDHCI_WRITE_PROTECT;
374 
375 	WR4(sc, HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_MAXVAL);
376 	WR4(sc, HC_HOSTCONFIG, HC_HSTCF_INT_BUSY);
377 }
378 
379 static int
380 bcm_sdhost_probe(device_t dev)
381 {
382 
383 	dprintf("%s:\n", __func__);
384 
385 	if (!ofw_bus_status_okay(dev))
386 		return (ENXIO);
387 
388 	if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
389 		return (ENXIO);
390 
391 	device_set_desc(dev, "Broadcom 2708 SDHOST controller");
392 
393 	return (BUS_PROBE_DEFAULT);
394 }
395 
396 static int
397 bcm_sdhost_attach(device_t dev)
398 {
399 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
400 	int rid, err;
401 	u_int default_freq;
402 
403 	dprintf("%s: dev=%p sc=%p unit=%d\n",
404 	    __func__, dev, sc, device_get_unit(dev));
405 
406 	mtx_init(&sc->mtx, "BCM SDHOST mtx", "bcm_sdhost",
407 	    MTX_DEF | MTX_RECURSE);
408 
409 	sc->sc_dev = dev;
410 	sc->sc_req = NULL;
411 
412 	sc->cmdbusy = 0;
413 	sc->mmc_app_cmd = 0;
414 	sc->sdhci_int_status = 0;
415 	sc->sdhci_signal_enable = 0;
416 	sc->sdhci_present_state = 0;
417 	sc->sdhci_blocksize = 0;
418 	sc->sdhci_blockcount = 0;
419 
420 	sc->sdcard_rca = 0;
421 
422 	default_freq = 50;
423 	err = 0;
424 
425 	if (bootverbose)
426 		device_printf(dev, "SDHCI frequency: %dMHz\n", default_freq);
427 
428 	rid = 0;
429 	sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
430 	    RF_ACTIVE);
431 	if (!sc->sc_mem_res) {
432 		device_printf(dev, "cannot allocate memory window\n");
433 		err = ENXIO;
434 		goto fail;
435 	}
436 
437 	sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
438 	sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
439 
440 	bcm_sdhost_reset(dev, &sc->sc_slot);
441 
442 	bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
443 
444 	rid = 0;
445 	sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
446 	    RF_ACTIVE);
447 	if (!sc->sc_irq_res) {
448 		device_printf(dev, "cannot allocate interrupt\n");
449 		err = ENXIO;
450 		goto fail;
451 	}
452 
453 	if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
454 	    NULL, bcm_sdhost_intr, sc, &sc->sc_intrhand)) {
455 		device_printf(dev, "cannot setup interrupt handler\n");
456 		err = ENXIO;
457 		goto fail;
458 	}
459 
460 	sc->sc_slot.caps = 0;
461 	sc->sc_slot.caps |= SDHCI_CAN_VDD_330;
462 	sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD;
463 	sc->sc_slot.caps |= (default_freq << SDHCI_CLOCK_BASE_SHIFT);
464 
465 	sc->sc_slot.quirks = 0;
466 	sc->sc_slot.quirks |= SDHCI_QUIRK_MISSING_CAPS;
467 	sc->sc_slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
468 
469 	sc->sc_slot.opt = 0;
470 
471 	/* XXX ?
472 	sc->slot->timeout_clk = ...;
473 	*/
474 
475 	sdhci_init_slot(dev, &sc->sc_slot, 0);
476 
477 	bus_generic_probe(dev);
478 	bus_generic_attach(dev);
479 
480 	sdhci_start_slot(&sc->sc_slot);
481 
482 	return (0);
483 
484     fail:
485 	if (sc->sc_intrhand)
486 		bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
487 	if (sc->sc_irq_res)
488 		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
489 	if (sc->sc_mem_res)
490 		bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
491 
492 	return (err);
493 }
494 
495 static int
496 bcm_sdhost_detach(device_t dev)
497 {
498 
499 	dprintf("%s:\n", __func__);
500 
501 	return (EBUSY);
502 }
503 
504 /*
505  * rv 0 --> command finished
506  * rv 1 --> command timed out
507  */
508 static inline int
509 bcm_sdhost_waitcommand(struct bcm_sdhost_softc *sc)
510 {
511 	int timeout = 1000;
512 
513 	mtx_assert(&sc->mtx, MA_OWNED);
514 
515 	while ((RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) && --timeout > 0) {
516 		DELAY(100);
517 	}
518 
519 	return ((timeout > 0) ? 0 : 1);
520 }
521 
522 static int
523 bcm_sdhost_waitcommand_status(struct bcm_sdhost_softc *sc)
524 {
525 	u_int32_t cdst;
526 	int i;
527 
528 	/* wait for card to change status from
529 	 * ''prg'' to ''trn''
530 	 * card status: sd specs p. 103
531 	 */
532 	i = 0;
533 	do {
534 		DELAY(1000);
535 		WR4(sc, HC_ARGUMENT, sc->sdcard_rca << 16);
536 		WR4(sc, HC_COMMAND,
537 		    MMC_SEND_STATUS | HC_CMD_ENABLE);
538 		bcm_sdhost_waitcommand(sc);
539 		cdst = RD4(sc, HC_RESPONSE_0);
540 		dprintf("%s: card status %08x (cs %d)\n",
541 		    __func__, cdst, (cdst & 0x0e00) >> 9);
542 		if (i++ > 100) {
543 			printf("%s: giving up, "
544 			    "card status %08x (cs %d)\n",
545 			    __func__, cdst,
546 			    (cdst & 0x0e00) >> 9);
547 			return (1);
548 			break;
549 		}
550 	} while (((cdst & 0x0e00) >> 9) != 4);
551 
552 	return (0);
553 }
554 
555 static void
556 bcm_sdhost_intr(void *arg)
557 {
558 	struct bcm_sdhost_softc *sc = arg;
559 	struct sdhci_slot *slot = &sc->sc_slot;
560 	uint32_t hstst;
561 	uint32_t cmd;
562 
563 	mtx_lock(&sc->mtx);
564 
565 	hstst = RD4(sc, HC_HOSTSTATUS);
566 	cmd = RD4(sc, HC_COMMAND);
567 	if (hstst & HC_HSTST_HAVEDATA) {
568 		if (cmd & HC_CMD_READ) {
569 			sc->sdhci_present_state |= SDHCI_DATA_AVAILABLE;
570 			sc->sdhci_int_status |= SDHCI_INT_DATA_AVAIL;
571 		} else if (cmd & HC_CMD_WRITE) {
572 			sc->sdhci_present_state |= SDHCI_SPACE_AVAILABLE;
573 			sc->sdhci_int_status |= SDHCI_INT_SPACE_AVAIL;
574 		} else {
575 			panic("%s: hstst & HC_HSTST_HAVEDATA but no "
576 			    "HC_CMD_READ or HC_CMD_WRITE: cmd=%0x8 "
577 			    "hstst=%08x\n", __func__, cmd, hstst);
578 		}
579 	} else {
580 		sc->sdhci_present_state &=
581 		    ~(SDHCI_DATA_AVAILABLE|SDHCI_SPACE_AVAILABLE);
582 		sc->sdhci_int_status &=
583 		    ~(SDHCI_INT_DATA_AVAIL|SDHCI_INT_SPACE_AVAIL);
584 	}
585 
586 	if (hstst & HC_HSTST_MASK_ERROR_ALL) {
587 		printf("%s: ERROR: HC_HOSTSTATUS: %08x\n", __func__, hstst);
588 		bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
589 		sc->sdhci_int_status |= SDHCI_INT_ERROR;
590 	} else {
591 		sc->sdhci_int_status &= ~SDHCI_INT_ERROR;
592 	}
593 
594 	dprintf("%s: hstst=%08x offset=%08lx sdhci_present_state=%08x "
595 	    "sdhci_int_status=%08x\n", __func__, hstst, slot->offset,
596 	    sc->sdhci_present_state, sc->sdhci_int_status);
597 
598 	sdhci_generic_intr(&sc->sc_slot);
599 
600 	sc->sdhci_int_status &=
601 	    ~(SDHCI_INT_ERROR|SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END);
602 	sc->sdhci_present_state &= ~SDHCI_DATA_AVAILABLE;
603 
604 	if ((hstst & HC_HSTST_HAVEDATA) &&
605 	    (sc->sdhci_blocksize * sc->sdhci_blockcount == slot->offset)) {
606 		dprintf("%s: offset=%08lx sdhci_blocksize=%08x "
607 		    "sdhci_blockcount=%08x\n", __func__, slot->offset,
608 		    sc->sdhci_blocksize, sc->sdhci_blockcount);
609 		sc->sdhci_int_status &=
610 		    ~(SDHCI_INT_DATA_AVAIL|SDHCI_INT_SPACE_AVAIL);
611 		sc->sdhci_int_status |= SDHCI_INT_DATA_END;
612 		sdhci_generic_intr(&sc->sc_slot);
613 		sc->sdhci_int_status &= ~SDHCI_INT_DATA_END;
614 
615 		if ((cmd & HC_CMD_COMMAND_MASK) == MMC_READ_MULTIPLE_BLOCK ||
616 		    (cmd & HC_CMD_COMMAND_MASK) == MMC_WRITE_MULTIPLE_BLOCK) {
617 			WR4(sc, HC_ARGUMENT, 0x00000000);
618 			WR4(sc, HC_COMMAND,
619 			    MMC_STOP_TRANSMISSION | HC_CMD_ENABLE);
620 
621 			if (bcm_sdhost_waitcommand(sc)) {
622 				printf("%s: timeout #1\n", __func__);
623 				bcm_sdhost_print_regs(sc, &sc->sc_slot,
624 				    __LINE__, 1);
625 			}
626 		}
627 
628 		if (cmd & HC_CMD_WRITE) {
629 			if (bcm_sdhost_waitcommand_status(sc) != 0)
630 				sc->sdhci_int_status |= SDHCI_INT_ERROR;
631 		}
632 
633 		slot->data_done = 1;
634 
635 		sc->sdhci_int_status |= SDHCI_INT_RESPONSE;
636 		sdhci_generic_intr(&sc->sc_slot);
637 		sc->sdhci_int_status &= ~(SDHCI_INT_RESPONSE|SDHCI_INT_ERROR);
638 	}
639 
640 	/* this resets the interrupt */
641 	WR4(sc, HC_HOSTSTATUS,
642 	    (HC_HSTST_INT_BUSY|HC_HSTST_INT_BLOCK|HC_HSTST_HAVEDATA));
643 
644 	mtx_unlock(&sc->mtx);
645 }
646 
647 static int
648 bcm_sdhost_get_ro(device_t bus, device_t child)
649 {
650 
651 	dprintf("%s:\n", __func__);
652 
653 	return (0);
654 }
655 
656 static bool
657 bcm_sdhost_get_card_present(device_t dev, struct sdhci_slot *slot)
658 {
659 
660 	dprintf("%s:\n", __func__);
661 
662 	return (1);
663 }
664 
665 static void
666 bcm_sdhost_command(device_t dev, struct sdhci_slot *slot, uint16_t val)
667 {
668 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
669 	struct mmc_data *data = slot->curcmd->data;
670 	uint16_t val2;
671 	uint8_t opcode;
672 	uint8_t flags;
673 
674 	mtx_assert(&sc->mtx, MA_OWNED);
675 
676 	if (RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) {
677 		panic("%s: HC_CMD_ENABLE on entry\n", __func__);
678 	}
679 
680 	if (sc->cmdbusy == 1)
681 		panic("%s: cmdbusy\n", __func__);
682 
683 	sc->cmdbusy = 1;
684 
685 	val2 = ((val >> 8) & HC_CMD_COMMAND_MASK) | HC_CMD_ENABLE;
686 
687 	opcode = val >> 8;
688 	flags = val & 0xff;
689 
690 	if (opcode == MMC_APP_CMD)
691 		sc->mmc_app_cmd = 1;
692 
693 	if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_LONG)
694 		val2 |= HC_CMD_RESPONSE_LONG;
695 	else if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT_BUSY)
696 		/* XXX XXX when enabled, cmd 7 (select card) blocks forever */
697 		;/*val2 |= HC_CMD_BUSY; */
698 	else if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT)
699 		;
700 	else
701 		val2 |= HC_CMD_RESPONSE_NONE;
702 
703 	if (val2 & HC_CMD_BUSY)
704 		sc->sdhci_present_state |=
705 		    SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT;
706 
707 	if (data != NULL && data->flags & MMC_DATA_READ)
708 		val2 |= HC_CMD_READ;
709 	else if (data != NULL && data->flags & MMC_DATA_WRITE)
710 		val2 |= HC_CMD_WRITE;
711 
712 	dprintf("%s: SDHCI_COMMAND_FLAGS --> HC_COMMAND   %04x --> %04x\n",
713 	    __func__, val, val2);
714 
715 	if (opcode == MMC_READ_MULTIPLE_BLOCK ||
716 	    opcode == MMC_WRITE_MULTIPLE_BLOCK) {
717 		u_int32_t save_sdarg;
718 
719 		dprintf("%s: issuing MMC_SET_BLOCK_COUNT: CMD %08x ARG %08x\n",
720 		    __func__, MMC_SET_BLOCK_COUNT | HC_CMD_ENABLE,
721 		    sc->sdhci_blockcount);
722 
723 		save_sdarg = RD4(sc, HC_ARGUMENT);
724 		WR4(sc, HC_ARGUMENT, sc->sdhci_blockcount);
725 		WR4(sc, HC_COMMAND, MMC_SET_BLOCK_COUNT | HC_CMD_ENABLE);
726 
727 		/* Seems to always return timeout */
728 
729 		if (bcm_sdhost_waitcommand(sc)) {
730 			printf("%s: timeout #2\n", __func__);
731 			bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
732 		} else {
733 			bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
734 		}
735 		WR4(sc, HC_ARGUMENT, save_sdarg);
736 
737 	} else if (opcode == MMC_SELECT_CARD) {
738 		sc->sdcard_rca = (RD4(sc, HC_ARGUMENT) >> 16);
739 	}
740 
741 	/* actually issuing the command */
742 	WR4(sc, HC_COMMAND, val2);
743 
744 	if (val2 & HC_CMD_READ || val2 & HC_CMD_WRITE) {
745 		u_int8_t hstcfg;
746 
747 		hstcfg = RD4(sc, HC_HOSTCONFIG);
748 		hstcfg |= (HC_HSTCF_INT_BUSY | HC_HSTCF_INT_DATA);
749 		WR4(sc, HC_HOSTCONFIG, hstcfg);
750 		slot->data_done = 0;
751 
752 		if (bcm_sdhost_waitcommand(sc)) {
753 			printf("%s: timeout #3\n", __func__);
754 			bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
755 		}
756 
757 	} else if (opcode == MMC_ERASE) {
758 		if (bcm_sdhost_waitcommand_status(sc) != 0) {
759 			printf("%s: timeout #4\n", __func__);
760 			bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
761 		}
762 		slot->data_done = 1;
763 		sc->sdhci_present_state &=
764 		    ~(SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT);
765 
766 	} else {
767 		if (bcm_sdhost_waitcommand(sc)) {
768 			printf("%s: timeout #5\n", __func__);
769 			bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
770 		}
771 		slot->data_done = 1;
772 		sc->sdhci_present_state &=
773 		    ~(SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT);
774 	}
775 
776 	bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
777 
778 	if (RD4(sc, HC_HOSTSTATUS) & HC_HSTST_TIMEOUT_CMD)
779 		slot->curcmd->error = MMC_ERR_TIMEOUT;
780 	else if (RD4(sc, HC_COMMAND) & HC_CMD_FAILED)
781 		slot->curcmd->error = MMC_ERR_FAILED;
782 
783 	dprintf("%s: curcmd->flags=%d data_done=%d\n",
784 	    __func__, slot->curcmd->flags, slot->data_done);
785 
786 	if (val2 & HC_CMD_RESPONSE_NONE)
787 		slot->curcmd->error = 0;
788 
789 	if (sc->mmc_app_cmd == 1 && opcode != MMC_APP_CMD)
790 		sc->mmc_app_cmd = 0;
791 
792 	if (RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) {
793 		bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
794 		panic("%s: still HC_CMD_ENABLE on exit\n", __func__);
795 	}
796 
797 	sc->cmdbusy = 0;
798 
799 	if (!(val2 & HC_CMD_READ || val2 & HC_CMD_WRITE))
800 		sc->sdhci_int_status |= SDHCI_INT_RESPONSE;
801 
802 	/* HACK, so sdhci_finish_command() does not
803 	 * have to be exported
804 	 */
805 	mtx_unlock(&slot->mtx);
806 	sdhci_generic_intr(slot);
807 	mtx_lock(&slot->mtx);
808 	sc->sdhci_int_status &= ~SDHCI_INT_RESPONSE;
809 }
810 
811 static uint8_t
812 bcm_sdhost_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
813 {
814 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
815 	uint32_t val1, val2;
816 
817 	mtx_lock(&sc->mtx);
818 
819 	switch (off) {
820 	case SDHCI_HOST_CONTROL:
821 		val1 = RD4(sc, HC_HOSTCONFIG);
822 		val2 = 0;
823 		if (val1 & HC_HSTCF_EXTBUS_4BIT)
824 			val2 |= SDHCI_CTRL_4BITBUS;
825 		dprintf("%s: SDHCI_HOST_CONTROL --> HC_HOSTCONFIG val2 %02x\n",
826 		    __func__, val2);
827 		break;
828 	case SDHCI_POWER_CONTROL:
829 		val1 = RD1(sc, HC_POWER);
830 		val2 = (val1 == 1) ? 0x0f : 0;
831 		dprintf("%s: SDHCI_POWER_CONTROL --> HC_POWER     val2 %02x\n",
832 		    __func__, val2);
833 		break;
834 	case SDHCI_BLOCK_GAP_CONTROL:
835 		dprintf("%s: SDHCI_BLOCK_GAP_CONTROL\n", __func__);
836 		val2 = 0;
837 		break;
838 	case SDHCI_WAKE_UP_CONTROL:
839 		dprintf("%s: SDHCI_WAKE_UP_CONTROL\n", __func__);
840 		val2 = 0;
841 		break;
842 	case SDHCI_TIMEOUT_CONTROL:
843 		dprintf("%s: SDHCI_TIMEOUT_CONTROL\n", __func__);
844 		val2 = 0;
845 		break;
846 	case SDHCI_SOFTWARE_RESET:
847 		dprintf("%s: SDHCI_SOFTWARE_RESET\n", __func__);
848 		val2 = 0;
849 		break;
850 	case SDHCI_ADMA_ERR:
851 		dprintf("%s: SDHCI_ADMA_ERR\n", __func__);
852 		val2 = 0;
853 		break;
854 	default:
855 		dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
856 		val2 = 0;
857 		break;
858 	}
859 
860 	mtx_unlock(&sc->mtx);
861 
862 	return (val2);
863 }
864 
865 static uint16_t
866 bcm_sdhost_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
867 {
868 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
869 	uint32_t val2, val; /* = RD4(sc, off & ~3); */
870 
871 	mtx_lock(&sc->mtx);
872 
873 	switch (off) {
874 	case SDHCI_BLOCK_SIZE:
875 		val2 = sc->sdhci_blocksize;
876 		dprintf("%s: SDHCI_BLOCK_SIZE      --> HC_BLOCKSIZE   %08x\n",
877 		    __func__, val2);
878 		break;
879 	case SDHCI_BLOCK_COUNT:
880 		val2 = sc->sdhci_blockcount;
881 		dprintf("%s: SDHCI_BLOCK_COUNT     --> HC_BLOCKCOUNT  %08x\n",
882 		    __func__, val2);
883 		break;
884 	case SDHCI_TRANSFER_MODE:
885 		dprintf("%s: SDHCI_TRANSFER_MODE\n", __func__);
886 		val2 = 0;
887 		break;
888 	case SDHCI_CLOCK_CONTROL:
889 		val = RD4(sc, HC_CLOCKDIVISOR);
890 		val2 = (val << SDHCI_DIVIDER_SHIFT) |
891 		    SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN |
892 		    SDHCI_CLOCK_INT_STABLE;
893 		dprintf("%s: SDHCI_CLOCK_CONTROL     %04x --> %04x\n",
894 		    __func__, val, val2);
895 		break;
896 	case SDHCI_ACMD12_ERR:
897 		dprintf("%s: SDHCI_ACMD12_ERR\n", __func__);
898 		val2 = 0;
899 		break;
900 	case SDHCI_HOST_CONTROL2:
901 		dprintf("%s: SDHCI_HOST_CONTROL2\n", __func__);
902 		val2 = 0;
903 		break;
904 	case SDHCI_SLOT_INT_STATUS:
905 		dprintf("%s: SDHCI_SLOT_INT_STATUS\n", __func__);
906 		val2 = 0;
907 		break;
908 	case SDHCI_HOST_VERSION:
909 		dprintf("%s: SDHCI_HOST_VERSION\n", __func__);
910 		val2 = 0;
911 		break;
912 	default:
913 		dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
914 		val2 = 0;
915 		break;
916 	}
917 
918 	mtx_unlock(&sc->mtx);
919 
920 	return (val2);
921 }
922 
923 static uint32_t
924 bcm_sdhost_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
925 {
926 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
927 	uint32_t val2;
928 
929 	mtx_lock(&sc->mtx);
930 
931 	switch (off) {
932 	case SDHCI_DMA_ADDRESS:
933 		dprintf("%s: SDHCI_DMA_ADDRESS\n", __func__);
934 		val2 = 0;
935 		break;
936 	case SDHCI_ARGUMENT:
937 		dprintf("%s: SDHCI_ARGUMENT\n", __func__);
938 		val2 = (RD4(sc, HC_COMMAND) << 16) |
939 		    (RD4(sc, HC_ARGUMENT) & 0x0000ffff);
940 		break;
941 	case SDHCI_RESPONSE + 0:
942 		val2 = RD4(sc, HC_RESPONSE_0);
943 		dprintf("%s: SDHCI_RESPONSE+0       %08x\n", __func__, val2);
944 		break;
945 	case SDHCI_RESPONSE + 4:
946 		val2 = RD4(sc, HC_RESPONSE_1);
947 		dprintf("%s: SDHCI_RESPONSE+4       %08x\n", __func__, val2);
948 		break;
949 	case SDHCI_RESPONSE + 8:
950 		val2 = RD4(sc, HC_RESPONSE_2);
951 		dprintf("%s: SDHCI_RESPONSE+8       %08x\n", __func__, val2);
952 		break;
953 	case SDHCI_RESPONSE + 12:
954 		val2 = RD4(sc, HC_RESPONSE_3);
955 		dprintf("%s: SDHCI_RESPONSE+12      %08x\n", __func__, val2);
956 		break;
957 	case SDHCI_BUFFER:
958 		dprintf("%s: SDHCI_BUFFER\n", __func__);
959 		val2 = 0;
960 		break;
961 	case SDHCI_PRESENT_STATE:
962 		dprintf("%s: SDHCI_PRESENT_STATE      %08x\n",
963 		    __func__, sc->sdhci_present_state);
964 		val2 = sc->sdhci_present_state;
965 		break;
966 	case SDHCI_INT_STATUS:
967 		dprintf("%s: SDHCI_INT_STATUS        %08x\n",
968 		    __func__, sc->sdhci_int_status);
969 		val2 = sc->sdhci_int_status;
970 		break;
971 	case SDHCI_INT_ENABLE:
972 		dprintf("%s: SDHCI_INT_ENABLE\n", __func__);
973 		val2 = 0;
974 		break;
975 	case SDHCI_SIGNAL_ENABLE:
976 		dprintf("%s: SDHCI_SIGNAL_ENABLE      %08x\n",
977 		    __func__, sc->sdhci_signal_enable);
978 		val2 = sc->sdhci_signal_enable;
979 		break;
980 	case SDHCI_CAPABILITIES:
981 		val2 = 0;
982 		break;
983 	case SDHCI_CAPABILITIES2:
984 		dprintf("%s: SDHCI_CAPABILITIES2\n", __func__);
985 		val2 = 0;
986 		break;
987 	case SDHCI_MAX_CURRENT:
988 		dprintf("%s: SDHCI_MAX_CURRENT\n", __func__);
989 		val2 = 0;
990 		break;
991 	case SDHCI_ADMA_ADDRESS_LO:
992 		dprintf("%s: SDHCI_ADMA_ADDRESS_LO\n", __func__);
993 		val2 = 0;
994 		break;
995 	default:
996 		dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
997 		val2 = 0;
998 		break;
999 	}
1000 
1001 	mtx_unlock(&sc->mtx);
1002 
1003 	return (val2);
1004 }
1005 
1006 static void
1007 bcm_sdhost_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
1008     uint32_t *data, bus_size_t count)
1009 {
1010 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
1011 	bus_size_t i;
1012 	bus_size_t avail;
1013 	uint32_t edm;
1014 
1015 	mtx_lock(&sc->mtx);
1016 
1017 	dprintf("%s: off=%08lx count=%08lx\n", __func__, off, count);
1018 
1019 	for (i = 0; i < count;) {
1020 		edm = RD4(sc, HC_DEBUG);
1021 		avail = ((edm >> 4) & 0x1f);
1022 		if (i + avail > count)
1023 			avail = count - i;
1024 		if (avail > 0)
1025 			bus_space_read_multi_4(sc->sc_bst, sc->sc_bsh,
1026 			    HC_DATAPORT, data + i, avail);
1027 		i += avail;
1028 		DELAY(1);
1029 	}
1030 
1031 	mtx_unlock(&sc->mtx);
1032 }
1033 
1034 static void
1035 bcm_sdhost_write_1(device_t dev, struct sdhci_slot *slot,
1036     bus_size_t off, uint8_t val)
1037 {
1038 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
1039 	uint32_t val2;
1040 
1041 	mtx_lock(&sc->mtx);
1042 
1043 	switch (off) {
1044 	case SDHCI_HOST_CONTROL:
1045 		val2 = RD4(sc, HC_HOSTCONFIG);
1046 		val2 |= HC_HSTCF_INT_BUSY;
1047 		val2 |= HC_HSTCF_INTBUS_WIDE | HC_HSTCF_SLOW_CARD;
1048 		if (val & SDHCI_CTRL_4BITBUS)
1049 			val2 |= HC_HSTCF_EXTBUS_4BIT;
1050 		dprintf("%s: SDHCI_HOST_CONTROL --> HC_HOSTC %04x --> %04x\n",
1051 		    __func__, val, val2);
1052 		WR4(sc, HC_HOSTCONFIG, val2);
1053 		break;
1054 	case SDHCI_POWER_CONTROL:
1055 		val2 = (val != 0) ? 1 : 0;
1056 		dprintf("%s: SDHCI_POWER_CONTROL --> HC_POWER %02x --> %02x\n",
1057 		    __func__, val, val2);
1058 		WR1(sc, HC_POWER, val2);
1059 		break;
1060 	case SDHCI_BLOCK_GAP_CONTROL:
1061 		dprintf("%s: SDHCI_BLOCK_GAP_CONTROL   val=%02x\n",
1062 		    __func__, val);
1063 		break;
1064 	case SDHCI_TIMEOUT_CONTROL:
1065 		dprintf("%s: SDHCI_TIMEOUT_CONTROL     val=%02x\n",
1066 		    __func__, val);
1067 		break;
1068 	case SDHCI_SOFTWARE_RESET:
1069 		dprintf("%s: SDHCI_SOFTWARE_RESET      val=%02x\n",
1070 		    __func__, val);
1071 		break;
1072 	case SDHCI_ADMA_ERR:
1073 		dprintf("%s: SDHCI_ADMA_ERR            val=%02x\n",
1074 		    __func__, val);
1075 		break;
1076 	default:
1077 		dprintf("%s: UNKNOWN off=%08lx val=%08x\n",
1078 		    __func__, off, val);
1079 		break;
1080 	}
1081 
1082 	mtx_unlock(&sc->mtx);
1083 }
1084 
1085 static void
1086 bcm_sdhost_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val)
1087 {
1088 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
1089 	uint16_t val2;
1090 
1091 	mtx_lock(&sc->mtx);
1092 
1093 	switch (off) {
1094 	case SDHCI_BLOCK_SIZE:
1095 		dprintf("%s: SDHCI_BLOCK_SIZE          val=%04x\n" ,
1096 		    __func__, val);
1097 		sc->sdhci_blocksize = val;
1098 		WR2(sc, HC_BLOCKSIZE, val);
1099 		break;
1100 
1101 	case SDHCI_BLOCK_COUNT:
1102 		dprintf("%s: SDHCI_BLOCK_COUNT         val=%04x\n" ,
1103 		    __func__, val);
1104 		sc->sdhci_blockcount = val;
1105 		WR2(sc, HC_BLOCKCOUNT, val);
1106 		break;
1107 
1108 	case SDHCI_TRANSFER_MODE:
1109 		dprintf("%s: SDHCI_TRANSFER_MODE       val=%04x\n" ,
1110 		    __func__, val);
1111 		break;
1112 
1113 	case SDHCI_COMMAND_FLAGS:
1114 		bcm_sdhost_command(dev, slot, val);
1115 		break;
1116 
1117 	case SDHCI_CLOCK_CONTROL:
1118 		val2 = (val & ~SDHCI_DIVIDER_MASK) >> SDHCI_DIVIDER_SHIFT;
1119 		/* get crc16 errors with cdiv=0 */
1120 		if (val2 == 0)
1121 			val2 = 1;
1122 		dprintf("%s: SDHCI_CLOCK_CONTROL       %04x --> SCDIV %04x\n",
1123 		    __func__, val, val2);
1124 		WR4(sc, HC_CLOCKDIVISOR, val2);
1125 		break;
1126 
1127 	case SDHCI_ACMD12_ERR:
1128 		dprintf("%s: SDHCI_ACMD12_ERR          val=%04x\n" ,
1129 		    __func__, val);
1130 		break;
1131 
1132 	case SDHCI_HOST_CONTROL2:
1133 		dprintf("%s: SDHCI_HOST_CONTROL2       val=%04x\n" ,
1134 		    __func__, val);
1135 		break;
1136 
1137 	case SDHCI_SLOT_INT_STATUS:
1138 		dprintf("%s: SDHCI_SLOT_INT_STATUS     val=%04x\n" ,
1139 		    __func__, val);
1140 		break;
1141 
1142 	default:
1143 		dprintf("%s: UNKNOWN off=%08lx val=%04x\n",
1144 		    __func__, off, val);
1145 		break;
1146 	}
1147 
1148 	mtx_unlock(&sc->mtx);
1149 }
1150 
1151 static void
1152 bcm_sdhost_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val)
1153 {
1154 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
1155 	uint32_t val2;
1156 	uint32_t hstcfg;
1157 
1158 	mtx_lock(&sc->mtx);
1159 
1160 	switch (off) {
1161 	case SDHCI_ARGUMENT:
1162 		val2 = val;
1163 		dprintf("%s: SDHCI_ARGUMENT --> HC_ARGUMENT   val=%08x\n",
1164 		    __func__, val);
1165 		WR4(sc, HC_ARGUMENT, val2);
1166 		break;
1167 	case SDHCI_INT_STATUS:
1168 		dprintf("%s: SDHCI_INT_STATUS           val=%08x\n",
1169 		    __func__, val);
1170 		sc->sdhci_int_status = val;
1171 		break;
1172 	case SDHCI_INT_ENABLE:
1173 		dprintf("%s: SDHCI_INT_ENABLE          val=%08x\n" ,
1174 		     __func__, val);
1175 		break;
1176 	case SDHCI_SIGNAL_ENABLE:
1177 		sc->sdhci_signal_enable = val;
1178 		hstcfg = RD4(sc, HC_HOSTCONFIG);
1179 		if (val != 0)
1180 			hstcfg &= ~(HC_HSTCF_INT_BLOCK | HC_HSTCF_INT_DATA);
1181 		else
1182 			hstcfg |= (HC_HSTCF_INT_BUSY|HC_HSTCF_INT_BLOCK|
1183 			         HC_HSTCF_INT_DATA);
1184 		hstcfg |= HC_HSTCF_INT_BUSY;
1185 		dprintf("%s: SDHCI_SIGNAL_ENABLE --> HC_HOSTC %08x --> %08x\n" ,
1186 		    __func__, val, hstcfg);
1187 		WR4(sc, HC_HOSTCONFIG, hstcfg);
1188 		break;
1189 	case SDHCI_CAPABILITIES:
1190 		dprintf("%s: SDHCI_CAPABILITIES        val=%08x\n",
1191 		    __func__, val);
1192 		break;
1193 	case SDHCI_CAPABILITIES2:
1194 		dprintf("%s: SDHCI_CAPABILITIES2       val=%08x\n",
1195 		    __func__, val);
1196 		break;
1197 	case SDHCI_MAX_CURRENT:
1198 		dprintf("%s: SDHCI_MAX_CURRENT         val=%08x\n",
1199 		    __func__, val);
1200 		break;
1201 	case SDHCI_ADMA_ADDRESS_LO:
1202 		dprintf("%s: SDHCI_ADMA_ADDRESS_LO     val=%08x\n",
1203 		    __func__, val);
1204 		break;
1205 	default:
1206 		dprintf("%s: UNKNOWN off=%08lx val=%08x\n",
1207 		    __func__, off, val);
1208 		break;
1209 	}
1210 
1211 	mtx_unlock(&sc->mtx);
1212 }
1213 
1214 static void
1215 bcm_sdhost_write_multi_4(device_t dev, struct sdhci_slot *slot,
1216     bus_size_t off, uint32_t *data, bus_size_t count)
1217 {
1218 	struct bcm_sdhost_softc *sc = device_get_softc(dev);
1219 	bus_size_t i;
1220 	bus_size_t space;
1221 	uint32_t edm;
1222 
1223 	mtx_lock(&sc->mtx);
1224 
1225 	dprintf("%s: off=%08lx count=%02lx\n", __func__, off, count);
1226 
1227 	for (i = 0; i < count;) {
1228 		edm = RD4(sc, HC_DEBUG);
1229 		space = HC_FIFO_SIZE - ((edm >> 4) & 0x1f);
1230 		if (i + space > count)
1231 			space = count - i;
1232 		if (space > 0)
1233 			bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh,
1234 			    HC_DATAPORT, data + i, space);
1235 		i += space;
1236 		DELAY(1);
1237         }
1238 
1239 	/* wait until FIFO is really empty */
1240 	while (((RD4(sc, HC_DEBUG) >> 4) & 0x1f) > 0)
1241 		DELAY(1);
1242 
1243 	mtx_unlock(&sc->mtx);
1244 }
1245 
1246 static device_method_t bcm_sdhost_methods[] = {
1247 	/* Device interface */
1248 	DEVMETHOD(device_probe,		bcm_sdhost_probe),
1249 	DEVMETHOD(device_attach,	bcm_sdhost_attach),
1250 	DEVMETHOD(device_detach,	bcm_sdhost_detach),
1251 
1252 	/* Bus interface */
1253 	DEVMETHOD(bus_read_ivar,	sdhci_generic_read_ivar),
1254 	DEVMETHOD(bus_write_ivar,	sdhci_generic_write_ivar),
1255 
1256 	/* MMC bridge interface */
1257 	DEVMETHOD(mmcbr_update_ios,	sdhci_generic_update_ios),
1258 	DEVMETHOD(mmcbr_request,	sdhci_generic_request),
1259 	DEVMETHOD(mmcbr_get_ro,		bcm_sdhost_get_ro),
1260 	DEVMETHOD(mmcbr_acquire_host,	sdhci_generic_acquire_host),
1261 	DEVMETHOD(mmcbr_release_host,	sdhci_generic_release_host),
1262 
1263 	/* SDHCI registers accessors */
1264 	DEVMETHOD(sdhci_read_1,		bcm_sdhost_read_1),
1265 	DEVMETHOD(sdhci_read_2,		bcm_sdhost_read_2),
1266 	DEVMETHOD(sdhci_read_4,		bcm_sdhost_read_4),
1267 	DEVMETHOD(sdhci_read_multi_4,	bcm_sdhost_read_multi_4),
1268 	DEVMETHOD(sdhci_write_1,	bcm_sdhost_write_1),
1269 	DEVMETHOD(sdhci_write_2,	bcm_sdhost_write_2),
1270 	DEVMETHOD(sdhci_write_4,	bcm_sdhost_write_4),
1271 	DEVMETHOD(sdhci_write_multi_4,	bcm_sdhost_write_multi_4),
1272 	DEVMETHOD(sdhci_get_card_present,bcm_sdhost_get_card_present),
1273 
1274 	DEVMETHOD_END
1275 };
1276 
1277 static driver_t bcm_sdhost_driver = {
1278 	"sdhost_bcm",
1279 	bcm_sdhost_methods,
1280 	sizeof(struct bcm_sdhost_softc),
1281 };
1282 
1283 DRIVER_MODULE(sdhost_bcm, simplebus, bcm_sdhost_driver, NULL, NULL);
1284 SDHCI_DEPEND(sdhost_bcm);
1285 #ifndef MMCCAM
1286 MMC_DECLARE_BRIDGE(sdhost_bcm);
1287 #endif
1288