Unverified Commit df8c5ad0 authored by Mark Brown's avatar Mark Brown
Browse files

Configure Clocks, Add Internal DMA support

Merge series from Vishwaroop A <va@nvidia.com>:

This series introduces QSPI clock configuration and internal DMA
support for Quad SPI controller. The patches have been reorganized
for better logical flow and review comments from v2 have been addressed.
parents 7caae118 c283fcdc
Loading
Loading
Loading
Loading
+34 −21
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/spi/spi.h>
#include <linux/acpi.h>
#include <linux/property.h>
#include <linux/sizes.h>

#define QSPI_COMMAND1				0x000
#define QSPI_BIT_LENGTH(x)			(((x) & 0x1f) << 0)
@@ -134,7 +135,7 @@
#define QSPI_COMMAND_VALUE_SET(X)		(((x) & 0xFF) << 0)

#define QSPI_CMB_SEQ_CMD_CFG			0x1a0
#define QSPI_COMMAND_X1_X2_X4(x)		(((x) & 0x3) << 13)
#define QSPI_COMMAND_X1_X2_X4(x)		((((x) >> 1) & 0x3) << 13)
#define QSPI_COMMAND_X1_X2_X4_MASK		(0x03 << 13)
#define QSPI_COMMAND_SDR_DDR			BIT(12)
#define QSPI_COMMAND_SIZE_SET(x)		(((x) & 0xFF) << 0)
@@ -147,7 +148,7 @@
#define QSPI_ADDRESS_VALUE_SET(X)		(((x) & 0xFFFF) << 0)

#define QSPI_CMB_SEQ_ADDR_CFG			0x1ac
#define QSPI_ADDRESS_X1_X2_X4(x)		(((x) & 0x3) << 13)
#define QSPI_ADDRESS_X1_X2_X4(x)		((((x) >> 1) & 0x3) << 13)
#define QSPI_ADDRESS_X1_X2_X4_MASK		(0x03 << 13)
#define QSPI_ADDRESS_SDR_DDR			BIT(12)
#define QSPI_ADDRESS_SIZE_SET(x)		(((x) & 0xFF) << 0)
@@ -156,10 +157,14 @@
#define DATA_DIR_RX				BIT(1)

#define QSPI_DMA_TIMEOUT			(msecs_to_jiffies(1000))
#define DEFAULT_QSPI_DMA_BUF_LEN		(64 * 1024)
#define CMD_TRANSFER				0
#define ADDR_TRANSFER				1
#define DATA_TRANSFER				2
#define DEFAULT_QSPI_DMA_BUF_LEN		SZ_64K

enum tegra_qspi_transfer_type {
	CMD_TRANSFER   = 0,
	ADDR_TRANSFER  = 1,
	DUMMY_TRANSFER = 2,
	DATA_TRANSFER  = 3
};

struct tegra_qspi_soc_data {
	bool has_dma;
@@ -1036,10 +1041,6 @@ static u32 tegra_qspi_addr_config(bool is_ddr, u8 bus_width, u8 len)
{
	u32 addr_config = 0;

	/* Extract Address configuration and value */
	is_ddr = 0; //Only SDR mode supported
	bus_width = 0; //X1 mode

	if (is_ddr)
		addr_config |= QSPI_ADDRESS_SDR_DDR;
	else
@@ -1079,16 +1080,23 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
		switch (transfer_phase) {
		case CMD_TRANSFER:
			/* X1 SDR mode */
			cmd_config = tegra_qspi_cmd_config(false, 0,
			cmd_config = tegra_qspi_cmd_config(false, xfer->tx_nbits,
							   xfer->len);
			cmd_value = *((const u8 *)(xfer->tx_buf));
			break;
		case ADDR_TRANSFER:
			/* X1 SDR mode */
			addr_config = tegra_qspi_addr_config(false, 0,
			addr_config = tegra_qspi_addr_config(false, xfer->tx_nbits,
							     xfer->len);
			address_value = *((const u32 *)(xfer->tx_buf));
			break;
		case DUMMY_TRANSFER:
			if (xfer->dummy_data) {
				tqspi->dummy_cycles = xfer->len * 8 / xfer->tx_nbits;
				break;
			}
			transfer_phase++;
			fallthrough;
		case DATA_TRANSFER:
			/* Program Command, Address value in register */
			tegra_qspi_writel(tqspi, cmd_value, QSPI_CMB_SEQ_CMD);
@@ -1163,26 +1171,22 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi,
				ret = -EIO;
				goto exit;
			}
			if (!xfer->cs_change) {
				tegra_qspi_transfer_end(spi);
				spi_transfer_delay_exec(xfer);
			}
			break;
		default:
			ret = -EINVAL;
			goto exit;
		}
		msg->actual_length += xfer->len;
		if (!xfer->cs_change && transfer_phase == DATA_TRANSFER) {
			tegra_qspi_transfer_end(spi);
			spi_transfer_delay_exec(xfer);
		}
		transfer_phase++;
	}
	ret = 0;

exit:
	msg->status = ret;
	if (ret < 0) {
		tegra_qspi_transfer_end(spi);
		spi_transfer_delay_exec(xfer);
	}

	return ret;
}
@@ -1300,7 +1304,9 @@ static bool tegra_qspi_validate_cmb_seq(struct tegra_qspi *tqspi,
	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
		transfer_count++;
	}
	if (!tqspi->soc_data->cmb_xfer_capable || transfer_count != 3)
	if (!tqspi->soc_data->cmb_xfer_capable)
		return false;
	if (transfer_count > 4 || transfer_count < 3)
		return false;
	xfer = list_first_entry(&msg->transfers, typeof(*xfer),
				transfer_list);
@@ -1310,6 +1316,13 @@ static bool tegra_qspi_validate_cmb_seq(struct tegra_qspi *tqspi,
	if (xfer->len > 4 || xfer->len < 3)
		return false;
	xfer = list_next_entry(xfer, transfer_list);
	if (transfer_count == 4) {
		if (xfer->dummy_data != 1)
			return false;
		if ((xfer->len * 8 / xfer->tx_nbits) > QSPI_DUMMY_CYCLES_MAX)
			return false;
		xfer = list_next_entry(xfer, transfer_list);
	}
	if (!tqspi->soc_data->has_dma && xfer->len > (QSPI_FIFO_DEPTH << 2))
		return false;