Lines Matching +full:sdhci +full:- +full:caps
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
52 #include <dev/sdhci/sdhci.h>
78 ((((NUM_DMA_SEGS * BCM_SDHCI_BUFFER_SIZE) - 1) / PAGE_SIZE) + 1)
83 ((slot)->curcmd->data->len - (slot)->offset)
95 TUNABLE_INT("hw.bcm2835.sdhci.debug", &bcm2835_sdhci_debug);
97 &bcm2835_sdhci_debug, 0, "bcm2835 SDHCI debug level");
121 .clock_src = -1,
131 .clock_src = -1,
138 {"broadcom,bcm2835-sdhci", (uintptr_t)&bcm2835_sdhci_conf},
139 {"brcm,bcm2835-sdhci", (uintptr_t)&bcm2835_sdhci_conf},
140 {"brcm,bcm2835-mmc", (uintptr_t)&bcm2835_sdhci_conf},
141 {"brcm,bcm2711-emmc2", (uintptr_t)&bcm2838_emmc2_conf},
142 {"brcm,bcm2838-emmc2", (uintptr_t)&bcm2838_emmc2_conf},
146 TUNABLE_INT("hw.bcm2835.sdhci.hs", &bcm2835_sdhci_hs);
147 TUNABLE_INT("hw.bcm2835.sdhci.pio_mode", &bcm2835_sdhci_pio_mode);
193 KASSERT(sc->dmamap_seg_count == 0, ("leaked DMA segment")); in bcm_sdhci_dmacb()
194 sc->dmamap_status = err; in bcm_sdhci_dmacb()
195 sc->dmamap_seg_count = nseg; in bcm_sdhci_dmacb()
197 /* Note nseg is guaranteed to be zero if err is non-zero. */ in bcm_sdhci_dmacb()
199 sc->dmamap_seg_addrs[i] = segs[i].ds_addr; in bcm_sdhci_dmacb()
200 sc->dmamap_seg_sizes[i] = segs[i].ds_len; in bcm_sdhci_dmacb()
211 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) in bcm_sdhci_probe()
214 device_set_desc(dev, "Broadcom 2708 SDHCI controller"); in bcm_sdhci_probe()
228 sc->sc_dev = dev; in bcm_sdhci_attach()
229 sc->sc_req = NULL; in bcm_sdhci_attach()
231 sc->conf = (struct bcm_mmc_conf *)ofw_bus_search_compatible(dev, in bcm_sdhci_attach()
232 compat_data)->ocd_data; in bcm_sdhci_attach()
233 if (sc->conf == 0) in bcm_sdhci_attach()
244 err = bcm2835_mbox_get_clock_rate(sc->conf->clock_id, &default_freq); in bcm_sdhci_attach()
250 node = ofw_bus_get_node(sc->sc_dev); in bcm_sdhci_attach()
251 if ((OF_getencprop(node, "clock-frequency", &cell, in bcm_sdhci_attach()
256 default_freq = sc->conf->default_freq; in bcm_sdhci_attach()
259 device_printf(dev, "SDHCI frequency: %dMHz\n", default_freq); in bcm_sdhci_attach()
261 if (sc->conf->clock_src > 0) { in bcm_sdhci_attach()
263 sc->clkman = devclass_get_device( in bcm_sdhci_attach()
265 if (sc->clkman == NULL) { in bcm_sdhci_attach()
270 f = bcm2835_clkman_set_frequency(sc->clkman, in bcm_sdhci_attach()
271 sc->conf->clock_src, default_freq); in bcm_sdhci_attach()
282 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, in bcm_sdhci_attach()
284 if (!sc->sc_mem_res) { in bcm_sdhci_attach()
290 sc->sc_bst = rman_get_bustag(sc->sc_mem_res); in bcm_sdhci_attach()
291 sc->sc_bsh = rman_get_bushandle(sc->sc_mem_res); in bcm_sdhci_attach()
294 sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, in bcm_sdhci_attach()
296 if (!sc->sc_irq_res) { in bcm_sdhci_attach()
302 if (bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE, in bcm_sdhci_attach()
303 NULL, bcm_sdhci_intr, sc, &sc->sc_intrhand)) { in bcm_sdhci_attach()
310 sc->sc_slot.opt = SDHCI_PLATFORM_TRANSFER; in bcm_sdhci_attach()
312 sc->sc_slot.caps = SDHCI_CAN_VDD_330 | SDHCI_CAN_VDD_180; in bcm_sdhci_attach()
314 sc->sc_slot.caps |= SDHCI_CAN_DO_HISPD; in bcm_sdhci_attach()
315 sc->sc_slot.caps |= (default_freq << SDHCI_CLOCK_BASE_SHIFT); in bcm_sdhci_attach()
316 sc->sc_slot.quirks = sc->conf->quirks; in bcm_sdhci_attach()
318 sdhci_init_slot(dev, &sc->sc_slot, 0); in bcm_sdhci_attach()
319 mmc_fdt_parse(dev, 0, &sc->sc_mmc_helper, &sc->sc_slot.host); in bcm_sdhci_attach()
321 sc->sc_dma_ch = bcm_dma_allocate(BCM_DMA_CH_ANY); in bcm_sdhci_attach()
322 if (sc->sc_dma_ch == BCM_DMA_CH_INVALID) in bcm_sdhci_attach()
325 err = bcm_dma_setup_intr(sc->sc_dma_ch, bcm_sdhci_dma_intr, sc); in bcm_sdhci_attach()
339 &sc->sc_dma_tag); in bcm_sdhci_attach()
346 err = bus_dmamap_create(sc->sc_dma_tag, 0, &sc->sc_dma_map); in bcm_sdhci_attach()
353 sc->sc_sdhci_buffer_phys = rman_get_start(sc->sc_mem_res) + in bcm_sdhci_attach()
359 sdhci_start_slot(&sc->sc_slot); in bcm_sdhci_attach()
362 sc->blksz_and_count = SDHCI_READ_4(dev, &sc->sc_slot, SDHCI_BLOCK_SIZE); in bcm_sdhci_attach()
363 sc->cmd_and_mode = SDHCI_READ_4(dev, &sc->sc_slot, SDHCI_TRANSFER_MODE); in bcm_sdhci_attach()
368 if (sc->sc_intrhand) in bcm_sdhci_attach()
369 bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_intrhand); in bcm_sdhci_attach()
370 if (sc->sc_irq_res) in bcm_sdhci_attach()
371 bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq_res); in bcm_sdhci_attach()
372 if (sc->sc_mem_res) in bcm_sdhci_attach()
373 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); in bcm_sdhci_attach()
390 sdhci_generic_intr(&sc->sc_slot); in bcm_sdhci_intr()
401 ios = &sc->sc_slot.host.ios; in bcm_sdhci_update_ios()
403 if (ios->power_mode == power_up) { in bcm_sdhci_update_ios()
404 if (sc->sc_mmc_helper.vmmc_supply) in bcm_sdhci_update_ios()
405 regulator_enable(sc->sc_mmc_helper.vmmc_supply); in bcm_sdhci_update_ios()
406 if (sc->sc_mmc_helper.vqmmc_supply) in bcm_sdhci_update_ios()
407 regulator_enable(sc->sc_mmc_helper.vqmmc_supply); in bcm_sdhci_update_ios()
414 if (ios->power_mode == power_off) { in bcm_sdhci_update_ios()
415 if (sc->sc_mmc_helper.vmmc_supply) in bcm_sdhci_update_ios()
416 regulator_disable(sc->sc_mmc_helper.vmmc_supply); in bcm_sdhci_update_ios()
417 if (sc->sc_mmc_helper.vqmmc_supply) in bcm_sdhci_update_ios()
418 regulator_disable(sc->sc_mmc_helper.vqmmc_supply); in bcm_sdhci_update_ios()
434 uint32_t val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, off); in RD4()
442 bus_space_write_4(sc->sc_bst, sc->sc_bsh, off, val); in WR4()
445 * consecutive writes to registers that are within two SD-card in WR4()
448 if (sc->sc_slot.clock > 0) in WR4()
449 DELAY(((2 * 1000000) / sc->sc_slot.clock) + 1); in WR4()
468 * Standard 32-bit handling of command and transfer mode, as in bcm_sdhci_read_2()
472 sc->need_update_blk) in bcm_sdhci_read_2()
473 val32 = sc->blksz_and_count; in bcm_sdhci_read_2()
475 val32 = sc->cmd_and_mode; in bcm_sdhci_read_2()
496 bus_space_read_multi_4(sc->sc_bst, sc->sc_bsh, off, data, count); in bcm_sdhci_read_multi_4()
527 sc->need_update_blk) in bcm_sdhci_write_2()
528 val32 = sc->blksz_and_count; in bcm_sdhci_write_2()
530 val32 = sc->cmd_and_mode; in bcm_sdhci_write_2()
538 sc->cmd_and_mode = val32; in bcm_sdhci_write_2()
540 sc->blksz_and_count = val32; in bcm_sdhci_write_2()
541 sc->need_update_blk = true; in bcm_sdhci_write_2()
545 if (sc->need_update_blk) { in bcm_sdhci_write_2()
546 WR4(sc, SDHCI_BLOCK_SIZE, sc->blksz_and_count); in bcm_sdhci_write_2()
547 sc->need_update_blk = false; in bcm_sdhci_write_2()
550 sc->cmd_and_mode = val32; in bcm_sdhci_write_2()
570 bus_space_write_multi_4(sc->sc_bst, sc->sc_bsh, off, data, count); in bcm_sdhci_write_multi_4()
580 slot = &sc->sc_slot; in bcm_sdhci_start_dma_seg()
581 mtx_assert(&slot->mtx, MA_OWNED); in bcm_sdhci_start_dma_seg()
582 idx = sc->dmamap_seg_index++; in bcm_sdhci_start_dma_seg()
583 len = sc->dmamap_seg_sizes[idx]; in bcm_sdhci_start_dma_seg()
584 slot->offset += len; in bcm_sdhci_start_dma_seg()
587 if (slot->curcmd->data->flags & MMC_DATA_READ) { in bcm_sdhci_start_dma_seg()
592 bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_NONE, in bcm_sdhci_start_dma_seg()
594 bcm_dma_setup_dst(sc->sc_dma_ch, BCM_DMA_DREQ_NONE, in bcm_sdhci_start_dma_seg()
596 psrc = sc->sc_sdhci_buffer_phys; in bcm_sdhci_start_dma_seg()
597 pdst = sc->dmamap_seg_addrs[idx]; in bcm_sdhci_start_dma_seg()
604 bcm_dma_setup_src(sc->sc_dma_ch, BCM_DMA_DREQ_NONE, in bcm_sdhci_start_dma_seg()
606 bcm_dma_setup_dst(sc->sc_dma_ch, sc->conf->emmc_dreq, in bcm_sdhci_start_dma_seg()
608 psrc = sc->dmamap_seg_addrs[idx]; in bcm_sdhci_start_dma_seg()
609 pdst = sc->sc_sdhci_buffer_phys; in bcm_sdhci_start_dma_seg()
616 * interrupts (or SDHCI error interrupts) until the IO is done. in bcm_sdhci_start_dma_seg()
619 bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, sync_op); in bcm_sdhci_start_dma_seg()
621 slot->intmask &= ~DATA_XFER_MASK; in bcm_sdhci_start_dma_seg()
622 bcm_sdhci_write_4(sc->sc_dev, slot, SDHCI_SIGNAL_ENABLE, in bcm_sdhci_start_dma_seg()
623 slot->intmask); in bcm_sdhci_start_dma_seg()
628 * allocate a channel) cause a non-zero return from bcm_dma_start(). in bcm_sdhci_start_dma_seg()
630 err = bcm_dma_start(sc->sc_dma_ch, psrc, pdst, len); in bcm_sdhci_start_dma_seg()
637 struct sdhci_slot *slot = &sc->sc_slot; in bcm_sdhci_dma_exit()
639 mtx_assert(&slot->mtx, MA_OWNED); in bcm_sdhci_dma_exit()
641 /* Re-enable interrupts */ in bcm_sdhci_dma_exit()
642 slot->intmask |= DATA_XFER_MASK; in bcm_sdhci_dma_exit()
643 bcm_sdhci_write_4(slot->bus, slot, SDHCI_SIGNAL_ENABLE, in bcm_sdhci_dma_exit()
644 slot->intmask); in bcm_sdhci_dma_exit()
650 struct sdhci_slot *slot = &sc->sc_slot; in bcm_sdhci_dma_unload()
652 if (sc->dmamap_seg_count == 0) in bcm_sdhci_dma_unload()
654 if ((slot->curcmd->data->flags & MMC_DATA_READ) != 0) in bcm_sdhci_dma_unload()
655 bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, in bcm_sdhci_dma_unload()
658 bus_dmamap_sync(sc->sc_dma_tag, sc->sc_dma_map, in bcm_sdhci_dma_unload()
660 bus_dmamap_unload(sc->sc_dma_tag, sc->sc_dma_map); in bcm_sdhci_dma_unload()
662 sc->dmamap_seg_count = 0; in bcm_sdhci_dma_unload()
663 sc->dmamap_seg_index = 0; in bcm_sdhci_dma_unload()
670 struct sdhci_slot *slot = &sc->sc_slot; in bcm_sdhci_dma_intr()
673 mtx_lock(&slot->mtx); in bcm_sdhci_dma_intr()
674 if (slot->curcmd == NULL) in bcm_sdhci_dma_intr()
679 * status of the sdhci controller and whether there's more data left. in bcm_sdhci_dma_intr()
681 if (sc->dmamap_seg_index < sc->dmamap_seg_count) { in bcm_sdhci_dma_intr()
691 * can continue via DMA, do so. Otherwise, re-enable interrupts and in bcm_sdhci_dma_intr()
694 reg = bcm_sdhci_read_4(slot->bus, slot, SDHCI_INT_STATUS) & in bcm_sdhci_dma_intr()
699 bcm_sdhci_write_4(slot->bus, slot, SDHCI_INT_STATUS, in bcm_sdhci_dma_intr()
703 if (slot->curcmd->error != 0) { in bcm_sdhci_dma_intr()
711 bcm_sdhci_write_4(slot->bus, slot, SDHCI_INT_STATUS, in bcm_sdhci_dma_intr()
713 slot->flags &= ~PLATFORM_DATA_STARTED; in bcm_sdhci_dma_intr()
719 mtx_unlock(&slot->mtx); in bcm_sdhci_dma_intr()
725 struct bcm_sdhci_softc *sc = device_get_softc(slot->bus); in bcm_sdhci_start_dma()
729 mtx_assert(&slot->mtx, MA_OWNED); in bcm_sdhci_start_dma()
732 buf = (uint8_t *)slot->curcmd->data->data + slot->offset; in bcm_sdhci_start_dma()
740 if (bus_dmamap_load(sc->sc_dma_tag, sc->sc_dma_map, buf, left, in bcm_sdhci_start_dma()
742 sc->dmamap_status != 0) { in bcm_sdhci_start_dma()
743 slot->curcmd->error = MMC_ERR_NO_MEMORY; in bcm_sdhci_start_dma()
755 struct bcm_sdhci_softc *sc = device_get_softc(slot->bus); in bcm_sdhci_will_handle_transfer()
759 * We don't want to perform DMA in this context -- interrupts are in bcm_sdhci_will_handle_transfer()
767 * SDHCI framework, when it should not have. This really needs to be in bcm_sdhci_will_handle_transfer()
770 KASSERT(sc->dmamap_seg_count == 0, in bcm_sdhci_will_handle_transfer()
771 ("data pending interrupt pushed through SDHCI framework")); in bcm_sdhci_will_handle_transfer()
777 * SDHCI-driven PIO once we're below the block size. in bcm_sdhci_will_handle_transfer()
797 struct bcm_sdhci_softc *sc = device_get_softc(slot->bus); in bcm_sdhci_finish_transfer()
801 * SDHCI_INT_DATA_END to get this far -- just make sure we don't leave in bcm_sdhci_finish_transfer()
804 if (sc->dmamap_seg_count != 0) { in bcm_sdhci_finish_transfer()
809 * regressed to SDHCI-driven PIO to finish the operation and in bcm_sdhci_finish_transfer()
810 * this is certainly caused by developer-error. in bcm_sdhci_finish_transfer()
840 /* SDHCI registers accessors */