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