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

Merge branch 'spi-5.1' into spi-5.2

parents 9fda6693 a026525d
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -77,7 +77,7 @@
#define CFGR1_PCSPOL	BIT(8)
#define CFGR1_PCSPOL	BIT(8)
#define CFGR1_NOSTALL	BIT(3)
#define CFGR1_NOSTALL	BIT(3)
#define CFGR1_MASTER	BIT(0)
#define CFGR1_MASTER	BIT(0)
#define FSR_RXCOUNT	(BIT(16)|BIT(17)|BIT(18))
#define FSR_TXCOUNT	(0xFF)
#define RSR_RXEMPTY	BIT(1)
#define RSR_RXEMPTY	BIT(1)
#define TCR_CPOL	BIT(31)
#define TCR_CPOL	BIT(31)
#define TCR_CPHA	BIT(30)
#define TCR_CPHA	BIT(30)
@@ -771,7 +771,7 @@ static irqreturn_t fsl_lpspi_isr(int irq, void *dev_id)
	}
	}


	if (temp_SR & SR_MBF ||
	if (temp_SR & SR_MBF ||
	    readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_RXCOUNT) {
	    readl(fsl_lpspi->base + IMX7ULP_FSR) & FSR_TXCOUNT) {
		writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
		writel(SR_FCF, fsl_lpspi->base + IMX7ULP_SR);
		fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
		fsl_lpspi_intctrl(fsl_lpspi, IER_FCIE);
		return IRQ_HANDLED;
		return IRQ_HANDLED;
+0 −1
Original line number Original line Diff line number Diff line
@@ -35,7 +35,6 @@
 * platform_device->driver_data ... points to spi_gpio
 * platform_device->driver_data ... points to spi_gpio
 *
 *
 * spi->controller_state ... reserved for bitbang framework code
 * spi->controller_state ... reserved for bitbang framework code
 * spi->controller_data ... holds chipselect GPIO
 *
 *
 * spi->master->dev.driver_data ... points to spi_gpio->bitbang
 * spi->master->dev.driver_data ... points to spi_gpio->bitbang
 */
 */
+1 −1
Original line number Original line Diff line number Diff line
@@ -559,7 +559,7 @@ static int pic32_spi_one_transfer(struct spi_master *master,
		dev_err(&spi->dev, "wait error/timedout\n");
		dev_err(&spi->dev, "wait error/timedout\n");
		if (dma_issued) {
		if (dma_issued) {
			dmaengine_terminate_all(master->dma_rx);
			dmaengine_terminate_all(master->dma_rx);
			dmaengine_terminate_all(master->dma_rx);
			dmaengine_terminate_all(master->dma_tx);
		}
		}
		ret = -ETIMEDOUT;
		ret = -ETIMEDOUT;
	} else {
	} else {
+146 −62
Original line number Original line Diff line number Diff line
@@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
				x |= (u32)(*tx_buf++) << (i * 8);
				x |= (u32)(*tx_buf++) << (i * 8);
			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
		}
		}

		tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
	} else {
	} else {
		unsigned int write_bytes;
		max_n_32bit = min(tspi->curr_dma_words,  tx_empty_count);
		max_n_32bit = min(tspi->curr_dma_words,  tx_empty_count);
		written_words = max_n_32bit;
		written_words = max_n_32bit;
		nbytes = written_words * tspi->bytes_per_word;
		nbytes = written_words * tspi->bytes_per_word;
		if (nbytes > t->len - tspi->cur_pos)
			nbytes = t->len - tspi->cur_pos;
		write_bytes = nbytes;
		for (count = 0; count < max_n_32bit; count++) {
		for (count = 0; count < max_n_32bit; count++) {
			u32 x = 0;
			u32 x = 0;


@@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
				x |= (u32)(*tx_buf++) << (i * 8);
				x |= (u32)(*tx_buf++) << (i * 8);
			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
		}
		}

		tspi->cur_tx_pos += write_bytes;
	}
	}
	tspi->cur_tx_pos += written_words * tspi->bytes_per_word;

	return written_words;
	return written_words;
}
}


