Ejemplo n.º 1
0
/**
 * zynq_qspi_start_transfer - Initiates the QSPI transfer
 * @master:	Pointer to the spi_master structure which provides
 *		information about the controller.
 * @qspi:	Pointer to the spi_device structure
 * @transfer:	Pointer to the spi_transfer structure which provide information
 *		about next transfer parameters
 *
 * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
 * transfer to be completed.
 *
 * Return:	Number of bytes transferred in the last transfer
 */
static int zynq_qspi_start_transfer(struct spi_master *master,
				    struct spi_device *qspi,
				    struct spi_transfer *transfer)
{
	struct zynq_qspi *xqspi = spi_master_get_devdata(master);
	u32 data;

	xqspi->txbuf = transfer->tx_buf;
	xqspi->rxbuf = transfer->rx_buf;
	xqspi->bytes_to_transfer = transfer->len;
	xqspi->bytes_to_receive = transfer->len;

	zynq_qspi_setup_transfer(qspi, transfer);

	if (transfer->len >= 4) {
		zynq_qspi_fill_tx_fifo(xqspi, ZYNQ_QSPI_FIFO_DEPTH);
	} else {
		zynq_qspi_copy_write_data(xqspi, &data, transfer->len);

		if (!xqspi->is_dual || xqspi->is_instr)
			zynq_qspi_write(xqspi, ZYNQ_QSPI_TXD_00_01_OFFSET +
					((transfer->len - 1) * 4), data);
		else {
			zynq_qspi_tx_dual_parallel(xqspi, data, transfer->len);
		}
	}

	zynq_qspi_write(xqspi, ZYNQ_QSPI_IEN_OFFSET,
			ZYNQ_QSPI_IXR_ALL_MASK);

	return transfer->len;
}
Ejemplo n.º 2
0
/**
 * zynq_qspi_irq - Interrupt service routine of the QSPI controller
 * @irq:	IRQ number
 * @dev_id:	Pointer to the xqspi structure
 *
 * This function handles TX empty only.
 * On TX empty interrupt this function reads the received data from RX FIFO and
 * fills the TX FIFO if there is any data remaining to be transferred.
 *
 * Return:	IRQ_HANDLED when interrupt is handled; IRQ_NONE otherwise.
 */
