static bool wb_sdmmc_enable(struct wb_softc *wb) { int i = 5000; REPORT(wb, "TRACE: enable(wb)\n"); /* put the device in a known state */ wb_idx_write(wb, WB_INDEX_SETUP, WB_SETUP_SOFT_RST); while (--i > 0 && wb_idx_read(wb, WB_INDEX_SETUP) & WB_SETUP_SOFT_RST) delay(10); if (i == 0) { aprint_error_dev(wb->wb_dev, "timeout resetting device\n"); return false; } wb_idx_write(wb, WB_INDEX_CLK, WB_CLK_375K); wb_idx_write(wb, WB_INDEX_FIFOEN, 0); wb_idx_write(wb, WB_INDEX_DMA, 0); wb_idx_write(wb, WB_INDEX_PBSMSB, 0); wb_idx_write(wb, WB_INDEX_PBSLSB, 0); /* drain FIFO */ while ((wb_read(wb, WB_SD_FIFOSTS) & WB_FIFO_EMPTY) == 0) wb_read(wb, WB_SD_FIFO); wb_write(wb, WB_SD_CSR, 0); wb_write(wb, WB_SD_INTCTL, WB_INT_DEFAULT); wb_sdmmc_card_detect(wb); return true; }
static int wb_sdmmc_transfer_data(struct wb_softc *wb, struct sdmmc_command *cmd) { uint8_t fifosts; int datalen, retry = 5000; if (wb->wb_sdmmc_intsts & WB_INT_CARD) return EIO; fifosts = wb_read(wb, WB_SD_FIFOSTS); if (ISSET(cmd->c_flags, SCF_CMD_READ)) { if (fifosts & WB_FIFO_EMPTY) { while (--retry > 0) { fifosts = wb_read(wb, WB_SD_FIFOSTS); if ((fifosts & WB_FIFO_EMPTY) == 0) break; delay(100); } if (retry == 0) return EBUSY; } if (fifosts & WB_FIFO_FULL) datalen = 16; else datalen = fifosts & WB_FIFO_DEPTH_MASK; } else { if (fifosts & WB_FIFO_FULL) { while (--retry > 0) { fifosts = wb_read(wb, WB_SD_FIFOSTS); if ((fifosts & WB_FIFO_FULL) == 0) break; delay(100); } if (retry == 0) return EBUSY; } if (fifosts & WB_FIFO_EMPTY) datalen = 16; else datalen = 16 - (fifosts & WB_FIFO_DEPTH_MASK); } datalen = MIN(datalen, cmd->c_resid); if (datalen > 0) { if (ISSET(cmd->c_flags, SCF_CMD_READ)) wb_sdmmc_read_data(wb, cmd->c_buf, datalen); else wb_sdmmc_write_data(wb, cmd->c_buf, datalen); cmd->c_buf += datalen; cmd->c_resid -= datalen; } return 0; }
/* * intr handler */ int wb_sdmmc_intr(struct wb_softc *wb) { uint8_t val; val = wb_read(wb, WB_SD_INTSTS); if (val == 0xff || val == 0x00) return 0; if (wb->wb_sdmmc_dev == NULL) return 1; wb->wb_sdmmc_intsts |= val; if (wb_sdmmc_debug) { char buf[64]; snprintb(buf, sizeof(buf), "\20\1TC\2BUSYEND\3PROGEND\4TIMEOUT" "\5CRC\6FIFO\7CARD\010PENDING", val); REPORT(wb, "WB_SD_INTSTS = %s\n", buf); } if (val & WB_INT_CARD) callout_schedule(&wb->wb_sdmmc_callout, hz / 4); return 1; }
void wb_led(struct wb_softc *wb, bool enable) { uint8_t val; val = wb_read(wb, WB_SD_CSR); if (enable) val |= WB_CSR_MS_LED; else val &= ~WB_CSR_MS_LED; wb_write(wb, WB_SD_CSR, val); }
static bool wb_sdmmc_disable(struct wb_softc *wb) { uint8_t val; REPORT(wb, "TRACE: disable(wb)\n"); val = wb_read(wb, WB_SD_CSR); val |= WB_CSR_POWER_N; wb_write(wb, WB_SD_CSR, val); return true; }
static int wb_sdmmc_write_protect(sdmmc_chipset_handle_t sch) { struct wb_softc *wb = sch; int rv; wb_led(wb, true); rv = (wb_read(wb, WB_SD_CSR) & WB_CSR_WRITE_PROTECT) ? 1 : 0; wb_led(wb, false); REPORT(wb, "TRACE: sdmmc/write_protect(wb) -> %d\n", rv); return rv; }
static int wb_sdmmc_card_detect(sdmmc_chipset_handle_t sch) { struct wb_softc *wb = sch; int rv; wb_led(wb, true); rv = (wb_read(wb, WB_SD_CSR) & WB_CSR_CARD_PRESENT) ? 1 : 0; wb_led(wb, false); REPORT(wb, "TRACE: sdmmc/card_detect(wb) -> %d\n", rv); return rv; }
unsigned char inb (unsigned long port) { return wb_read(port); }