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