+static void glamo_mci_read_worker(struct work_struct *work)
+{
+ struct glamo_mci_host *host = container_of(work, struct glamo_mci_host,
+ read_work);
+ struct mmc_command *cmd;
+ uint16_t status;
+ uint16_t blocks_ready;
+ size_t data_read = 0;
+ size_t data_ready;
+ struct scatterlist *sg;
+ u16 __iomem *from_ptr = host->data_base;
+ void *sg_pointer;
+
+
+ cmd = host->mrq->cmd;
+ sg = cmd->data->sg;
+ do {
+ status = glamo_reg_read(host, GLAMO_REG_MMC_RB_STAT1);
+
+ if (status & (GLAMO_STAT1_MMC_RTOUT | GLAMO_STAT1_MMC_DTOUT))
+ cmd->error = -ETIMEDOUT;
+ if (status & (GLAMO_STAT1_MMC_BWERR | GLAMO_STAT1_MMC_BRERR))
+ cmd->error = -EILSEQ;
+ if (cmd->error) {
+ dev_info(&host->pdev->dev, "Error after cmd: 0x%x\n", status);
+ goto done;
+ }
+
+ blocks_ready = glamo_reg_read(host, GLAMO_REG_MMC_RB_BLKCNT);
+ data_ready = blocks_ready * cmd->data->blksz;
+
+ if (data_ready == data_read)
+ yield();
+
+ while(sg && data_read + sg->length <= data_ready) {
+ sg_pointer = page_address(sg_page(sg)) + sg->offset;
+ memcpy(sg_pointer, from_ptr, sg->length);
+ from_ptr += sg->length >> 1;
+
+ data_read += sg->length;
+ sg = sg_next(sg);
+ }
+
+ } while(sg);
+ cmd->data->bytes_xfered = data_read;
+
+ do {
+ status = glamo_reg_read(host, GLAMO_REG_MMC_RB_STAT1);
+ } while (!(status & GLAMO_STAT1_MMC_IDLE));
+
+ if (host->mrq->stop)
+ glamo_mci_send_command(host, host->mrq->stop);
+
+ do {
+ status = glamo_reg_read(host, GLAMO_REG_MMC_RB_STAT1);
+ } while (!(status & GLAMO_STAT1_MMC_IDLE));
+done:
+ host->mrq = NULL;
+ glamo_mci_request_done(host, cmd->mrq);
+}
+