version 1.44, 2014/05/24 12:10:32 |
version 1.44.2.7, 2015/03/09 09:29:33 |
Line 222 sdhc_cfprint(void *aux, const char *pnp) |
|
Line 222 sdhc_cfprint(void *aux, const char *pnp) |
|
{ |
{ |
const struct sdmmcbus_attach_args * const saa = aux; |
const struct sdmmcbus_attach_args * const saa = aux; |
const struct sdhc_host * const hp = saa->saa_sch; |
const struct sdhc_host * const hp = saa->saa_sch; |
|
|
if (pnp) { |
if (pnp) { |
aprint_normal("sdmmc at %s", pnp); |
aprint_normal("sdmmc at %s", pnp); |
} |
} |
Line 268 sdhc_host_found(struct sdhc_softc *sc, b |
|
Line 268 sdhc_host_found(struct sdhc_softc *sc, b |
|
mutex_init(&hp->intr_mtx, MUTEX_DEFAULT, IPL_SDMMC); |
mutex_init(&hp->intr_mtx, MUTEX_DEFAULT, IPL_SDMMC); |
cv_init(&hp->intr_cv, "sdhcintr"); |
cv_init(&hp->intr_cv, "sdhcintr"); |
|
|
sdhcver = HREAD2(hp, SDHC_HOST_CTL_VERSION); |
if (ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) { |
|
sdhcver = HREAD4(hp, SDHC_ESDHC_HOST_CTL_VERSION); |
|
} else { |
|
sdhcver = HREAD2(hp, SDHC_HOST_CTL_VERSION); |
|
} |
aprint_normal_dev(sc->sc_dev, "SD Host Specification "); |
aprint_normal_dev(sc->sc_dev, "SD Host Specification "); |
hp->specver = SDHC_SPEC_VERSION(sdhcver); |
hp->specver = SDHC_SPEC_VERSION(sdhcver); |
switch (SDHC_SPEC_VERSION(sdhcver)) { |
switch (SDHC_SPEC_VERSION(sdhcver)) { |
Line 353 sdhc_host_found(struct sdhc_softc *sc, b |
|
Line 357 sdhc_host_found(struct sdhc_softc *sc, b |
|
/* |
/* |
* Determine SD bus voltage levels supported by the controller. |
* Determine SD bus voltage levels supported by the controller. |
*/ |
*/ |
if (ISSET(caps, SDHC_EMBEDDED_SLOT) && |
if (ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V) && |
ISSET(caps, SDHC_VOLTAGE_SUPP_1_8V)) { |
(hp->specver < SDHC_SPEC_VERS_300 || |
|
ISSET(caps, SDHC_EMBEDDED_SLOT))) { |
SET(hp->ocr, MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V); |
SET(hp->ocr, MMC_OCR_1_7V_1_8V | MMC_OCR_1_8V_1_9V); |
} |
} |
if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_0V)) { |
if (ISSET(caps, SDHC_VOLTAGE_SUPP_3_0V)) { |
Line 420 sdhc_host_found(struct sdhc_softc *sc, b |
|
Line 425 sdhc_host_found(struct sdhc_softc *sc, b |
|
if (ISSET(caps, SDHC_HIGH_SPEED_SUPP)) |
if (ISSET(caps, SDHC_HIGH_SPEED_SUPP)) |
saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED; |
saa.saa_caps |= SMC_CAPS_SD_HIGHSPEED; |
if (ISSET(hp->flags, SHF_USE_DMA)) { |
if (ISSET(hp->flags, SHF_USE_DMA)) { |
saa.saa_caps |= SMC_CAPS_DMA | SMC_CAPS_MULTI_SEG_DMA; |
saa.saa_caps |= SMC_CAPS_DMA; |
|
if (!ISSET(hp->sc->sc_flags, SDHC_FLAG_ENHANCED)) |
|
saa.saa_caps |= SMC_CAPS_MULTI_SEG_DMA; |
} |
} |
if (ISSET(sc->sc_flags, SDHC_FLAG_SINGLE_ONLY)) |
if (ISSET(sc->sc_flags, SDHC_FLAG_SINGLE_ONLY)) |
saa.saa_caps |= SMC_CAPS_SINGLE_ONLY; |
saa.saa_caps |= SMC_CAPS_SINGLE_ONLY; |
Line 813 sdhc_clock_divisor(struct sdhc_host *hp, |
|
Line 820 sdhc_clock_divisor(struct sdhc_host *hp, |
|
} |
} |
if (hp->specver == SDHC_SPEC_VERS_300) { |
if (hp->specver == SDHC_SPEC_VERS_300) { |
div = howmany(hp->clkbase, freq); |
div = howmany(hp->clkbase, freq); |
|
div = div > 1 ? howmany(div, 2) : 0; |
if (div > 0x3ff) |
if (div > 0x3ff) |
return false; |
return false; |
*divp = (((div >> 8) & SDHC_SDCLK_XDIV_MASK) |
*divp = (((div >> 8) & SDHC_SDCLK_XDIV_MASK) |
Line 1031 sdhc_card_enable_intr(sdmmc_chipset_hand |
|
Line 1039 sdhc_card_enable_intr(sdmmc_chipset_hand |
|
} |
} |
} |
} |
|
|
static void |
static void |
sdhc_card_intr_ack(sdmmc_chipset_handle_t sch) |
sdhc_card_intr_ack(sdmmc_chipset_handle_t sch) |
{ |
{ |
struct sdhc_host *hp = (struct sdhc_host *)sch; |
struct sdhc_host *hp = (struct sdhc_host *)sch; |
Line 1074 sdhc_exec_command(sdmmc_chipset_handle_t |
|
Line 1082 sdhc_exec_command(sdmmc_chipset_handle_t |
|
} else { |
} else { |
HSET2(hp, SDHC_NINTR_SIGNAL_EN, ready); |
HSET2(hp, SDHC_NINTR_SIGNAL_EN, ready); |
HSET2(hp, SDHC_NINTR_STATUS_EN, ready); |
HSET2(hp, SDHC_NINTR_STATUS_EN, ready); |
} |
} |
mutex_exit(&hp->intr_mtx); |
mutex_exit(&hp->intr_mtx); |
} |
} |
|
|
Line 1196 sdhc_start_command(struct sdhc_host *hp, |
|
Line 1204 sdhc_start_command(struct sdhc_host *hp, |
|
/* XXX only for memory commands? */ |
/* XXX only for memory commands? */ |
mode |= SDHC_AUTO_CMD12_ENABLE; |
mode |= SDHC_AUTO_CMD12_ENABLE; |
} |
} |
if (cmd->c_dmamap != NULL && cmd->c_datalen > 0) { |
if (cmd->c_dmamap != NULL && cmd->c_datalen > 0 && |
|
!ISSET(sc->sc_flags, SDHC_FLAG_EXTERNAL_DMA)) { |
mode |= SDHC_DMA_ENABLE; |
mode |= SDHC_DMA_ENABLE; |
} |
} |
|
|
Line 1269 sdhc_start_command(struct sdhc_host *hp, |
|
Line 1278 sdhc_start_command(struct sdhc_host *hp, |
|
static void |
static void |
sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd) |
sdhc_transfer_data(struct sdhc_host *hp, struct sdmmc_command *cmd) |
{ |
{ |
|
struct sdhc_softc *sc = hp->sc; |
int error; |
int error; |
|
|
DPRINTF(1,("%s: data transfer: resp=%08x datalen=%u\n", HDEVNAME(hp), |
DPRINTF(1,("%s: data transfer: resp=%08x datalen=%u\n", HDEVNAME(hp), |
Line 1284 sdhc_transfer_data(struct sdhc_host *hp, |
|
Line 1294 sdhc_transfer_data(struct sdhc_host *hp, |
|
} |
} |
#endif |
#endif |
|
|
if (cmd->c_dmamap != NULL) |
if (cmd->c_dmamap != NULL) { |
error = sdhc_transfer_data_dma(hp, cmd); |
if (hp->sc->sc_vendor_transfer_data_dma != NULL) { |
else |
error = hp->sc->sc_vendor_transfer_data_dma(sc, cmd); |
|
if (error == 0 && !sdhc_wait_intr(hp, |
|
SDHC_TRANSFER_COMPLETE, SDHC_TRANSFER_TIMEOUT)) { |
|
error = ETIMEDOUT; |
|
} |
|
} else { |
|
error = sdhc_transfer_data_dma(hp, cmd); |
|
} |
|
} else |
error = sdhc_transfer_data_pio(hp, cmd); |
error = sdhc_transfer_data_pio(hp, cmd); |
if (error) |
if (error) |
cmd->c_error = error; |
cmd->c_error = error; |
Line 1640 sdhc_wait_intr(struct sdhc_host *hp, int |
|
Line 1658 sdhc_wait_intr(struct sdhc_host *hp, int |
|
|
|
DPRINTF(2,("%s: intr status %#x error %#x\n", HDEVNAME(hp), status, |
DPRINTF(2,("%s: intr status %#x error %#x\n", HDEVNAME(hp), status, |
hp->intr_error_status)); |
hp->intr_error_status)); |
|
|
/* Command timeout has higher priority than command complete. */ |
/* Command timeout has higher priority than command complete. */ |
if (ISSET(status, SDHC_ERROR_INTERRUPT) || hp->intr_error_status) { |
if (ISSET(status, SDHC_ERROR_INTERRUPT) || hp->intr_error_status) { |
hp->intr_error_status = 0; |
hp->intr_error_status = 0; |
Line 1698 sdhc_intr(void *arg) |
|
Line 1716 sdhc_intr(void *arg) |
|
HWRITE2(hp, SDHC_EINTR_STATUS, error); |
HWRITE2(hp, SDHC_EINTR_STATUS, error); |
} |
} |
} |
} |
|
|
DPRINTF(2,("%s: interrupt status=%x error=%x\n", HDEVNAME(hp), |
DPRINTF(2,("%s: interrupt status=%x error=%x\n", HDEVNAME(hp), |
status, error)); |
status, error)); |
|
|
Line 1721 sdhc_intr(void *arg) |
|
Line 1739 sdhc_intr(void *arg) |
|
* Wake up the sdmmc event thread to scan for cards. |
* Wake up the sdmmc event thread to scan for cards. |
*/ |
*/ |
if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) { |
if (ISSET(status, SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)) { |
sdmmc_needs_discover(hp->sdmmc); |
if (hp->sdmmc != NULL) { |
|
sdmmc_needs_discover(hp->sdmmc); |
|
} |
if (ISSET(sc->sc_flags, SDHC_FLAG_ENHANCED)) { |
if (ISSET(sc->sc_flags, SDHC_FLAG_ENHANCED)) { |
HCLR4(hp, SDHC_NINTR_STATUS_EN, |
HCLR4(hp, SDHC_NINTR_STATUS_EN, |
status & (SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)); |
status & (SDHC_CARD_REMOVAL|SDHC_CARD_INSERTION)); |