static irqreturn_t zynq_qspi_irq(int irq, void *dev_id)
{
	struct spi_master *master = dev_id;
	struct zynq_qspi *xqspi = spi_master_get_devdata(master);
	u32 intr_status, rxcount, rxindex = 0;
	u8 offset[3] = {ZYNQ_QSPI_TXD_00_01_OFFSET, ZYNQ_QSPI_TXD_00_10_OFFSET,
			ZYNQ_QSPI_TXD_00_11_OFFSET};

	intr_status = zynq_qspi_read(xqspi, ZYNQ_QSPI_STATUS_OFFSET);
	zynq_qspi_write(xqspi, ZYNQ_QSPI_STATUS_OFFSET , intr_status);

	if ((intr_status & ZYNQ_QSPI_IXR_TXNFULL_MASK) ||
	    (intr_status & ZYNQ_QSPI_IXR_RXNEMTY_MASK)) {
		/*
		 * This bit is set when Tx FIFO has < THRESHOLD entries.
		 * We have the THRESHOLD value set to 1,
		 * so this bit indicates Tx FIFO is empty.
		 */
		u32 data;

		rxcount = xqspi->bytes_to_receive - xqspi->bytes_to_transfer;
		rxcount = (rxcount % 4) ? ((rxcount/4) + 1) : (rxcount/4);

		/* Read out the data from the RX FIFO */
		while ((rxindex < rxcount) &&
		       (rxindex < ZYNQ_QSPI_RX_THRESHOLD)) {
			if (xqspi->bytes_to_receive >= 4) {
				if (xqspi->rxbuf) {
					(*(u32 *)xqspi->rxbuf) =
					zynq_qspi_read(xqspi,
						       ZYNQ_QSPI_RXD_OFFSET);
					xqspi->rxbuf += 4;
				} else {
					data = zynq_qspi_read(xqspi,
							ZYNQ_QSPI_RXD_OFFSET);
				}
				xqspi->bytes_to_receive -= 4;
			} else {
				data = zynq_qspi_read(xqspi,
						      ZYNQ_QSPI_RXD_OFFSET);
				zynq_qspi_copy_read_data(xqspi, data,
						xqspi->bytes_to_receive);
			}
			rxindex++;
		}

		if (xqspi->bytes_to_transfer) {
			if (xqspi->bytes_to_transfer >= 4) {
				/* There is more data to send */
				zynq_qspi_fill_tx_fifo(xqspi,
						       ZYNQ_QSPI_RX_THRESHOLD);
			} else if (intr_status & ZYNQ_QSPI_IXR_TXNFULL_MASK) {
				int tmp;
				tmp = xqspi->bytes_to_transfer;
				zynq_qspi_copy_write_data(xqspi, &data,
					xqspi->bytes_to_transfer);

				if (!xqspi->is_dual || xqspi->is_instr)
					zynq_qspi_write(xqspi,
							offset[tmp - 1], data);
				else {
					zynq_qspi_tx_dual_parallel(xqspi, data,
								   tmp);
				}
			}
		} else {
			/*
			 * If transfer and receive is completed then only send
			 * complete signal.
			 */
			if (!xqspi->bytes_to_receive) {
				zynq_qspi_write(xqspi,
						ZYNQ_QSPI_IDIS_OFFSET,
						ZYNQ_QSPI_IXR_ALL_MASK);
				spi_finalize_current_transfer(master);
				xqspi->is_instr = 0;
			}
		}
		return IRQ_HANDLED;
	}

	return IRQ_NONE;
}
Ejemplo n.º 3
0
/*
 * zynq_qspi_start_transfer - Initiates the QSPI transfer
 * @qspi:	Pointer to the spi_device structure
 * @transfer:	Pointer to the spi_transfer structure which provide information
 *		about next transfer parameters
 *
 * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
 * transfer to be completed.
 *
 * returns:	Number of bytes transferred in the last transfer
 */
static int zynq_qspi_start_transfer(struct spi_device *qspi,
			struct spi_transfer *transfer)
{
	struct zynq_qspi *zqspi = &qspi->master;
	static u8 current_u_page;
	u32 data = 0;
	u8 instruction = 0;
	u8 index;

	debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__,
	      (u32)qspi, (u32)transfer, transfer->len);

	zqspi->txbuf = transfer->tx_buf;
	zqspi->rxbuf = transfer->rx_buf;
	zqspi->bytes_to_transfer = transfer->len;
	zqspi->bytes_to_receive = transfer->len;

	if (zqspi->txbuf)
		instruction = *(u8 *)zqspi->txbuf;

	if (instruction && zqspi->is_inst) {
		for (index = 0; index < ARRAY_SIZE(flash_inst); index++)
			if (instruction == flash_inst[index].opcode)
				break;

		/*
		 * Instruction might have already been transmitted. This is a
		 * 'data only' transfer
		 */
		if (index == ARRAY_SIZE(flash_inst))
			goto xfer_data;

		zqspi->curr_inst = &flash_inst[index];
		zqspi->inst_response = 1;

		if ((zqspi->is_dual == MODE_DUAL_STACKED) &&
				(current_u_page != zqspi->u_page)) {
			if (zqspi->u_page) {
				/* Configure two memories on shared bus
				 * by enabling upper mem
				 */
				writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK |
					ZYNQ_QSPI_LCFG_U_PAGE |
					(1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) |
					ZYNQ_QSPI_FR_QOUT_CODE),
					&zynq_qspi_base->lcr);
			} else {
				/* Configure two memories on shared bus
				 * by enabling lower mem
				 */
				writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK |
					(1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) |
					ZYNQ_QSPI_FR_QOUT_CODE),
					&zynq_qspi_base->lcr);
			}

			current_u_page = zqspi->u_page;
		}

		/* Get the instruction */
		data = 0;
		zynq_qspi_copy_write_data(zqspi, &data,
					zqspi->curr_inst->inst_size);

		/*
		 * Write the instruction to LSB of the FIFO. The core is
		 * designed such that it is not necessary to check whether the
		 * write FIFO is full before writing. However, write would be
		 * delayed if the user tries to write when write FIFO is full
		 */
		writel(data, &zynq_qspi_base->confr +
				(zqspi->curr_inst->offset / 4));

		/*
		 * Read status register and Read ID instructions don't require
		 * to ignore the extra bytes in response of instruction as
		 * response contains the value
		 */
		if ((instruction == ZYNQ_QSPI_FLASH_OPCODE_RDSR1) ||
		    (instruction == ZYNQ_QSPI_FLASH_OPCODE_RDSR2) ||
		    (instruction == ZYNQ_QSPI_FLASH_OPCODE_RDID) ||
		    (instruction == ZYNQ_QSPI_FLASH_OPCODE_BRRD) ||
		    (instruction == ZYNQ_QSPI_FLASH_OPCODE_RDEAR)) {
			if (zqspi->bytes_to_transfer < 4)
				zqspi->bytes_to_transfer = 0;
			else
				zqspi->bytes_to_transfer -= 3;
		}
	}

