2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2018 Klaus P. Ohrhallinger <k@7he.at>
7 * Based on bcm2835_sdhci.c:
8 * Copyright (c) 2012 Oleksandr Tymoshenko <gonzo@freebsd.org>
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
37 * pin 48-53 - card slot
38 * pin 34-39 - radio module
40 * alt-0 - rubbish SDHCI (0x7e202000) aka sdhost
41 * alt-3 - advanced SDHCI (0x7e300000) aka sdhci/mmc/sdio
43 * driving card slot with mmc:
46 * brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>;
47 * brcm,function = <0x7>;
48 * brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
52 * brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>;
53 * brcm,function = <0x4>;
54 * brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
58 * driving card slot with sdhost:
61 * brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>;
62 * brcm,function = <0x4>;
63 * brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
67 * brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>;
68 * brcm,function = <0x7>;
69 * brcm,pull = <0x0 0x2 0x2 0x2 0x2 0x2>;
75 #include <sys/param.h>
76 #include <sys/systm.h>
79 #include <sys/kernel.h>
81 #include <sys/malloc.h>
82 #include <sys/module.h>
83 #include <sys/mutex.h>
85 #include <sys/sysctl.h>
86 #include <sys/taskqueue.h>
89 #include <machine/bus.h>
91 #include <dev/ofw/ofw_bus.h>
92 #include <dev/ofw/ofw_bus_subr.h>
94 #include <dev/mmc/bridge.h>
95 #include <dev/mmc/mmcreg.h>
97 #include <dev/sdhci/sdhci.h>
100 #include "sdhci_if.h"
102 #include "opt_mmccam.h"
104 #include "bcm2835_dma.h"
105 #include <arm/broadcom/bcm2835/bcm2835_mbox_prop.h>
106 #include "bcm2835_vcbus.h"
109 /* #define SDHOST_DEBUG */
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
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
139 #define HC_CLOCKDIVISOR_MAXVAL 0x07ff
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
151 #define HC_HSTST_RESET 0xffff
153 #define HC_HSTST_MASK_ERROR_DATA (HC_HSTST_ERROR_FIFO | \
154 HC_HSTST_ERROR_CRC7 | HC_HSTST_ERROR_CRC16 | HC_HSTST_TIMEOUT_DATA)
156 #define HC_HSTST_MASK_ERROR_ALL (HC_HSTST_MASK_ERROR_DATA | \
157 HC_HSTST_TIMEOUT_CMD)
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
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
173 #define HC_FIFO_SIZE 16
174 #define HC_FIFO_THRESH_READ 4
175 #define HC_FIFO_THRESH_WRITE 4
177 #define HC_TIMEOUT_DEFAULT 0x00f00000
179 #define BCM2835_DEFAULT_SDHCI_FREQ 50
181 static int bcm2835_sdhost_debug = 0;
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");
189 #define dprintf(fmt, args...) \
191 if (bcm2835_sdhost_debug > 0) \
192 printf(fmt,##args); \
196 #define dprintf(fmt, args...)
198 #endif /* ! SDHOST_DEBUG */
200 static struct ofw_compat_data compat_data[] = {
201 {"brcm,bcm2835-sdhost", 1},
205 struct bcm_sdhost_softc {
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;
212 struct mmc_request * sc_req;
213 struct sdhci_slot sc_slot;
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;
226 u_int32_t sdcard_rca;
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 *);
234 static int bcm_sdhost_get_ro(device_t, device_t);
237 static inline uint32_t
238 RD4(struct bcm_sdhost_softc *sc, bus_size_t off)
242 val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off);
248 WR4(struct bcm_sdhost_softc *sc, bus_size_t off, uint32_t val)
251 bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val);
254 static inline uint16_t
255 RD2(struct bcm_sdhost_softc *sc, bus_size_t off)
259 val = RD4(sc, off & ~3);
261 return ((val >> (off & 3)*8) & 0xffff);
264 static inline uint8_t
265 RD1(struct bcm_sdhost_softc *sc, bus_size_t off)
269 val = RD4(sc, off & ~3);
271 return ((val >> (off & 3)*8) & 0xff);
275 WR2(struct bcm_sdhost_softc *sc, bus_size_t off, uint16_t val)
279 val32 = RD4(sc, off & ~3);
280 val32 &= ~(0xffff << (off & 3)*8);
281 val32 |= (val << (off & 3)*8);
282 WR4(sc, off & ~3, val32);
286 WR1(struct bcm_sdhost_softc *sc, bus_size_t off, uint8_t val)
290 val32 = RD4(sc, off & ~3);
291 val32 &= ~(0xff << (off & 3)*8);
292 val32 |= (val << (off & 3)*8);
293 WR4(sc, off & ~3, val32);
297 bcm_sdhost_print_regs(struct bcm_sdhost_softc *sc, struct sdhci_slot *slot,
301 if (bcm2835_sdhost_debug > 0 || error > 0) {
303 printf("%s: sc=%p slot=%p\n",
305 printf("HC_COMMAND: 0x%08x\n",
306 RD4(sc, HC_COMMAND));
307 printf("HC_ARGUMENT: 0x%08x\n",
308 RD4(sc, HC_ARGUMENT));
309 printf("HC_TIMEOUTCOUNTER: 0x%08x\n",
310 RD4(sc, HC_TIMEOUTCOUNTER));
311 printf("HC_CLOCKDIVISOR: 0x%08x\n",
312 RD4(sc, HC_CLOCKDIVISOR));
313 printf("HC_RESPONSE_0: 0x%08x\n",
314 RD4(sc, HC_RESPONSE_0));
315 printf("HC_RESPONSE_1: 0x%08x\n",
316 RD4(sc, HC_RESPONSE_1));
317 printf("HC_RESPONSE_2: 0x%08x\n",
318 RD4(sc, HC_RESPONSE_2));
319 printf("HC_RESPONSE_3: 0x%08x\n",
320 RD4(sc, HC_RESPONSE_3));
321 printf("HC_HOSTSTATUS: 0x%08x\n",
322 RD4(sc, HC_HOSTSTATUS));
323 printf("HC_POWER: 0x%08x\n",
325 printf("HC_DEBUG: 0x%08x\n",
327 printf("HC_HOSTCONFIG: 0x%08x\n",
328 RD4(sc, HC_HOSTCONFIG));
329 printf("HC_BLOCKSIZE: 0x%08x\n",
330 RD4(sc, HC_BLOCKSIZE));
331 printf("HC_BLOCKCOUNT: 0x%08x\n",
332 RD4(sc, HC_BLOCKCOUNT));
337 printf("%04d | HC_COMMAND: 0x%08x HC_ARGUMENT: 0x%08x "
338 "HC_HOSTSTATUS: 0x%08x HC_HOSTCONFIG: 0x%08x\n",
339 line, RD4(sc, HC_COMMAND), RD4(sc, HC_ARGUMENT),
340 RD4(sc, HC_HOSTSTATUS), RD4(sc, HC_HOSTCONFIG));
346 bcm_sdhost_reset(device_t dev, struct sdhci_slot *slot)
348 struct bcm_sdhost_softc *sc = device_get_softc(dev);
351 WR4(sc, HC_POWER, 0);
353 WR4(sc, HC_COMMAND, 0);
354 WR4(sc, HC_ARGUMENT, 0);
355 WR4(sc, HC_TIMEOUTCOUNTER, HC_TIMEOUT_DEFAULT);
356 WR4(sc, HC_CLOCKDIVISOR, 0);
357 WR4(sc, HC_HOSTSTATUS, HC_HSTST_RESET);
358 WR4(sc, HC_HOSTCONFIG, 0);
359 WR4(sc, HC_BLOCKSIZE, 0);
360 WR4(sc, HC_BLOCKCOUNT, 0);
362 dbg = RD4(sc, HC_DEBUG);
363 dbg &= ~( (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_READ_SHIFT) |
364 (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_WRITE_SHIFT) );
365 dbg |= (HC_FIFO_THRESH_READ << HC_DBG_FIFO_THRESH_READ_SHIFT) |
366 (HC_FIFO_THRESH_WRITE << HC_DBG_FIFO_THRESH_WRITE_SHIFT);
367 WR4(sc, HC_DEBUG, dbg);
371 WR4(sc, HC_POWER, 1);
375 sc->sdhci_present_state = SDHCI_CARD_PRESENT | SDHCI_CARD_STABLE |
378 WR4(sc, HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_MAXVAL);
379 WR4(sc, HC_HOSTCONFIG, HC_HSTCF_INT_BUSY);
383 bcm_sdhost_probe(device_t dev)
386 dprintf("%s:\n", __func__);
388 if (!ofw_bus_status_okay(dev))
391 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
394 device_set_desc(dev, "Broadcom 2708 SDHOST controller");
396 return (BUS_PROBE_DEFAULT);
400 bcm_sdhost_attach(device_t dev)
402 struct bcm_sdhost_softc *sc = device_get_softc(dev);
406 dprintf("%s: dev=%p sc=%p unit=%d\n",
407 __func__, dev, sc, device_get_unit(dev));
409 mtx_init(&sc->mtx, "BCM SDHOST mtx", "bcm_sdhost",
410 MTX_DEF | MTX_RECURSE);
417 sc->sdhci_int_status = 0;
418 sc->sdhci_signal_enable = 0;
419 sc->sdhci_present_state = 0;
420 sc->sdhci_blocksize = 0;
421 sc->sdhci_blockcount = 0;
429 device_printf(dev, "SDHCI frequency: %dMHz\n", default_freq);
432 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
434 if (!sc->sc_mem_res) {
435 device_printf(dev, "cannot allocate memory window\n");
440 sc->sc_bst = rman_get_bustag(sc->sc_mem_res);
441 sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res);
443 bcm_sdhost_reset(dev, &sc->sc_slot);
445 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
448 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
450 if (!sc->sc_irq_res) {
451 device_printf(dev, "cannot allocate interrupt\n");
456 if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
457 NULL, bcm_sdhost_intr, sc, &sc->sc_intrhand)) {
458 device_printf(dev, "cannot setup interrupt handler\n");
463 sc->sc_slot.caps = 0;
464 sc->sc_slot.caps |= SDHCI_CAN_VDD_330;
465 sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD;
466 sc->sc_slot.caps |= (default_freq << SDHCI_CLOCK_BASE_SHIFT);
468 sc->sc_slot.quirks = 0;
469 sc->sc_slot.quirks |= SDHCI_QUIRK_MISSING_CAPS;
470 sc->sc_slot.quirks |= SDHCI_QUIRK_DONT_SHIFT_RESPONSE;
475 sc->slot->timeout_clk = ...;
478 sdhci_init_slot(dev, &sc->sc_slot, 0);
480 bus_generic_probe(dev);
481 bus_generic_attach(dev);
483 sdhci_start_slot(&sc->sc_slot);
489 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand);
491 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res);
493 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res);
499 bcm_sdhost_detach(device_t dev)
502 dprintf("%s:\n", __func__);
508 * rv 0 --> command finished
509 * rv 1 --> command timed out
512 bcm_sdhost_waitcommand(struct bcm_sdhost_softc *sc)
516 mtx_assert(&sc->mtx, MA_OWNED);
518 while ((RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) && --timeout > 0) {
522 return ((timeout > 0) ? 0 : 1);
526 bcm_sdhost_waitcommand_status(struct bcm_sdhost_softc *sc)
531 /* wait for card to change status from
533 * card status: sd specs p. 103
538 WR4(sc, HC_ARGUMENT, sc->sdcard_rca << 16);
540 MMC_SEND_STATUS | HC_CMD_ENABLE);
541 bcm_sdhost_waitcommand(sc);
542 cdst = RD4(sc, HC_RESPONSE_0);
543 dprintf("%s: card status %08x (cs %d)\n",
544 __func__, cdst, (cdst & 0x0e00) >> 9);
546 printf("%s: giving up, "
547 "card status %08x (cs %d)\n",
549 (cdst & 0x0e00) >> 9);
553 } while (((cdst & 0x0e00) >> 9) != 4);
559 bcm_sdhost_intr(void *arg)
561 struct bcm_sdhost_softc *sc = arg;
562 struct sdhci_slot *slot = &sc->sc_slot;
568 hstst = RD4(sc, HC_HOSTSTATUS);
569 cmd = RD4(sc, HC_COMMAND);
570 if (hstst & HC_HSTST_HAVEDATA) {
571 if (cmd & HC_CMD_READ) {
572 sc->sdhci_present_state |= SDHCI_DATA_AVAILABLE;
573 sc->sdhci_int_status |= SDHCI_INT_DATA_AVAIL;
574 } else if (cmd & HC_CMD_WRITE) {
575 sc->sdhci_present_state |= SDHCI_SPACE_AVAILABLE;
576 sc->sdhci_int_status |= SDHCI_INT_SPACE_AVAIL;
578 panic("%s: hstst & HC_HSTST_HAVEDATA but no "
579 "HC_CMD_READ or HC_CMD_WRITE: cmd=%0x8 "
580 "hstst=%08x\n", __func__, cmd, hstst);
583 sc->sdhci_present_state &=
584 ~(SDHCI_DATA_AVAILABLE|SDHCI_SPACE_AVAILABLE);
585 sc->sdhci_int_status &=
586 ~(SDHCI_INT_DATA_AVAIL|SDHCI_INT_SPACE_AVAIL);
589 if (hstst & HC_HSTST_MASK_ERROR_ALL) {
590 printf("%s: ERROR: HC_HOSTSTATUS: %08x\n", __func__, hstst);
591 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
592 sc->sdhci_int_status |= SDHCI_INT_ERROR;
594 sc->sdhci_int_status &= ~SDHCI_INT_ERROR;
597 dprintf("%s: hstst=%08x offset=%08lx sdhci_present_state=%08x "
598 "sdhci_int_status=%08x\n", __func__, hstst, slot->offset,
599 sc->sdhci_present_state, sc->sdhci_int_status);
601 sdhci_generic_intr(&sc->sc_slot);
603 sc->sdhci_int_status &=
604 ~(SDHCI_INT_ERROR|SDHCI_INT_DATA_AVAIL|SDHCI_INT_DATA_END);
605 sc->sdhci_present_state &= ~SDHCI_DATA_AVAILABLE;
607 if ((hstst & HC_HSTST_HAVEDATA) &&
608 (sc->sdhci_blocksize * sc->sdhci_blockcount == slot->offset)) {
609 dprintf("%s: offset=%08lx sdhci_blocksize=%08x "
610 "sdhci_blockcount=%08x\n", __func__, slot->offset,
611 sc->sdhci_blocksize, sc->sdhci_blockcount);
612 sc->sdhci_int_status &=
613 ~(SDHCI_INT_DATA_AVAIL|SDHCI_INT_SPACE_AVAIL);
614 sc->sdhci_int_status |= SDHCI_INT_DATA_END;
615 sdhci_generic_intr(&sc->sc_slot);
616 sc->sdhci_int_status &= ~SDHCI_INT_DATA_END;
618 if ((cmd & HC_CMD_COMMAND_MASK) == MMC_READ_MULTIPLE_BLOCK ||
619 (cmd & HC_CMD_COMMAND_MASK) == MMC_WRITE_MULTIPLE_BLOCK) {
620 WR4(sc, HC_ARGUMENT, 0x00000000);
622 MMC_STOP_TRANSMISSION | HC_CMD_ENABLE);
624 if (bcm_sdhost_waitcommand(sc)) {
625 printf("%s: timeout #1\n", __func__);
626 bcm_sdhost_print_regs(sc, &sc->sc_slot,
631 if (cmd & HC_CMD_WRITE) {
632 if (bcm_sdhost_waitcommand_status(sc) != 0)
633 sc->sdhci_int_status |= SDHCI_INT_ERROR;
638 sc->sdhci_int_status |= SDHCI_INT_RESPONSE;
639 sdhci_generic_intr(&sc->sc_slot);
640 sc->sdhci_int_status &= ~(SDHCI_INT_RESPONSE|SDHCI_INT_ERROR);
643 /* this resets the interrupt */
644 WR4(sc, HC_HOSTSTATUS,
645 (HC_HSTST_INT_BUSY|HC_HSTST_INT_BLOCK|HC_HSTST_HAVEDATA));
647 mtx_unlock(&sc->mtx);
651 bcm_sdhost_get_ro(device_t bus, device_t child)
654 dprintf("%s:\n", __func__);
660 bcm_sdhost_get_card_present(device_t dev, struct sdhci_slot *slot)
663 dprintf("%s:\n", __func__);
669 bcm_sdhost_command(device_t dev, struct sdhci_slot *slot, uint16_t val)
671 struct bcm_sdhost_softc *sc = device_get_softc(dev);
672 struct mmc_data *data = slot->curcmd->data;
677 mtx_assert(&sc->mtx, MA_OWNED);
679 if (RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) {
680 panic("%s: HC_CMD_ENABLE on entry\n", __func__);
683 if (sc->cmdbusy == 1)
684 panic("%s: cmdbusy\n", __func__);
688 val2 = ((val >> 8) & HC_CMD_COMMAND_MASK) | HC_CMD_ENABLE;
693 if (opcode == MMC_APP_CMD)
696 if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_LONG)
697 val2 |= HC_CMD_RESPONSE_LONG;
698 else if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT_BUSY)
699 /* XXX XXX when enabled, cmd 7 (select card) blocks forever */
700 ;/*val2 |= HC_CMD_BUSY; */
701 else if ((flags & SDHCI_CMD_RESP_MASK) == SDHCI_CMD_RESP_SHORT)
704 val2 |= HC_CMD_RESPONSE_NONE;
706 if (val2 & HC_CMD_BUSY)
707 sc->sdhci_present_state |=
708 SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT;
710 if (data != NULL && data->flags & MMC_DATA_READ)
712 else if (data != NULL && data->flags & MMC_DATA_WRITE)
713 val2 |= HC_CMD_WRITE;
715 dprintf("%s: SDHCI_COMMAND_FLAGS --> HC_COMMAND %04x --> %04x\n",
716 __func__, val, val2);
718 if (opcode == MMC_READ_MULTIPLE_BLOCK ||
719 opcode == MMC_WRITE_MULTIPLE_BLOCK) {
720 u_int32_t save_sdarg;
722 dprintf("%s: issuing MMC_SET_BLOCK_COUNT: CMD %08x ARG %08x\n",
723 __func__, MMC_SET_BLOCK_COUNT | HC_CMD_ENABLE,
724 sc->sdhci_blockcount);
726 save_sdarg = RD4(sc, HC_ARGUMENT);
727 WR4(sc, HC_ARGUMENT, sc->sdhci_blockcount);
728 WR4(sc, HC_COMMAND, MMC_SET_BLOCK_COUNT | HC_CMD_ENABLE);
730 /* Seems to always return timeout */
732 if (bcm_sdhost_waitcommand(sc)) {
733 printf("%s: timeout #2\n", __func__);
734 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
736 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
738 WR4(sc, HC_ARGUMENT, save_sdarg);
740 } else if (opcode == MMC_SELECT_CARD) {
741 sc->sdcard_rca = (RD4(sc, HC_ARGUMENT) >> 16);
744 /* actually issuing the command */
745 WR4(sc, HC_COMMAND, val2);
747 if (val2 & HC_CMD_READ || val2 & HC_CMD_WRITE) {
750 hstcfg = RD4(sc, HC_HOSTCONFIG);
751 hstcfg |= (HC_HSTCF_INT_BUSY | HC_HSTCF_INT_DATA);
752 WR4(sc, HC_HOSTCONFIG, hstcfg);
755 if (bcm_sdhost_waitcommand(sc)) {
756 printf("%s: timeout #3\n", __func__);
757 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
760 } else if (opcode == MMC_ERASE) {
761 if (bcm_sdhost_waitcommand_status(sc) != 0) {
762 printf("%s: timeout #4\n", __func__);
763 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
766 sc->sdhci_present_state &=
767 ~(SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT);
770 if (bcm_sdhost_waitcommand(sc)) {
771 printf("%s: timeout #5\n", __func__);
772 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
775 sc->sdhci_present_state &=
776 ~(SDHCI_CMD_INHIBIT | SDHCI_DAT_INHIBIT);
779 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 0);
781 if (RD4(sc, HC_HOSTSTATUS) & HC_HSTST_TIMEOUT_CMD)
782 slot->curcmd->error = MMC_ERR_TIMEOUT;
783 else if (RD4(sc, HC_COMMAND) & HC_CMD_FAILED)
784 slot->curcmd->error = MMC_ERR_FAILED;
786 dprintf("%s: curcmd->flags=%d data_done=%d\n",
787 __func__, slot->curcmd->flags, slot->data_done);
789 if (val2 & HC_CMD_RESPONSE_NONE)
790 slot->curcmd->error = 0;
792 if (sc->mmc_app_cmd == 1 && opcode != MMC_APP_CMD)
795 if (RD4(sc, HC_COMMAND) & HC_CMD_ENABLE) {
796 bcm_sdhost_print_regs(sc, &sc->sc_slot, __LINE__, 1);
797 panic("%s: still HC_CMD_ENABLE on exit\n", __func__);
802 if (!(val2 & HC_CMD_READ || val2 & HC_CMD_WRITE))
803 sc->sdhci_int_status |= SDHCI_INT_RESPONSE;
805 /* HACK, so sdhci_finish_command() does not
806 * have to be exported
808 mtx_unlock(&slot->mtx);
809 sdhci_generic_intr(slot);
810 mtx_lock(&slot->mtx);
811 sc->sdhci_int_status &= ~SDHCI_INT_RESPONSE;
815 bcm_sdhost_read_1(device_t dev, struct sdhci_slot *slot, bus_size_t off)
817 struct bcm_sdhost_softc *sc = device_get_softc(dev);
823 case SDHCI_HOST_CONTROL:
824 val1 = RD4(sc, HC_HOSTCONFIG);
826 if (val1 & HC_HSTCF_EXTBUS_4BIT)
827 val2 |= SDHCI_CTRL_4BITBUS;
828 dprintf("%s: SDHCI_HOST_CONTROL --> HC_HOSTCONFIG val2 %02x\n",
831 case SDHCI_POWER_CONTROL:
832 val1 = RD1(sc, HC_POWER);
833 val2 = (val1 == 1) ? 0x0f : 0;
834 dprintf("%s: SDHCI_POWER_CONTROL --> HC_POWER val2 %02x\n",
837 case SDHCI_BLOCK_GAP_CONTROL:
838 dprintf("%s: SDHCI_BLOCK_GAP_CONTROL\n", __func__);
841 case SDHCI_WAKE_UP_CONTROL:
842 dprintf("%s: SDHCI_WAKE_UP_CONTROL\n", __func__);
845 case SDHCI_TIMEOUT_CONTROL:
846 dprintf("%s: SDHCI_TIMEOUT_CONTROL\n", __func__);
849 case SDHCI_SOFTWARE_RESET:
850 dprintf("%s: SDHCI_SOFTWARE_RESET\n", __func__);
854 dprintf("%s: SDHCI_ADMA_ERR\n", __func__);
858 dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
863 mtx_unlock(&sc->mtx);
869 bcm_sdhost_read_2(device_t dev, struct sdhci_slot *slot, bus_size_t off)
871 struct bcm_sdhost_softc *sc = device_get_softc(dev);
872 uint32_t val2, val; /* = RD4(sc, off & ~3); */
877 case SDHCI_BLOCK_SIZE:
878 val2 = sc->sdhci_blocksize;
879 dprintf("%s: SDHCI_BLOCK_SIZE --> HC_BLOCKSIZE %08x\n",
882 case SDHCI_BLOCK_COUNT:
883 val2 = sc->sdhci_blockcount;
884 dprintf("%s: SDHCI_BLOCK_COUNT --> HC_BLOCKCOUNT %08x\n",
887 case SDHCI_TRANSFER_MODE:
888 dprintf("%s: SDHCI_TRANSFER_MODE\n", __func__);
891 case SDHCI_CLOCK_CONTROL:
892 val = RD4(sc, HC_CLOCKDIVISOR);
893 val2 = (val << SDHCI_DIVIDER_SHIFT) |
894 SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_INT_EN |
895 SDHCI_CLOCK_INT_STABLE;
896 dprintf("%s: SDHCI_CLOCK_CONTROL %04x --> %04x\n",
897 __func__, val, val2);
899 case SDHCI_ACMD12_ERR:
900 dprintf("%s: SDHCI_ACMD12_ERR\n", __func__);
903 case SDHCI_HOST_CONTROL2:
904 dprintf("%s: SDHCI_HOST_CONTROL2\n", __func__);
907 case SDHCI_SLOT_INT_STATUS:
908 dprintf("%s: SDHCI_SLOT_INT_STATUS\n", __func__);
911 case SDHCI_HOST_VERSION:
912 dprintf("%s: SDHCI_HOST_VERSION\n", __func__);
916 dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
921 mtx_unlock(&sc->mtx);
927 bcm_sdhost_read_4(device_t dev, struct sdhci_slot *slot, bus_size_t off)
929 struct bcm_sdhost_softc *sc = device_get_softc(dev);
935 case SDHCI_DMA_ADDRESS:
936 dprintf("%s: SDHCI_DMA_ADDRESS\n", __func__);
940 dprintf("%s: SDHCI_ARGUMENT\n", __func__);
941 val2 = (RD4(sc, HC_COMMAND) << 16) |
942 (RD4(sc, HC_ARGUMENT) & 0x0000ffff);
944 case SDHCI_RESPONSE + 0:
945 val2 = RD4(sc, HC_RESPONSE_0);
946 dprintf("%s: SDHCI_RESPONSE+0 %08x\n", __func__, val2);
948 case SDHCI_RESPONSE + 4:
949 val2 = RD4(sc, HC_RESPONSE_1);
950 dprintf("%s: SDHCI_RESPONSE+4 %08x\n", __func__, val2);
952 case SDHCI_RESPONSE + 8:
953 val2 = RD4(sc, HC_RESPONSE_2);
954 dprintf("%s: SDHCI_RESPONSE+8 %08x\n", __func__, val2);
956 case SDHCI_RESPONSE + 12:
957 val2 = RD4(sc, HC_RESPONSE_3);
958 dprintf("%s: SDHCI_RESPONSE+12 %08x\n", __func__, val2);
961 dprintf("%s: SDHCI_BUFFER\n", __func__);
964 case SDHCI_PRESENT_STATE:
965 dprintf("%s: SDHCI_PRESENT_STATE %08x\n",
966 __func__, sc->sdhci_present_state);
967 val2 = sc->sdhci_present_state;
969 case SDHCI_INT_STATUS:
970 dprintf("%s: SDHCI_INT_STATUS %08x\n",
971 __func__, sc->sdhci_int_status);
972 val2 = sc->sdhci_int_status;
974 case SDHCI_INT_ENABLE:
975 dprintf("%s: SDHCI_INT_ENABLE\n", __func__);
978 case SDHCI_SIGNAL_ENABLE:
979 dprintf("%s: SDHCI_SIGNAL_ENABLE %08x\n",
980 __func__, sc->sdhci_signal_enable);
981 val2 = sc->sdhci_signal_enable;
983 case SDHCI_CAPABILITIES:
986 case SDHCI_CAPABILITIES2:
987 dprintf("%s: SDHCI_CAPABILITIES2\n", __func__);
990 case SDHCI_MAX_CURRENT:
991 dprintf("%s: SDHCI_MAX_CURRENT\n", __func__);
994 case SDHCI_ADMA_ADDRESS_LO:
995 dprintf("%s: SDHCI_ADMA_ADDRESS_LO\n", __func__);
999 dprintf("%s: UNKNOWN off=%08lx\n", __func__, off);
1004 mtx_unlock(&sc->mtx);
1010 bcm_sdhost_read_multi_4(device_t dev, struct sdhci_slot *slot, bus_size_t off,
1011 uint32_t *data, bus_size_t count)
1013 struct bcm_sdhost_softc *sc = device_get_softc(dev);
1020 dprintf("%s: off=%08lx count=%08lx\n", __func__, off, count);
1022 for (i = 0; i < count;) {
1023 edm = RD4(sc, HC_DEBUG);
1024 avail = ((edm >> 4) & 0x1f);
1025 if (i + avail > count)
1028 bus_space_read_multi_4(sc->sc_bst, sc->sc_bsh,
1029 HC_DATAPORT, data + i, avail);
1034 mtx_unlock(&sc->mtx);
1038 bcm_sdhost_write_1(device_t dev, struct sdhci_slot *slot,
1039 bus_size_t off, uint8_t val)
1041 struct bcm_sdhost_softc *sc = device_get_softc(dev);
1047 case SDHCI_HOST_CONTROL:
1048 val2 = RD4(sc, HC_HOSTCONFIG);
1049 val2 |= HC_HSTCF_INT_BUSY;
1050 val2 |= HC_HSTCF_INTBUS_WIDE | HC_HSTCF_SLOW_CARD;
1051 if (val & SDHCI_CTRL_4BITBUS)
1052 val2 |= HC_HSTCF_EXTBUS_4BIT;
1053 dprintf("%s: SDHCI_HOST_CONTROL --> HC_HOSTC %04x --> %04x\n",
1054 __func__, val, val2);
1055 WR4(sc, HC_HOSTCONFIG, val2);
1057 case SDHCI_POWER_CONTROL:
1058 val2 = (val != 0) ? 1 : 0;
1059 dprintf("%s: SDHCI_POWER_CONTROL --> HC_POWER %02x --> %02x\n",
1060 __func__, val, val2);
1061 WR1(sc, HC_POWER, val2);
1063 case SDHCI_BLOCK_GAP_CONTROL:
1064 dprintf("%s: SDHCI_BLOCK_GAP_CONTROL val=%02x\n",
1067 case SDHCI_TIMEOUT_CONTROL:
1068 dprintf("%s: SDHCI_TIMEOUT_CONTROL val=%02x\n",
1071 case SDHCI_SOFTWARE_RESET:
1072 dprintf("%s: SDHCI_SOFTWARE_RESET val=%02x\n",
1075 case SDHCI_ADMA_ERR:
1076 dprintf("%s: SDHCI_ADMA_ERR val=%02x\n",
1080 dprintf("%s: UNKNOWN off=%08lx val=%08x\n",
1081 __func__, off, val);
1085 mtx_unlock(&sc->mtx);
1089 bcm_sdhost_write_2(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint16_t val)
1091 struct bcm_sdhost_softc *sc = device_get_softc(dev);
1097 case SDHCI_BLOCK_SIZE:
1098 dprintf("%s: SDHCI_BLOCK_SIZE val=%04x\n" ,
1100 sc->sdhci_blocksize = val;
1101 WR2(sc, HC_BLOCKSIZE, val);
1104 case SDHCI_BLOCK_COUNT:
1105 dprintf("%s: SDHCI_BLOCK_COUNT val=%04x\n" ,
1107 sc->sdhci_blockcount = val;
1108 WR2(sc, HC_BLOCKCOUNT, val);
1111 case SDHCI_TRANSFER_MODE:
1112 dprintf("%s: SDHCI_TRANSFER_MODE val=%04x\n" ,
1116 case SDHCI_COMMAND_FLAGS:
1117 bcm_sdhost_command(dev, slot, val);
1120 case SDHCI_CLOCK_CONTROL:
1121 val2 = (val & ~SDHCI_DIVIDER_MASK) >> SDHCI_DIVIDER_SHIFT;
1122 /* get crc16 errors with cdiv=0 */
1125 dprintf("%s: SDHCI_CLOCK_CONTROL %04x --> SCDIV %04x\n",
1126 __func__, val, val2);
1127 WR4(sc, HC_CLOCKDIVISOR, val2);
1130 case SDHCI_ACMD12_ERR:
1131 dprintf("%s: SDHCI_ACMD12_ERR val=%04x\n" ,
1135 case SDHCI_HOST_CONTROL2:
1136 dprintf("%s: SDHCI_HOST_CONTROL2 val=%04x\n" ,
1140 case SDHCI_SLOT_INT_STATUS:
1141 dprintf("%s: SDHCI_SLOT_INT_STATUS val=%04x\n" ,
1146 dprintf("%s: UNKNOWN off=%08lx val=%04x\n",
1147 __func__, off, val);
1151 mtx_unlock(&sc->mtx);
1155 bcm_sdhost_write_4(device_t dev, struct sdhci_slot *slot, bus_size_t off, uint32_t val)
1157 struct bcm_sdhost_softc *sc = device_get_softc(dev);
1164 case SDHCI_ARGUMENT:
1166 dprintf("%s: SDHCI_ARGUMENT --> HC_ARGUMENT val=%08x\n",
1168 WR4(sc, HC_ARGUMENT, val2);
1170 case SDHCI_INT_STATUS:
1171 dprintf("%s: SDHCI_INT_STATUS val=%08x\n",
1173 sc->sdhci_int_status = val;
1175 case SDHCI_INT_ENABLE:
1176 dprintf("%s: SDHCI_INT_ENABLE val=%08x\n" ,
1179 case SDHCI_SIGNAL_ENABLE:
1180 sc->sdhci_signal_enable = val;
1181 hstcfg = RD4(sc, HC_HOSTCONFIG);
1183 hstcfg &= ~(HC_HSTCF_INT_BLOCK | HC_HSTCF_INT_DATA);
1185 hstcfg |= (HC_HSTCF_INT_BUSY|HC_HSTCF_INT_BLOCK|
1187 hstcfg |= HC_HSTCF_INT_BUSY;
1188 dprintf("%s: SDHCI_SIGNAL_ENABLE --> HC_HOSTC %08x --> %08x\n" ,
1189 __func__, val, hstcfg);
1190 WR4(sc, HC_HOSTCONFIG, hstcfg);
1192 case SDHCI_CAPABILITIES:
1193 dprintf("%s: SDHCI_CAPABILITIES val=%08x\n",
1196 case SDHCI_CAPABILITIES2:
1197 dprintf("%s: SDHCI_CAPABILITIES2 val=%08x\n",
1200 case SDHCI_MAX_CURRENT:
1201 dprintf("%s: SDHCI_MAX_CURRENT val=%08x\n",
1204 case SDHCI_ADMA_ADDRESS_LO:
1205 dprintf("%s: SDHCI_ADMA_ADDRESS_LO val=%08x\n",
1209 dprintf("%s: UNKNOWN off=%08lx val=%08x\n",
1210 __func__, off, val);
1214 mtx_unlock(&sc->mtx);
1218 bcm_sdhost_write_multi_4(device_t dev, struct sdhci_slot *slot,
1219 bus_size_t off, uint32_t *data, bus_size_t count)
1221 struct bcm_sdhost_softc *sc = device_get_softc(dev);
1228 dprintf("%s: off=%08lx count=%02lx\n", __func__, off, count);
1230 for (i = 0; i < count;) {
1231 edm = RD4(sc, HC_DEBUG);
1232 space = HC_FIFO_SIZE - ((edm >> 4) & 0x1f);
1233 if (i + space > count)
1236 bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh,
1237 HC_DATAPORT, data + i, space);
1242 /* wait until FIFO is really empty */
1243 while (((RD4(sc, HC_DEBUG) >> 4) & 0x1f) > 0)
1246 mtx_unlock(&sc->mtx);
1249 static device_method_t bcm_sdhost_methods[] = {
1250 /* Device interface */
1251 DEVMETHOD(device_probe, bcm_sdhost_probe),
1252 DEVMETHOD(device_attach, bcm_sdhost_attach),
1253 DEVMETHOD(device_detach, bcm_sdhost_detach),
1256 DEVMETHOD(bus_read_ivar, sdhci_generic_read_ivar),
1257 DEVMETHOD(bus_write_ivar, sdhci_generic_write_ivar),
1259 /* MMC bridge interface */
1260 DEVMETHOD(mmcbr_update_ios, sdhci_generic_update_ios),
1261 DEVMETHOD(mmcbr_request, sdhci_generic_request),
1262 DEVMETHOD(mmcbr_get_ro, bcm_sdhost_get_ro),
1263 DEVMETHOD(mmcbr_acquire_host, sdhci_generic_acquire_host),
1264 DEVMETHOD(mmcbr_release_host, sdhci_generic_release_host),
1266 /* SDHCI registers accessors */
1267 DEVMETHOD(sdhci_read_1, bcm_sdhost_read_1),
1268 DEVMETHOD(sdhci_read_2, bcm_sdhost_read_2),
1269 DEVMETHOD(sdhci_read_4, bcm_sdhost_read_4),
1270 DEVMETHOD(sdhci_read_multi_4, bcm_sdhost_read_multi_4),
1271 DEVMETHOD(sdhci_write_1, bcm_sdhost_write_1),
1272 DEVMETHOD(sdhci_write_2, bcm_sdhost_write_2),
1273 DEVMETHOD(sdhci_write_4, bcm_sdhost_write_4),
1274 DEVMETHOD(sdhci_write_multi_4, bcm_sdhost_write_multi_4),
1275 DEVMETHOD(sdhci_get_card_present,bcm_sdhost_get_card_present),
1280 static devclass_t bcm_sdhost_devclass;
1282 static driver_t bcm_sdhost_driver = {
1285 sizeof(struct bcm_sdhost_softc),
1288 DRIVER_MODULE(sdhost_bcm, simplebus, bcm_sdhost_driver, bcm_sdhost_devclass,
1290 MODULE_DEPEND(sdhost_bcm, sdhci, 1, 1, 1);
1292 MMC_DECLARE_BRIDGE(sdhost_bcm);