@@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
			for (i = 0; len && (i < 4); i++, len--)
			for (i = 0; len && (i < 4); i++, len--)
				*rx_buf++ = (x >> i*8) & 0xFF;
				*rx_buf++ = (x >> i*8) & 0xFF;
		}
		}
		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
		read_words += tspi->curr_dma_words;
		read_words += tspi->curr_dma_words;
		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
	} else {
	} else {
		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
		u8 bytes_per_word = tspi->bytes_per_word;
		unsigned int read_bytes;


		len = rx_full_count * bytes_per_word;
		if (len > t->len - tspi->cur_pos)
			len = t->len - tspi->cur_pos;
		read_bytes = len;
		for (count = 0; count < rx_full_count; count++) {
		for (count = 0; count < rx_full_count; count++) {
			u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;
			u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;


			for (i = 0; (i < tspi->bytes_per_word); i++)
			for (i = 0; len && (i < bytes_per_word); i++, len--)
				*rx_buf++ = (x >> (i*8)) & 0xFF;
				*rx_buf++ = (x >> (i*8)) & 0xFF;
		}
		}
		tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word;
		read_words += rx_full_count;
		read_words += rx_full_count;
		tspi->cur_rx_pos += read_bytes;
	}
	}

	return read_words;
	return read_words;
}
}


@@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;


		memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
		memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
		tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
	} else {
	} else {
		unsigned int i;
		unsigned int i;
		unsigned int count;
		unsigned int count;
		u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
		u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
		unsigned int write_bytes;


		if (consume > t->len - tspi->cur_pos)
			consume = t->len - tspi->cur_pos;
		write_bytes = consume;
		for (count = 0; count < tspi->curr_dma_words; count++) {
		for (count = 0; count < tspi->curr_dma_words; count++) {
			u32 x = 0;
			u32 x = 0;


@@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
				x |= (u32)(*tx_buf++) << (i * 8);
				x |= (u32)(*tx_buf++) << (i * 8);
			tspi->tx_dma_buf[count] = x;
			tspi->tx_dma_buf[count] = x;
		}
		}

		tspi->cur_tx_pos += write_bytes;
	}
	}
	tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;


	/* Make the dma buffer to read by dma */
	/* Make the dma buffer to read by dma */
	dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys,
	dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys,
@@ -405,20 +426,28 @@ static void tegra_spi_copy_spi_rxbuf_to_client_rxbuf(
		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;


		memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
		memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
	} else {
	} else {
		unsigned int i;
		unsigned int i;
		unsigned int count;
		unsigned int count;
		unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
		unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
		unsigned int read_bytes;


		if (consume > t->len - tspi->cur_pos)
			consume = t->len - tspi->cur_pos;
		read_bytes = consume;
		for (count = 0; count < tspi->curr_dma_words; count++) {
		for (count = 0; count < tspi->curr_dma_words; count++) {
			u32 x = tspi->rx_dma_buf[count] & rx_mask;
			u32 x = tspi->rx_dma_buf[count] & rx_mask;


			for (i = 0; (i < tspi->bytes_per_word); i++)
			for (i = 0; consume && (i < tspi->bytes_per_word);
							i++, consume--)
				*rx_buf++ = (x >> (i*8)) & 0xFF;
				*rx_buf++ = (x >> (i*8)) & 0xFF;
		}
		}

		tspi->cur_rx_pos += read_bytes;
	}
	}
	tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;


	/* Make the dma buffer to read by dma */
	/* Make the dma buffer to read by dma */
	dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
	dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
@@ -470,22 +499,39 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
	return 0;
	return 0;
}
}


static int tegra_spi_start_dma_based_transfer(
static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi)
		struct tegra_spi_data *tspi, struct spi_transfer *t)
{
{
	u32 val;
	unsigned long timeout = jiffies + HZ;
	unsigned int len;
	int ret = 0;
	u32 status;
	u32 status;


	/* Make sure that Rx and Tx fifo are empty */
	status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
	status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
	if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
	if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
		dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
		status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH;
			(unsigned)status);
		tegra_spi_writel(tspi, status, SPI_FIFO_STATUS);
		while ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
			status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
			if (time_after(jiffies, timeout)) {
				dev_err(tspi->dev,
					"timeout waiting for fifo flush\n");
				return -EIO;
				return -EIO;
			}
			}


			udelay(1);
		}
	}

	return 0;
}

