Exemplo n.º 1
0
static int zynq_qspi_transfer(struct spi_device *qspi,
		struct spi_transfer *transfer)
{
	struct zynq_qspi *zqspi = &qspi->master;
	unsigned cs_change = 1;
	int status = 0;

	debug("%s\n", __func__);

	while (1) {
		if (transfer->bits_per_word || transfer->speed_hz) {
			status = zynq_qspi_setup_transfer(qspi, transfer);
			if (status < 0)
				break;
		}

		/* Select the chip if required */
		if (cs_change)
			zynq_qspi_chipselect(qspi, 1);

		cs_change = transfer->cs_change;

		if (!transfer->tx_buf && !transfer->rx_buf && transfer->len) {
			status = -1;
			break;
		}

		/* Request the transfer */
		if (transfer->len) {
			status = zynq_qspi_start_transfer(qspi, transfer);
			zqspi->is_inst = 0;
		}

		if (status != transfer->len) {
			if (status > 0)
				status = -EMSGSIZE;
			break;
		}
		status = 0;

		if (transfer->delay_usecs)
			udelay(transfer->delay_usecs);

		if (cs_change)
			/* Deselect the chip */
			zynq_qspi_chipselect(qspi, 0);

		break;
	}

	zynq_qspi_setup_transfer(qspi, NULL);

	return 0;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
/**
 * zynq_qspi_setup - Configure the QSPI controller
 * @qspi:	Pointer to the spi_device structure
 *
 * Sets the operational mode of QSPI controller for the next QSPI transfer, baud
 * rate and divisor value to setup the requested qspi clock.
 *
 * Return:	0 on success and error value on failure
 */
static int zynq_qspi_setup(struct spi_device *qspi)
{
	if (qspi->master->busy)
		return -EBUSY;

	return zynq_qspi_setup_transfer(qspi, NULL);
}
Exemplo n.º 4
0
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
		unsigned int max_hz, unsigned int mode)
{
	int is_dual;
	unsigned long lqspi_frequency;
	struct zynq_qspi_slave *qspi;

	debug("%s: bus: %d cs: %d max_hz: %d mode: %d\n",
	      __func__, bus, cs, max_hz, mode);

	if (!spi_cs_is_valid(bus, cs))
		return NULL;

	is_dual = zynq_qspi_check_is_dual_flash();

	if (is_dual == MODE_UNKNOWN) {
		printf("%s: No QSPI device detected based on MIO settings\n",
		       __func__);
		return NULL;
	}

	zynq_qspi_init_hw(is_dual, cs);

	qspi = spi_alloc_slave(struct zynq_qspi_slave, bus, cs);
	if (!qspi) {
		printf("%s: Fail to allocate zynq_qspi_slave\n", __func__);
		return NULL;
	}

	lqspi_frequency = zynq_clk_get_rate(lqspi_clk);
	if (!lqspi_frequency) {
		debug("Defaulting to 200000000 Hz qspi clk");
		qspi->qspi.master.input_clk_hz = 200000000;
	} else {
		qspi->qspi.master.input_clk_hz = lqspi_frequency;
		debug("Qspi clk frequency set to %ld Hz\n", lqspi_frequency);
	}

	qspi->slave.is_dual = is_dual;
	qspi->slave.rd_cmd = READ_CMD_FULL;
	qspi->slave.wr_cmd = PAGE_PROGRAM | QUAD_PAGE_PROGRAM;
	qspi->qspi.master.speed_hz = qspi->qspi.master.input_clk_hz / 2;
	qspi->qspi.max_speed_hz = qspi->qspi.master.speed_hz;
	qspi->qspi.master.is_dual = is_dual;
	qspi->qspi.mode = mode;
	qspi->qspi.chip_select = 0;
	qspi->qspi.bits_per_word = 32;
	zynq_qspi_setup_transfer(&qspi->qspi, NULL);

	return &qspi->slave;
}