bcm2835_sdhost.c revision 1.3.4.2 1 /* $NetBSD: bcm2835_sdhost.c,v 1.3.4.2 2017/12/03 11:35:52 jdolecek Exp $ */
2
3 /*-
4 * Copyright (c) 2017 Jared McNeill <jmcneill (at) invisible.ca>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: bcm2835_sdhost.c,v 1.3.4.2 2017/12/03 11:35:52 jdolecek Exp $");
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35 #include <sys/intr.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/gpio.h>
39
40 #include <arm/broadcom/bcm2835reg.h>
41 #include <arm/broadcom/bcm_amba.h>
42 #include <arm/broadcom/bcm2835_dmac.h>
43
44 #include <dev/sdmmc/sdmmcvar.h>
45 #include <dev/sdmmc/sdmmcchip.h>
46 #include <dev/sdmmc/sdmmc_ioreg.h>
47
48 #define SDCMD 0x00
49 #define SDCMD_NEW __BIT(15)
50 #define SDCMD_FAIL __BIT(14)
51 #define SDCMD_BUSY __BIT(11)
52 #define SDCMD_NORESP __BIT(10)
53 #define SDCMD_LONGRESP __BIT(9)
54 #define SDCMD_WRITE __BIT(7)
55 #define SDCMD_READ __BIT(6)
56 #define SDARG 0x04
57 #define SDTOUT 0x08
58 #define SDTOUT_DEFAULT 0xf00000
59 #define SDCDIV 0x0c
60 #define SDCDIV_MASK __BITS(10,0)
61 #define SDRSP0 0x10
62 #define SDRSP1 0x14
63 #define SDRSP2 0x18
64 #define SDRSP3 0x1c
65 #define SDHSTS 0x20
66 #define SDHSTS_BUSY __BIT(10)
67 #define SDHSTS_BLOCK __BIT(9)
68 #define SDHSTS_SDIO __BIT(8)
69 #define SDHSTS_REW_TO __BIT(7)
70 #define SDHSTS_CMD_TO __BIT(6)
71 #define SDHSTS_CRC16_E __BIT(5)
72 #define SDHSTS_CRC7_E __BIT(4)
73 #define SDHSTS_FIFO_E __BIT(3)
74 #define SDHSTS_DATA __BIT(0)
75 #define SDVDD 0x30
76 #define SDVDD_POWER __BIT(0)
77 #define SDEDM 0x34
78 #define SDEDM_RD_FIFO __BITS(18,14)
79 #define SDEDM_WR_FIFO __BITS(13,9)
80 #define SDHCFG 0x38
81 #define SDHCFG_BUSY_EN __BIT(10)
82 #define SDHCFG_BLOCK_EN __BIT(8)
83 #define SDHCFG_SDIO_EN __BIT(5)
84 #define SDHCFG_DATA_EN __BIT(4)
85 #define SDHCFG_SLOW __BIT(3)
86 #define SDHCFG_WIDE_EXT __BIT(2)
87 #define SDHCFG_WIDE_INT __BIT(1)
88 #define SDHCFG_REL_CMD __BIT(0)
89 #define SDHBCT 0x3c
90 #define SDDATA 0x40
91 #define SDHBLC 0x50
92
93 struct sdhost_softc;
94
95 static int sdhost_match(device_t, cfdata_t, void *);
96 static void sdhost_attach(device_t, device_t, void *);
97 static void sdhost_attach_i(device_t);
98
99 static int sdhost_intr(void *);
100 static int sdhost_dma_setup(struct sdhost_softc *);
101 static void sdhost_dma_done(uint32_t, uint32_t, void *);
102
103 static int sdhost_host_reset(sdmmc_chipset_handle_t);
104 static uint32_t sdhost_host_ocr(sdmmc_chipset_handle_t);
105 static int sdhost_host_maxblklen(sdmmc_chipset_handle_t);
106 static int sdhost_card_detect(sdmmc_chipset_handle_t);
107 static int sdhost_write_protect(sdmmc_chipset_handle_t);
108 static int sdhost_bus_power(sdmmc_chipset_handle_t, uint32_t);
109 static int sdhost_bus_clock(sdmmc_chipset_handle_t, int, bool);
110 static int sdhost_bus_width(sdmmc_chipset_handle_t, int);
111 static int sdhost_bus_rod(sdmmc_chipset_handle_t, int);
112 static void sdhost_exec_command(sdmmc_chipset_handle_t,
113 struct sdmmc_command *);
114 static void sdhost_card_enable_intr(sdmmc_chipset_handle_t, int);
115 static void sdhost_card_intr_ack(sdmmc_chipset_handle_t);
116
117 static struct sdmmc_chip_functions sdhost_chip_functions = {
118 .host_reset = sdhost_host_reset,
119 .host_ocr = sdhost_host_ocr,
120 .host_maxblklen = sdhost_host_maxblklen,
121 .card_detect = sdhost_card_detect,
122 .write_protect = sdhost_write_protect,
123 .bus_power = sdhost_bus_power,
124 .bus_clock_ddr = sdhost_bus_clock,
125 .bus_width = sdhost_bus_width,
126 .bus_rod = sdhost_bus_rod,
127 .exec_command = sdhost_exec_command,
128 .card_enable_intr = sdhost_card_enable_intr,
129 .card_intr_ack = sdhost_card_intr_ack,
130 };
131
132 struct sdhost_softc {
133 device_t sc_dev;
134 bus_space_tag_t sc_bst;
135 bus_space_handle_t sc_bsh;
136 bus_dma_tag_t sc_dmat;
137
138 bus_addr_t sc_addr;
139
140 void *sc_ih;
141 kmutex_t sc_intr_lock;
142 kcondvar_t sc_intr_cv;
143 kcondvar_t sc_dma_cv;
144
145 u_int sc_rate;
146
147 int sc_mmc_width;
148 int sc_mmc_present;
149
150 device_t sc_sdmmc_dev;
151
152 struct bcm_dmac_channel *sc_dmac;
153
154 bus_dmamap_t sc_dmamap;
155 bus_dma_segment_t sc_segs[1];
156 struct bcm_dmac_conblk *sc_cblk;
157
158 uint32_t sc_intr_hsts;
159
160 uint32_t sc_dma_status;
161 uint32_t sc_dma_error;
162 };
163
164 CFATTACH_DECL_NEW(bcmsdhost, sizeof(struct sdhost_softc),
165 sdhost_match, sdhost_attach, NULL, NULL);
166
167 #define SDHOST_WRITE(sc, reg, val) \
168 bus_space_write_4((sc)->sc_bst, (sc)->sc_bsh, (reg), (val))
169 #define SDHOST_READ(sc, reg) \
170 bus_space_read_4((sc)->sc_bst, (sc)->sc_bsh, (reg))
171
172 static int
173 sdhost_match(device_t parent, cfdata_t cf, void *aux)
174 {
175 struct amba_attach_args * const aaa = aux;
176
177 return strcmp(aaa->aaa_name, "sdhost") == 0;
178 }
179
180 static void
181 sdhost_attach(device_t parent, device_t self, void *aux)
182 {
183 struct sdhost_softc * const sc = device_private(self);
184 struct amba_attach_args * const aaa = aux;
185 prop_dictionary_t dict = device_properties(self);
186 bool disable = false;
187
188 sc->sc_dev = self;
189 sc->sc_bst = aaa->aaa_iot;
190 sc->sc_dmat = aaa->aaa_dmat;
191 sc->sc_addr = aaa->aaa_addr;
192 mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_BIO);
193 cv_init(&sc->sc_intr_cv, "sdhostintr");
194 cv_init(&sc->sc_dma_cv, "sdhostdma");
195
196 if (bus_space_map(sc->sc_bst, aaa->aaa_addr, aaa->aaa_size, 0,
197 &sc->sc_bsh) != 0) {
198 aprint_error(": couldn't map registers\n");
199 return;
200 }
201
202 aprint_naive("\n");
203 aprint_normal(": SD HOST controller\n");
204
205 prop_dictionary_get_bool(dict, "disable", &disable);
206 if (disable) {
207 aprint_naive(": disabled\n");
208 aprint_normal(": disabled\n");
209 return;
210 }
211
212 prop_dictionary_get_uint32(dict, "frequency", &sc->sc_rate);
213 if (sc->sc_rate == 0) {
214 aprint_error_dev(self, "couldn't get clock frequency\n");
215 return;
216 }
217
218 aprint_debug_dev(self, "ref freq %u Hz\n", sc->sc_rate);
219
220 if (sdhost_dma_setup(sc) != 0) {
221 aprint_error_dev(self, "failed to setup DMA\n");
222 return;
223 }
224
225 sc->sc_ih = intr_establish(aaa->aaa_intr, IPL_SDMMC, IST_LEVEL,
226 sdhost_intr, sc);
227 if (sc->sc_ih == NULL) {
228 aprint_error_dev(self, "failed to establish interrupt %d\n",
229 aaa->aaa_intr);
230 return;
231 }
232 aprint_normal_dev(self, "interrupting on intr %d\n", aaa->aaa_intr);
233
234 config_interrupts(self, sdhost_attach_i);
235 }
236
237 static int
238 sdhost_dma_setup(struct sdhost_softc *sc)
239 {
240 int error, rseg;
241
242 sc->sc_dmac = bcm_dmac_alloc(BCM_DMAC_TYPE_NORMAL, IPL_SDMMC,
243 sdhost_dma_done, sc);
244 if (sc->sc_dmac == NULL)
245 return ENXIO;
246
247 error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE,
248 PAGE_SIZE, sc->sc_segs, 1, &rseg, BUS_DMA_WAITOK);
249 if (error)
250 return error;
251
252 error = bus_dmamem_map(sc->sc_dmat, sc->sc_segs, rseg, PAGE_SIZE,
253 (void **)&sc->sc_cblk, BUS_DMA_WAITOK);
254 if (error)
255 return error;
256
257 memset(sc->sc_cblk, 0, PAGE_SIZE);
258
259 error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
260 BUS_DMA_WAITOK, &sc->sc_dmamap);
261 if (error)
262 return error;
263
264 error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, sc->sc_cblk,
265 PAGE_SIZE, NULL, BUS_DMA_WAITOK|BUS_DMA_WRITE);
266 if (error)
267 return error;
268
269 return 0;
270 }
271
272 static void
273 sdhost_attach_i(device_t self)
274 {
275 struct sdhost_softc *sc = device_private(self);
276 struct sdmmcbus_attach_args saa;
277
278 sdhost_host_reset(sc);
279 sdhost_bus_width(sc, 1);
280 sdhost_bus_clock(sc, 400, false);
281
282 memset(&saa, 0, sizeof(saa));
283 saa.saa_busname = "sdmmc";
284 saa.saa_sct = &sdhost_chip_functions;
285 saa.saa_sch = sc;
286 saa.saa_dmat = sc->sc_dmat;
287 saa.saa_clkmin = 400;
288 saa.saa_clkmax = 50000;
289 saa.saa_caps = SMC_CAPS_DMA |
290 SMC_CAPS_MULTI_SEG_DMA |
291 SMC_CAPS_SD_HIGHSPEED |
292 SMC_CAPS_MMC_HIGHSPEED |
293 SMC_CAPS_4BIT_MODE;
294
295 sc->sc_sdmmc_dev = config_found(self, &saa, NULL);
296 }
297
298 static int
299 sdhost_intr(void *priv)
300 {
301 struct sdhost_softc * const sc = priv;
302
303 mutex_enter(&sc->sc_intr_lock);
304 const uint32_t hsts = SDHOST_READ(sc, SDHSTS);
305 if (!hsts) {
306 mutex_exit(&sc->sc_intr_lock);
307 return 0;
308 }
309 SDHOST_WRITE(sc, SDHSTS, hsts);
310
311 #ifdef SDHOST_DEBUG
312 device_printf(sc->sc_dev, "mmc intr hsts %#x\n", hsts);
313 #endif
314
315 if (hsts) {
316 sc->sc_intr_hsts |= hsts;
317 cv_broadcast(&sc->sc_intr_cv);
318 }
319
320 mutex_exit(&sc->sc_intr_lock);
321
322 return 1;
323 }
324
325 static int
326 sdhost_dma_transfer(struct sdhost_softc *sc, struct sdmmc_command *cmd)
327 {
328 size_t seg;
329 int error;
330
331 KASSERT(mutex_owned(&sc->sc_intr_lock));
332
333 for (seg = 0; seg < cmd->c_dmamap->dm_nsegs; seg++) {
334 sc->sc_cblk[seg].cb_ti =
335 __SHIFTIN(13, DMAC_TI_PERMAP); /* SD HOST */
336 sc->sc_cblk[seg].cb_txfr_len =
337 cmd->c_dmamap->dm_segs[seg].ds_len;
338 /*
339 * All transfers are assumed to be multiples of 32-bits.
340 */
341 KASSERTMSG((sc->sc_cblk[seg].cb_txfr_len & 0x3) == 0,
342 "seg %zu len %d", seg, sc->sc_cblk[seg].cb_txfr_len);
343 if (ISSET(cmd->c_flags, SCF_CMD_READ)) {
344 sc->sc_cblk[seg].cb_ti |= DMAC_TI_DEST_INC;
345 /*
346 * Use 128-bit mode if transfer is a multiple of
347 * 16-bytes.
348 */
349 if ((sc->sc_cblk[seg].cb_txfr_len & 0xf) == 0)
350 sc->sc_cblk[seg].cb_ti |= DMAC_TI_DEST_WIDTH;
351 sc->sc_cblk[seg].cb_ti |= DMAC_TI_SRC_DREQ;
352 sc->sc_cblk[seg].cb_source_ad =
353 sc->sc_addr + SDDATA;
354 sc->sc_cblk[seg].cb_dest_ad =
355 cmd->c_dmamap->dm_segs[seg].ds_addr;
356 } else {
357 sc->sc_cblk[seg].cb_ti |= DMAC_TI_SRC_INC;
358 /*
359 * Use 128-bit mode if transfer is a multiple of
360 * 16-bytes.
361 */
362 if ((sc->sc_cblk[seg].cb_txfr_len & 0xf) == 0)
363 sc->sc_cblk[seg].cb_ti |= DMAC_TI_SRC_WIDTH;
364 sc->sc_cblk[seg].cb_ti |= DMAC_TI_DEST_DREQ;
365 sc->sc_cblk[seg].cb_ti |= DMAC_TI_WAIT_RESP;
366 sc->sc_cblk[seg].cb_source_ad =
367 cmd->c_dmamap->dm_segs[seg].ds_addr;
368 sc->sc_cblk[seg].cb_dest_ad =
369 sc->sc_addr + SDDATA;
370 }
371 sc->sc_cblk[seg].cb_stride = 0;
372 if (seg == cmd->c_dmamap->dm_nsegs - 1) {
373 sc->sc_cblk[seg].cb_ti |= DMAC_TI_INTEN;
374 sc->sc_cblk[seg].cb_nextconbk = 0;
375 } else {
376 sc->sc_cblk[seg].cb_nextconbk =
377 sc->sc_dmamap->dm_segs[0].ds_addr +
378 sizeof(struct bcm_dmac_conblk) * (seg+1);
379 }
380 sc->sc_cblk[seg].cb_padding[0] = 0;
381 sc->sc_cblk[seg].cb_padding[1] = 0;
382 }
383
384 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
385 sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
386
387 error = 0;
388
389 sc->sc_dma_status = 0;
390 sc->sc_dma_error = 0;
391
392 bcm_dmac_set_conblk_addr(sc->sc_dmac,
393 sc->sc_dmamap->dm_segs[0].ds_addr);
394 error = bcm_dmac_transfer(sc->sc_dmac);
395 if (error)
396 return error;
397
398 return 0;
399 }
400
401 static int
402 sdhost_dma_wait(struct sdhost_softc *sc, struct sdmmc_command *cmd)
403 {
404 int error = 0;
405
406 while (sc->sc_dma_status == 0 && sc->sc_dma_error == 0) {
407 error = cv_timedwait(&sc->sc_dma_cv, &sc->sc_intr_lock, hz*5);
408 if (error == EWOULDBLOCK) {
409 device_printf(sc->sc_dev, "transfer timeout!\n");
410 bcm_dmac_halt(sc->sc_dmac);
411 error = ETIMEDOUT;
412 break;
413 }
414 }
415
416 if (sc->sc_dma_status & DMAC_CS_END) {
417 cmd->c_resid = 0;
418 error = 0;
419 } else {
420 error = EIO;
421 }
422
423 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0,
424 sc->sc_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
425
426 return error;
427 }
428
429 static void
430 sdhost_dma_done(uint32_t status, uint32_t error, void *arg)
431 {
432 struct sdhost_softc * const sc = arg;
433
434 if (status != (DMAC_CS_INT|DMAC_CS_END))
435 device_printf(sc->sc_dev, "dma status %#x error %#x\n",
436 status, error);
437
438 mutex_enter(&sc->sc_intr_lock);
439 sc->sc_dma_status = status;
440 sc->sc_dma_error = error;
441 cv_broadcast(&sc->sc_dma_cv);
442 mutex_exit(&sc->sc_intr_lock);
443 }
444
445 static int
446 sdhost_wait_idle(struct sdhost_softc *sc, int timeout)
447 {
448 int retry;
449
450 KASSERT(mutex_owned(&sc->sc_intr_lock));
451
452 retry = timeout * 1000;
453
454 while (--retry > 0) {
455 const uint32_t cmd = SDHOST_READ(sc, SDCMD);
456 if ((cmd & SDCMD_NEW) == 0)
457 return 0;
458 delay(1);
459 }
460
461 return ETIMEDOUT;
462 }
463
464 static int
465 sdhost_host_reset(sdmmc_chipset_handle_t sch)
466 {
467 struct sdhost_softc * const sc = sch;
468 uint32_t edm;
469
470 SDHOST_WRITE(sc, SDVDD, 0);
471 SDHOST_WRITE(sc, SDCMD, 0);
472 SDHOST_WRITE(sc, SDARG, 0);
473 SDHOST_WRITE(sc, SDTOUT, SDTOUT_DEFAULT);
474 SDHOST_WRITE(sc, SDCDIV, 0);
475 SDHOST_WRITE(sc, SDHSTS, SDHOST_READ(sc, SDHSTS));
476 SDHOST_WRITE(sc, SDHCFG, 0);
477 SDHOST_WRITE(sc, SDHBCT, 0);
478 SDHOST_WRITE(sc, SDHBLC, 0);
479
480 edm = SDHOST_READ(sc, SDEDM);
481 edm &= ~(SDEDM_RD_FIFO|SDEDM_WR_FIFO);
482 edm |= __SHIFTIN(4, SDEDM_RD_FIFO);
483 edm |= __SHIFTIN(4, SDEDM_WR_FIFO);
484 SDHOST_WRITE(sc, SDEDM, edm);
485 delay(20000);
486 SDHOST_WRITE(sc, SDVDD, SDVDD_POWER);
487 delay(20000);
488
489 SDHOST_WRITE(sc, SDHCFG, 0);
490 SDHOST_WRITE(sc, SDCDIV, SDCDIV_MASK);
491
492 return 0;
493 }
494
495 static uint32_t
496 sdhost_host_ocr(sdmmc_chipset_handle_t sch)
497 {
498 return MMC_OCR_3_2V_3_3V | MMC_OCR_3_3V_3_4V | MMC_OCR_HCS;
499 }
500
501 static int
502 sdhost_host_maxblklen(sdmmc_chipset_handle_t sch)
503 {
504 return 8192;
505 }
506
507 static int
508 sdhost_card_detect(sdmmc_chipset_handle_t sch)
509 {
510 return 1; /* XXX */
511 }
512
513 static int
514 sdhost_write_protect(sdmmc_chipset_handle_t sch)
515 {
516 return 0; /* no write protect pin, assume rw */
517 }
518
519 static int
520 sdhost_bus_power(sdmmc_chipset_handle_t sch, uint32_t ocr)
521 {
522 return 0;
523 }
524
525 static int
526 sdhost_bus_clock(sdmmc_chipset_handle_t sch, int freq, bool ddr)
527 {
528 struct sdhost_softc * const sc = sch;
529 u_int target_rate = freq * 1000;
530 int div;
531
532 if (freq == 0)
533 div = SDCDIV_MASK;
534 else {
535 div = sc->sc_rate / target_rate;
536 if (div < 2)
537 div = 2;
538 if ((sc->sc_rate / div) > target_rate)
539 div++;
540 div -= 2;
541 if (div > SDCDIV_MASK)
542 div = SDCDIV_MASK;
543 }
544
545 SDHOST_WRITE(sc, SDCDIV, div);
546
547 return 0;
548 }
549
550 static int
551 sdhost_bus_width(sdmmc_chipset_handle_t sch, int width)
552 {
553 struct sdhost_softc * const sc = sch;
554 uint32_t hcfg;
555
556 #ifdef SDHOST_DEBUG
557 aprint_normal_dev(sc->sc_dev, "width = %d\n", width);
558 #endif
559
560 hcfg = SDHOST_READ(sc, SDHCFG);
561 if (width == 4)
562 hcfg |= SDHCFG_WIDE_EXT;
563 else
564 hcfg &= ~SDHCFG_WIDE_EXT;
565 hcfg |= (SDHCFG_WIDE_INT | SDHCFG_SLOW);
566 SDHOST_WRITE(sc, SDHCFG, hcfg);
567
568 return 0;
569 }
570
571 static int
572 sdhost_bus_rod(sdmmc_chipset_handle_t sch, int on)
573 {
574 return -1;
575 }
576
577 static void
578 sdhost_exec_command(sdmmc_chipset_handle_t sch, struct sdmmc_command *cmd)
579 {
580 struct sdhost_softc * const sc = sch;
581 uint32_t cmdval, hcfg;
582 u_int nblks;
583
584 #ifdef SDHOST_DEBUG
585 aprint_normal_dev(sc->sc_dev,
586 "opcode %d flags 0x%x data %p datalen %d blklen %d\n",
587 cmd->c_opcode, cmd->c_flags, cmd->c_data, cmd->c_datalen,
588 cmd->c_blklen);
589 #endif
590
591 mutex_enter(&sc->sc_intr_lock);
592
593 hcfg = SDHOST_READ(sc, SDHCFG);
594 SDHOST_WRITE(sc, SDHCFG, hcfg | SDHCFG_BUSY_EN);
595
596 sc->sc_intr_hsts = 0;
597
598 cmd->c_error = sdhost_wait_idle(sc, 5000);
599 if (cmd->c_error != 0) {
600 #ifdef SDHOST_DEBUG
601 device_printf(sc->sc_dev, "device is busy\n");
602 #endif
603 goto done;
604 }
605
606 cmdval = SDCMD_NEW;
607 if (!ISSET(cmd->c_flags, SCF_RSP_PRESENT))
608 cmdval |= SDCMD_NORESP;
609 if (ISSET(cmd->c_flags, SCF_RSP_136))
610 cmdval |= SDCMD_LONGRESP;
611 if (ISSET(cmd->c_flags, SCF_RSP_BSY))
612 cmdval |= SDCMD_BUSY;
613
614 if (cmd->c_datalen > 0) {
615 if (ISSET(cmd->c_flags, SCF_CMD_READ))
616 cmdval |= SDCMD_READ;
617 else
618 cmdval |= SDCMD_WRITE;
619
620 nblks = cmd->c_datalen / cmd->c_blklen;
621 if (nblks == 0 || (cmd->c_datalen % cmd->c_blklen) != 0)
622 ++nblks;
623
624 SDHOST_WRITE(sc, SDHBCT, cmd->c_blklen);
625 SDHOST_WRITE(sc, SDHBLC, nblks);
626
627 cmd->c_resid = cmd->c_datalen;
628 cmd->c_error = sdhost_dma_transfer(sc, cmd);
629 if (cmd->c_error != 0) {
630 #ifdef SDHOST_DEBUG
631 device_printf(sc->sc_dev, "dma transfer failed: %d\n",
632 cmd->c_error);
633 #endif
634 goto done;
635 }
636 }
637
638 SDHOST_WRITE(sc, SDARG, cmd->c_arg);
639 SDHOST_WRITE(sc, SDCMD, cmdval | cmd->c_opcode);
640
641 if (cmd->c_datalen > 0) {
642 cmd->c_error = sdhost_dma_wait(sc, cmd);
643 if (cmd->c_error != 0) {
644 #ifdef SDHOST_DEBUG
645 device_printf(sc->sc_dev,
646 "wait dma failed: %d\n", cmd->c_error);
647 #endif
648 goto done;
649 }
650 }
651
652 cmd->c_error = sdhost_wait_idle(sc, 5000);
653 if (cmd->c_error != 0) {
654 #ifdef SDHOST_DEBUG
655 device_printf(sc->sc_dev,
656 "wait cmd idle (%#x) failed: %d\n",
657 SDHOST_READ(sc, SDCMD), cmd->c_error);
658 #endif
659 }
660
661 if ((SDHOST_READ(sc, SDCMD) & SDCMD_FAIL) != 0) {
662 #ifdef SDHOST_DEBUG
663 device_printf(sc->sc_dev, "SDCMD: %#x\n",
664 SDHOST_READ(sc, SDCMD));
665 #endif
666 cmd->c_error = EIO;
667 goto done;
668 }
669
670 if (ISSET(cmd->c_flags, SCF_RSP_PRESENT)) {
671 if (ISSET(cmd->c_flags, SCF_RSP_136)) {
672 cmd->c_resp[0] = SDHOST_READ(sc, SDRSP0);
673 cmd->c_resp[1] = SDHOST_READ(sc, SDRSP1);
674 cmd->c_resp[2] = SDHOST_READ(sc, SDRSP2);
675 cmd->c_resp[3] = SDHOST_READ(sc, SDRSP3);
676 if (ISSET(cmd->c_flags, SCF_RSP_CRC)) {
677 cmd->c_resp[0] = (cmd->c_resp[0] >> 8) |
678 (cmd->c_resp[1] << 24);
679 cmd->c_resp[1] = (cmd->c_resp[1] >> 8) |
680 (cmd->c_resp[2] << 24);
681 cmd->c_resp[2] = (cmd->c_resp[2] >> 8) |
682 (cmd->c_resp[3] << 24);
683 cmd->c_resp[3] = (cmd->c_resp[3] >> 8);
684 }
685 } else {
686 cmd->c_resp[0] = SDHOST_READ(sc, SDRSP0);
687 }
688 }
689
690 done:
691 cmd->c_flags |= SCF_ITSDONE;
692 SDHOST_WRITE(sc, SDHCFG, hcfg);
693 SDHOST_WRITE(sc, SDHSTS, SDHOST_READ(sc, SDHSTS));
694 mutex_exit(&sc->sc_intr_lock);
695
696 #ifdef SDHOST_DEBUG
697 if (cmd->c_error != 0)
698 device_printf(sc->sc_dev, "command failed with error %d\n",
699 cmd->c_error);
700 #endif
701 }
702
703 static void
704 sdhost_card_enable_intr(sdmmc_chipset_handle_t sch, int enable)
705 {
706 }
707
708 static void
709 sdhost_card_intr_ack(sdmmc_chipset_handle_t sch)
710 {
711 }
712