static int tegra_spi_start_dma_based_transfer(
		struct tegra_spi_data *tspi, struct spi_transfer *t)
{
	u32 val;
	unsigned int len;
	int ret = 0;
	u8 dma_burst;
	struct dma_slave_config dma_sconfig = {0};

	val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
	val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
	tegra_spi_writel(tspi, val, SPI_DMA_BLK);
	tegra_spi_writel(tspi, val, SPI_DMA_BLK);


@@ -496,12 +542,16 @@ static int tegra_spi_start_dma_based_transfer(
		len = tspi->curr_dma_words * 4;
		len = tspi->curr_dma_words * 4;


	/* Set attention level based on length of transfer */
	/* Set attention level based on length of transfer */
	if (len & 0xF)
	if (len & 0xF) {
		val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1;
		val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1;
	else if (((len) >> 4) & 0x1)
		dma_burst = 1;
	} else if (((len) >> 4) & 0x1) {
		val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4;
		val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4;
	else
		dma_burst = 4;
	} else {
		val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8;
		val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8;
		dma_burst = 8;
	}


	if (tspi->cur_direction & DATA_DIR_TX)
	if (tspi->cur_direction & DATA_DIR_TX)
		val |= SPI_IE_TX;
		val |= SPI_IE_TX;
@@ -512,7 +562,18 @@ static int tegra_spi_start_dma_based_transfer(
	tegra_spi_writel(tspi, val, SPI_DMA_CTL);
	tegra_spi_writel(tspi, val, SPI_DMA_CTL);
	tspi->dma_control_reg = val;
	tspi->dma_control_reg = val;


	dma_sconfig.device_fc = true;
	if (tspi->cur_direction & DATA_DIR_TX) {
	if (tspi->cur_direction & DATA_DIR_TX) {
		dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO;
		dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		dma_sconfig.dst_maxburst = dma_burst;
		ret = dmaengine_slave_config(tspi->tx_dma_chan, &dma_sconfig);
		if (ret < 0) {
			dev_err(tspi->dev,
				"DMA slave config failed: %d\n", ret);
			return ret;
		}

		tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t);
		tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t);
		ret = tegra_spi_start_tx_dma(tspi, len);
		ret = tegra_spi_start_tx_dma(tspi, len);
		if (ret < 0) {
		if (ret < 0) {
@@ -523,6 +584,16 @@ static int tegra_spi_start_dma_based_transfer(
	}
	}


	if (tspi->cur_direction & DATA_DIR_RX) {
	if (tspi->cur_direction & DATA_DIR_RX) {
		dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO;
		dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		dma_sconfig.src_maxburst = dma_burst;
		ret = dmaengine_slave_config(tspi->rx_dma_chan, &dma_sconfig);
		if (ret < 0) {
			dev_err(tspi->dev,
				"DMA slave config failed: %d\n", ret);
			return ret;
		}

		/* Make the dma buffer to read by dma */
		/* Make the dma buffer to read by dma */
		dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
		dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
				tspi->dma_buf_size, DMA_FROM_DEVICE);
				tspi->dma_buf_size, DMA_FROM_DEVICE);
@@ -582,7 +653,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
	u32 *dma_buf;
	u32 *dma_buf;
	dma_addr_t dma_phys;
	dma_addr_t dma_phys;
	int ret;
	int ret;
	struct dma_slave_config dma_sconfig;


	dma_chan = dma_request_slave_channel_reason(tspi->dev,
	dma_chan = dma_request_slave_channel_reason(tspi->dev,
					dma_to_memory ? "rx" : "tx");
					dma_to_memory ? "rx" : "tx");
@@ -602,19 +672,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	if (dma_to_memory) {
		dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO;
		dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		dma_sconfig.src_maxburst = 0;
	} else {
		dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO;
		dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
		dma_sconfig.dst_maxburst = 0;
	}

	ret = dmaengine_slave_config(dma_chan, &dma_sconfig);
	if (ret)
		goto scrub;
	if (dma_to_memory) {
	if (dma_to_memory) {
		tspi->rx_dma_chan = dma_chan;
		tspi->rx_dma_chan = dma_chan;
		tspi->rx_dma_buf = dma_buf;
		tspi->rx_dma_buf = dma_buf;
@@ -625,11 +682,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
		tspi->tx_dma_phys = dma_phys;
		tspi->tx_dma_phys = dma_phys;
	}
	}
	return 0;
	return 0;

scrub:
	dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys);
	dma_release_channel(dma_chan);
	return ret;
}
}


static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
@@ -735,6 +787,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,


