162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * SPI driver for NVIDIA's Tegra114 SPI Controller.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/clk.h>
962306a36Sopenharmony_ci#include <linux/completion.h>
1062306a36Sopenharmony_ci#include <linux/delay.h>
1162306a36Sopenharmony_ci#include <linux/dmaengine.h>
1262306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1362306a36Sopenharmony_ci#include <linux/dmapool.h>
1462306a36Sopenharmony_ci#include <linux/err.h>
1562306a36Sopenharmony_ci#include <linux/interrupt.h>
1662306a36Sopenharmony_ci#include <linux/io.h>
1762306a36Sopenharmony_ci#include <linux/kernel.h>
1862306a36Sopenharmony_ci#include <linux/kthread.h>
1962306a36Sopenharmony_ci#include <linux/module.h>
2062306a36Sopenharmony_ci#include <linux/platform_device.h>
2162306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2262306a36Sopenharmony_ci#include <linux/of.h>
2362306a36Sopenharmony_ci#include <linux/reset.h>
2462306a36Sopenharmony_ci#include <linux/spi/spi.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define SPI_COMMAND1				0x000
2762306a36Sopenharmony_ci#define SPI_BIT_LENGTH(x)			(((x) & 0x1f) << 0)
2862306a36Sopenharmony_ci#define SPI_PACKED				(1 << 5)
2962306a36Sopenharmony_ci#define SPI_TX_EN				(1 << 11)
3062306a36Sopenharmony_ci#define SPI_RX_EN				(1 << 12)
3162306a36Sopenharmony_ci#define SPI_BOTH_EN_BYTE			(1 << 13)
3262306a36Sopenharmony_ci#define SPI_BOTH_EN_BIT				(1 << 14)
3362306a36Sopenharmony_ci#define SPI_LSBYTE_FE				(1 << 15)
3462306a36Sopenharmony_ci#define SPI_LSBIT_FE				(1 << 16)
3562306a36Sopenharmony_ci#define SPI_BIDIROE				(1 << 17)
3662306a36Sopenharmony_ci#define SPI_IDLE_SDA_DRIVE_LOW			(0 << 18)
3762306a36Sopenharmony_ci#define SPI_IDLE_SDA_DRIVE_HIGH			(1 << 18)
3862306a36Sopenharmony_ci#define SPI_IDLE_SDA_PULL_LOW			(2 << 18)
3962306a36Sopenharmony_ci#define SPI_IDLE_SDA_PULL_HIGH			(3 << 18)
4062306a36Sopenharmony_ci#define SPI_IDLE_SDA_MASK			(3 << 18)
4162306a36Sopenharmony_ci#define SPI_CS_SW_VAL				(1 << 20)
4262306a36Sopenharmony_ci#define SPI_CS_SW_HW				(1 << 21)
4362306a36Sopenharmony_ci/* SPI_CS_POL_INACTIVE bits are default high */
4462306a36Sopenharmony_ci						/* n from 0 to 3 */
4562306a36Sopenharmony_ci#define SPI_CS_POL_INACTIVE(n)			(1 << (22 + (n)))
4662306a36Sopenharmony_ci#define SPI_CS_POL_INACTIVE_MASK		(0xF << 22)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define SPI_CS_SEL_0				(0 << 26)
4962306a36Sopenharmony_ci#define SPI_CS_SEL_1				(1 << 26)
5062306a36Sopenharmony_ci#define SPI_CS_SEL_2				(2 << 26)
5162306a36Sopenharmony_ci#define SPI_CS_SEL_3				(3 << 26)
5262306a36Sopenharmony_ci#define SPI_CS_SEL_MASK				(3 << 26)
5362306a36Sopenharmony_ci#define SPI_CS_SEL(x)				(((x) & 0x3) << 26)
5462306a36Sopenharmony_ci#define SPI_CONTROL_MODE_0			(0 << 28)
5562306a36Sopenharmony_ci#define SPI_CONTROL_MODE_1			(1 << 28)
5662306a36Sopenharmony_ci#define SPI_CONTROL_MODE_2			(2 << 28)
5762306a36Sopenharmony_ci#define SPI_CONTROL_MODE_3			(3 << 28)
5862306a36Sopenharmony_ci#define SPI_CONTROL_MODE_MASK			(3 << 28)
5962306a36Sopenharmony_ci#define SPI_MODE_SEL(x)				(((x) & 0x3) << 28)
6062306a36Sopenharmony_ci#define SPI_M_S					(1 << 30)
6162306a36Sopenharmony_ci#define SPI_PIO					(1 << 31)
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci#define SPI_COMMAND2				0x004
6462306a36Sopenharmony_ci#define SPI_TX_TAP_DELAY(x)			(((x) & 0x3F) << 6)
6562306a36Sopenharmony_ci#define SPI_RX_TAP_DELAY(x)			(((x) & 0x3F) << 0)
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#define SPI_CS_TIMING1				0x008
6862306a36Sopenharmony_ci#define SPI_SETUP_HOLD(setup, hold)		(((setup) << 4) | (hold))
6962306a36Sopenharmony_ci#define SPI_CS_SETUP_HOLD(reg, cs, val)			\
7062306a36Sopenharmony_ci		((((val) & 0xFFu) << ((cs) * 8)) |	\
7162306a36Sopenharmony_ci		((reg) & ~(0xFFu << ((cs) * 8))))
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#define SPI_CS_TIMING2				0x00C
7462306a36Sopenharmony_ci#define CYCLES_BETWEEN_PACKETS_0(x)		(((x) & 0x1F) << 0)
7562306a36Sopenharmony_ci#define CS_ACTIVE_BETWEEN_PACKETS_0		(1 << 5)
7662306a36Sopenharmony_ci#define CYCLES_BETWEEN_PACKETS_1(x)		(((x) & 0x1F) << 8)
7762306a36Sopenharmony_ci#define CS_ACTIVE_BETWEEN_PACKETS_1		(1 << 13)
7862306a36Sopenharmony_ci#define CYCLES_BETWEEN_PACKETS_2(x)		(((x) & 0x1F) << 16)
7962306a36Sopenharmony_ci#define CS_ACTIVE_BETWEEN_PACKETS_2		(1 << 21)
8062306a36Sopenharmony_ci#define CYCLES_BETWEEN_PACKETS_3(x)		(((x) & 0x1F) << 24)
8162306a36Sopenharmony_ci#define CS_ACTIVE_BETWEEN_PACKETS_3		(1 << 29)
8262306a36Sopenharmony_ci#define SPI_SET_CS_ACTIVE_BETWEEN_PACKETS(reg, cs, val)		\
8362306a36Sopenharmony_ci		(reg = (((val) & 0x1) << ((cs) * 8 + 5)) |	\
8462306a36Sopenharmony_ci			((reg) & ~(1 << ((cs) * 8 + 5))))
8562306a36Sopenharmony_ci#define SPI_SET_CYCLES_BETWEEN_PACKETS(reg, cs, val)		\
8662306a36Sopenharmony_ci		(reg = (((val) & 0x1F) << ((cs) * 8)) |		\
8762306a36Sopenharmony_ci			((reg) & ~(0x1F << ((cs) * 8))))
8862306a36Sopenharmony_ci#define MAX_SETUP_HOLD_CYCLES			16
8962306a36Sopenharmony_ci#define MAX_INACTIVE_CYCLES			32
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci#define SPI_TRANS_STATUS			0x010
9262306a36Sopenharmony_ci#define SPI_BLK_CNT(val)			(((val) >> 0) & 0xFFFF)
9362306a36Sopenharmony_ci#define SPI_SLV_IDLE_COUNT(val)			(((val) >> 16) & 0xFF)
9462306a36Sopenharmony_ci#define SPI_RDY					(1 << 30)
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#define SPI_FIFO_STATUS				0x014
9762306a36Sopenharmony_ci#define SPI_RX_FIFO_EMPTY			(1 << 0)
9862306a36Sopenharmony_ci#define SPI_RX_FIFO_FULL			(1 << 1)
9962306a36Sopenharmony_ci#define SPI_TX_FIFO_EMPTY			(1 << 2)
10062306a36Sopenharmony_ci#define SPI_TX_FIFO_FULL			(1 << 3)
10162306a36Sopenharmony_ci#define SPI_RX_FIFO_UNF				(1 << 4)
10262306a36Sopenharmony_ci#define SPI_RX_FIFO_OVF				(1 << 5)
10362306a36Sopenharmony_ci#define SPI_TX_FIFO_UNF				(1 << 6)
10462306a36Sopenharmony_ci#define SPI_TX_FIFO_OVF				(1 << 7)
10562306a36Sopenharmony_ci#define SPI_ERR					(1 << 8)
10662306a36Sopenharmony_ci#define SPI_TX_FIFO_FLUSH			(1 << 14)
10762306a36Sopenharmony_ci#define SPI_RX_FIFO_FLUSH			(1 << 15)
10862306a36Sopenharmony_ci#define SPI_TX_FIFO_EMPTY_COUNT(val)		(((val) >> 16) & 0x7F)
10962306a36Sopenharmony_ci#define SPI_RX_FIFO_FULL_COUNT(val)		(((val) >> 23) & 0x7F)
11062306a36Sopenharmony_ci#define SPI_FRAME_END				(1 << 30)
11162306a36Sopenharmony_ci#define SPI_CS_INACTIVE				(1 << 31)
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci#define SPI_FIFO_ERROR				(SPI_RX_FIFO_UNF | \
11462306a36Sopenharmony_ci			SPI_RX_FIFO_OVF | SPI_TX_FIFO_UNF | SPI_TX_FIFO_OVF)
11562306a36Sopenharmony_ci#define SPI_FIFO_EMPTY			(SPI_RX_FIFO_EMPTY | SPI_TX_FIFO_EMPTY)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci#define SPI_TX_DATA				0x018
11862306a36Sopenharmony_ci#define SPI_RX_DATA				0x01C
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci#define SPI_DMA_CTL				0x020
12162306a36Sopenharmony_ci#define SPI_TX_TRIG_1				(0 << 15)
12262306a36Sopenharmony_ci#define SPI_TX_TRIG_4				(1 << 15)
12362306a36Sopenharmony_ci#define SPI_TX_TRIG_8				(2 << 15)
12462306a36Sopenharmony_ci#define SPI_TX_TRIG_16				(3 << 15)
12562306a36Sopenharmony_ci#define SPI_TX_TRIG_MASK			(3 << 15)
12662306a36Sopenharmony_ci#define SPI_RX_TRIG_1				(0 << 19)
12762306a36Sopenharmony_ci#define SPI_RX_TRIG_4				(1 << 19)
12862306a36Sopenharmony_ci#define SPI_RX_TRIG_8				(2 << 19)
12962306a36Sopenharmony_ci#define SPI_RX_TRIG_16				(3 << 19)
13062306a36Sopenharmony_ci#define SPI_RX_TRIG_MASK			(3 << 19)
13162306a36Sopenharmony_ci#define SPI_IE_TX				(1 << 28)
13262306a36Sopenharmony_ci#define SPI_IE_RX				(1 << 29)
13362306a36Sopenharmony_ci#define SPI_CONT				(1 << 30)
13462306a36Sopenharmony_ci#define SPI_DMA					(1 << 31)
13562306a36Sopenharmony_ci#define SPI_DMA_EN				SPI_DMA
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci#define SPI_DMA_BLK				0x024
13862306a36Sopenharmony_ci#define SPI_DMA_BLK_SET(x)			(((x) & 0xFFFF) << 0)
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci#define SPI_TX_FIFO				0x108
14162306a36Sopenharmony_ci#define SPI_RX_FIFO				0x188
14262306a36Sopenharmony_ci#define SPI_INTR_MASK				0x18c
14362306a36Sopenharmony_ci#define SPI_INTR_ALL_MASK			(0x1fUL << 25)
14462306a36Sopenharmony_ci#define MAX_CHIP_SELECT				4
14562306a36Sopenharmony_ci#define SPI_FIFO_DEPTH				64
14662306a36Sopenharmony_ci#define DATA_DIR_TX				(1 << 0)
14762306a36Sopenharmony_ci#define DATA_DIR_RX				(1 << 1)
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci#define SPI_DMA_TIMEOUT				(msecs_to_jiffies(1000))
15062306a36Sopenharmony_ci#define DEFAULT_SPI_DMA_BUF_LEN			(16*1024)
15162306a36Sopenharmony_ci#define TX_FIFO_EMPTY_COUNT_MAX			SPI_TX_FIFO_EMPTY_COUNT(0x40)
15262306a36Sopenharmony_ci#define RX_FIFO_FULL_COUNT_ZERO			SPI_RX_FIFO_FULL_COUNT(0)
15362306a36Sopenharmony_ci#define MAX_HOLD_CYCLES				16
15462306a36Sopenharmony_ci#define SPI_DEFAULT_SPEED			25000000
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_cistruct tegra_spi_soc_data {
15762306a36Sopenharmony_ci	bool has_intr_mask_reg;
15862306a36Sopenharmony_ci};
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_cistruct tegra_spi_client_data {
16162306a36Sopenharmony_ci	int tx_clk_tap_delay;
16262306a36Sopenharmony_ci	int rx_clk_tap_delay;
16362306a36Sopenharmony_ci};
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistruct tegra_spi_data {
16662306a36Sopenharmony_ci	struct device				*dev;
16762306a36Sopenharmony_ci	struct spi_master			*master;
16862306a36Sopenharmony_ci	spinlock_t				lock;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	struct clk				*clk;
17162306a36Sopenharmony_ci	struct reset_control			*rst;
17262306a36Sopenharmony_ci	void __iomem				*base;
17362306a36Sopenharmony_ci	phys_addr_t				phys;
17462306a36Sopenharmony_ci	unsigned				irq;
17562306a36Sopenharmony_ci	u32					cur_speed;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	struct spi_device			*cur_spi;
17862306a36Sopenharmony_ci	struct spi_device			*cs_control;
17962306a36Sopenharmony_ci	unsigned				cur_pos;
18062306a36Sopenharmony_ci	unsigned				words_per_32bit;
18162306a36Sopenharmony_ci	unsigned				bytes_per_word;
18262306a36Sopenharmony_ci	unsigned				curr_dma_words;
18362306a36Sopenharmony_ci	unsigned				cur_direction;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	unsigned				cur_rx_pos;
18662306a36Sopenharmony_ci	unsigned				cur_tx_pos;
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	unsigned				dma_buf_size;
18962306a36Sopenharmony_ci	unsigned				max_buf_size;
19062306a36Sopenharmony_ci	bool					is_curr_dma_xfer;
19162306a36Sopenharmony_ci	bool					use_hw_based_cs;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	struct completion			rx_dma_complete;
19462306a36Sopenharmony_ci	struct completion			tx_dma_complete;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	u32					tx_status;
19762306a36Sopenharmony_ci	u32					rx_status;
19862306a36Sopenharmony_ci	u32					status_reg;
19962306a36Sopenharmony_ci	bool					is_packed;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	u32					command1_reg;
20262306a36Sopenharmony_ci	u32					dma_control_reg;
20362306a36Sopenharmony_ci	u32					def_command1_reg;
20462306a36Sopenharmony_ci	u32					def_command2_reg;
20562306a36Sopenharmony_ci	u32					spi_cs_timing1;
20662306a36Sopenharmony_ci	u32					spi_cs_timing2;
20762306a36Sopenharmony_ci	u8					last_used_cs;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	struct completion			xfer_completion;
21062306a36Sopenharmony_ci	struct spi_transfer			*curr_xfer;
21162306a36Sopenharmony_ci	struct dma_chan				*rx_dma_chan;
21262306a36Sopenharmony_ci	u32					*rx_dma_buf;
21362306a36Sopenharmony_ci	dma_addr_t				rx_dma_phys;
21462306a36Sopenharmony_ci	struct dma_async_tx_descriptor		*rx_dma_desc;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	struct dma_chan				*tx_dma_chan;
21762306a36Sopenharmony_ci	u32					*tx_dma_buf;
21862306a36Sopenharmony_ci	dma_addr_t				tx_dma_phys;
21962306a36Sopenharmony_ci	struct dma_async_tx_descriptor		*tx_dma_desc;
22062306a36Sopenharmony_ci	const struct tegra_spi_soc_data		*soc_data;
22162306a36Sopenharmony_ci};
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistatic int tegra_spi_runtime_suspend(struct device *dev);
22462306a36Sopenharmony_cistatic int tegra_spi_runtime_resume(struct device *dev);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistatic inline u32 tegra_spi_readl(struct tegra_spi_data *tspi,
22762306a36Sopenharmony_ci		unsigned long reg)
22862306a36Sopenharmony_ci{
22962306a36Sopenharmony_ci	return readl(tspi->base + reg);
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_cistatic inline void tegra_spi_writel(struct tegra_spi_data *tspi,
23362306a36Sopenharmony_ci		u32 val, unsigned long reg)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	writel(val, tspi->base + reg);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/* Read back register to make sure that register writes completed */
23862306a36Sopenharmony_ci	if (reg != SPI_TX_FIFO)
23962306a36Sopenharmony_ci		readl(tspi->base + SPI_COMMAND1);
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic void tegra_spi_clear_status(struct tegra_spi_data *tspi)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	u32 val;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	/* Write 1 to clear status register */
24762306a36Sopenharmony_ci	val = tegra_spi_readl(tspi, SPI_TRANS_STATUS);
24862306a36Sopenharmony_ci	tegra_spi_writel(tspi, val, SPI_TRANS_STATUS);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* Clear fifo status error if any */
25162306a36Sopenharmony_ci	val = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
25262306a36Sopenharmony_ci	if (val & SPI_ERR)
25362306a36Sopenharmony_ci		tegra_spi_writel(tspi, SPI_ERR | SPI_FIFO_ERROR,
25462306a36Sopenharmony_ci				SPI_FIFO_STATUS);
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cistatic unsigned tegra_spi_calculate_curr_xfer_param(
25862306a36Sopenharmony_ci	struct spi_device *spi, struct tegra_spi_data *tspi,
25962306a36Sopenharmony_ci	struct spi_transfer *t)
26062306a36Sopenharmony_ci{
26162306a36Sopenharmony_ci	unsigned remain_len = t->len - tspi->cur_pos;
26262306a36Sopenharmony_ci	unsigned max_word;
26362306a36Sopenharmony_ci	unsigned bits_per_word = t->bits_per_word;
26462306a36Sopenharmony_ci	unsigned max_len;
26562306a36Sopenharmony_ci	unsigned total_fifo_words;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	if ((bits_per_word == 8 || bits_per_word == 16 ||
27062306a36Sopenharmony_ci	     bits_per_word == 32) && t->len > 3) {
27162306a36Sopenharmony_ci		tspi->is_packed = true;
27262306a36Sopenharmony_ci		tspi->words_per_32bit = 32/bits_per_word;
27362306a36Sopenharmony_ci	} else {
27462306a36Sopenharmony_ci		tspi->is_packed = false;
27562306a36Sopenharmony_ci		tspi->words_per_32bit = 1;
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	if (tspi->is_packed) {
27962306a36Sopenharmony_ci		max_len = min(remain_len, tspi->max_buf_size);
28062306a36Sopenharmony_ci		tspi->curr_dma_words = max_len/tspi->bytes_per_word;
28162306a36Sopenharmony_ci		total_fifo_words = (max_len + 3) / 4;
28262306a36Sopenharmony_ci	} else {
28362306a36Sopenharmony_ci		max_word = (remain_len - 1) / tspi->bytes_per_word + 1;
28462306a36Sopenharmony_ci		max_word = min(max_word, tspi->max_buf_size/4);
28562306a36Sopenharmony_ci		tspi->curr_dma_words = max_word;
28662306a36Sopenharmony_ci		total_fifo_words = max_word;
28762306a36Sopenharmony_ci	}
28862306a36Sopenharmony_ci	return total_fifo_words;
28962306a36Sopenharmony_ci}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_cistatic unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
29262306a36Sopenharmony_ci	struct tegra_spi_data *tspi, struct spi_transfer *t)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	unsigned nbytes;
29562306a36Sopenharmony_ci	unsigned tx_empty_count;
29662306a36Sopenharmony_ci	u32 fifo_status;
29762306a36Sopenharmony_ci	unsigned max_n_32bit;
29862306a36Sopenharmony_ci	unsigned i, count;
29962306a36Sopenharmony_ci	unsigned int written_words;
30062306a36Sopenharmony_ci	unsigned fifo_words_left;
30162306a36Sopenharmony_ci	u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	fifo_status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
30462306a36Sopenharmony_ci	tx_empty_count = SPI_TX_FIFO_EMPTY_COUNT(fifo_status);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	if (tspi->is_packed) {
30762306a36Sopenharmony_ci		fifo_words_left = tx_empty_count * tspi->words_per_32bit;
30862306a36Sopenharmony_ci		written_words = min(fifo_words_left, tspi->curr_dma_words);
30962306a36Sopenharmony_ci		nbytes = written_words * tspi->bytes_per_word;
31062306a36Sopenharmony_ci		max_n_32bit = DIV_ROUND_UP(nbytes, 4);
31162306a36Sopenharmony_ci		for (count = 0; count < max_n_32bit; count++) {
31262306a36Sopenharmony_ci			u32 x = 0;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci			for (i = 0; (i < 4) && nbytes; i++, nbytes--)
31562306a36Sopenharmony_ci				x |= (u32)(*tx_buf++) << (i * 8);
31662306a36Sopenharmony_ci			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
31762306a36Sopenharmony_ci		}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
32062306a36Sopenharmony_ci	} else {
32162306a36Sopenharmony_ci		unsigned int write_bytes;
32262306a36Sopenharmony_ci		max_n_32bit = min(tspi->curr_dma_words,  tx_empty_count);
32362306a36Sopenharmony_ci		written_words = max_n_32bit;
32462306a36Sopenharmony_ci		nbytes = written_words * tspi->bytes_per_word;
32562306a36Sopenharmony_ci		if (nbytes > t->len - tspi->cur_pos)
32662306a36Sopenharmony_ci			nbytes = t->len - tspi->cur_pos;
32762306a36Sopenharmony_ci		write_bytes = nbytes;
32862306a36Sopenharmony_ci		for (count = 0; count < max_n_32bit; count++) {
32962306a36Sopenharmony_ci			u32 x = 0;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci			for (i = 0; nbytes && (i < tspi->bytes_per_word);
33262306a36Sopenharmony_ci							i++, nbytes--)
33362306a36Sopenharmony_ci				x |= (u32)(*tx_buf++) << (i * 8);
33462306a36Sopenharmony_ci			tegra_spi_writel(tspi, x, SPI_TX_FIFO);
33562306a36Sopenharmony_ci		}
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci		tspi->cur_tx_pos += write_bytes;
33862306a36Sopenharmony_ci	}
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	return written_words;
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf(
34462306a36Sopenharmony_ci		struct tegra_spi_data *tspi, struct spi_transfer *t)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	unsigned rx_full_count;
34762306a36Sopenharmony_ci	u32 fifo_status;
34862306a36Sopenharmony_ci	unsigned i, count;
34962306a36Sopenharmony_ci	unsigned int read_words = 0;
35062306a36Sopenharmony_ci	unsigned len;
35162306a36Sopenharmony_ci	u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_rx_pos;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	fifo_status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
35462306a36Sopenharmony_ci	rx_full_count = SPI_RX_FIFO_FULL_COUNT(fifo_status);
35562306a36Sopenharmony_ci	if (tspi->is_packed) {
35662306a36Sopenharmony_ci		len = tspi->curr_dma_words * tspi->bytes_per_word;
35762306a36Sopenharmony_ci		for (count = 0; count < rx_full_count; count++) {
35862306a36Sopenharmony_ci			u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci			for (i = 0; len && (i < 4); i++, len--)
36162306a36Sopenharmony_ci				*rx_buf++ = (x >> i*8) & 0xFF;
36262306a36Sopenharmony_ci		}
36362306a36Sopenharmony_ci		read_words += tspi->curr_dma_words;
36462306a36Sopenharmony_ci		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
36562306a36Sopenharmony_ci	} else {
36662306a36Sopenharmony_ci		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
36762306a36Sopenharmony_ci		u8 bytes_per_word = tspi->bytes_per_word;
36862306a36Sopenharmony_ci		unsigned int read_bytes;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci		len = rx_full_count * bytes_per_word;
37162306a36Sopenharmony_ci		if (len > t->len - tspi->cur_pos)
37262306a36Sopenharmony_ci			len = t->len - tspi->cur_pos;
37362306a36Sopenharmony_ci		read_bytes = len;
37462306a36Sopenharmony_ci		for (count = 0; count < rx_full_count; count++) {
37562306a36Sopenharmony_ci			u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci			for (i = 0; len && (i < bytes_per_word); i++, len--)
37862306a36Sopenharmony_ci				*rx_buf++ = (x >> (i*8)) & 0xFF;
37962306a36Sopenharmony_ci		}
38062306a36Sopenharmony_ci		read_words += rx_full_count;
38162306a36Sopenharmony_ci		tspi->cur_rx_pos += read_bytes;
38262306a36Sopenharmony_ci	}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	return read_words;
38562306a36Sopenharmony_ci}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_cistatic void tegra_spi_copy_client_txbuf_to_spi_txbuf(
38862306a36Sopenharmony_ci		struct tegra_spi_data *tspi, struct spi_transfer *t)
38962306a36Sopenharmony_ci{
39062306a36Sopenharmony_ci	/* Make the dma buffer to read by cpu */
39162306a36Sopenharmony_ci	dma_sync_single_for_cpu(tspi->dev, tspi->tx_dma_phys,
39262306a36Sopenharmony_ci				tspi->dma_buf_size, DMA_TO_DEVICE);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (tspi->is_packed) {
39562306a36Sopenharmony_ci		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci		memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
39862306a36Sopenharmony_ci		tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
39962306a36Sopenharmony_ci	} else {
40062306a36Sopenharmony_ci		unsigned int i;
40162306a36Sopenharmony_ci		unsigned int count;
40262306a36Sopenharmony_ci		u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
40362306a36Sopenharmony_ci		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
40462306a36Sopenharmony_ci		unsigned int write_bytes;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci		if (consume > t->len - tspi->cur_pos)
40762306a36Sopenharmony_ci			consume = t->len - tspi->cur_pos;
40862306a36Sopenharmony_ci		write_bytes = consume;
40962306a36Sopenharmony_ci		for (count = 0; count < tspi->curr_dma_words; count++) {
41062306a36Sopenharmony_ci			u32 x = 0;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci			for (i = 0; consume && (i < tspi->bytes_per_word);
41362306a36Sopenharmony_ci							i++, consume--)
41462306a36Sopenharmony_ci				x |= (u32)(*tx_buf++) << (i * 8);
41562306a36Sopenharmony_ci			tspi->tx_dma_buf[count] = x;
41662306a36Sopenharmony_ci		}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci		tspi->cur_tx_pos += write_bytes;
41962306a36Sopenharmony_ci	}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	/* Make the dma buffer to read by dma */
42262306a36Sopenharmony_ci	dma_sync_single_for_device(tspi->dev, tspi->tx_dma_phys,
42362306a36Sopenharmony_ci				tspi->dma_buf_size, DMA_TO_DEVICE);
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic void tegra_spi_copy_spi_rxbuf_to_client_rxbuf(
42762306a36Sopenharmony_ci		struct tegra_spi_data *tspi, struct spi_transfer *t)
42862306a36Sopenharmony_ci{
42962306a36Sopenharmony_ci	/* Make the dma buffer to read by cpu */
43062306a36Sopenharmony_ci	dma_sync_single_for_cpu(tspi->dev, tspi->rx_dma_phys,
43162306a36Sopenharmony_ci		tspi->dma_buf_size, DMA_FROM_DEVICE);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	if (tspi->is_packed) {
43462306a36Sopenharmony_ci		unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci		memcpy(t->rx_buf + tspi->cur_rx_pos, tspi->rx_dma_buf, len);
43762306a36Sopenharmony_ci		tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
43862306a36Sopenharmony_ci	} else {
43962306a36Sopenharmony_ci		unsigned int i;
44062306a36Sopenharmony_ci		unsigned int count;
44162306a36Sopenharmony_ci		unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos;
44262306a36Sopenharmony_ci		u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
44362306a36Sopenharmony_ci		unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
44462306a36Sopenharmony_ci		unsigned int read_bytes;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci		if (consume > t->len - tspi->cur_pos)
44762306a36Sopenharmony_ci			consume = t->len - tspi->cur_pos;
44862306a36Sopenharmony_ci		read_bytes = consume;
44962306a36Sopenharmony_ci		for (count = 0; count < tspi->curr_dma_words; count++) {
45062306a36Sopenharmony_ci			u32 x = tspi->rx_dma_buf[count] & rx_mask;
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci			for (i = 0; consume && (i < tspi->bytes_per_word);
45362306a36Sopenharmony_ci							i++, consume--)
45462306a36Sopenharmony_ci				*rx_buf++ = (x >> (i*8)) & 0xFF;
45562306a36Sopenharmony_ci		}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci		tspi->cur_rx_pos += read_bytes;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	/* Make the dma buffer to read by dma */
46162306a36Sopenharmony_ci	dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
46262306a36Sopenharmony_ci		tspi->dma_buf_size, DMA_FROM_DEVICE);
46362306a36Sopenharmony_ci}
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_cistatic void tegra_spi_dma_complete(void *args)
46662306a36Sopenharmony_ci{
46762306a36Sopenharmony_ci	struct completion *dma_complete = args;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	complete(dma_complete);
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_cistatic int tegra_spi_start_tx_dma(struct tegra_spi_data *tspi, int len)
47362306a36Sopenharmony_ci{
47462306a36Sopenharmony_ci	reinit_completion(&tspi->tx_dma_complete);
47562306a36Sopenharmony_ci	tspi->tx_dma_desc = dmaengine_prep_slave_single(tspi->tx_dma_chan,
47662306a36Sopenharmony_ci				tspi->tx_dma_phys, len, DMA_MEM_TO_DEV,
47762306a36Sopenharmony_ci				DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
47862306a36Sopenharmony_ci	if (!tspi->tx_dma_desc) {
47962306a36Sopenharmony_ci		dev_err(tspi->dev, "Not able to get desc for Tx\n");
48062306a36Sopenharmony_ci		return -EIO;
48162306a36Sopenharmony_ci	}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	tspi->tx_dma_desc->callback = tegra_spi_dma_complete;
48462306a36Sopenharmony_ci	tspi->tx_dma_desc->callback_param = &tspi->tx_dma_complete;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	dmaengine_submit(tspi->tx_dma_desc);
48762306a36Sopenharmony_ci	dma_async_issue_pending(tspi->tx_dma_chan);
48862306a36Sopenharmony_ci	return 0;
48962306a36Sopenharmony_ci}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_cistatic int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len)
49262306a36Sopenharmony_ci{
49362306a36Sopenharmony_ci	reinit_completion(&tspi->rx_dma_complete);
49462306a36Sopenharmony_ci	tspi->rx_dma_desc = dmaengine_prep_slave_single(tspi->rx_dma_chan,
49562306a36Sopenharmony_ci				tspi->rx_dma_phys, len, DMA_DEV_TO_MEM,
49662306a36Sopenharmony_ci				DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
49762306a36Sopenharmony_ci	if (!tspi->rx_dma_desc) {
49862306a36Sopenharmony_ci		dev_err(tspi->dev, "Not able to get desc for Rx\n");
49962306a36Sopenharmony_ci		return -EIO;
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	tspi->rx_dma_desc->callback = tegra_spi_dma_complete;
50362306a36Sopenharmony_ci	tspi->rx_dma_desc->callback_param = &tspi->rx_dma_complete;
50462306a36Sopenharmony_ci
50562306a36Sopenharmony_ci	dmaengine_submit(tspi->rx_dma_desc);
50662306a36Sopenharmony_ci	dma_async_issue_pending(tspi->rx_dma_chan);
50762306a36Sopenharmony_ci	return 0;
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_cistatic int tegra_spi_flush_fifos(struct tegra_spi_data *tspi)
51162306a36Sopenharmony_ci{
51262306a36Sopenharmony_ci	unsigned long timeout = jiffies + HZ;
51362306a36Sopenharmony_ci	u32 status;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
51662306a36Sopenharmony_ci	if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
51762306a36Sopenharmony_ci		status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH;
51862306a36Sopenharmony_ci		tegra_spi_writel(tspi, status, SPI_FIFO_STATUS);
51962306a36Sopenharmony_ci		while ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
52062306a36Sopenharmony_ci			status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
52162306a36Sopenharmony_ci			if (time_after(jiffies, timeout)) {
52262306a36Sopenharmony_ci				dev_err(tspi->dev,
52362306a36Sopenharmony_ci					"timeout waiting for fifo flush\n");
52462306a36Sopenharmony_ci				return -EIO;
52562306a36Sopenharmony_ci			}
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci			udelay(1);
52862306a36Sopenharmony_ci		}
52962306a36Sopenharmony_ci	}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci	return 0;
53262306a36Sopenharmony_ci}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_cistatic int tegra_spi_start_dma_based_transfer(
53562306a36Sopenharmony_ci		struct tegra_spi_data *tspi, struct spi_transfer *t)
53662306a36Sopenharmony_ci{
53762306a36Sopenharmony_ci	u32 val;
53862306a36Sopenharmony_ci	unsigned int len;
53962306a36Sopenharmony_ci	int ret = 0;
54062306a36Sopenharmony_ci	u8 dma_burst;
54162306a36Sopenharmony_ci	struct dma_slave_config dma_sconfig = {0};
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
54462306a36Sopenharmony_ci	tegra_spi_writel(tspi, val, SPI_DMA_BLK);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	if (tspi->is_packed)
54762306a36Sopenharmony_ci		len = DIV_ROUND_UP(tspi->curr_dma_words * tspi->bytes_per_word,
54862306a36Sopenharmony_ci					4) * 4;
54962306a36Sopenharmony_ci	else
55062306a36Sopenharmony_ci		len = tspi->curr_dma_words * 4;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	/* Set attention level based on length of transfer */
55362306a36Sopenharmony_ci	if (len & 0xF) {
55462306a36Sopenharmony_ci		val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1;
55562306a36Sopenharmony_ci		dma_burst = 1;
55662306a36Sopenharmony_ci	} else if (((len) >> 4) & 0x1) {
55762306a36Sopenharmony_ci		val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4;
55862306a36Sopenharmony_ci		dma_burst = 4;
55962306a36Sopenharmony_ci	} else {
56062306a36Sopenharmony_ci		val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8;
56162306a36Sopenharmony_ci		dma_burst = 8;
56262306a36Sopenharmony_ci	}
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_ci	if (!tspi->soc_data->has_intr_mask_reg) {
56562306a36Sopenharmony_ci		if (tspi->cur_direction & DATA_DIR_TX)
56662306a36Sopenharmony_ci			val |= SPI_IE_TX;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci		if (tspi->cur_direction & DATA_DIR_RX)
56962306a36Sopenharmony_ci			val |= SPI_IE_RX;
57062306a36Sopenharmony_ci	}
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	tegra_spi_writel(tspi, val, SPI_DMA_CTL);
57362306a36Sopenharmony_ci	tspi->dma_control_reg = val;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	dma_sconfig.device_fc = true;
57662306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_TX) {
57762306a36Sopenharmony_ci		dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO;
57862306a36Sopenharmony_ci		dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
57962306a36Sopenharmony_ci		dma_sconfig.dst_maxburst = dma_burst;
58062306a36Sopenharmony_ci		ret = dmaengine_slave_config(tspi->tx_dma_chan, &dma_sconfig);
58162306a36Sopenharmony_ci		if (ret < 0) {
58262306a36Sopenharmony_ci			dev_err(tspi->dev,
58362306a36Sopenharmony_ci				"DMA slave config failed: %d\n", ret);
58462306a36Sopenharmony_ci			return ret;
58562306a36Sopenharmony_ci		}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci		tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t);
58862306a36Sopenharmony_ci		ret = tegra_spi_start_tx_dma(tspi, len);
58962306a36Sopenharmony_ci		if (ret < 0) {
59062306a36Sopenharmony_ci			dev_err(tspi->dev,
59162306a36Sopenharmony_ci				"Starting tx dma failed, err %d\n", ret);
59262306a36Sopenharmony_ci			return ret;
59362306a36Sopenharmony_ci		}
59462306a36Sopenharmony_ci	}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_RX) {
59762306a36Sopenharmony_ci		dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO;
59862306a36Sopenharmony_ci		dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
59962306a36Sopenharmony_ci		dma_sconfig.src_maxburst = dma_burst;
60062306a36Sopenharmony_ci		ret = dmaengine_slave_config(tspi->rx_dma_chan, &dma_sconfig);
60162306a36Sopenharmony_ci		if (ret < 0) {
60262306a36Sopenharmony_ci			dev_err(tspi->dev,
60362306a36Sopenharmony_ci				"DMA slave config failed: %d\n", ret);
60462306a36Sopenharmony_ci			return ret;
60562306a36Sopenharmony_ci		}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci		/* Make the dma buffer to read by dma */
60862306a36Sopenharmony_ci		dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
60962306a36Sopenharmony_ci				tspi->dma_buf_size, DMA_FROM_DEVICE);
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci		ret = tegra_spi_start_rx_dma(tspi, len);
61262306a36Sopenharmony_ci		if (ret < 0) {
61362306a36Sopenharmony_ci			dev_err(tspi->dev,
61462306a36Sopenharmony_ci				"Starting rx dma failed, err %d\n", ret);
61562306a36Sopenharmony_ci			if (tspi->cur_direction & DATA_DIR_TX)
61662306a36Sopenharmony_ci				dmaengine_terminate_all(tspi->tx_dma_chan);
61762306a36Sopenharmony_ci			return ret;
61862306a36Sopenharmony_ci		}
61962306a36Sopenharmony_ci	}
62062306a36Sopenharmony_ci	tspi->is_curr_dma_xfer = true;
62162306a36Sopenharmony_ci	tspi->dma_control_reg = val;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	val |= SPI_DMA_EN;
62462306a36Sopenharmony_ci	tegra_spi_writel(tspi, val, SPI_DMA_CTL);
62562306a36Sopenharmony_ci	return ret;
62662306a36Sopenharmony_ci}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_cistatic int tegra_spi_start_cpu_based_transfer(
62962306a36Sopenharmony_ci		struct tegra_spi_data *tspi, struct spi_transfer *t)
63062306a36Sopenharmony_ci{
63162306a36Sopenharmony_ci	u32 val;
63262306a36Sopenharmony_ci	unsigned cur_words;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_TX)
63562306a36Sopenharmony_ci		cur_words = tegra_spi_fill_tx_fifo_from_client_txbuf(tspi, t);
63662306a36Sopenharmony_ci	else
63762306a36Sopenharmony_ci		cur_words = tspi->curr_dma_words;
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci	val = SPI_DMA_BLK_SET(cur_words - 1);
64062306a36Sopenharmony_ci	tegra_spi_writel(tspi, val, SPI_DMA_BLK);
64162306a36Sopenharmony_ci
64262306a36Sopenharmony_ci	val = 0;
64362306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_TX)
64462306a36Sopenharmony_ci		val |= SPI_IE_TX;
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_RX)
64762306a36Sopenharmony_ci		val |= SPI_IE_RX;
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci	tegra_spi_writel(tspi, val, SPI_DMA_CTL);
65062306a36Sopenharmony_ci	tspi->dma_control_reg = val;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	tspi->is_curr_dma_xfer = false;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	val = tspi->command1_reg;
65562306a36Sopenharmony_ci	val |= SPI_PIO;
65662306a36Sopenharmony_ci	tegra_spi_writel(tspi, val, SPI_COMMAND1);
65762306a36Sopenharmony_ci	return 0;
65862306a36Sopenharmony_ci}
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_cistatic int tegra_spi_init_dma_param(struct tegra_spi_data *tspi,
66162306a36Sopenharmony_ci			bool dma_to_memory)
66262306a36Sopenharmony_ci{
66362306a36Sopenharmony_ci	struct dma_chan *dma_chan;
66462306a36Sopenharmony_ci	u32 *dma_buf;
66562306a36Sopenharmony_ci	dma_addr_t dma_phys;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	dma_chan = dma_request_chan(tspi->dev, dma_to_memory ? "rx" : "tx");
66862306a36Sopenharmony_ci	if (IS_ERR(dma_chan))
66962306a36Sopenharmony_ci		return dev_err_probe(tspi->dev, PTR_ERR(dma_chan),
67062306a36Sopenharmony_ci				     "Dma channel is not available\n");
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci	dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size,
67362306a36Sopenharmony_ci				&dma_phys, GFP_KERNEL);
67462306a36Sopenharmony_ci	if (!dma_buf) {
67562306a36Sopenharmony_ci		dev_err(tspi->dev, " Not able to allocate the dma buffer\n");
67662306a36Sopenharmony_ci		dma_release_channel(dma_chan);
67762306a36Sopenharmony_ci		return -ENOMEM;
67862306a36Sopenharmony_ci	}
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	if (dma_to_memory) {
68162306a36Sopenharmony_ci		tspi->rx_dma_chan = dma_chan;
68262306a36Sopenharmony_ci		tspi->rx_dma_buf = dma_buf;
68362306a36Sopenharmony_ci		tspi->rx_dma_phys = dma_phys;
68462306a36Sopenharmony_ci	} else {
68562306a36Sopenharmony_ci		tspi->tx_dma_chan = dma_chan;
68662306a36Sopenharmony_ci		tspi->tx_dma_buf = dma_buf;
68762306a36Sopenharmony_ci		tspi->tx_dma_phys = dma_phys;
68862306a36Sopenharmony_ci	}
68962306a36Sopenharmony_ci	return 0;
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_cistatic void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
69362306a36Sopenharmony_ci	bool dma_to_memory)
69462306a36Sopenharmony_ci{
69562306a36Sopenharmony_ci	u32 *dma_buf;
69662306a36Sopenharmony_ci	dma_addr_t dma_phys;
69762306a36Sopenharmony_ci	struct dma_chan *dma_chan;
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	if (dma_to_memory) {
70062306a36Sopenharmony_ci		dma_buf = tspi->rx_dma_buf;
70162306a36Sopenharmony_ci		dma_chan = tspi->rx_dma_chan;
70262306a36Sopenharmony_ci		dma_phys = tspi->rx_dma_phys;
70362306a36Sopenharmony_ci		tspi->rx_dma_chan = NULL;
70462306a36Sopenharmony_ci		tspi->rx_dma_buf = NULL;
70562306a36Sopenharmony_ci	} else {
70662306a36Sopenharmony_ci		dma_buf = tspi->tx_dma_buf;
70762306a36Sopenharmony_ci		dma_chan = tspi->tx_dma_chan;
70862306a36Sopenharmony_ci		dma_phys = tspi->tx_dma_phys;
70962306a36Sopenharmony_ci		tspi->tx_dma_buf = NULL;
71062306a36Sopenharmony_ci		tspi->tx_dma_chan = NULL;
71162306a36Sopenharmony_ci	}
71262306a36Sopenharmony_ci	if (!dma_chan)
71362306a36Sopenharmony_ci		return;
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci	dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys);
71662306a36Sopenharmony_ci	dma_release_channel(dma_chan);
71762306a36Sopenharmony_ci}
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_cistatic int tegra_spi_set_hw_cs_timing(struct spi_device *spi)
72062306a36Sopenharmony_ci{
72162306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
72262306a36Sopenharmony_ci	struct spi_delay *setup = &spi->cs_setup;
72362306a36Sopenharmony_ci	struct spi_delay *hold = &spi->cs_hold;
72462306a36Sopenharmony_ci	struct spi_delay *inactive = &spi->cs_inactive;
72562306a36Sopenharmony_ci	u8 setup_dly, hold_dly;
72662306a36Sopenharmony_ci	u32 setup_hold;
72762306a36Sopenharmony_ci	u32 spi_cs_timing;
72862306a36Sopenharmony_ci	u32 inactive_cycles;
72962306a36Sopenharmony_ci	u8 cs_state;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	if (setup->unit != SPI_DELAY_UNIT_SCK ||
73262306a36Sopenharmony_ci	    hold->unit != SPI_DELAY_UNIT_SCK ||
73362306a36Sopenharmony_ci	    inactive->unit != SPI_DELAY_UNIT_SCK) {
73462306a36Sopenharmony_ci		dev_err(&spi->dev,
73562306a36Sopenharmony_ci			"Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n",
73662306a36Sopenharmony_ci			SPI_DELAY_UNIT_SCK);
73762306a36Sopenharmony_ci		return -EINVAL;
73862306a36Sopenharmony_ci	}
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_ci	setup_dly = min_t(u8, setup->value, MAX_SETUP_HOLD_CYCLES);
74162306a36Sopenharmony_ci	hold_dly = min_t(u8, hold->value, MAX_SETUP_HOLD_CYCLES);
74262306a36Sopenharmony_ci	if (setup_dly && hold_dly) {
74362306a36Sopenharmony_ci		setup_hold = SPI_SETUP_HOLD(setup_dly - 1, hold_dly - 1);
74462306a36Sopenharmony_ci		spi_cs_timing = SPI_CS_SETUP_HOLD(tspi->spi_cs_timing1,
74562306a36Sopenharmony_ci						  spi_get_chipselect(spi, 0),
74662306a36Sopenharmony_ci						  setup_hold);
74762306a36Sopenharmony_ci		if (tspi->spi_cs_timing1 != spi_cs_timing) {
74862306a36Sopenharmony_ci			tspi->spi_cs_timing1 = spi_cs_timing;
74962306a36Sopenharmony_ci			tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING1);
75062306a36Sopenharmony_ci		}
75162306a36Sopenharmony_ci	}
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	inactive_cycles = min_t(u8, inactive->value, MAX_INACTIVE_CYCLES);
75462306a36Sopenharmony_ci	if (inactive_cycles)
75562306a36Sopenharmony_ci		inactive_cycles--;
75662306a36Sopenharmony_ci	cs_state = inactive_cycles ? 0 : 1;
75762306a36Sopenharmony_ci	spi_cs_timing = tspi->spi_cs_timing2;
75862306a36Sopenharmony_ci	SPI_SET_CS_ACTIVE_BETWEEN_PACKETS(spi_cs_timing, spi_get_chipselect(spi, 0),
75962306a36Sopenharmony_ci					  cs_state);
76062306a36Sopenharmony_ci	SPI_SET_CYCLES_BETWEEN_PACKETS(spi_cs_timing, spi_get_chipselect(spi, 0),
76162306a36Sopenharmony_ci				       inactive_cycles);
76262306a36Sopenharmony_ci	if (tspi->spi_cs_timing2 != spi_cs_timing) {
76362306a36Sopenharmony_ci		tspi->spi_cs_timing2 = spi_cs_timing;
76462306a36Sopenharmony_ci		tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2);
76562306a36Sopenharmony_ci	}
76662306a36Sopenharmony_ci
76762306a36Sopenharmony_ci	return 0;
76862306a36Sopenharmony_ci}
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_cistatic u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
77162306a36Sopenharmony_ci					struct spi_transfer *t,
77262306a36Sopenharmony_ci					bool is_first_of_msg,
77362306a36Sopenharmony_ci					bool is_single_xfer)
77462306a36Sopenharmony_ci{
77562306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
77662306a36Sopenharmony_ci	struct tegra_spi_client_data *cdata = spi->controller_data;
77762306a36Sopenharmony_ci	u32 speed = t->speed_hz;
77862306a36Sopenharmony_ci	u8 bits_per_word = t->bits_per_word;
77962306a36Sopenharmony_ci	u32 command1, command2;
78062306a36Sopenharmony_ci	int req_mode;
78162306a36Sopenharmony_ci	u32 tx_tap = 0, rx_tap = 0;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	if (speed != tspi->cur_speed) {
78462306a36Sopenharmony_ci		clk_set_rate(tspi->clk, speed);
78562306a36Sopenharmony_ci		tspi->cur_speed = speed;
78662306a36Sopenharmony_ci	}
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	tspi->cur_spi = spi;
78962306a36Sopenharmony_ci	tspi->cur_pos = 0;
79062306a36Sopenharmony_ci	tspi->cur_rx_pos = 0;
79162306a36Sopenharmony_ci	tspi->cur_tx_pos = 0;
79262306a36Sopenharmony_ci	tspi->curr_xfer = t;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	if (is_first_of_msg) {
79562306a36Sopenharmony_ci		tegra_spi_clear_status(tspi);
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci		command1 = tspi->def_command1_reg;
79862306a36Sopenharmony_ci		command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci		command1 &= ~SPI_CONTROL_MODE_MASK;
80162306a36Sopenharmony_ci		req_mode = spi->mode & 0x3;
80262306a36Sopenharmony_ci		if (req_mode == SPI_MODE_0)
80362306a36Sopenharmony_ci			command1 |= SPI_CONTROL_MODE_0;
80462306a36Sopenharmony_ci		else if (req_mode == SPI_MODE_1)
80562306a36Sopenharmony_ci			command1 |= SPI_CONTROL_MODE_1;
80662306a36Sopenharmony_ci		else if (req_mode == SPI_MODE_2)
80762306a36Sopenharmony_ci			command1 |= SPI_CONTROL_MODE_2;
80862306a36Sopenharmony_ci		else if (req_mode == SPI_MODE_3)
80962306a36Sopenharmony_ci			command1 |= SPI_CONTROL_MODE_3;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci		if (spi->mode & SPI_LSB_FIRST)
81262306a36Sopenharmony_ci			command1 |= SPI_LSBIT_FE;
81362306a36Sopenharmony_ci		else
81462306a36Sopenharmony_ci			command1 &= ~SPI_LSBIT_FE;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci		if (spi->mode & SPI_3WIRE)
81762306a36Sopenharmony_ci			command1 |= SPI_BIDIROE;
81862306a36Sopenharmony_ci		else
81962306a36Sopenharmony_ci			command1 &= ~SPI_BIDIROE;
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci		if (tspi->cs_control) {
82262306a36Sopenharmony_ci			if (tspi->cs_control != spi)
82362306a36Sopenharmony_ci				tegra_spi_writel(tspi, command1, SPI_COMMAND1);
82462306a36Sopenharmony_ci			tspi->cs_control = NULL;
82562306a36Sopenharmony_ci		} else
82662306a36Sopenharmony_ci			tegra_spi_writel(tspi, command1, SPI_COMMAND1);
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_ci		/* GPIO based chip select control */
82962306a36Sopenharmony_ci		if (spi_get_csgpiod(spi, 0))
83062306a36Sopenharmony_ci			gpiod_set_value(spi_get_csgpiod(spi, 0), 1);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci		if (is_single_xfer && !(t->cs_change)) {
83362306a36Sopenharmony_ci			tspi->use_hw_based_cs = true;
83462306a36Sopenharmony_ci			command1 &= ~(SPI_CS_SW_HW | SPI_CS_SW_VAL);
83562306a36Sopenharmony_ci		} else {
83662306a36Sopenharmony_ci			tspi->use_hw_based_cs = false;
83762306a36Sopenharmony_ci			command1 |= SPI_CS_SW_HW;
83862306a36Sopenharmony_ci			if (spi->mode & SPI_CS_HIGH)
83962306a36Sopenharmony_ci				command1 |= SPI_CS_SW_VAL;
84062306a36Sopenharmony_ci			else
84162306a36Sopenharmony_ci				command1 &= ~SPI_CS_SW_VAL;
84262306a36Sopenharmony_ci		}
84362306a36Sopenharmony_ci
84462306a36Sopenharmony_ci		if (tspi->last_used_cs != spi_get_chipselect(spi, 0)) {
84562306a36Sopenharmony_ci			if (cdata && cdata->tx_clk_tap_delay)
84662306a36Sopenharmony_ci				tx_tap = cdata->tx_clk_tap_delay;
84762306a36Sopenharmony_ci			if (cdata && cdata->rx_clk_tap_delay)
84862306a36Sopenharmony_ci				rx_tap = cdata->rx_clk_tap_delay;
84962306a36Sopenharmony_ci			command2 = SPI_TX_TAP_DELAY(tx_tap) |
85062306a36Sopenharmony_ci				   SPI_RX_TAP_DELAY(rx_tap);
85162306a36Sopenharmony_ci			if (command2 != tspi->def_command2_reg)
85262306a36Sopenharmony_ci				tegra_spi_writel(tspi, command2, SPI_COMMAND2);
85362306a36Sopenharmony_ci			tspi->last_used_cs = spi_get_chipselect(spi, 0);
85462306a36Sopenharmony_ci		}
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	} else {
85762306a36Sopenharmony_ci		command1 = tspi->command1_reg;
85862306a36Sopenharmony_ci		command1 &= ~SPI_BIT_LENGTH(~0);
85962306a36Sopenharmony_ci		command1 |= SPI_BIT_LENGTH(bits_per_word - 1);
86062306a36Sopenharmony_ci	}
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	return command1;
86362306a36Sopenharmony_ci}
86462306a36Sopenharmony_ci
86562306a36Sopenharmony_cistatic int tegra_spi_start_transfer_one(struct spi_device *spi,
86662306a36Sopenharmony_ci		struct spi_transfer *t, u32 command1)
86762306a36Sopenharmony_ci{
86862306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
86962306a36Sopenharmony_ci	unsigned total_fifo_words;
87062306a36Sopenharmony_ci	int ret;
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t);
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	if (t->rx_nbits == SPI_NBITS_DUAL || t->tx_nbits == SPI_NBITS_DUAL)
87562306a36Sopenharmony_ci		command1 |= SPI_BOTH_EN_BIT;
87662306a36Sopenharmony_ci	else
87762306a36Sopenharmony_ci		command1 &= ~SPI_BOTH_EN_BIT;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	if (tspi->is_packed)
88062306a36Sopenharmony_ci		command1 |= SPI_PACKED;
88162306a36Sopenharmony_ci	else
88262306a36Sopenharmony_ci		command1 &= ~SPI_PACKED;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN);
88562306a36Sopenharmony_ci	tspi->cur_direction = 0;
88662306a36Sopenharmony_ci	if (t->rx_buf) {
88762306a36Sopenharmony_ci		command1 |= SPI_RX_EN;
88862306a36Sopenharmony_ci		tspi->cur_direction |= DATA_DIR_RX;
88962306a36Sopenharmony_ci	}
89062306a36Sopenharmony_ci	if (t->tx_buf) {
89162306a36Sopenharmony_ci		command1 |= SPI_TX_EN;
89262306a36Sopenharmony_ci		tspi->cur_direction |= DATA_DIR_TX;
89362306a36Sopenharmony_ci	}
89462306a36Sopenharmony_ci	command1 |= SPI_CS_SEL(spi_get_chipselect(spi, 0));
89562306a36Sopenharmony_ci	tegra_spi_writel(tspi, command1, SPI_COMMAND1);
89662306a36Sopenharmony_ci	tspi->command1_reg = command1;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
89962306a36Sopenharmony_ci		tspi->def_command1_reg, (unsigned)command1);
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	ret = tegra_spi_flush_fifos(tspi);
90262306a36Sopenharmony_ci	if (ret < 0)
90362306a36Sopenharmony_ci		return ret;
90462306a36Sopenharmony_ci	if (total_fifo_words > SPI_FIFO_DEPTH)
90562306a36Sopenharmony_ci		ret = tegra_spi_start_dma_based_transfer(tspi, t);
90662306a36Sopenharmony_ci	else
90762306a36Sopenharmony_ci		ret = tegra_spi_start_cpu_based_transfer(tspi, t);
90862306a36Sopenharmony_ci	return ret;
90962306a36Sopenharmony_ci}
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_cistatic struct tegra_spi_client_data
91262306a36Sopenharmony_ci	*tegra_spi_parse_cdata_dt(struct spi_device *spi)
91362306a36Sopenharmony_ci{
91462306a36Sopenharmony_ci	struct tegra_spi_client_data *cdata;
91562306a36Sopenharmony_ci	struct device_node *slave_np;
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci	slave_np = spi->dev.of_node;
91862306a36Sopenharmony_ci	if (!slave_np) {
91962306a36Sopenharmony_ci		dev_dbg(&spi->dev, "device node not found\n");
92062306a36Sopenharmony_ci		return NULL;
92162306a36Sopenharmony_ci	}
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_ci	cdata = kzalloc(sizeof(*cdata), GFP_KERNEL);
92462306a36Sopenharmony_ci	if (!cdata)
92562306a36Sopenharmony_ci		return NULL;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	of_property_read_u32(slave_np, "nvidia,tx-clk-tap-delay",
92862306a36Sopenharmony_ci			     &cdata->tx_clk_tap_delay);
92962306a36Sopenharmony_ci	of_property_read_u32(slave_np, "nvidia,rx-clk-tap-delay",
93062306a36Sopenharmony_ci			     &cdata->rx_clk_tap_delay);
93162306a36Sopenharmony_ci	return cdata;
93262306a36Sopenharmony_ci}
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_cistatic void tegra_spi_cleanup(struct spi_device *spi)
93562306a36Sopenharmony_ci{
93662306a36Sopenharmony_ci	struct tegra_spi_client_data *cdata = spi->controller_data;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	spi->controller_data = NULL;
93962306a36Sopenharmony_ci	if (spi->dev.of_node)
94062306a36Sopenharmony_ci		kfree(cdata);
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic int tegra_spi_setup(struct spi_device *spi)
94462306a36Sopenharmony_ci{
94562306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
94662306a36Sopenharmony_ci	struct tegra_spi_client_data *cdata = spi->controller_data;
94762306a36Sopenharmony_ci	u32 val;
94862306a36Sopenharmony_ci	unsigned long flags;
94962306a36Sopenharmony_ci	int ret;
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci	dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
95262306a36Sopenharmony_ci		spi->bits_per_word,
95362306a36Sopenharmony_ci		spi->mode & SPI_CPOL ? "" : "~",
95462306a36Sopenharmony_ci		spi->mode & SPI_CPHA ? "" : "~",
95562306a36Sopenharmony_ci		spi->max_speed_hz);
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	if (!cdata) {
95862306a36Sopenharmony_ci		cdata = tegra_spi_parse_cdata_dt(spi);
95962306a36Sopenharmony_ci		spi->controller_data = cdata;
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(tspi->dev);
96362306a36Sopenharmony_ci	if (ret < 0) {
96462306a36Sopenharmony_ci		dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
96562306a36Sopenharmony_ci		if (cdata)
96662306a36Sopenharmony_ci			tegra_spi_cleanup(spi);
96762306a36Sopenharmony_ci		return ret;
96862306a36Sopenharmony_ci	}
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci	if (tspi->soc_data->has_intr_mask_reg) {
97162306a36Sopenharmony_ci		val = tegra_spi_readl(tspi, SPI_INTR_MASK);
97262306a36Sopenharmony_ci		val &= ~SPI_INTR_ALL_MASK;
97362306a36Sopenharmony_ci		tegra_spi_writel(tspi, val, SPI_INTR_MASK);
97462306a36Sopenharmony_ci	}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	spin_lock_irqsave(&tspi->lock, flags);
97762306a36Sopenharmony_ci	/* GPIO based chip select control */
97862306a36Sopenharmony_ci	if (spi_get_csgpiod(spi, 0))
97962306a36Sopenharmony_ci		gpiod_set_value(spi_get_csgpiod(spi, 0), 0);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	val = tspi->def_command1_reg;
98262306a36Sopenharmony_ci	if (spi->mode & SPI_CS_HIGH)
98362306a36Sopenharmony_ci		val &= ~SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0));
98462306a36Sopenharmony_ci	else
98562306a36Sopenharmony_ci		val |= SPI_CS_POL_INACTIVE(spi_get_chipselect(spi, 0));
98662306a36Sopenharmony_ci	tspi->def_command1_reg = val;
98762306a36Sopenharmony_ci	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
98862306a36Sopenharmony_ci	spin_unlock_irqrestore(&tspi->lock, flags);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	pm_runtime_put(tspi->dev);
99162306a36Sopenharmony_ci	return 0;
99262306a36Sopenharmony_ci}
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_cistatic void tegra_spi_transfer_end(struct spi_device *spi)
99562306a36Sopenharmony_ci{
99662306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
99762306a36Sopenharmony_ci	int cs_val = (spi->mode & SPI_CS_HIGH) ? 0 : 1;
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	/* GPIO based chip select control */
100062306a36Sopenharmony_ci	if (spi_get_csgpiod(spi, 0))
100162306a36Sopenharmony_ci		gpiod_set_value(spi_get_csgpiod(spi, 0), 0);
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci	if (!tspi->use_hw_based_cs) {
100462306a36Sopenharmony_ci		if (cs_val)
100562306a36Sopenharmony_ci			tspi->command1_reg |= SPI_CS_SW_VAL;
100662306a36Sopenharmony_ci		else
100762306a36Sopenharmony_ci			tspi->command1_reg &= ~SPI_CS_SW_VAL;
100862306a36Sopenharmony_ci		tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1);
100962306a36Sopenharmony_ci	}
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_cistatic void tegra_spi_dump_regs(struct tegra_spi_data *tspi)
101562306a36Sopenharmony_ci{
101662306a36Sopenharmony_ci	dev_dbg(tspi->dev, "============ SPI REGISTER DUMP ============\n");
101762306a36Sopenharmony_ci	dev_dbg(tspi->dev, "Command1:    0x%08x | Command2:    0x%08x\n",
101862306a36Sopenharmony_ci		tegra_spi_readl(tspi, SPI_COMMAND1),
101962306a36Sopenharmony_ci		tegra_spi_readl(tspi, SPI_COMMAND2));
102062306a36Sopenharmony_ci	dev_dbg(tspi->dev, "DMA_CTL:     0x%08x | DMA_BLK:     0x%08x\n",
102162306a36Sopenharmony_ci		tegra_spi_readl(tspi, SPI_DMA_CTL),
102262306a36Sopenharmony_ci		tegra_spi_readl(tspi, SPI_DMA_BLK));
102362306a36Sopenharmony_ci	dev_dbg(tspi->dev, "TRANS_STAT:  0x%08x | FIFO_STATUS: 0x%08x\n",
102462306a36Sopenharmony_ci		tegra_spi_readl(tspi, SPI_TRANS_STATUS),
102562306a36Sopenharmony_ci		tegra_spi_readl(tspi, SPI_FIFO_STATUS));
102662306a36Sopenharmony_ci}
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_cistatic int tegra_spi_transfer_one_message(struct spi_master *master,
102962306a36Sopenharmony_ci			struct spi_message *msg)
103062306a36Sopenharmony_ci{
103162306a36Sopenharmony_ci	bool is_first_msg = true;
103262306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(master);
103362306a36Sopenharmony_ci	struct spi_transfer *xfer;
103462306a36Sopenharmony_ci	struct spi_device *spi = msg->spi;
103562306a36Sopenharmony_ci	int ret;
103662306a36Sopenharmony_ci	bool skip = false;
103762306a36Sopenharmony_ci	int single_xfer;
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci	msg->status = 0;
104062306a36Sopenharmony_ci	msg->actual_length = 0;
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci	single_xfer = list_is_singular(&msg->transfers);
104362306a36Sopenharmony_ci	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
104462306a36Sopenharmony_ci		u32 cmd1;
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci		reinit_completion(&tspi->xfer_completion);
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci		cmd1 = tegra_spi_setup_transfer_one(spi, xfer, is_first_msg,
104962306a36Sopenharmony_ci						    single_xfer);
105062306a36Sopenharmony_ci
105162306a36Sopenharmony_ci		if (!xfer->len) {
105262306a36Sopenharmony_ci			ret = 0;
105362306a36Sopenharmony_ci			skip = true;
105462306a36Sopenharmony_ci			goto complete_xfer;
105562306a36Sopenharmony_ci		}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci		ret = tegra_spi_start_transfer_one(spi, xfer, cmd1);
105862306a36Sopenharmony_ci		if (ret < 0) {
105962306a36Sopenharmony_ci			dev_err(tspi->dev,
106062306a36Sopenharmony_ci				"spi can not start transfer, err %d\n", ret);
106162306a36Sopenharmony_ci			goto complete_xfer;
106262306a36Sopenharmony_ci		}
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci		is_first_msg = false;
106562306a36Sopenharmony_ci		ret = wait_for_completion_timeout(&tspi->xfer_completion,
106662306a36Sopenharmony_ci						SPI_DMA_TIMEOUT);
106762306a36Sopenharmony_ci		if (WARN_ON(ret == 0)) {
106862306a36Sopenharmony_ci			dev_err(tspi->dev, "spi transfer timeout\n");
106962306a36Sopenharmony_ci			if (tspi->is_curr_dma_xfer &&
107062306a36Sopenharmony_ci			    (tspi->cur_direction & DATA_DIR_TX))
107162306a36Sopenharmony_ci				dmaengine_terminate_all(tspi->tx_dma_chan);
107262306a36Sopenharmony_ci			if (tspi->is_curr_dma_xfer &&
107362306a36Sopenharmony_ci			    (tspi->cur_direction & DATA_DIR_RX))
107462306a36Sopenharmony_ci				dmaengine_terminate_all(tspi->rx_dma_chan);
107562306a36Sopenharmony_ci			ret = -EIO;
107662306a36Sopenharmony_ci			tegra_spi_dump_regs(tspi);
107762306a36Sopenharmony_ci			tegra_spi_flush_fifos(tspi);
107862306a36Sopenharmony_ci			reset_control_assert(tspi->rst);
107962306a36Sopenharmony_ci			udelay(2);
108062306a36Sopenharmony_ci			reset_control_deassert(tspi->rst);
108162306a36Sopenharmony_ci			tspi->last_used_cs = master->num_chipselect + 1;
108262306a36Sopenharmony_ci			goto complete_xfer;
108362306a36Sopenharmony_ci		}
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci		if (tspi->tx_status ||  tspi->rx_status) {
108662306a36Sopenharmony_ci			dev_err(tspi->dev, "Error in Transfer\n");
108762306a36Sopenharmony_ci			ret = -EIO;
108862306a36Sopenharmony_ci			tegra_spi_dump_regs(tspi);
108962306a36Sopenharmony_ci			goto complete_xfer;
109062306a36Sopenharmony_ci		}
109162306a36Sopenharmony_ci		msg->actual_length += xfer->len;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_cicomplete_xfer:
109462306a36Sopenharmony_ci		if (ret < 0 || skip) {
109562306a36Sopenharmony_ci			tegra_spi_transfer_end(spi);
109662306a36Sopenharmony_ci			spi_transfer_delay_exec(xfer);
109762306a36Sopenharmony_ci			goto exit;
109862306a36Sopenharmony_ci		} else if (list_is_last(&xfer->transfer_list,
109962306a36Sopenharmony_ci					&msg->transfers)) {
110062306a36Sopenharmony_ci			if (xfer->cs_change)
110162306a36Sopenharmony_ci				tspi->cs_control = spi;
110262306a36Sopenharmony_ci			else {
110362306a36Sopenharmony_ci				tegra_spi_transfer_end(spi);
110462306a36Sopenharmony_ci				spi_transfer_delay_exec(xfer);
110562306a36Sopenharmony_ci			}
110662306a36Sopenharmony_ci		} else if (xfer->cs_change) {
110762306a36Sopenharmony_ci			tegra_spi_transfer_end(spi);
110862306a36Sopenharmony_ci			spi_transfer_delay_exec(xfer);
110962306a36Sopenharmony_ci		}
111062306a36Sopenharmony_ci
111162306a36Sopenharmony_ci	}
111262306a36Sopenharmony_ci	ret = 0;
111362306a36Sopenharmony_ciexit:
111462306a36Sopenharmony_ci	msg->status = ret;
111562306a36Sopenharmony_ci	spi_finalize_current_message(master);
111662306a36Sopenharmony_ci	return ret;
111762306a36Sopenharmony_ci}
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_cistatic irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi)
112062306a36Sopenharmony_ci{
112162306a36Sopenharmony_ci	struct spi_transfer *t = tspi->curr_xfer;
112262306a36Sopenharmony_ci	unsigned long flags;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	spin_lock_irqsave(&tspi->lock, flags);
112562306a36Sopenharmony_ci	if (tspi->tx_status ||  tspi->rx_status) {
112662306a36Sopenharmony_ci		dev_err(tspi->dev, "CpuXfer ERROR bit set 0x%x\n",
112762306a36Sopenharmony_ci			tspi->status_reg);
112862306a36Sopenharmony_ci		dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
112962306a36Sopenharmony_ci			tspi->command1_reg, tspi->dma_control_reg);
113062306a36Sopenharmony_ci		tegra_spi_dump_regs(tspi);
113162306a36Sopenharmony_ci		tegra_spi_flush_fifos(tspi);
113262306a36Sopenharmony_ci		complete(&tspi->xfer_completion);
113362306a36Sopenharmony_ci		spin_unlock_irqrestore(&tspi->lock, flags);
113462306a36Sopenharmony_ci		reset_control_assert(tspi->rst);
113562306a36Sopenharmony_ci		udelay(2);
113662306a36Sopenharmony_ci		reset_control_deassert(tspi->rst);
113762306a36Sopenharmony_ci		return IRQ_HANDLED;
113862306a36Sopenharmony_ci	}
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_RX)
114162306a36Sopenharmony_ci		tegra_spi_read_rx_fifo_to_client_rxbuf(tspi, t);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_TX)
114462306a36Sopenharmony_ci		tspi->cur_pos = tspi->cur_tx_pos;
114562306a36Sopenharmony_ci	else
114662306a36Sopenharmony_ci		tspi->cur_pos = tspi->cur_rx_pos;
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	if (tspi->cur_pos == t->len) {
114962306a36Sopenharmony_ci		complete(&tspi->xfer_completion);
115062306a36Sopenharmony_ci		goto exit;
115162306a36Sopenharmony_ci	}
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	tegra_spi_calculate_curr_xfer_param(tspi->cur_spi, tspi, t);
115462306a36Sopenharmony_ci	tegra_spi_start_cpu_based_transfer(tspi, t);
115562306a36Sopenharmony_ciexit:
115662306a36Sopenharmony_ci	spin_unlock_irqrestore(&tspi->lock, flags);
115762306a36Sopenharmony_ci	return IRQ_HANDLED;
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_cistatic irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi)
116162306a36Sopenharmony_ci{
116262306a36Sopenharmony_ci	struct spi_transfer *t = tspi->curr_xfer;
116362306a36Sopenharmony_ci	long wait_status;
116462306a36Sopenharmony_ci	int err = 0;
116562306a36Sopenharmony_ci	unsigned total_fifo_words;
116662306a36Sopenharmony_ci	unsigned long flags;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	/* Abort dmas if any error */
116962306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_TX) {
117062306a36Sopenharmony_ci		if (tspi->tx_status) {
117162306a36Sopenharmony_ci			dmaengine_terminate_all(tspi->tx_dma_chan);
117262306a36Sopenharmony_ci			err += 1;
117362306a36Sopenharmony_ci		} else {
117462306a36Sopenharmony_ci			wait_status = wait_for_completion_interruptible_timeout(
117562306a36Sopenharmony_ci				&tspi->tx_dma_complete, SPI_DMA_TIMEOUT);
117662306a36Sopenharmony_ci			if (wait_status <= 0) {
117762306a36Sopenharmony_ci				dmaengine_terminate_all(tspi->tx_dma_chan);
117862306a36Sopenharmony_ci				dev_err(tspi->dev, "TxDma Xfer failed\n");
117962306a36Sopenharmony_ci				err += 1;
118062306a36Sopenharmony_ci			}
118162306a36Sopenharmony_ci		}
118262306a36Sopenharmony_ci	}
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_RX) {
118562306a36Sopenharmony_ci		if (tspi->rx_status) {
118662306a36Sopenharmony_ci			dmaengine_terminate_all(tspi->rx_dma_chan);
118762306a36Sopenharmony_ci			err += 2;
118862306a36Sopenharmony_ci		} else {
118962306a36Sopenharmony_ci			wait_status = wait_for_completion_interruptible_timeout(
119062306a36Sopenharmony_ci				&tspi->rx_dma_complete, SPI_DMA_TIMEOUT);
119162306a36Sopenharmony_ci			if (wait_status <= 0) {
119262306a36Sopenharmony_ci				dmaengine_terminate_all(tspi->rx_dma_chan);
119362306a36Sopenharmony_ci				dev_err(tspi->dev, "RxDma Xfer failed\n");
119462306a36Sopenharmony_ci				err += 2;
119562306a36Sopenharmony_ci			}
119662306a36Sopenharmony_ci		}
119762306a36Sopenharmony_ci	}
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	spin_lock_irqsave(&tspi->lock, flags);
120062306a36Sopenharmony_ci	if (err) {
120162306a36Sopenharmony_ci		dev_err(tspi->dev, "DmaXfer: ERROR bit set 0x%x\n",
120262306a36Sopenharmony_ci			tspi->status_reg);
120362306a36Sopenharmony_ci		dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
120462306a36Sopenharmony_ci			tspi->command1_reg, tspi->dma_control_reg);
120562306a36Sopenharmony_ci		tegra_spi_dump_regs(tspi);
120662306a36Sopenharmony_ci		tegra_spi_flush_fifos(tspi);
120762306a36Sopenharmony_ci		complete(&tspi->xfer_completion);
120862306a36Sopenharmony_ci		spin_unlock_irqrestore(&tspi->lock, flags);
120962306a36Sopenharmony_ci		reset_control_assert(tspi->rst);
121062306a36Sopenharmony_ci		udelay(2);
121162306a36Sopenharmony_ci		reset_control_deassert(tspi->rst);
121262306a36Sopenharmony_ci		return IRQ_HANDLED;
121362306a36Sopenharmony_ci	}
121462306a36Sopenharmony_ci
121562306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_RX)
121662306a36Sopenharmony_ci		tegra_spi_copy_spi_rxbuf_to_client_rxbuf(tspi, t);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_TX)
121962306a36Sopenharmony_ci		tspi->cur_pos = tspi->cur_tx_pos;
122062306a36Sopenharmony_ci	else
122162306a36Sopenharmony_ci		tspi->cur_pos = tspi->cur_rx_pos;
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	if (tspi->cur_pos == t->len) {
122462306a36Sopenharmony_ci		complete(&tspi->xfer_completion);
122562306a36Sopenharmony_ci		goto exit;
122662306a36Sopenharmony_ci	}
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci	/* Continue transfer in current message */
122962306a36Sopenharmony_ci	total_fifo_words = tegra_spi_calculate_curr_xfer_param(tspi->cur_spi,
123062306a36Sopenharmony_ci							tspi, t);
123162306a36Sopenharmony_ci	if (total_fifo_words > SPI_FIFO_DEPTH)
123262306a36Sopenharmony_ci		err = tegra_spi_start_dma_based_transfer(tspi, t);
123362306a36Sopenharmony_ci	else
123462306a36Sopenharmony_ci		err = tegra_spi_start_cpu_based_transfer(tspi, t);
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ciexit:
123762306a36Sopenharmony_ci	spin_unlock_irqrestore(&tspi->lock, flags);
123862306a36Sopenharmony_ci	return IRQ_HANDLED;
123962306a36Sopenharmony_ci}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_cistatic irqreturn_t tegra_spi_isr_thread(int irq, void *context_data)
124262306a36Sopenharmony_ci{
124362306a36Sopenharmony_ci	struct tegra_spi_data *tspi = context_data;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	if (!tspi->is_curr_dma_xfer)
124662306a36Sopenharmony_ci		return handle_cpu_based_xfer(tspi);
124762306a36Sopenharmony_ci	return handle_dma_based_xfer(tspi);
124862306a36Sopenharmony_ci}
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_cistatic irqreturn_t tegra_spi_isr(int irq, void *context_data)
125162306a36Sopenharmony_ci{
125262306a36Sopenharmony_ci	struct tegra_spi_data *tspi = context_data;
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_ci	tspi->status_reg = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
125562306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_TX)
125662306a36Sopenharmony_ci		tspi->tx_status = tspi->status_reg &
125762306a36Sopenharmony_ci					(SPI_TX_FIFO_UNF | SPI_TX_FIFO_OVF);
125862306a36Sopenharmony_ci
125962306a36Sopenharmony_ci	if (tspi->cur_direction & DATA_DIR_RX)
126062306a36Sopenharmony_ci		tspi->rx_status = tspi->status_reg &
126162306a36Sopenharmony_ci					(SPI_RX_FIFO_OVF | SPI_RX_FIFO_UNF);
126262306a36Sopenharmony_ci	tegra_spi_clear_status(tspi);
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	return IRQ_WAKE_THREAD;
126562306a36Sopenharmony_ci}
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_cistatic struct tegra_spi_soc_data tegra114_spi_soc_data = {
126862306a36Sopenharmony_ci	.has_intr_mask_reg = false,
126962306a36Sopenharmony_ci};
127062306a36Sopenharmony_ci
127162306a36Sopenharmony_cistatic struct tegra_spi_soc_data tegra124_spi_soc_data = {
127262306a36Sopenharmony_ci	.has_intr_mask_reg = false,
127362306a36Sopenharmony_ci};
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_cistatic struct tegra_spi_soc_data tegra210_spi_soc_data = {
127662306a36Sopenharmony_ci	.has_intr_mask_reg = true,
127762306a36Sopenharmony_ci};
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_cistatic const struct of_device_id tegra_spi_of_match[] = {
128062306a36Sopenharmony_ci	{
128162306a36Sopenharmony_ci		.compatible = "nvidia,tegra114-spi",
128262306a36Sopenharmony_ci		.data	    = &tegra114_spi_soc_data,
128362306a36Sopenharmony_ci	}, {
128462306a36Sopenharmony_ci		.compatible = "nvidia,tegra124-spi",
128562306a36Sopenharmony_ci		.data	    = &tegra124_spi_soc_data,
128662306a36Sopenharmony_ci	}, {
128762306a36Sopenharmony_ci		.compatible = "nvidia,tegra210-spi",
128862306a36Sopenharmony_ci		.data	    = &tegra210_spi_soc_data,
128962306a36Sopenharmony_ci	},
129062306a36Sopenharmony_ci	{}
129162306a36Sopenharmony_ci};
129262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, tegra_spi_of_match);
129362306a36Sopenharmony_ci
129462306a36Sopenharmony_cistatic int tegra_spi_probe(struct platform_device *pdev)
129562306a36Sopenharmony_ci{
129662306a36Sopenharmony_ci	struct spi_master	*master;
129762306a36Sopenharmony_ci	struct tegra_spi_data	*tspi;
129862306a36Sopenharmony_ci	struct resource		*r;
129962306a36Sopenharmony_ci	int ret, spi_irq;
130062306a36Sopenharmony_ci	int bus_num;
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	master = spi_alloc_master(&pdev->dev, sizeof(*tspi));
130362306a36Sopenharmony_ci	if (!master) {
130462306a36Sopenharmony_ci		dev_err(&pdev->dev, "master allocation failed\n");
130562306a36Sopenharmony_ci		return -ENOMEM;
130662306a36Sopenharmony_ci	}
130762306a36Sopenharmony_ci	platform_set_drvdata(pdev, master);
130862306a36Sopenharmony_ci	tspi = spi_master_get_devdata(master);
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci	if (of_property_read_u32(pdev->dev.of_node, "spi-max-frequency",
131162306a36Sopenharmony_ci				 &master->max_speed_hz))
131262306a36Sopenharmony_ci		master->max_speed_hz = 25000000; /* 25MHz */
131362306a36Sopenharmony_ci
131462306a36Sopenharmony_ci	/* the spi->mode bits understood by this driver: */
131562306a36Sopenharmony_ci	master->use_gpio_descriptors = true;
131662306a36Sopenharmony_ci	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
131762306a36Sopenharmony_ci			    SPI_TX_DUAL | SPI_RX_DUAL | SPI_3WIRE;
131862306a36Sopenharmony_ci	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
131962306a36Sopenharmony_ci	master->setup = tegra_spi_setup;
132062306a36Sopenharmony_ci	master->cleanup = tegra_spi_cleanup;
132162306a36Sopenharmony_ci	master->transfer_one_message = tegra_spi_transfer_one_message;
132262306a36Sopenharmony_ci	master->set_cs_timing = tegra_spi_set_hw_cs_timing;
132362306a36Sopenharmony_ci	master->num_chipselect = MAX_CHIP_SELECT;
132462306a36Sopenharmony_ci	master->auto_runtime_pm = true;
132562306a36Sopenharmony_ci	bus_num = of_alias_get_id(pdev->dev.of_node, "spi");
132662306a36Sopenharmony_ci	if (bus_num >= 0)
132762306a36Sopenharmony_ci		master->bus_num = bus_num;
132862306a36Sopenharmony_ci
132962306a36Sopenharmony_ci	tspi->master = master;
133062306a36Sopenharmony_ci	tspi->dev = &pdev->dev;
133162306a36Sopenharmony_ci	spin_lock_init(&tspi->lock);
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	tspi->soc_data = of_device_get_match_data(&pdev->dev);
133462306a36Sopenharmony_ci	if (!tspi->soc_data) {
133562306a36Sopenharmony_ci		dev_err(&pdev->dev, "unsupported tegra\n");
133662306a36Sopenharmony_ci		ret = -ENODEV;
133762306a36Sopenharmony_ci		goto exit_free_master;
133862306a36Sopenharmony_ci	}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	tspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
134162306a36Sopenharmony_ci	if (IS_ERR(tspi->base)) {
134262306a36Sopenharmony_ci		ret = PTR_ERR(tspi->base);
134362306a36Sopenharmony_ci		goto exit_free_master;
134462306a36Sopenharmony_ci	}
134562306a36Sopenharmony_ci	tspi->phys = r->start;
134662306a36Sopenharmony_ci
134762306a36Sopenharmony_ci	spi_irq = platform_get_irq(pdev, 0);
134862306a36Sopenharmony_ci	if (spi_irq < 0) {
134962306a36Sopenharmony_ci		ret = spi_irq;
135062306a36Sopenharmony_ci		goto exit_free_master;
135162306a36Sopenharmony_ci	}
135262306a36Sopenharmony_ci	tspi->irq = spi_irq;
135362306a36Sopenharmony_ci
135462306a36Sopenharmony_ci	tspi->clk = devm_clk_get(&pdev->dev, "spi");
135562306a36Sopenharmony_ci	if (IS_ERR(tspi->clk)) {
135662306a36Sopenharmony_ci		dev_err(&pdev->dev, "can not get clock\n");
135762306a36Sopenharmony_ci		ret = PTR_ERR(tspi->clk);
135862306a36Sopenharmony_ci		goto exit_free_master;
135962306a36Sopenharmony_ci	}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
136262306a36Sopenharmony_ci	if (IS_ERR(tspi->rst)) {
136362306a36Sopenharmony_ci		dev_err(&pdev->dev, "can not get reset\n");
136462306a36Sopenharmony_ci		ret = PTR_ERR(tspi->rst);
136562306a36Sopenharmony_ci		goto exit_free_master;
136662306a36Sopenharmony_ci	}
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	tspi->max_buf_size = SPI_FIFO_DEPTH << 2;
136962306a36Sopenharmony_ci	tspi->dma_buf_size = DEFAULT_SPI_DMA_BUF_LEN;
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	ret = tegra_spi_init_dma_param(tspi, true);
137262306a36Sopenharmony_ci	if (ret < 0)
137362306a36Sopenharmony_ci		goto exit_free_master;
137462306a36Sopenharmony_ci	ret = tegra_spi_init_dma_param(tspi, false);
137562306a36Sopenharmony_ci	if (ret < 0)
137662306a36Sopenharmony_ci		goto exit_rx_dma_free;
137762306a36Sopenharmony_ci	tspi->max_buf_size = tspi->dma_buf_size;
137862306a36Sopenharmony_ci	init_completion(&tspi->tx_dma_complete);
137962306a36Sopenharmony_ci	init_completion(&tspi->rx_dma_complete);
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	init_completion(&tspi->xfer_completion);
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
138462306a36Sopenharmony_ci	if (!pm_runtime_enabled(&pdev->dev)) {
138562306a36Sopenharmony_ci		ret = tegra_spi_runtime_resume(&pdev->dev);
138662306a36Sopenharmony_ci		if (ret)
138762306a36Sopenharmony_ci			goto exit_pm_disable;
138862306a36Sopenharmony_ci	}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(&pdev->dev);
139162306a36Sopenharmony_ci	if (ret < 0) {
139262306a36Sopenharmony_ci		dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret);
139362306a36Sopenharmony_ci		goto exit_pm_disable;
139462306a36Sopenharmony_ci	}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	reset_control_assert(tspi->rst);
139762306a36Sopenharmony_ci	udelay(2);
139862306a36Sopenharmony_ci	reset_control_deassert(tspi->rst);
139962306a36Sopenharmony_ci	tspi->def_command1_reg  = SPI_M_S;
140062306a36Sopenharmony_ci	tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
140162306a36Sopenharmony_ci	tspi->spi_cs_timing1 = tegra_spi_readl(tspi, SPI_CS_TIMING1);
140262306a36Sopenharmony_ci	tspi->spi_cs_timing2 = tegra_spi_readl(tspi, SPI_CS_TIMING2);
140362306a36Sopenharmony_ci	tspi->def_command2_reg = tegra_spi_readl(tspi, SPI_COMMAND2);
140462306a36Sopenharmony_ci	tspi->last_used_cs = master->num_chipselect + 1;
140562306a36Sopenharmony_ci	pm_runtime_put(&pdev->dev);
140662306a36Sopenharmony_ci	ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
140762306a36Sopenharmony_ci				   tegra_spi_isr_thread, IRQF_ONESHOT,
140862306a36Sopenharmony_ci				   dev_name(&pdev->dev), tspi);
140962306a36Sopenharmony_ci	if (ret < 0) {
141062306a36Sopenharmony_ci		dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
141162306a36Sopenharmony_ci			tspi->irq);
141262306a36Sopenharmony_ci		goto exit_pm_disable;
141362306a36Sopenharmony_ci	}
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	master->dev.of_node = pdev->dev.of_node;
141662306a36Sopenharmony_ci	ret = devm_spi_register_master(&pdev->dev, master);
141762306a36Sopenharmony_ci	if (ret < 0) {
141862306a36Sopenharmony_ci		dev_err(&pdev->dev, "can not register to master err %d\n", ret);
141962306a36Sopenharmony_ci		goto exit_free_irq;
142062306a36Sopenharmony_ci	}
142162306a36Sopenharmony_ci	return ret;
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ciexit_free_irq:
142462306a36Sopenharmony_ci	free_irq(spi_irq, tspi);
142562306a36Sopenharmony_ciexit_pm_disable:
142662306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
142762306a36Sopenharmony_ci	if (!pm_runtime_status_suspended(&pdev->dev))
142862306a36Sopenharmony_ci		tegra_spi_runtime_suspend(&pdev->dev);
142962306a36Sopenharmony_ci	tegra_spi_deinit_dma_param(tspi, false);
143062306a36Sopenharmony_ciexit_rx_dma_free:
143162306a36Sopenharmony_ci	tegra_spi_deinit_dma_param(tspi, true);
143262306a36Sopenharmony_ciexit_free_master:
143362306a36Sopenharmony_ci	spi_master_put(master);
143462306a36Sopenharmony_ci	return ret;
143562306a36Sopenharmony_ci}
143662306a36Sopenharmony_ci
143762306a36Sopenharmony_cistatic void tegra_spi_remove(struct platform_device *pdev)
143862306a36Sopenharmony_ci{
143962306a36Sopenharmony_ci	struct spi_master *master = platform_get_drvdata(pdev);
144062306a36Sopenharmony_ci	struct tegra_spi_data	*tspi = spi_master_get_devdata(master);
144162306a36Sopenharmony_ci
144262306a36Sopenharmony_ci	free_irq(tspi->irq, tspi);
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci	if (tspi->tx_dma_chan)
144562306a36Sopenharmony_ci		tegra_spi_deinit_dma_param(tspi, false);
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	if (tspi->rx_dma_chan)
144862306a36Sopenharmony_ci		tegra_spi_deinit_dma_param(tspi, true);
144962306a36Sopenharmony_ci
145062306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
145162306a36Sopenharmony_ci	if (!pm_runtime_status_suspended(&pdev->dev))
145262306a36Sopenharmony_ci		tegra_spi_runtime_suspend(&pdev->dev);
145362306a36Sopenharmony_ci}
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP
145662306a36Sopenharmony_cistatic int tegra_spi_suspend(struct device *dev)
145762306a36Sopenharmony_ci{
145862306a36Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	return spi_master_suspend(master);
146162306a36Sopenharmony_ci}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_cistatic int tegra_spi_resume(struct device *dev)
146462306a36Sopenharmony_ci{
146562306a36Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
146662306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(master);
146762306a36Sopenharmony_ci	int ret;
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dev);
147062306a36Sopenharmony_ci	if (ret < 0) {
147162306a36Sopenharmony_ci		dev_err(dev, "pm runtime failed, e = %d\n", ret);
147262306a36Sopenharmony_ci		return ret;
147362306a36Sopenharmony_ci	}
147462306a36Sopenharmony_ci	tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1);
147562306a36Sopenharmony_ci	tegra_spi_writel(tspi, tspi->def_command2_reg, SPI_COMMAND2);
147662306a36Sopenharmony_ci	tspi->last_used_cs = master->num_chipselect + 1;
147762306a36Sopenharmony_ci	pm_runtime_put(dev);
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci	return spi_master_resume(master);
148062306a36Sopenharmony_ci}
148162306a36Sopenharmony_ci#endif
148262306a36Sopenharmony_ci
148362306a36Sopenharmony_cistatic int tegra_spi_runtime_suspend(struct device *dev)
148462306a36Sopenharmony_ci{
148562306a36Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
148662306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(master);
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	/* Flush all write which are in PPSB queue by reading back */
148962306a36Sopenharmony_ci	tegra_spi_readl(tspi, SPI_COMMAND1);
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci	clk_disable_unprepare(tspi->clk);
149262306a36Sopenharmony_ci	return 0;
149362306a36Sopenharmony_ci}
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_cistatic int tegra_spi_runtime_resume(struct device *dev)
149662306a36Sopenharmony_ci{
149762306a36Sopenharmony_ci	struct spi_master *master = dev_get_drvdata(dev);
149862306a36Sopenharmony_ci	struct tegra_spi_data *tspi = spi_master_get_devdata(master);
149962306a36Sopenharmony_ci	int ret;
150062306a36Sopenharmony_ci
150162306a36Sopenharmony_ci	ret = clk_prepare_enable(tspi->clk);
150262306a36Sopenharmony_ci	if (ret < 0) {
150362306a36Sopenharmony_ci		dev_err(tspi->dev, "clk_prepare failed: %d\n", ret);
150462306a36Sopenharmony_ci		return ret;
150562306a36Sopenharmony_ci	}
150662306a36Sopenharmony_ci	return 0;
150762306a36Sopenharmony_ci}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_cistatic const struct dev_pm_ops tegra_spi_pm_ops = {
151062306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(tegra_spi_runtime_suspend,
151162306a36Sopenharmony_ci		tegra_spi_runtime_resume, NULL)
151262306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(tegra_spi_suspend, tegra_spi_resume)
151362306a36Sopenharmony_ci};
151462306a36Sopenharmony_cistatic struct platform_driver tegra_spi_driver = {
151562306a36Sopenharmony_ci	.driver = {
151662306a36Sopenharmony_ci		.name		= "spi-tegra114",
151762306a36Sopenharmony_ci		.pm		= &tegra_spi_pm_ops,
151862306a36Sopenharmony_ci		.of_match_table	= tegra_spi_of_match,
151962306a36Sopenharmony_ci	},
152062306a36Sopenharmony_ci	.probe =	tegra_spi_probe,
152162306a36Sopenharmony_ci	.remove_new =	tegra_spi_remove,
152262306a36Sopenharmony_ci};
152362306a36Sopenharmony_cimodule_platform_driver(tegra_spi_driver);
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ciMODULE_ALIAS("platform:spi-tegra114");
152662306a36Sopenharmony_ciMODULE_DESCRIPTION("NVIDIA Tegra114 SPI Controller Driver");
152762306a36Sopenharmony_ciMODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
152862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
1529