Beispiel #1
0
static u32 ug_io_transaction(u32 in)
{
	u32 *csr_reg = ug_io_base + EXI_CSR;
	u32 *data_reg = ug_io_base + EXI_DATA;
	u32 *cr_reg = ug_io_base + EXI_CR;
	u32 csr, data, cr;

	/* select */
	csr = EXI_CSR_CLK_32MHZ | EXI_CSR_CS_0;
	out_be32(csr_reg, csr);

	/* read/write */
	data = in;
	out_be32(data_reg, data);
	cr = EXI_CR_TLEN(2) | EXI_CR_READ_WRITE | EXI_CR_TSTART;
	out_be32(cr_reg, cr);

	while (in_be32(cr_reg) & EXI_CR_TSTART)
		barrier();

	/* deselect */
	out_be32(csr_reg, 0);

	data = in_be32(data_reg);
	return data;
}
/*
 * Internal. Start a transfer using "interrupt-driven immediate" mode.
 */
static void exi_start_idi_transfer_raw(struct exi_channel *exi_channel,
				       void *data, size_t len, int mode)
{
	void __iomem *io_base = exi_channel->io_base;
	u32 __iomem *csr_reg = io_base + EXI_CSR;
	u32 val = ~0;
	unsigned long flags;

	BUG_ON(len < 1 || len > 4);

	exi_channel->stats_idi_xfers++;
	exi_channel->stats_xfers++;

	if ((mode & EXI_OP_WRITE)) {
		switch (len) {
		case 1:
			val = *((u8 *)data) << 24;
			break;
		case 2:
			val = *((u16 *)data) << 16;
			break;
		case 3:
			val = *((u16 *)data) << 16;
			val |= *((u8 *)data+2) << 8;
			break;
		case 4:
			val = *((u32 *)data);
			break;
		default:
			break;
		}
	}

	out_be32(io_base + EXI_DATA, val);

	/* enable the Transfer Complete interrupt */
	spin_lock_irqsave(&exi_channel->io_lock, flags);
	out_be32(csr_reg, in_be32(csr_reg) | EXI_CSR_TCINTMASK);
	spin_unlock_irqrestore(&exi_channel->io_lock, flags);

	/* start the transfer */
	out_be32(io_base + EXI_CR,
		 EXI_CR_TSTART | EXI_CR_TLEN(len) | (mode&0xf));
}