static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, u32 start_addr) { u32 ctrl, stat, rdy, mask, timeout, block = 0; if (host->sdhci_caps & SDHCI_CAN_DO_SDMA) { ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; ctrl |= SDHCI_CTRL_SDMA; sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL); } timeout = 1000000; rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL; mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE; do { stat = sdhci_readl(host, SDHCI_INT_STATUS); if (stat & SDHCI_INT_ERROR) { vmm_printf("%s: Error detected in status(0x%X)!\n", __func__, stat); return VMM_EFAIL; } if (stat & rdy) { if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)) { continue; } sdhci_writel(host, rdy, SDHCI_INT_STATUS); sdhci_transfer_pio(host, data); data->dest += data->blocksize; if (++block >= data->blocks) { break; } } if (host->sdhci_caps & SDHCI_CAN_DO_SDMA) { if (stat & SDHCI_INT_DMA_END) { sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS); start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1); start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE; sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS); } } if (timeout-- > 0) { vmm_udelay(10); } else { vmm_printf("%s: Transfer data timeout\n", __func__); return VMM_ETIMEDOUT; } } while (!(stat & SDHCI_INT_DATA_END)); return VMM_OK; }
static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, unsigned int start_addr) { unsigned int stat, rdy, mask, timeout, block = 0; bool transfer_done = false; #ifdef CONFIG_MMC_SDHCI_SDMA unsigned char ctrl; ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); #endif timeout = 1000000; rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL; mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE; do { stat = sdhci_readl(host, SDHCI_INT_STATUS); if (stat & SDHCI_INT_ERROR) { pr_debug("%s: Error detected in status(0x%X)!\n", __func__, stat); return -EIO; } if (!transfer_done && (stat & rdy)) { if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)) continue; sdhci_writel(host, rdy, SDHCI_INT_STATUS); sdhci_transfer_pio(host, data); data->dest += data->blocksize; if (++block >= data->blocks) { /* Keep looping until the SDHCI_INT_DATA_END is * cleared, even if we finished sending all the * blocks. */ transfer_done = true; continue; } } #ifdef CONFIG_MMC_SDHCI_SDMA if (!transfer_done && (stat & SDHCI_INT_DMA_END)) { sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS); start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1); start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE; sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS); } #endif if (timeout-- > 0) udelay(10); else { printf("%s: Transfer data timeout\n", __func__); return -ETIMEDOUT; } } while (!(stat & SDHCI_INT_DATA_END)); return 0; }
static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, unsigned int start_addr) { unsigned int stat, rdy, mask, timeout, block = 0; #ifdef CONFIG_MMC_SDMA unsigned char ctrl; ctrl = sdhci_readl(host, SDHCI_HOST_CONTROL); ctrl &= ~SDHCI_CTRL_DMA_MASK; ctrl |= SDHCI_CTRL_SDMA; sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL); #endif timeout = 1000000; rdy = SDHCI_INT_SPACE_AVAIL | SDHCI_INT_DATA_AVAIL; mask = SDHCI_DATA_AVAILABLE | SDHCI_SPACE_AVAILABLE; do { stat = sdhci_readl(host, SDHCI_INT_STATUS); if (stat & SDHCI_INT_ERROR) { printf("Error detected in status(0x%X)!\n", stat); return -1; } if (stat & rdy) { if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & mask)) continue; sdhci_writel(host, rdy, SDHCI_INT_STATUS); sdhci_transfer_pio(host, data); data->dest += data->blocksize; if (++block >= data->blocks) break; } #ifdef CONFIG_MMC_SDMA if (stat & SDHCI_INT_DMA_END) { sdhci_writel(host, SDHCI_INT_DMA_END, SDHCI_INT_STATUS); start_addr &= ~(SDHCI_DEFAULT_BOUNDARY_SIZE - 1); start_addr += SDHCI_DEFAULT_BOUNDARY_SIZE; sdhci_writel(host, start_addr, SDHCI_DMA_ADDRESS); } #endif if (timeout-- > 0) udelay(10); else { printf("Transfer data timeout\n"); return -1; } } while (!(stat & SDHCI_INT_DATA_END)); return 0; }