Beispiel #1
0
void
sdhc_acpi_attach(struct device *parent, struct device *self, void *aux)
{
	struct acpi_attach_args *aaa = aux;
	struct sdhc_acpi_softc *sc = (struct sdhc_acpi_softc *)self;
	struct aml_value res;

	sc->sc_acpi = (struct acpi_softc *)parent;
	sc->sc_node = aaa->aaa_node;
	printf(": %s", sc->sc_node->name);

	if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) {
		printf(", can't find registers\n");
		return;
	}

	aml_parse_resource(&res, sdhc_acpi_parse_resources, sc);
	printf(" addr 0x%lx/0x%lx", sc->sc_addr, sc->sc_size);
	if (sc->sc_addr == 0 || sc->sc_size == 0) {
		printf("\n");
		return;
	}

	printf(" irq %d", sc->sc_irq);

	sc->sc_memt = aaa->aaa_memt;
	if (bus_space_map(sc->sc_memt, sc->sc_addr, sc->sc_size, 0,
	    &sc->sc_memh)) {
		printf(", can't map registers\n");
		return;
	}

	sc->sc_ih = acpi_intr_establish(sc->sc_irq, sc->sc_irq_flags, IPL_BIO,
	    sdhc_intr, sc, sc->sc.sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(", can't establish interrupt\n");
		return;
	}

	printf("\n");

	sc->sc.sc_host = &sc->sc_host;
	sdhc_host_found(&sc->sc, sc->sc_memt, sc->sc_memh, sc->sc_size, 0, 0);
}
Beispiel #2
0
static void
bcmemmc_attach_i(device_t self)
{
	struct bcmemmc_softc * const sc = device_private(self);
	int error;

	error = sdhc_host_found(&sc->sc, sc->sc_iot, sc->sc_ioh, sc->sc_ios);
	if (error != 0) {
		aprint_error_dev(self, "couldn't initialize host, error=%d\n",
		    error);
		goto fail;
	}
	return;

fail:
	/* XXX add bus_dma failure cleanup */
	if (sc->sc_ih) {
		intr_disestablish(sc->sc_ih);
		sc->sc_ih = NULL;
	}
	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
}
Beispiel #3
0
static void
sdhc_attach(device_t parent, device_t self, void *aux)
{
	struct sdhc_axi_softc *sc = device_private(self);
	struct axi_attach_args *aa = aux;
	bus_space_tag_t iot = aa->aa_iot;
	bus_space_handle_t ioh;
	u_int perclk = 0, v;

	sc->sc_sdhc.sc_dev = self;
	sc->sc_sdhc.sc_dmat = aa->aa_dmat;

	if (bus_space_map(iot, aa->aa_addr, AIPS2_USDHC_SIZE, 0, &ioh)) {
		aprint_error_dev(self, "can't map\n");
		return;
	}

	aprint_normal(": Ultra Secured Digial Host Controller\n");
	aprint_naive("\n");
	sc->sc_sdhc.sc_host = sc->sc_hosts;

	switch (aa->aa_addr) {
	case IMX6_AIPS2_BASE + AIPS2_USDHC1_BASE:
		v = imx6_ccm_read(CCM_CCGR6);
		imx6_ccm_write(CCM_CCGR6, v | CCM_CCGR6_USDHC1_CLK_ENABLE(3));
		perclk = imx6_get_clock(IMX6CLK_USDHC1);
		sdhc_set_gpio_cd(sc, "usdhc1-cd-gpio");
		break;
	case IMX6_AIPS2_BASE + AIPS2_USDHC2_BASE:
		v = imx6_ccm_read(CCM_CCGR6);
		imx6_ccm_write(CCM_CCGR6, v | CCM_CCGR6_USDHC2_CLK_ENABLE(3));
		perclk = imx6_get_clock(IMX6CLK_USDHC2);
		sdhc_set_gpio_cd(sc, "usdhc2-cd-gpio");
		break;
	case IMX6_AIPS2_BASE + AIPS2_USDHC3_BASE:
		v = imx6_ccm_read(CCM_CCGR6);
		imx6_ccm_write(CCM_CCGR6, v | CCM_CCGR6_USDHC3_CLK_ENABLE(3));
		perclk = imx6_get_clock(IMX6CLK_USDHC3);
		sdhc_set_gpio_cd(sc, "usdhc3-cd-gpio");
		break;
	case IMX6_AIPS2_BASE + AIPS2_USDHC4_BASE:
		v = imx6_ccm_read(CCM_CCGR6);
		imx6_ccm_write(CCM_CCGR6, v | CCM_CCGR6_USDHC4_CLK_ENABLE(3));
		perclk = imx6_get_clock(IMX6CLK_USDHC4);
		sdhc_set_gpio_cd(sc, "usdhc4-cd-gpio");
		break;
	}

	sc->sc_sdhc.sc_clkbase = perclk / 1000;
	sc->sc_sdhc.sc_flags |=
	    SDHC_FLAG_USE_DMA |
	    SDHC_FLAG_NO_PWR0 |
	    SDHC_FLAG_HAVE_DVS |
	    SDHC_FLAG_32BIT_ACCESS |
	    SDHC_FLAG_8BIT_MODE |
	    SDHC_FLAG_USE_ADMA2 |
	    SDHC_FLAG_POLL_CARD_DET |
	    SDHC_FLAG_USDHC;

	sc->sc_ih = intr_establish(aa->aa_irq, IPL_SDMMC, IST_LEVEL,
	    sdhc_intr, &sc->sc_sdhc);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "can't establish interrupt\n");
		return;
	}

	sc->sc_sdhc.sc_vendor_card_detect = imx6_sdhc_card_detect;
	if (sdhc_host_found(&sc->sc_sdhc, iot, ioh, AIPS2_USDHC_SIZE)) {
		aprint_error_dev(self, "can't initialize host\n");
		return;
	}

	if (!pmf_device_register1(self, sdhc_suspend, sdhc_resume,
	    sdhc_shutdown)) {
		aprint_error_dev(self, "can't establish power hook\n");
	}
}
static void
sdhc_pci_attach(device_t parent, device_t self, void *aux)
{
	struct sdhc_pci_softc *sc = device_private(self);
	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
	pci_chipset_tag_t pc = pa->pa_pc;
	pcitag_t tag = pa->pa_tag;
	pci_intr_handle_t ih;
	pcireg_t csr;
	pcireg_t slotinfo;
	char const *intrstr;
	int nslots;
	int reg;
	int cnt;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	bus_size_t size;
	uint32_t flags;
	char intrbuf[PCI_INTRSTR_LEN];

	sc->sc.sc_dev = self;
	sc->sc.sc_dmat = pa->pa_dmat;
	sc->sc.sc_host = NULL;

	sc->sc_pc = pc;

	pci_aprint_devinfo(pa, NULL);

	/* Some controllers needs special treatment. */
	flags = sdhc_pci_lookup_quirk_flags(pa);
	if (ISSET(flags, SDHC_PCI_QUIRK_TI_HACK))
		sdhc_pci_quirk_ti_hack(pa);
	if (ISSET(flags, SDHC_PCI_QUIRK_FORCE_DMA))
		SET(sc->sc.sc_flags, SDHC_FLAG_FORCE_DMA);
	if (ISSET(flags, SDHC_PCI_QUIRK_NO_PWR0))
		SET(sc->sc.sc_flags, SDHC_FLAG_NO_PWR0);
	if (ISSET(flags, SDHC_PCI_QUIRK_RICOH_LOWER_FREQ_HACK))
		sdhc_pci_quirk_ricoh_lower_freq_hack(pa);

	/*
	 * Map and attach all hosts supported by the host controller.
	 */
	slotinfo = pci_conf_read(pc, tag, SDHC_PCI_CONF_SLOT_INFO);
	nslots = SDHC_PCI_NUM_SLOTS(slotinfo);

	/* Allocate an array big enough to hold all the possible hosts */
	sc->sc.sc_host = malloc(sizeof(struct sdhc_host *) * nslots,
	    M_DEVBUF, M_NOWAIT | M_ZERO);
	if (sc->sc.sc_host == NULL) {
		aprint_error_dev(self, "couldn't alloc memory\n");
		goto err;
	}

	/* Enable the device. */
	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
		       csr | PCI_COMMAND_MASTER_ENABLE);

	/* Map and establish the interrupt. */
	if (pci_intr_map(pa, &ih)) {
		aprint_error_dev(self, "couldn't map interrupt\n");
		goto err;
	}

	intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf));
	sc->sc_ih = pci_intr_establish(pc, ih, IPL_SDMMC, sdhc_intr, &sc->sc);
	if (sc->sc_ih == NULL) {
		aprint_error_dev(self, "couldn't establish interrupt\n");
		goto err;
	}
	aprint_normal_dev(self, "interrupting at %s\n", intrstr);

	/* Enable use of DMA if supported by the interface. */
	if ((PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA))
		SET(sc->sc.sc_flags, SDHC_FLAG_USE_DMA);

	/* XXX: handle 64-bit BARs */
	cnt = 0;
	for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) *
		 sizeof(uint32_t);
	     reg < SDHC_PCI_BAR_END && nslots > 0;
	     reg += sizeof(uint32_t), nslots--) {
		if (pci_mapreg_map(pa, reg, PCI_MAPREG_TYPE_MEM, 0,
		    &iot, &ioh, NULL, &size)) {
			continue;
		}

		cnt++;
		if (sdhc_host_found(&sc->sc, iot, ioh, size) != 0) {
			/* XXX: sc->sc_host leak */
			aprint_error_dev(self,
			    "couldn't initialize host (0x%x)\n", reg);
		}
	}
	if (cnt == 0) {
		aprint_error_dev(self, "couldn't map register\n");
		goto err;
	}

	if (!pmf_device_register1(self, sdhc_suspend, sdhc_resume,
	    sdhc_shutdown)) {
		aprint_error_dev(self, "couldn't establish powerhook\n");
	}

	return;

