Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/broadcom/bcm2835/bcm2835_sdhost.c
39566 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2018 Klaus P. Ohrhallinger <[email protected]>
5
* All rights reserved.
6
*
7
* Based on bcm2835_sdhci.c:
8
* Copyright (c) 2012 Oleksandr Tymoshenko <[email protected]>
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
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
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
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
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
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
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
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
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
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
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_identify_children(dev);
476
bus_attach_children(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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1287