]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/broadcom/bcm2835/bcm2835_sdhost.c
Update to Zstandard 1.4.5
[FreeBSD/FreeBSD.git] / sys / arm / broadcom / bcm2835 / bcm2835_sdhost.c
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