Exemple #1
0
static void omap_mmc_transfer(struct omap_mmc_s *host)
{
    uint8_t value;

    if (!host->transfer)
        return;

    while (1) {
        if (host->ddir) {
            if (host->fifo_len > host->af_level)
                break;

            value = sd_read_data(host->card);
            host->fifo[(host->fifo_start + host->fifo_len) & 31] = value;
            if (-- host->blen_counter) {
                value = sd_read_data(host->card);
                host->fifo[(host->fifo_start + host->fifo_len) & 31] |=
                        value << 8;
                host->blen_counter --;
            }

            host->fifo_len ++;
        } else {
            if (!host->fifo_len)
                break;

            value = host->fifo[host->fifo_start] & 0xff;
            sd_write_data(host->card, value);
            if (-- host->blen_counter) {
                value = host->fifo[host->fifo_start] >> 8;
                sd_write_data(host->card, value);
                host->blen_counter --;
            }

            host->fifo_start ++;
            host->fifo_len --;
            host->fifo_start &= 31;
        }

        if (host->blen_counter == 0) {
            host->nblk_counter --;
            host->blen_counter = host->blen;

            if (host->nblk_counter == 0) {
                host->nblk_counter = host->nblk;
                host->transfer = 0;
                host->status |= 0x0008;
                break;
            }
        }
    }
Exemple #2
0
static void pxa2xx_mmci_fifo_update(PXA2xxMMCIState *s)
{
    if (!s->active)
        return;

    if (s->cmdat & CMDAT_WR_RD) {
        while (s->bytesleft && s->tx_len) {
            sd_write_data(s->card, s->tx_fifo[s->tx_start ++]);
            s->tx_start &= 0x1f;
            s->tx_len --;
            s->bytesleft --;
        }
        if (s->bytesleft)
            s->intreq |= INT_TXFIFO_REQ;
    } else
        while (s->bytesleft && s->rx_len < 32) {
            s->rx_fifo[(s->rx_start + (s->rx_len ++)) & 0x1f] =
                sd_read_data(s->card);
            s->bytesleft --;
            s->intreq |= INT_RXFIFO_REQ;
        }

    if (!s->bytesleft) {
        s->active = 0;
        s->intreq |= INT_DATA_DONE;
        s->status |= STAT_DATA_DONE;

        if (s->cmdat & CMDAT_WR_RD) {
            s->intreq |= INT_PRG_DONE;
            s->status |= STAT_PRG_DONE;
        }
    }

    pxa2xx_mmci_int_update(s);
}
static int sd_generic_write(struct sd_host *host,
			    u8 opcode, u32 arg,
			    void *data, size_t len, int token)
{
	struct sd_command *cmd = &host->cmd;
	int retval;

	/* build raw command */
	sd_cmd(cmd, opcode, arg);

	/* select card, send command and wait for response */
	retval = sd_start_command(host, cmd);
	if (retval < 0)
		goto out;
	if (retval != 0x00) {
		retval = -EIO;
		goto out;
	}

	/* send data token, data and crc, get data response */
	retval = sd_write_data(host, data, len, token);
	if (retval < 0)
		goto out;

	retval = 0;

out:
	/* burn extra cycles and deselect card */
	sd_end_command(host);

	if (retval < 0)
		DBG("write, offset=%d, len=%d\n", arg, len);

	return retval;
}
Exemple #4
0
static void memcard_write(void *opaque, hwaddr addr, uint64_t value,
                          unsigned size)
{
    MilkymistMemcardState *s = opaque;

    trace_milkymist_memcard_memory_write(addr, value);

    addr >>= 2;
    switch (addr) {
    case R_PENDING:
        /* clear rx pending bits */
        s->regs[R_PENDING] &= ~(value & (PENDING_CMD_RX | PENDING_DAT_RX));
        update_pending_bits(s);
        break;
    case R_CMD:
        if (!s->enabled) {
            break;
        }
        if (s->ignore_next_cmd) {
            s->ignore_next_cmd = 0;
            break;
        }
        s->command[s->command_write_ptr] = value & 0xff;
        s->command_write_ptr = (s->command_write_ptr + 1) % 6;
        if (s->command_write_ptr == 0) {
            memcard_sd_command(s);
        }
        break;
    case R_DAT:
        if (!s->enabled) {
            break;
        }
        sd_write_data(s->card, (value >> 24) & 0xff);
        sd_write_data(s->card, (value >> 16) & 0xff);
        sd_write_data(s->card, (value >> 8) & 0xff);
        sd_write_data(s->card, value & 0xff);
        break;
    case R_ENABLE:
        s->regs[addr] = value;
        update_pending_bits(s);
        break;
    case R_CLK2XDIV:
    case R_START:
        s->regs[addr] = value;
        break;

    default:
        error_report("milkymist_memcard: write access to unknown register 0x"
                TARGET_FMT_plx, addr << 2);
        break;
    }
}
Exemple #5
0
static void pl181_fifo_run(pl181_state *s)
{
    uint32_t bits;
    uint32_t value;
    int n;
    int limit;
    int is_read;

    is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
    if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
            && !s->linux_hack) {
        limit = is_read ? PL181_FIFO_LEN : 0;
        n = 0;
        value = 0;
        while (s->datacnt && s->fifo_len != limit) {
            if (is_read) {
                value |= (uint32_t)sd_read_data(s->card) << (n * 8);
                n++;
                if (n == 4) {
                    pl181_fifo_push(s, value);
                    value = 0;
                    n = 0;
                }
            } else {
                if (n == 0) {
                    value = pl181_fifo_pop(s);
                    n = 4;
                }
                sd_write_data(s->card, value & 0xff);
                value >>= 8;
                n--;
            }
            s->datacnt--;
        }
        if (n && is_read) {
            pl181_fifo_push(s, value);
        }
    }
Exemple #6
0
static void sd_normal_rw(struct realtek_pci_sdmmc *host,
		struct mmc_request *mrq)
{
	struct mmc_command *cmd = mrq->cmd;
	struct mmc_data *data = mrq->data;
	u8 _cmd[5], *buf;

	_cmd[0] = 0x40 | (u8)cmd->opcode;
	put_unaligned_be32(cmd->arg, (u32 *)(&_cmd[1]));

	buf = kzalloc(data->blksz, GFP_NOIO);
	if (!buf) {
		cmd->error = -ENOMEM;
		return;
	}

	if (data->flags & MMC_DATA_READ) {
		if (host->initial_mode)
			sd_disable_initial_mode(host);

		cmd->error = sd_read_data(host, _cmd, (u16)data->blksz, buf,
				data->blksz, 200);

		if (host->initial_mode)
			sd_enable_initial_mode(host);

		sg_copy_from_buffer(data->sg, data->sg_len, buf, data->blksz);
	} else {
		sg_copy_to_buffer(data->sg, data->sg_len, buf, data->blksz);

		cmd->error = sd_write_data(host, _cmd, (u16)data->blksz, buf,
				data->blksz, 200);
	}

	kfree(buf);
}
Exemple #7
0
static void pl181_fifo_run(pl181_state *s)
{
    uint32_t bits;
    uint32_t value = 0;
    int n;
    int is_read;

    is_read = (s->datactrl & PL181_DATA_DIRECTION) != 0;
    if (s->datacnt != 0 && (!is_read || sd_data_ready(s->card))
            && !s->linux_hack) {
        if (is_read) {
            n = 0;
            while (s->datacnt && s->fifo_len < PL181_FIFO_LEN) {
                value |= (uint32_t)sd_read_data(s->card) << (n * 8);
                s->datacnt--;
                n++;
                if (n == 4) {
                    pl181_fifo_push(s, value);
                    n = 0;
                    value = 0;
                }
            }
            if (n != 0) {
                pl181_fifo_push(s, value);
            }
        } else { /* write */
            n = 0;
            while (s->datacnt > 0 && (s->fifo_len > 0 || n > 0)) {
                if (n == 0) {
                    value = pl181_fifo_pop(s);
                    n = 4;
                }
                n--;
                s->datacnt--;
                sd_write_data(s->card, value & 0xff);
                value >>= 8;
            }
        }
    }
    s->status &= ~(PL181_STATUS_RX_FIFO | PL181_STATUS_TX_FIFO);
    if (s->datacnt == 0) {
        s->status |= PL181_STATUS_DATAEND;
        /* HACK: */
        s->status |= PL181_STATUS_DATABLOCKEND;
        DPRINTF("Transfer Complete\n");
    }
    if (s->datacnt == 0 && s->fifo_len == 0) {
        s->datactrl &= ~PL181_DATA_ENABLE;
        DPRINTF("Data engine idle\n");
    } else {
        /* Update FIFO bits.  */
        bits = PL181_STATUS_TXACTIVE | PL181_STATUS_RXACTIVE;
        if (s->fifo_len == 0) {
            bits |= PL181_STATUS_TXFIFOEMPTY;
            bits |= PL181_STATUS_RXFIFOEMPTY;
        } else {
            bits |= PL181_STATUS_TXDATAAVLBL;
            bits |= PL181_STATUS_RXDATAAVLBL;
        }
        if (s->fifo_len == 16) {
            bits |= PL181_STATUS_TXFIFOFULL;
            bits |= PL181_STATUS_RXFIFOFULL;
        }
        if (s->fifo_len <= 8) {
            bits |= PL181_STATUS_TXFIFOHALFEMPTY;
        }
        if (s->fifo_len >= 8) {
            bits |= PL181_STATUS_RXFIFOHALFFULL;
        }
        if (s->datactrl & PL181_DATA_DIRECTION) {
            bits &= PL181_STATUS_RX_FIFO;
        } else {
            bits &= PL181_STATUS_TX_FIFO;
        }
        s->status |= bits;
    }
}
Exemple #8
0
/* Transfer data between the card and the FIFO.  This is complicated by
   the FIFO holding 32-bit words and the card taking data in single byte
   chunks.  FIFO bytes are transferred in little-endian order.  */
static void mmc_fifo_run(S5pc1xxMMCState *s)
{
    uint32_t value;
    int n;
    uint32_t pos;
    int is_read;
    uint32_t datacnt, boundary_chk, boundary_count;
    uint8_t dma_buf_boundary, dma_mask_flag;

    is_read = (s->trnmod & S5C_HSMMC_TRNS_READ) != 0;

    if (s->blkcnt != 0 && (!is_read || sd_data_ready(s->card))) {
        n = 0;
        value = 0;

        if (s->blkcnt > 1) {
            /* multi block */
            if (s->norintstsen & 0x8)
                dma_mask_flag = 1;  /* DMA enable */
            else
                dma_mask_flag = 0;  /* DMA disable */

            dma_buf_boundary = (s->blksize & 0xf000) >> 12;
            boundary_chk = 1 << (dma_buf_boundary+12);
            boundary_count = boundary_chk - (s->sysad % boundary_chk);
            while (s->blkcnt) {
                datacnt = s->blksize & 0x0fff;
                pos = 0;
                while (datacnt) {
                    if (is_read) {
                        value |= (uint32_t)sd_read_data(s->card) << (n * 8);
                        n++;
                        if (n == 4) {
                            mmc_fifo_push(s, pos, value);
                            value = 0;
                            n = 0;
                            pos += 4;
                        }
                    } else {
                        if (n == 0) {
                            value = mmc_fifo_pop(s, pos);
                            n = 4;
                            pos += 4;
                        }
                        sd_write_data(s->card, value & 0xff);
                        value >>= 8;
                        n--;
                    }
                    datacnt--;
                }
                s->sysad += s->blksize & 0x0fff;
                boundary_count -= s->blksize & 0x0fff;
                s->blkcnt--;

                if ((boundary_count == 0) && dma_mask_flag)
                    break;
            }
            if (s->blkcnt == 0)
                s->norintsts |= S5C_HSMMC_NIS_TRSCMP;
            else
                s->norintsts |= S5C_HSMMC_NIS_DMA;
        } else {