static int ms_transfer_data(struct realtek_pci_ms *host, unsigned char data_dir, u8 tpc, u8 cfg, struct scatterlist *sg) { struct rtsx_pcr *pcr = host->pcr; int err; unsigned int length = sg->length; u16 sec_cnt = (u16)(length / 512); u8 val, trans_mode, dma_dir; dev_dbg(ms_dev(host), "%s: tpc = 0x%02x, data_dir = %s, length = %d\n", __func__, tpc, (data_dir == READ) ? "READ" : "WRITE", length); if (data_dir == READ) { dma_dir = DMA_DIR_FROM_CARD; trans_mode = MS_TM_AUTO_READ; } else { dma_dir = DMA_DIR_TO_CARD; trans_mode = MS_TM_AUTO_WRITE; } rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TPC, 0xFF, tpc); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(length >> 24)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(length >> 16)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(length >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)length); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, dma_dir | DMA_EN | DMA_512); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END); rtsx_pci_send_cmd_no_wait(pcr); err = rtsx_pci_transfer_data(pcr, sg, 1, data_dir == READ, 10000); if (err < 0) { ms_clear_error(host); return err; } rtsx_pci_read_register(pcr, MS_TRANS_CFG, &val); if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT)) return -EIO; return 0; }
static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) { struct rtsx_pcr *pcr = host->pcr; struct mmc_host *mmc = host->mmc; struct mmc_card *card = mmc->card; struct mmc_data *data = mrq->data; int uhs = mmc_sd_card_uhs(card); int read = (data->flags & MMC_DATA_READ) ? 1 : 0; u8 cfg2, trans_mode; int err; size_t data_len = data->blksz * data->blocks; if (read) { cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 | SD_RSP_LEN_0; trans_mode = SD_TM_AUTO_READ_3; } else { cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 | SD_RSP_LEN_0; trans_mode = SD_TM_AUTO_WRITE_3; } if (!uhs) cfg2 |= SD_NO_CHECK_WAIT_CRC_TO; rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_L, 0xFF, 0x00); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BYTE_CNT_H, 0xFF, 0x02); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_L, 0xFF, (u8)data->blocks); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_BLOCK_CNT_H, 0xFF, (u8)(data->blocks >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(data_len >> 24)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(data_len >> 16)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(data_len >> 8)); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMATC0, 0xFF, (u8)data_len); if (read) { rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, DMA_DIR_FROM_CARD | DMA_EN | DMA_512); } else { rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, DMACTL, 0x03 | DMA_PACK_SIZE_MASK, DMA_DIR_TO_CARD | DMA_EN | DMA_512); } rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_TRANSFER, 0xFF, trans_mode | SD_TRANSFER_START); rtsx_pci_add_cmd(pcr, CHECK_REG_CMD, SD_TRANSFER, SD_TRANSFER_END, SD_TRANSFER_END); rtsx_pci_send_cmd_no_wait(pcr); err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); if (err < 0) { sd_clear_error(host); return err; } return 0; }