	if (tspi->is_packed)
	if (tspi->is_packed)
		command1 |= SPI_PACKED;
		command1 |= SPI_PACKED;
	else
		command1 &= ~SPI_PACKED;


	command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN);
	command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN);
	tspi->cur_direction = 0;
	tspi->cur_direction = 0;
@@ -753,6 +807,9 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi,
	dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
	dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
		tspi->def_command1_reg, (unsigned)command1);
		tspi->def_command1_reg, (unsigned)command1);


	ret = tegra_spi_flush_fifos(tspi);
	if (ret < 0)
		return ret;
	if (total_fifo_words > SPI_FIFO_DEPTH)
	if (total_fifo_words > SPI_FIFO_DEPTH)
		ret = tegra_spi_start_dma_based_transfer(tspi, t);
		ret = tegra_spi_start_dma_based_transfer(tspi, t);
	else
	else
@@ -804,6 +861,19 @@ static void tegra_spi_transfer_delay(int delay)
	udelay(delay % 1000);
	udelay(delay % 1000);
}
}


static void tegra_spi_transfer_end(struct spi_device *spi)
{
	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
	int cs_val = (spi->mode & SPI_CS_HIGH) ? 0 : 1;

	if (cs_val)
		tspi->command1_reg |= SPI_CS_SW_VAL;
	else
		tspi->command1_reg &= ~SPI_CS_SW_VAL;
	tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1);
	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
}

static int tegra_spi_transfer_one_message(struct spi_master *master,
static int tegra_spi_transfer_one_message(struct spi_master *master,
			struct spi_message *msg)
			struct spi_message *msg)
{
{
@@ -843,7 +913,17 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,
		if (WARN_ON(ret == 0)) {
		if (WARN_ON(ret == 0)) {
			dev_err(tspi->dev,
			dev_err(tspi->dev,
				"spi transfer timeout, err %d\n", ret);
				"spi transfer timeout, err %d\n", ret);
			if (tspi->is_curr_dma_xfer &&
			    (tspi->cur_direction & DATA_DIR_TX))
				dmaengine_terminate_all(tspi->tx_dma_chan);
			if (tspi->is_curr_dma_xfer &&
			    (tspi->cur_direction & DATA_DIR_RX))
				dmaengine_terminate_all(tspi->rx_dma_chan);
			ret = -EIO;
			ret = -EIO;
			tegra_spi_flush_fifos(tspi);
			reset_control_assert(tspi->rst);
			udelay(2);
			reset_control_deassert(tspi->rst);
			goto complete_xfer;
			goto complete_xfer;
		}
		}


@@ -856,8 +936,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master,


complete_xfer:
complete_xfer:
		if (ret < 0 || skip) {
		if (ret < 0 || skip) {
			tegra_spi_writel(tspi, tspi->def_command1_reg,
			tegra_spi_transfer_end(spi);
					SPI_COMMAND1);
			tegra_spi_transfer_delay(xfer->delay_usecs);
			tegra_spi_transfer_delay(xfer->delay_usecs);
			goto exit;
			goto exit;
		} else if (list_is_last(&xfer->transfer_list,
		} else if (list_is_last(&xfer->transfer_list,
@@ -865,13 +944,11 @@ complete_xfer:
			if (xfer->cs_change)
			if (xfer->cs_change)
				tspi->cs_control = spi;
				tspi->cs_control = spi;
			else {
			else {
				tegra_spi_writel(tspi, tspi->def_command1_reg,
				tegra_spi_transfer_end(spi);
						SPI_COMMAND1);
				tegra_spi_transfer_delay(xfer->delay_usecs);
				tegra_spi_transfer_delay(xfer->delay_usecs);
			}
			}
		} else if (xfer->cs_change) {
		} else if (xfer->cs_change) {
			tegra_spi_writel(tspi, tspi->def_command1_reg,
			tegra_spi_transfer_end(spi);
					SPI_COMMAND1);
			tegra_spi_transfer_delay(xfer->delay_usecs);
			tegra_spi_transfer_delay(xfer->delay_usecs);
		}
		}


@@ -894,11 +971,13 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi)
			tspi->status_reg);
			tspi->status_reg);
		dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
		dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
			tspi->command1_reg, tspi->dma_control_reg);
			tspi->command1_reg, tspi->dma_control_reg);
		tegra_spi_flush_fifos(tspi);
		complete(&tspi->xfer_completion);
		spin_unlock_irqrestore(&tspi->lock, flags);
		reset_control_assert(tspi->rst);
		reset_control_assert(tspi->rst);
		udelay(2);
		udelay(2);
		reset_control_deassert(tspi->rst);
		reset_control_deassert(tspi->rst);
		complete(&tspi->xfer_completion);
		return IRQ_HANDLED;
		goto exit;
	}
	}


	if (tspi->cur_direction & DATA_DIR_RX)
	if (tspi->cur_direction & DATA_DIR_RX)