err:
	if (sc->sc.sc_host != NULL) {
		free(sc->sc.sc_host, M_DEVBUF);
		sc->sc.sc_host = NULL;
	}
}
Beispiel #5
0
static void
obiosdhc_attach(device_t parent, device_t self, void *aux)
{
    struct obiosdhc_softc * const sc = device_private(self);
    struct obio_attach_args * const oa = aux;
    prop_dictionary_t prop = device_properties(self);
    uint32_t clkd, stat;
    int error, timo, clksft, n;
    bool support8bit = false;
    const char *transfer_mode = "PIO";
#ifdef TI_AM335X
    size_t i;
#endif

    prop_dictionary_get_bool(prop, "8bit", &support8bit);

    sc->sc.sc_dmat = oa->obio_dmat;
    sc->sc.sc_dev = self;
    sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS;
    sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
    sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
    sc->sc.sc_flags |= SDHC_FLAG_SINGLE_ONLY;
    if (support8bit)
        sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE;
#ifdef TI_AM335X
    sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET;
    sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
#endif
#if defined(OMAP_3530)
    sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
#endif
    sc->sc.sc_host = sc->sc_hosts;
    sc->sc.sc_clkbase = 96000;	/* 96MHZ */
    if (!prop_dictionary_get_uint32(prop, "clkmask", &sc->sc.sc_clkmsk))
        sc->sc.sc_clkmsk = 0x0000ffc0;
    sc->sc.sc_vendor_rod = obiosdhc_rod;
    sc->sc.sc_vendor_write_protect = obiosdhc_write_protect;
    sc->sc.sc_vendor_card_detect = obiosdhc_card_detect;
    sc->sc.sc_vendor_bus_clock = obiosdhc_bus_clock;
    sc->sc_bst = oa->obio_iot;

    clksft = ffs(sc->sc.sc_clkmsk) - 1;

    error = bus_space_map(sc->sc_bst, oa->obio_addr, oa->obio_size, 0,
                          &sc->sc_bsh);
    if (error) {
        aprint_error_dev(self,
                         "can't map registers: %d\n", error);
        return;
    }

    bus_space_subregion(sc->sc_bst, sc->sc_bsh, OMAP3_SDMMC_SDHC_OFFSET,
                        OMAP3_SDMMC_SDHC_SIZE, &sc->sc_sdhc_bsh);

#if NEDMA > 0
    if (oa->obio_edmabase != -1) {
        cv_init(&sc->sc_edma_cv, "sdhcedma");
        sc->sc_edma_fifo = oa->obio_addr +
                           OMAP3_SDMMC_SDHC_OFFSET + SDHC_DATA;
        obiosdhc_edma_init(sc, oa->obio_edmabase);
        sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
        sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA;
        sc->sc.sc_flags |= SDHC_FLAG_EXTDMA_DMAEN;
        sc->sc.sc_flags &= ~SDHC_FLAG_SINGLE_ONLY;
        sc->sc.sc_vendor_transfer_data_dma = obiosdhc_edma_xfer_data;
        transfer_mode = "EDMA";
    }
#endif

    aprint_naive("\n");
    aprint_normal(": SDHC controller (%s)\n", transfer_mode);

#ifdef TI_AM335X
    /* XXX Not really AM335X-specific.  */
    for (i = 0; i < __arraycount(am335x_sdhc); i++)
        if ((oa->obio_addr == am335x_sdhc[i].as_base_addr) &&
                (oa->obio_intr == am335x_sdhc[i].as_intr)) {
            prcm_module_enable(&am335x_sdhc[i].as_module);
            break;
        }
    KASSERT(i < __arraycount(am335x_sdhc));
#endif

    /* XXXXXX: Turn-on regulator via I2C. */
    /* XXXXXX: And enable ICLOCK/FCLOCK. */

    /* MMCHS Soft reset */
    bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
                      SYSCONFIG_SOFTRESET);
    timo = 3000000;	/* XXXX 3 sec. */
    while (timo--) {
        if (bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSSTATUS) &
                SYSSTATUS_RESETDONE)
            break;
        delay(1);
    }
    if (timo == 0)
        aprint_error_dev(self, "Soft reset timeout\n");
    bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_SYSCONFIG,
                      SYSCONFIG_ENAWAKEUP | SYSCONFIG_AUTOIDLE | SYSCONFIG_SIDLEMODE_AUTO |
                      SYSCONFIG_CLOCKACTIVITY_FCLK | SYSCONFIG_CLOCKACTIVITY_ICLK);

    sc->sc_ih = intr_establish(oa->obio_intr, IPL_VM, IST_LEVEL,
                               sdhc_intr, &sc->sc);
    if (sc->sc_ih == NULL) {
        aprint_error_dev(self, "failed to establish interrupt %d\n",
                         oa->obio_intr);
        goto fail;
    }

    error = sdhc_host_found(&sc->sc, sc->sc_bst, sc->sc_sdhc_bsh,
                            oa->obio_size - OMAP3_SDMMC_SDHC_OFFSET);
    if (error != 0) {
        aprint_error_dev(self, "couldn't initialize host, error=%d\n",
                         error);
        goto fail;
    }

    /* Set SDVS 1.8v and DTW 1bit mode */
    SDHC_WRITE(sc, SDHC_HOST_CTL,
               SDHC_VOLTAGE_1_8V << (SDHC_VOLTAGE_SHIFT + 8));
    bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
                      bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_OD);
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_INTCLK_ENABLE |
               SDHC_SDCLK_ENABLE);
    SDHC_WRITE(sc, SDHC_HOST_CTL,
               SDHC_READ(sc, SDHC_HOST_CTL) | SDHC_BUS_POWER << 8);
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);

    /*
     * 22.6.1.3.1.5 MMCHS Controller INIT Procedure Start
     * from 'OMAP35x Applications Processor  Technical Reference Manual'.
     *
     * During the INIT procedure, the MMCHS controller generates 80 clock
     * periods. In order to keep the 1ms gap, the MMCHS controller should
     * be configured to generate a clock whose frequency is smaller or
     * equal to 80 KHz.
     */

    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
    clkd = CLKD(80);
    n = 1;
    while (clkd & ~(sc->sc.sc_clkmsk >> clksft)) {
        clkd >>= 1;
        n <<= 1;
    }
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) | (clkd << clksft));
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);

    bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
                      bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) | CON_INIT);
    for (; n > 0; n--) {
        SDHC_WRITE(sc, SDHC_TRANSFER_MODE, 0x00000000);
        timo = 3000000;	/* XXXX 3 sec. */
        stat = 0;
        while (!(stat & SDHC_COMMAND_COMPLETE)) {
            stat = SDHC_READ(sc, SDHC_NINTR_STATUS);
            if (--timo == 0)
                break;
            delay(1);
        }
        if (timo == 0) {
            aprint_error_dev(self, "INIT Procedure timeout\n");
            break;
        }
        SDHC_WRITE(sc, SDHC_NINTR_STATUS, stat);
    }
    bus_space_write_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON,
                      bus_space_read_4(sc->sc_bst, sc->sc_bsh, MMCHS_CON) & ~CON_INIT);
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) & ~SDHC_SDCLK_ENABLE);
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) & ~sc->sc.sc_clkmsk);
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) | CLKD(150) << clksft);
    SDHC_WRITE(sc, SDHC_CLOCK_CTL,
               SDHC_READ(sc, SDHC_CLOCK_CTL) | SDHC_SDCLK_ENABLE);

    return;

