示例#1
0
static int zynqmp_qspi_start_io(struct zynqmp_qspi_priv *priv,
				u32 gen_fifo_cmd, u32 *buf)
{
	u32 len;
	u32 actuallen = priv->len;
	u32 config_reg, ier, isr;
	u32 timeout = GQSPI_TIMEOUT;
	struct zynqmp_qspi_regs *regs = priv->regs;
	u32 last_bits;
	u32 *traverse = buf;

	while (priv->len) {
		len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
		/* If exponent bit is set, reset immediate to be 2^len */
		if (gen_fifo_cmd & GQSPI_GFIFO_EXP_MASK)
			priv->bytes_to_receive = (1 << len);
		else
			priv->bytes_to_receive = len;
		zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);
		debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd);
		/* Manual start */
		config_reg = readl(&regs->confr);
		config_reg |= GQSPI_STRT_GEN_FIFO;
		writel(config_reg, &regs->confr);
		/* Enable RX interrupts for IO mode */
		ier = readl(&regs->ier);
		ier |= GQSPI_IXR_ALL_MASK;
		writel(ier, &regs->ier);
		while (priv->bytes_to_receive && timeout) {
			isr = readl(&regs->isr);
			if (isr & GQSPI_IXR_RXNEMTY_MASK) {
				if (priv->bytes_to_receive >= 4) {
					*traverse = readl(&regs->drxr);
					traverse++;
					priv->bytes_to_receive -= 4;
				} else {
					last_bits = readl(&regs->drxr);
					memcpy(traverse, &last_bits,
					       priv->bytes_to_receive);
					priv->bytes_to_receive = 0;
				}
				timeout = GQSPI_TIMEOUT;
			} else {
				udelay(1);
				timeout--;
			}
		}

		debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n",
		      (unsigned long)buf, (unsigned long)priv->rx_buf,
		      *buf, actuallen);
		if (!timeout) {
			printf("IO timeout: %d\n", readl(&regs->isr));
			return -1;
		}
	}

	return 0;
}
示例#2
0
static int zynqmp_qspi_start_dma(struct zynqmp_qspi_priv *priv,
				 u32 gen_fifo_cmd, u32 *buf)
{
	u32 addr;
	u32 size, len;
	u32 actuallen = priv->len;
	int ret = 0;
	struct zynqmp_qspi_dma_regs *dma_regs = priv->dma_regs;

	writel((unsigned long)buf, &dma_regs->dmadst);
	writel(roundup(priv->len, ARCH_DMA_MINALIGN), &dma_regs->dmasize);
	writel(GQSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier);
	addr = (unsigned long)buf;
	size = roundup(priv->len, ARCH_DMA_MINALIGN);
	flush_dcache_range(addr, addr + size);

	while (priv->len) {
		len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
		if (!(gen_fifo_cmd & GQSPI_GFIFO_EXP_MASK) &&
		    (len % ARCH_DMA_MINALIGN)) {
			gen_fifo_cmd &= ~GENMASK(7, 0);
			gen_fifo_cmd |= roundup(len, ARCH_DMA_MINALIGN);
		}
		zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd);

		debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd);
	}

	ret = wait_for_bit_le32(&dma_regs->dmaisr, GQSPI_DMA_DST_I_STS_DONE,
				1, GQSPI_TIMEOUT, 1);
	if (ret) {
		printf("DMA Timeout:0x%x\n", readl(&dma_regs->dmaisr));
		return -ETIMEDOUT;
	}

	writel(GQSPI_DMA_DST_I_STS_DONE, &dma_regs->dmaisr);

	debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n",
	      (unsigned long)buf, (unsigned long)priv->rx_buf, *buf,
	      actuallen);

	if (buf != priv->rx_buf)
		memcpy(priv->rx_buf, buf, actuallen);

	return 0;
}
示例#3
0
static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv)
{
	u32 gen_fifo_cmd;
	u32 len;
	int ret = 0;
	struct zynqmp_qspi_regs *regs = priv->regs;

	gen_fifo_cmd = zynqmp_qspi_bus_select(priv);
	gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_TX |
			ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK;

	if (priv->stripe)
		gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK;

	if (last_cmd == QUAD_PAGE_PROGRAM_CMD)
		gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_QSPI;
	else
		gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI;

	while (priv->len) {
		len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
		writel(gen_fifo_cmd, &regs->genfifo);

		debug("GFIFO_CMD_TX:0x%x\n", gen_fifo_cmd);

		if (gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK)
			ret = zynqmp_qspi_fill_tx_fifo(priv,
						       1 << len);
		else
			ret = zynqmp_qspi_fill_tx_fifo(priv,
						       len);

		if (ret)
			return ret;
	}
	return ret;
}
示例#4
0
static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv)
{
	u32 gen_fifo_cmd;
	u32 *buf;
	u32 addr;
	u32 size, len;
	u32 timeout = 10000000;
	u32 actuallen = priv->len;
	struct zynqmp_qspi_regs *regs = priv->regs;
	struct zynqmp_qspi_dma_regs *dma_regs = priv->dma_regs;

	gen_fifo_cmd = zynqmp_qspi_bus_select(priv);
	gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_RX |
			ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK;

	if (last_cmd == QUAD_OUT_READ_CMD)
		gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_QSPI;
	else
		gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI;

	if (priv->stripe)
		gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK;

	if (!((u32)priv->rx_buf & 0x3) && !(actuallen % 4)) {
		buf = (u32 *)priv->rx_buf;
	} else {
		ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, 4));
		buf = (u32 *)tmp;
	}
	writel((u32)buf, &dma_regs->dmadst);
	writel(roundup(priv->len, 4), &dma_regs->dmasize);
	writel(ZYNQMP_QSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier);
	addr = (u32)buf;
	size = roundup(priv->len, ARCH_DMA_MINALIGN);
	flush_dcache_range(addr, addr+size);

	while (priv->len) {
		len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd);
		if (!(gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK) &&
		    (len % 4)) {
			gen_fifo_cmd &= ~(0xFF);
			gen_fifo_cmd |= (len/4 + 1) * 4;
		}
		writel(gen_fifo_cmd, &regs->genfifo);

		debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd);
	}

	while (timeout) {
		if (readl(&dma_regs->dmaisr) &
		    ZYNQMP_QSPI_DMA_DST_I_STS_DONE) {
			writel(ZYNQMP_QSPI_DMA_DST_I_STS_DONE,
			       &dma_regs->dmaisr);
			break;
		}
		timeout--;
	}

	debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n",
	      (unsigned long)buf, (unsigned long)priv->rx_buf, *buf,
	      actuallen);
	if (!timeout) {
		debug("DMA Timeout:0x%x\n", readl(&dma_regs->dmaisr));
		return -1;
	}

	if (buf != priv->rx_buf)
		memcpy(priv->rx_buf, buf, actuallen);

	return 0;
}