@@ -966,11 +1045,12 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi)
			tspi->status_reg);
			tspi->status_reg);
		dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
		dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
			tspi->command1_reg, tspi->dma_control_reg);
			tspi->command1_reg, tspi->dma_control_reg);
		tegra_spi_flush_fifos(tspi);
		complete(&tspi->xfer_completion);
		spin_unlock_irqrestore(&tspi->lock, flags);
		reset_control_assert(tspi->rst);
		reset_control_assert(tspi->rst);
		udelay(2);
		udelay(2);
		reset_control_deassert(tspi->rst);
		reset_control_deassert(tspi->rst);
		complete(&tspi->xfer_completion);
		spin_unlock_irqrestore(&tspi->lock, flags);
		return IRQ_HANDLED;
		return IRQ_HANDLED;
	}
	}


@@ -1072,27 +1152,19 @@ static int tegra_spi_probe(struct platform_device *pdev)


	spi_irq = platform_get_irq(pdev, 0);
	spi_irq = platform_get_irq(pdev, 0);
	tspi->irq = spi_irq;
	tspi->irq = spi_irq;
	ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
			tegra_spi_isr_thread, IRQF_ONESHOT,
			dev_name(&pdev->dev), tspi);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
					tspi->irq);
		goto exit_free_master;
	}


	tspi->clk = devm_clk_get(&pdev->dev, "spi");
	tspi->clk = devm_clk_get(&pdev->dev, "spi");
	if (IS_ERR(tspi->clk)) {
	if (IS_ERR(tspi->clk)) {
		dev_err(&pdev->dev, "can not get clock\n");
		dev_err(&pdev->dev, "can not get clock\n");
		ret = PTR_ERR(tspi->clk);
		ret = PTR_ERR(tspi->clk);
		goto exit_free_irq;
		goto exit_free_master;
	}
	}


	tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
	tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
	if (IS_ERR(tspi->rst)) {
	if (IS_ERR(tspi->rst)) {
		dev_err(&pdev->dev, "can not get reset\n");
		dev_err(&pdev->dev, "can not get reset\n");
		ret = PTR_ERR(tspi->rst);
		ret = PTR_ERR(tspi->rst);
		goto exit_free_irq;
		goto exit_free_master;
	}
	}


	tspi->max_buf_size = SPI_FIFO_DEPTH << 2;
	tspi->max_buf_size = SPI_FIFO_DEPTH << 2;
@@ -1100,7 +1172,7 @@ static int tegra_spi_probe(struct platform_device *pdev)


	ret = tegra_spi_init_dma_param(tspi, true);
	ret = tegra_spi_init_dma_param(tspi, true);
	if (ret < 0)
	if (ret < 0)
		goto exit_free_irq;
		goto exit_free_master;
	ret = tegra_spi_init_dma_param(tspi, false);
	ret = tegra_spi_init_dma_param(tspi, false);
	if (ret < 0)
	if (ret < 0)
		goto exit_rx_dma_free;
		goto exit_rx_dma_free;
