Example #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;
}
Example #2
0
/*
 * zynq_qspi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible
 * @zqspi:	Pointer to the zynq_qspi structure
 */
static void zynq_qspi_fill_tx_fifo(struct zynq_qspi *zqspi, u32 size)
{
	u32 data = 0;
	u32 fifocount = 0;
	unsigned len, offset;
	static const unsigned offsets[4] = {
		ZYNQ_QSPI_TXD_00_00_OFFSET, ZYNQ_QSPI_TXD_00_01_OFFSET,
		ZYNQ_QSPI_TXD_00_10_OFFSET, ZYNQ_QSPI_TXD_00_11_OFFSET };

	while ((fifocount < size) &&
			(zqspi->bytes_to_transfer > 0)) {
		if (zqspi->bytes_to_transfer >= 4) {
			if (zqspi->txbuf) {
				memcpy(&data, zqspi->txbuf, 4);
				zqspi->txbuf += 4;
			} else {
				data = 0;
			}
			writel(data, &zynq_qspi_base->txd0r);
			zqspi->bytes_to_transfer -= 4;
			fifocount++;
		} else {
			/* Write TXD1, TXD2, TXD3 only if TxFIFO is empty. */
			if (!(readl(&zynq_qspi_base->isr)
					& ZYNQ_QSPI_IXR_TXNFULL_MASK) &&
					!zqspi->rxbuf)
				return;
			len = zqspi->bytes_to_transfer;
			zynq_qspi_copy_write_data(zqspi, &data, len);
			offset = (zqspi->rxbuf) ? offsets[0] : offsets[len];
			writel(data, &zynq_qspi_base->confr + (offset / 4));
		}
	}
}
Example #3
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;
}
Example #4
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);
}