xfer_data:
	/*
	 * In case of Fast, Dual and Quad reads, transmit the instruction first.
	 * Address and dummy byte should be transmitted after instruction
	 * is transmitted
	 */
	if (((zqspi->is_inst == 0) && (zqspi->bytes_to_transfer)) ||
	    ((zqspi->bytes_to_transfer) &&
	     (instruction != ZYNQ_QSPI_FLASH_OPCODE_FR) &&
	     (instruction != ZYNQ_QSPI_FLASH_OPCODE_DR) &&
	     (instruction != ZYNQ_QSPI_FLASH_OPCODE_QR) &&
	     (instruction != ZYNQ_QSPI_FLASH_OPCODE_DIOR)))
		zynq_qspi_fill_tx_fifo(zqspi, ZYNQ_QSPI_FIFO_DEPTH);

	writel(ZYNQ_QSPI_IXR_ALL_MASK, &zynq_qspi_base->ier);
	/* Start the transfer by enabling manual start bit */

	/* wait for completion */
	do {
		data = zynq_qspi_irq_poll(zqspi);
	} while (data == 0);

	return (transfer->len) - (zqspi->bytes_to_transfer);
}
Ejemplo n.º 4
0
/*
 * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
 * @zqspi:	Pointer to the zynq_qspi structure
 *
 * This function handles TX empty and Mode Fault interrupts only.
 * On TX empty interrupt this function reads the received data from RX FIFO and
 * fills the TX FIFO if there is any data remaining to be transferred.
 * On Mode Fault interrupt this function indicates that transfer is completed,
 * the SPI subsystem will identify the error as the remaining bytes to be
 * transferred is non-zero.
 *
 * returns:	0 for poll timeout
 *		1 transfer operation complete
 */