fail:
    if (sc->sc_ih) {
        intr_disestablish(sc->sc_ih);
        sc->sc_ih = NULL;
    }
    bus_space_unmap(sc->sc_bst, sc->sc_bsh, oa->obio_size);
}
Beispiel #6
0
void
sdhc_pci_attach(struct device *parent, struct device *self, void *aux)
{
	struct sdhc_pci_softc *sc = (struct sdhc_pci_softc *)self;
	struct pci_attach_args *pa = aux;
	pci_intr_handle_t ih;
	char const *intrstr;
	int slotinfo;
	int nslots;
	int usedma;
	int reg;
	bus_space_tag_t iot;
	bus_space_handle_t ioh;
	bus_size_t size;
	u_int32_t caps = 0;

	/* Some TI controllers needs special treatment. */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_TI &&
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_TI_PCI7XX1_SD &&
            pa->pa_function == 4)
		sdhc_takecontroller(pa);

	/* ENE controllers break if set to 0V bus power. */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_ENE &&
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENE_SDCARD)
		sc->sc.sc_flags |= SDHC_F_NOPWR0;

	/* Some RICOH controllers need to be bumped into the right mode. */
	if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
	    PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U823) {
		/* Enable SD2.0 mode. */
		sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0xfc);
		sdhc_pci_conf_write(pa, SDHC_PCI_MODE, SDHC_PCI_MODE_SD20);
		sdhc_pci_conf_write(pa, SDHC_PCI_MODE_KEY, 0x00);

		/*
		 * Some SD/MMC cards don't work with the default base
		 * clock frequency of 200MHz.  Lower it to 50Hz.
		 */
		sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x01);
		sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ, 50);
		sdhc_pci_conf_write(pa, SDHC_PCI_BASE_FREQ_KEY, 0x00);
	}

	if (pci_intr_map(pa, &ih)) {
		printf(": can't map interrupt\n");
		return;
	}

	intrstr = pci_intr_string(pa->pa_pc, ih);
	sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_SDMMC,
	    sdhc_intr, sc, sc->sc.sc_dev.dv_xname);
	if (sc->sc_ih == NULL) {
		printf(": can't establish interrupt\n");
		return;
	}
	printf(": %s\n", intrstr);

	/* Enable use of DMA if supported by the interface. */
	usedma = PCI_INTERFACE(pa->pa_class) == SDHC_PCI_INTERFACE_DMA;

	/*
	 * Map and attach all hosts supported by the host controller.
	 */
	slotinfo = pci_conf_read(pa->pa_pc, pa->pa_tag,
	    SDHC_PCI_CONF_SLOT_INFO);
	nslots = SDHC_PCI_NUM_SLOTS(slotinfo);

	/* Allocate an array big enough to hold all the possible hosts */
	sc->sc.sc_host = malloc(sizeof(struct sdhc_host *) * nslots, M_DEVBUF,
	    M_WAITOK);

	/* XXX: handle 64-bit BARs */
	for (reg = SDHC_PCI_BAR_START + SDHC_PCI_FIRST_BAR(slotinfo) *
		 sizeof(u_int32_t);
	     reg < SDHC_PCI_BAR_END && nslots > 0;
	     reg += sizeof(u_int32_t), nslots--) {

		if (pci_mem_find(pa->pa_pc, pa->pa_tag, reg,
		    NULL, NULL, NULL) != 0)
			continue;

		if (pci_mapreg_map(pa, reg, PCI_MAPREG_TYPE_MEM, 0,
		    &iot, &ioh, NULL, &size, 0)) {
			printf("%s at 0x%x: can't map registers\n",
			    sc->sc.sc_dev.dv_xname, reg);
			continue;
		}

		if (sdhc_host_found(&sc->sc, iot, ioh, size, usedma, caps) != 0)
			/* XXX: sc->sc_host leak */
			printf("%s at 0x%x: can't initialize host\n",
			    sc->sc.sc_dev.dv_xname, reg);
	}
}