@@ -1122,18 +1194,32 @@ static int tegra_spi_probe(struct platform_device *pdev)
		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
		goto exit_pm_disable;
		goto exit_pm_disable;
	}
	}

	reset_control_assert(tspi->rst);
	udelay(2);
	reset_control_deassert(tspi->rst);
	tspi->def_command1_reg  = SPI_M_S;
	tspi->def_command1_reg  = SPI_M_S;
	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
	pm_runtime_put(&pdev->dev);
	pm_runtime_put(&pdev->dev);
	ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
				   tegra_spi_isr_thread, IRQF_ONESHOT,
				   dev_name(&pdev->dev), tspi);
	if (ret < 0) {
		dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
			tspi->irq);
		goto exit_pm_disable;
	}


	master->dev.of_node = pdev->dev.of_node;
	master->dev.of_node = pdev->dev.of_node;
	ret = devm_spi_register_master(&pdev->dev, master);
	ret = devm_spi_register_master(&pdev->dev, master);
	if (ret < 0) {
	if (ret < 0) {
		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
		goto exit_pm_disable;
		goto exit_free_irq;
	}
	}
	return ret;
	return ret;


exit_free_irq:
	free_irq(spi_irq, tspi);
exit_pm_disable:
exit_pm_disable:
	pm_runtime_disable(&pdev->dev);
	pm_runtime_disable(&pdev->dev);
	if (!pm_runtime_status_suspended(&pdev->dev))
	if (!pm_runtime_status_suspended(&pdev->dev))
@@ -1141,8 +1227,6 @@ exit_pm_disable:
	tegra_spi_deinit_dma_param(tspi, false);
	tegra_spi_deinit_dma_param(tspi, false);
exit_rx_dma_free:
exit_rx_dma_free:
	tegra_spi_deinit_dma_param(tspi, true);
	tegra_spi_deinit_dma_param(tspi, true);
exit_free_irq:
	free_irq(spi_irq, tspi);
exit_free_master:
exit_free_master:
	spi_master_put(master);
	spi_master_put(master);
	return ret;
	return ret;
+9 −3
Original line number Original line Diff line number Diff line
@@ -717,9 +717,6 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
	command2 = tspi->command2_reg;
	command2 = tspi->command2_reg;
	command2 &= ~(SLINK_RXEN | SLINK_TXEN);
	command2 &= ~(SLINK_RXEN | SLINK_TXEN);


	tegra_slink_writel(tspi, command, SLINK_COMMAND);
	tspi->command_reg = command;

	tspi->cur_direction = 0;
	tspi->cur_direction = 0;
	if (t->rx_buf) {
	if (t->rx_buf) {
		command2 |= SLINK_RXEN;
		command2 |= SLINK_RXEN;
@@ -729,9 +726,18 @@ static int tegra_slink_start_transfer_one(struct spi_device *spi,
		command2 |= SLINK_TXEN;
		command2 |= SLINK_TXEN;
		tspi->cur_direction |= DATA_DIR_TX;
		tspi->cur_direction |= DATA_DIR_TX;
	}
	}

	/*
	 * Writing to the command2 register bevore the command register prevents
	 * a spike in chip_select line 0. This selects the chip_select line
	 * before changing the chip_select value.
	 */
	tegra_slink_writel(tspi, command2, SLINK_COMMAND2);
	tegra_slink_writel(tspi, command2, SLINK_COMMAND2);
	tspi->command2_reg = command2;
	tspi->command2_reg = command2;


	tegra_slink_writel(tspi, command, SLINK_COMMAND);
	tspi->command_reg = command;

	if (total_fifo_words > SLINK_FIFO_DEPTH)
	if (total_fifo_words > SLINK_FIFO_DEPTH)
		ret = tegra_slink_start_dma_based_transfer(tspi, t);
		ret = tegra_slink_start_dma_based_transfer(tspi, t);
	else
	else
Loading