static int zynq_qspi_irq_poll(struct zynq_qspi *zqspi)
{
	int max_loop;
	u32 intr_status;
	u32 rxindex = 0;
	u32 rxcount;

	debug("%s: zqspi: 0x%08x\n", __func__, (u32)zqspi);

	/* Poll until any of the interrupt status bits are set */
	max_loop = 0;
	do {
		intr_status = readl(&zynq_qspi_base->isr);
		max_loop++;
	} while ((intr_status == 0) && (max_loop < 100000));

	if (intr_status == 0) {
		printf("%s: Timeout\n", __func__);
		return 0;
	}

	writel(intr_status, &zynq_qspi_base->isr);

	/* Disable all interrupts */
	writel(ZYNQ_QSPI_IXR_ALL_MASK, &zynq_qspi_base->idisr);
	if ((intr_status & ZYNQ_QSPI_IXR_TXNFULL_MASK) ||
	    (intr_status & ZYNQ_QSPI_IXR_RXNEMTY_MASK)) {
		/*
		 * This bit is set when Tx FIFO has < THRESHOLD entries. We have
		 * the THRESHOLD value set to 1, so this bit indicates Tx FIFO
		 * is empty
		 */
		rxcount = zqspi->bytes_to_receive - zqspi->bytes_to_transfer;
		rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4);
		while ((rxindex < rxcount) &&
				(rxindex < ZYNQ_QSPI_RXFIFO_THRESHOLD)) {
		/* Read out the data from the RX FIFO */
			u32 data;

			data = readl(&zynq_qspi_base->drxr);

			if ((zqspi->inst_response) &&
			    (!((zqspi->curr_inst->opcode ==
				ZYNQ_QSPI_FLASH_OPCODE_RDSR1) ||
			       (zqspi->curr_inst->opcode ==
				ZYNQ_QSPI_FLASH_OPCODE_RDSR2)))) {
				zqspi->inst_response = 0;
				zynq_qspi_copy_read_data(zqspi, data,
						zqspi->curr_inst->inst_size);
			} else if (zqspi->bytes_to_receive < 4) {
				zynq_qspi_copy_read_data(zqspi, data,
						       zqspi->bytes_to_receive);
			} else {
				if (zqspi->rxbuf) {
					memcpy(zqspi->rxbuf, &data, 4);
					zqspi->rxbuf += 4;
				}
				zqspi->bytes_to_receive -= 4;
			}
			rxindex++;
		}

		if (zqspi->bytes_to_transfer) {
			/* There is more data to send */
			zynq_qspi_fill_tx_fifo(zqspi,
					       ZYNQ_QSPI_RXFIFO_THRESHOLD);

			writel(ZYNQ_QSPI_IXR_ALL_MASK, &zynq_qspi_base->ier);
		} else {
			/*
			 * If transfer and receive is completed then only send
			 * complete signal
			 */
			if (!zqspi->bytes_to_receive) {
				/* return operation complete */
				writel(ZYNQ_QSPI_IXR_ALL_MASK,
				       &zynq_qspi_base->idisr);
				return 1;
			}
		}
	}

	return 0;
}
Ejemplo n.º 5
0
/*
 * zynq_qspi_start_transfer - Initiates the QSPI transfer
 * @qspi:	Pointer to the spi_device structure
 * @transfer:	Pointer to the spi_transfer structure which provide information
 *		about next transfer parameters
 *
 * This function fills the TX FIFO, starts the QSPI transfer, and waits for the
 * transfer to be completed.
 *
 * returns:	Number of bytes transferred in the last transfer
 */
static int zynq_qspi_start_transfer(struct zynq_qspi_priv *priv)
{
	static u8 current_u_page;
	u32 data = 0;
	struct zynq_qspi_regs *regs = priv->regs;

	debug("%s: qspi: 0x%08x transfer: 0x%08x len: %d\n", __func__,
	      (u32)priv, (u32)priv, priv->len);

	priv->bytes_to_transfer = priv->len;
	priv->bytes_to_receive = priv->len;

	if (priv->is_inst && (priv->is_dual == SF_DUAL_STACKED_FLASH) &&
	    (current_u_page != priv->u_page)) {
		if (priv->u_page) {
			if (priv->is_dio == SF_DUALIO_FLASH)
				writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK |
					ZYNQ_QSPI_LCFG_U_PAGE |
					(1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) |
					ZYNQ_QSPI_FR_DUALIO_CODE),
					&regs->lcr);
			else
				/* Configure two memories on shared bus
				 * by enabling upper mem
				 */
				writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK |
					ZYNQ_QSPI_LCFG_U_PAGE |
					(1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) |
					ZYNQ_QSPI_FR_QOUT_CODE),
					&regs->lcr);
		} else {
			if (priv->is_dio == SF_DUALIO_FLASH)
				writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK |
					(1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) |
					ZYNQ_QSPI_FR_DUALIO_CODE),
					&regs->lcr);
			else
				/* Configure two memories on shared bus
				 * by enabling lower mem
				 */
				writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK |
					(1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) |
					ZYNQ_QSPI_FR_QOUT_CODE),
					&regs->lcr);
		}
		current_u_page = priv->u_page;
	}

	if (priv->len < 4)
		zynq_qspi_fill_tx_fifo(priv, priv->len);
	else
		zynq_qspi_fill_tx_fifo(priv, ZYNQ_QSPI_FIFO_DEPTH);

	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
	/* Start the transfer by enabling manual start bit */

	/* wait for completion */
	do {
		data = zynq_qspi_irq_poll(priv);
	} while (data == 0);

	return (priv->len) - (priv->bytes_to_transfer);
}
Ejemplo n.º 6
0
/*
 * zynq_qspi_irq_poll - Interrupt service routine of the QSPI controller
 * @zqspi:	Pointer to the zynq_qspi structure
 *
 * This function handles TX empty and Mode Fault interrupts only.
 * On TX empty interrupt this function reads the received data from RX FIFO and
 * fills the TX FIFO if there is any data remaining to be transferred.
 * On Mode Fault interrupt this function indicates that transfer is completed,
 * the SPI subsystem will identify the error as the remaining bytes to be
 * transferred is non-zero.
 *
 * returns:	0 for poll timeout
 *		1 transfer operation complete
 */
static int zynq_qspi_irq_poll(struct zynq_qspi_priv *priv)
{
	int max_loop;
	u32 intr_status;
	u32 rxindex = 0;
	u32 rxcount;
	struct zynq_qspi_regs *regs = priv->regs;

	debug("%s: zqspi: 0x%08x\n", __func__, (u32)priv);

	/* Poll until any of the interrupt status bits are set */
	max_loop = 0;
	do {
		intr_status = readl(&regs->isr);
		max_loop++;
	} while ((intr_status == 0) && (max_loop < 100000));

	if (intr_status == 0) {
		debug("%s: Timeout\n", __func__);
		return 0;
	}

	writel(intr_status, &regs->isr);

	/* Disable all interrupts */
	writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->idisr);
	if ((intr_status & ZYNQ_QSPI_IXR_TXNFULL_MASK) ||
	    (intr_status & ZYNQ_QSPI_IXR_RXNEMTY_MASK)) {
		/*
		 * This bit is set when Tx FIFO has < THRESHOLD entries. We have
		 * the THRESHOLD value set to 1, so this bit indicates Tx FIFO
		 * is empty
		 */
		rxcount = priv->bytes_to_receive - priv->bytes_to_transfer;
		rxcount = (rxcount % 4) ? ((rxcount/4)+1) : (rxcount/4);
		while ((rxindex < rxcount) &&
				(rxindex < ZYNQ_QSPI_RXFIFO_THRESHOLD)) {
			/* Read out the data from the RX FIFO */
			u32 data;
			data = readl(&regs->drxr);

			if (priv->bytes_to_receive >= 4) {
				if (priv->rxbuf) {
					memcpy(priv->rxbuf, &data, 4);
					priv->rxbuf += 4;
				}
				priv->bytes_to_receive -= 4;
			} else {
				zynq_qspi_copy_read_data(priv, data,
					priv->bytes_to_receive);
			}
			rxindex++;
		}

		if (priv->bytes_to_transfer) {
			/* There is more data to send */
			zynq_qspi_fill_tx_fifo(priv,
					       ZYNQ_QSPI_RXFIFO_THRESHOLD);

			writel(ZYNQ_QSPI_IXR_ALL_MASK, &regs->ier);
		} else {
			/*
			 * If transfer and receive is completed then only send
			 * complete signal
			 */
			if (!priv->bytes_to_receive) {
				/* return operation complete */
				writel(ZYNQ_QSPI_IXR_ALL_MASK,
				       &regs->idisr);
				return 1;
			}
		}
	}

	return 0;
}