From 7b3d10cdf54b8bc1dc0da21faed9789ac4da3684 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:23 -0700 Subject: spi: tegra114: clear packed bit for unpacked mode Fixes: Clear packed bit when not using packed mode. Packed bit is not cleared when not using packed mode. This results in transfer timeouts for the unpacked mode transfers followed by the packed mode transfers. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index a76acedd7e2f..1435792944c4 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -730,6 +730,8 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, if (tspi->is_packed) command1 |= SPI_PACKED; + else + command1 &= ~SPI_PACKED; command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN); tspi->cur_direction = 0; -- cgit v1.2.3-59-g8ed1b From 1a89ac5b91895127f7c586ec5075c3753ca25501 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:24 -0700 Subject: spi: tegra114: fix for unpacked mode transfers Fixes: computation of actual bytes to fill/receive in/from FIFO in unpacked mode when transfer length is not a multiple of requested bits per word. unpacked mode transfers fails when the transfer includes partial bytes in the last word. Total words to be written/read to/from FIFO is computed based on transfer length and bits per word. Unpacked mode includes 0 padding bytes for partial words to align with bits per word and these extra bytes are also accounted for calculating bytes left to transfer in the current driver. This causes extra bytes access of tx/rx buffers along with buffer index position crossing actual length where remain_len becomes negative and due to unsigned type, negative value is a 32 bit representation of signed value and transferred bytes never meets the actual transfer length resulting in transfer timeout and a hang. This patch fixes this with proper computation of the actual bytes to fill in FIFO during transmit and the actual bytes to read from FIFO during receive ignoring 0 padded bytes. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 1435792944c4..876eb2acdef1 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); tegra_spi_writel(tspi, x, SPI_TX_FIFO); } + + tspi->cur_tx_pos += written_words * tspi->bytes_per_word; } else { + unsigned int write_bytes; max_n_32bit = min(tspi->curr_dma_words, tx_empty_count); written_words = max_n_32bit; 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++) { u32 x = 0; @@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf( x |= (u32)(*tx_buf++) << (i * 8); 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; } @@ -344,20 +352,27 @@ static unsigned int tegra_spi_read_rx_fifo_to_client_rxbuf( for (i = 0; len && (i < 4); i++, len--) *rx_buf++ = (x >> i*8) & 0xFF; } - tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; read_words += tspi->curr_dma_words; + tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word; } else { 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++) { 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; } - tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word; read_words += rx_full_count; + tspi->cur_rx_pos += read_bytes; } + 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; 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 { unsigned int i; unsigned int count; u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos; 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++) { u32 x = 0; @@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf( x |= (u32)(*tx_buf++) << (i * 8); 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 */ 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; 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 { unsigned int i; unsigned int count; unsigned char *rx_buf = t->rx_buf + tspi->cur_rx_pos; 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++) { 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; } + + 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 */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, -- cgit v1.2.3-59-g8ed1b From 32bd1a9551cae34e6889afa235c7afdfede9aeac Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:27 -0700 Subject: spi: tegra114: terminate dma and reset on transfer timeout Fixes: terminate DMA and perform controller reset on transfer timeout to clear the FIFO's and errors. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 876eb2acdef1..a6153b905d1a 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -869,7 +869,16 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, if (WARN_ON(ret == 0)) { dev_err(tspi->dev, "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; + reset_control_assert(tspi->rst); + udelay(2); + reset_control_deassert(tspi->rst); goto complete_xfer; } -- cgit v1.2.3-59-g8ed1b From c4fc9e5b28ff787e35137c2cc13316bb11d7657b Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:28 -0700 Subject: spi: tegra114: flush fifos Fixes: Flush TX and RX FIFOs before start of new transfer and on FIFO overflow or underrun errors. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index a6153b905d1a..28aa080a94ff 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -499,22 +499,37 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data *tspi, int len) return 0; } -static int tegra_spi_start_dma_based_transfer( - struct tegra_spi_data *tspi, struct spi_transfer *t) +static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi) { - u32 val; - unsigned int len; - int ret = 0; + unsigned long timeout = jiffies + HZ; u32 status; - /* Make sure that Rx and Tx fifo are empty */ status = tegra_spi_readl(tspi, SPI_FIFO_STATUS); if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) { - dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n", - (unsigned)status); - return -EIO; + status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH; + 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; + } + + 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; + val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1); tegra_spi_writel(tspi, val, SPI_DMA_BLK); @@ -779,6 +794,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", tspi->def_command1_reg, (unsigned)command1); + ret = tegra_spi_flush_fifos(tspi); + if (ret < 0) + return ret; if (total_fifo_words > SPI_FIFO_DEPTH) ret = tegra_spi_start_dma_based_transfer(tspi, t); else @@ -876,6 +894,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, (tspi->cur_direction & DATA_DIR_RX)) dmaengine_terminate_all(tspi->rx_dma_chan); ret = -EIO; + tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); @@ -929,6 +948,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); + tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); @@ -1001,6 +1021,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); + tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); reset_control_deassert(tspi->rst); -- cgit v1.2.3-59-g8ed1b From f4ce428c41fb22e3ed55496dded94df44cb920fa Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:29 -0700 Subject: spi: tegra114: configure dma burst size to fifo trig level Fixes: Configure DMA burst size to be same as SPI TX/RX trigger levels to avoid mismatch. SPI FIFO trigger levels are calculated based on the transfer length. So this patch moves DMA slave configuration to happen before start of DMAs. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 52 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 28aa080a94ff..05bb2f9bff3c 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -529,6 +529,8 @@ static int tegra_spi_start_dma_based_transfer( 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); tegra_spi_writel(tspi, val, SPI_DMA_BLK); @@ -540,12 +542,16 @@ static int tegra_spi_start_dma_based_transfer( len = tspi->curr_dma_words * 4; /* Set attention level based on length of transfer */ - if (len & 0xF) + if (len & 0xF) { 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; - else + dma_burst = 4; + } else { val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8; + dma_burst = 8; + } if (tspi->cur_direction & DATA_DIR_TX) val |= SPI_IE_TX; @@ -556,7 +562,18 @@ static int tegra_spi_start_dma_based_transfer( tegra_spi_writel(tspi, val, SPI_DMA_CTL); tspi->dma_control_reg = val; + dma_sconfig.device_fc = true; 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); ret = tegra_spi_start_tx_dma(tspi, len); if (ret < 0) { @@ -567,6 +584,16 @@ static int tegra_spi_start_dma_based_transfer( } 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 */ dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys, tspi->dma_buf_size, DMA_FROM_DEVICE); @@ -626,7 +653,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, u32 *dma_buf; dma_addr_t dma_phys; int ret; - struct dma_slave_config dma_sconfig; dma_chan = dma_request_slave_channel_reason(tspi->dev, dma_to_memory ? "rx" : "tx"); @@ -646,19 +672,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, 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) { tspi->rx_dma_chan = dma_chan; tspi->rx_dma_buf = dma_buf; @@ -669,11 +682,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data *tspi, tspi->tx_dma_phys = dma_phys; } 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, -- cgit v1.2.3-59-g8ed1b From 019194933339b3e9b486639c8cb3692020844d65 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:32 -0700 Subject: spi: tegra114: reset controller on probe Fixes: SPI driver can be built as module so perform SPI controller reset on probe to make sure it is in valid state before initiating transfer. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 05bb2f9bff3c..09cfae3abce2 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1136,27 +1136,19 @@ static int tegra_spi_probe(struct platform_device *pdev) spi_irq = platform_get_irq(pdev, 0); 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"); if (IS_ERR(tspi->clk)) { dev_err(&pdev->dev, "can not get clock\n"); ret = PTR_ERR(tspi->clk); - goto exit_free_irq; + goto exit_free_master; } tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi"); if (IS_ERR(tspi->rst)) { dev_err(&pdev->dev, "can not get reset\n"); ret = PTR_ERR(tspi->rst); - goto exit_free_irq; + goto exit_free_master; } tspi->max_buf_size = SPI_FIFO_DEPTH << 2; @@ -1164,7 +1156,7 @@ static int tegra_spi_probe(struct platform_device *pdev) ret = tegra_spi_init_dma_param(tspi, true); if (ret < 0) - goto exit_free_irq; + goto exit_free_master; ret = tegra_spi_init_dma_param(tspi, false); if (ret < 0) goto exit_rx_dma_free; @@ -1186,18 +1178,32 @@ static int tegra_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret); goto exit_pm_disable; } + + reset_control_assert(tspi->rst); + udelay(2); + reset_control_deassert(tspi->rst); tspi->def_command1_reg = SPI_M_S; tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); 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; ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); - goto exit_pm_disable; + goto exit_free_irq; } return ret; +exit_free_irq: + free_irq(spi_irq, tspi); exit_pm_disable: pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) @@ -1205,8 +1211,6 @@ exit_pm_disable: tegra_spi_deinit_dma_param(tspi, false); exit_rx_dma_free: tegra_spi_deinit_dma_param(tspi, true); -exit_free_irq: - free_irq(spi_irq, tspi); exit_free_master: spi_master_put(master); return ret; -- cgit v1.2.3-59-g8ed1b From fc9ba6e3e28afcedf3bb3105b1d8cbc5c183c2a3 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:25 -0700 Subject: spi: tegra114: use packed mode for 32 bits per word Fixes: Use packed mode for 32 bits per word transfers to increase performance as each packet is a full 32-bit word. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index a76acedd7e2f..929358e3487a 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -259,7 +259,7 @@ static unsigned tegra_spi_calculate_curr_xfer_param( tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8); - if (bits_per_word == 8 || bits_per_word == 16) { + if (bits_per_word == 8 || bits_per_word == 16 || bits_per_word == 32) { tspi->is_packed = 1; tspi->words_per_32bit = 32/bits_per_word; } else { -- cgit v1.2.3-59-g8ed1b From 2b17a3c759e5e2ed3faafb69e243ec312e3bf0da Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Tue, 26 Mar 2019 22:56:33 -0700 Subject: spi: tegra114: add SPI_LSB_FIRST support Tegra SPI controller supports lsb first mode. Default is MSB bit first and on selection of SPI_LSB_FIRST through SPI mode transmission happens with LSB bit first. This patch adds SPI_LSB_FIRST flag to mode_bits and also configures it on request. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 929358e3487a..0c52aeeb1d4f 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -696,6 +696,11 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, else if (req_mode == SPI_MODE_3) command1 |= SPI_CONTROL_MODE_3; + if (spi->mode & SPI_LSB_FIRST) + command1 |= SPI_LSBIT_FE; + else + command1 &= ~SPI_LSBIT_FE; + if (tspi->cs_control) { if (tspi->cs_control != spi) tegra_spi_writel(tspi, command1, SPI_COMMAND1); @@ -1047,7 +1052,7 @@ static int tegra_spi_probe(struct platform_device *pdev) master->max_speed_hz = 25000000; /* 25MHz */ /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; master->setup = tegra_spi_setup; master->transfer_one_message = tegra_spi_transfer_one_message; master->num_chipselect = MAX_CHIP_SELECT; -- cgit v1.2.3-59-g8ed1b From f3e182c33e534f4caeb255a3ab927debc0d222aa Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:02 -0700 Subject: spi: tegra114: de-assert CS before SPI mode change With SW CS, during the transfer completion CS is de-asserted by writing default command1 register value to SPI_COMMAND1 register. With this both mode and CS state are set at the same time and if current transfer mode is different to default SPI mode and if mode change happens prior to CS de-assert, clock polarity can change while CS is active before transfer finishes. This causes Slave to see spurious clock edges resulting in data mismatch. This patch fixes this by de-asserting CS before writing SPI_COMMAND1 to its default value so through out the transfer it will be in same SPI mode. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 09cfae3abce2..8de002fc6943 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -856,6 +856,19 @@ static void tegra_spi_transfer_delay(int delay) 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, struct spi_message *msg) { @@ -918,8 +931,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, complete_xfer: if (ret < 0 || skip) { - tegra_spi_writel(tspi, tspi->def_command1_reg, - SPI_COMMAND1); + tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); goto exit; } else if (list_is_last(&xfer->transfer_list, @@ -927,13 +939,11 @@ complete_xfer: if (xfer->cs_change) tspi->cs_control = spi; else { - tegra_spi_writel(tspi, tspi->def_command1_reg, - SPI_COMMAND1); + tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } } else if (xfer->cs_change) { - tegra_spi_writel(tspi, tspi->def_command1_reg, - SPI_COMMAND1); + tegra_spi_transfer_end(spi); tegra_spi_transfer_delay(xfer->delay_usecs); } -- cgit v1.2.3-59-g8ed1b From a026525d4e45e3d9690bffd0b05d018ff5638b5a Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:03 -0700 Subject: spi: tegra114: avoid reset call in atomic context This patch moves SPI controller reset out of spin lock. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 8de002fc6943..b57f10182fae 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -967,11 +967,12 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", 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); udelay(2); reset_control_deassert(tspi->rst); - complete(&tspi->xfer_completion); - goto exit; + return IRQ_HANDLED; } if (tspi->cur_direction & DATA_DIR_RX) @@ -1040,11 +1041,11 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", 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); udelay(2); reset_control_deassert(tspi->rst); - complete(&tspi->xfer_completion); - spin_unlock_irqrestore(&tspi->lock, flags); return IRQ_HANDLED; } -- cgit v1.2.3-59-g8ed1b From a0253c8fa18129f423c22f175a83d81423e60715 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:04 -0700 Subject: spi: tegra114: dump SPI registers during timeout This patch dumps SPI registers on transfer error or timeout for debug purpose. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 8c33bf056196..99019f6d2d84 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -874,6 +874,20 @@ static void tegra_spi_transfer_end(struct spi_device *spi) tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); } +static void tegra_spi_dump_regs(struct tegra_spi_data *tspi) +{ + dev_dbg(tspi->dev, "============ SPI REGISTER DUMP ============\n"); + dev_dbg(tspi->dev, "Command1: 0x%08x | Command2: 0x%08x\n", + tegra_spi_readl(tspi, SPI_COMMAND1), + tegra_spi_readl(tspi, SPI_COMMAND2)); + dev_dbg(tspi->dev, "DMA_CTL: 0x%08x | DMA_BLK: 0x%08x\n", + tegra_spi_readl(tspi, SPI_DMA_CTL), + tegra_spi_readl(tspi, SPI_DMA_BLK)); + dev_dbg(tspi->dev, "TRANS_STAT: 0x%08x | FIFO_STATUS: 0x%08x\n", + tegra_spi_readl(tspi, SPI_TRANS_STATUS), + tegra_spi_readl(tspi, SPI_FIFO_STATUS)); +} + static int tegra_spi_transfer_one_message(struct spi_master *master, struct spi_message *msg) { @@ -920,6 +934,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, (tspi->cur_direction & DATA_DIR_RX)) dmaengine_terminate_all(tspi->rx_dma_chan); ret = -EIO; + tegra_spi_dump_regs(tspi); tegra_spi_flush_fifos(tspi); reset_control_assert(tspi->rst); udelay(2); @@ -930,6 +945,7 @@ static int tegra_spi_transfer_one_message(struct spi_master *master, if (tspi->tx_status || tspi->rx_status) { dev_err(tspi->dev, "Error in Transfer\n"); ret = -EIO; + tegra_spi_dump_regs(tspi); goto complete_xfer; } msg->actual_length += xfer->len; @@ -971,6 +987,7 @@ static irqreturn_t handle_cpu_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); + tegra_spi_dump_regs(tspi); tegra_spi_flush_fifos(tspi); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); @@ -1045,6 +1062,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_spi_data *tspi) tspi->status_reg); dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", tspi->command1_reg, tspi->dma_control_reg); + tegra_spi_dump_regs(tspi); tegra_spi_flush_fifos(tspi); complete(&tspi->xfer_completion); spin_unlock_irqrestore(&tspi->lock, flags); -- cgit v1.2.3-59-g8ed1b From f0a0bc90c6e7060778911c2b55d085105809d6cf Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:05 -0700 Subject: spi: tegra114: set supported bits per word Tegra SPI supports 4 through 32 bits per word. This patch sets bits_per_word_mask accordingly to support transfer with these bits per word. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 99019f6d2d84..c2ebf1ae632d 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1151,6 +1151,7 @@ static int tegra_spi_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->setup = tegra_spi_setup; master->transfer_one_message = tegra_spi_transfer_one_message; master->num_chipselect = MAX_CHIP_SELECT; -- cgit v1.2.3-59-g8ed1b From 76457eea24db3c7d51f623c08838bbffda6ac3ad Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:01 -0700 Subject: spi: tegra114: use unpacked mode for below 4 bytes Packed mode expects minimum transfer length of 4 bytes. This patch fixes this by using unpacked mode for transfers less than 4 bytes. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index c2ebf1ae632d..ea67ff3b5b2c 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -259,7 +259,8 @@ static unsigned tegra_spi_calculate_curr_xfer_param( tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8); - if (bits_per_word == 8 || bits_per_word == 16 || bits_per_word == 32) { + if ((bits_per_word == 8 || bits_per_word == 16 || + bits_per_word == 32) && t->len > 3) { tspi->is_packed = 1; tspi->words_per_32bit = 32/bits_per_word; } else { -- cgit v1.2.3-59-g8ed1b From d9088966c851ecbe820c053b347e8d565e4fa05c Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:06 -0700 Subject: spi: tegra114: set bus number based on id This patch sets SPI device id from the device tree as the bus number. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index ea67ff3b5b2c..402799c7f6b7 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1137,6 +1137,7 @@ static int tegra_spi_probe(struct platform_device *pdev) struct tegra_spi_data *tspi; struct resource *r; int ret, spi_irq; + int bus_num; master = spi_alloc_master(&pdev->dev, sizeof(*tspi)); if (!master) { @@ -1157,6 +1158,9 @@ static int tegra_spi_probe(struct platform_device *pdev) master->transfer_one_message = tegra_spi_transfer_one_message; master->num_chipselect = MAX_CHIP_SELECT; master->auto_runtime_pm = true; + bus_num = of_alias_get_id(pdev->dev.of_node, "spi"); + if (bus_num >= 0) + master->bus_num = bus_num; tspi->master = master; tspi->dev = &pdev->dev; -- cgit v1.2.3-59-g8ed1b From 9877a347f2056f7aa4e770de9a20048ad288f545 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:07 -0700 Subject: spi: tegra114: add dual mode support This patch adds support for dual mode SPI transfer. Dual mode uses both MOSI and MISO lines in parallel where the data is interleaved on MOSI and MISO lines increasing the throughput. Packet from Tx FIFO is transmitted on both MOSI and MISO lines and packet to Rx FIFO is received from both MOSI and MISO lines. Even bits are transmitted or received on the MOSI data line and odd bits are transmitted or received on the MISO data line. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 402799c7f6b7..1e749ce13029 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -786,6 +786,11 @@ static int tegra_spi_start_transfer_one(struct spi_device *spi, total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t); + if (t->rx_nbits == SPI_NBITS_DUAL || t->tx_nbits == SPI_NBITS_DUAL) + command1 |= SPI_BOTH_EN_BIT; + else + command1 &= ~SPI_BOTH_EN_BIT; + if (tspi->is_packed) command1 |= SPI_PACKED; else @@ -1152,7 +1157,8 @@ static int tegra_spi_probe(struct platform_device *pdev) master->max_speed_hz = 25000000; /* 25MHz */ /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST | + SPI_TX_DUAL | SPI_RX_DUAL; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->setup = tegra_spi_setup; master->transfer_one_message = tegra_spi_transfer_one_message; -- cgit v1.2.3-59-g8ed1b From 9d199231b000414e420a35912760f2d67e9c56d7 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:08 -0700 Subject: spi: tegra114: add 3 wire transfer mode support This patch adds 3 wire transfer support to SPI mode list along with its implementation. 3 wire or Bi-directional mode uses only one serial data pin for the transfer. SPI in master mode uses MOSI data line only and MISO data line is not used. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 1e749ce13029..751672b3bc16 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -754,6 +754,11 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, else command1 &= ~SPI_LSBIT_FE; + if (spi->mode & SPI_3WIRE) + command1 |= SPI_BIDIROE; + else + command1 &= ~SPI_BIDIROE; + if (tspi->cs_control) { if (tspi->cs_control != spi) tegra_spi_writel(tspi, command1, SPI_COMMAND1); @@ -1158,7 +1163,7 @@ static int tegra_spi_probe(struct platform_device *pdev) /* the spi->mode bits understood by this driver: */ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST | - SPI_TX_DUAL | SPI_RX_DUAL; + SPI_TX_DUAL | SPI_RX_DUAL | SPI_3WIRE; master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); master->setup = tegra_spi_setup; master->transfer_one_message = tegra_spi_transfer_one_message; -- cgit v1.2.3-59-g8ed1b From fa28fd3421373794e98eb3e511969fea5a8b2fc3 Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Thu, 4 Apr 2019 17:14:12 -0700 Subject: spi: tegra114: add support for interrupt mask This patch creates tegra_spi_soc_data structure to maintain and implement SPI HW feature differences between different Tegra chips and also creates a separate compatible string for T124/T210. Tegra210 and later has a separate interrupt mask register SPI_INTR_MASK for enabling or disabling interrupts while Tegra124 and prior uses interrupt enable bits in SPI_DMA_CTL register. This patch creates flag has_intr_mask_reg in tegra_spi_soc_data to identify this and implements accordingly. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 53 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 751672b3bc16..b8c6393e2190 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -149,6 +149,8 @@ #define SPI_TX_FIFO 0x108 #define SPI_RX_FIFO 0x188 +#define SPI_INTR_MASK 0x18c +#define SPI_INTR_ALL_MASK (0x1fUL << 25) #define MAX_CHIP_SELECT 4 #define SPI_FIFO_DEPTH 64 #define DATA_DIR_TX (1 << 0) @@ -161,6 +163,10 @@ #define MAX_HOLD_CYCLES 16 #define SPI_DEFAULT_SPEED 25000000 +struct tegra_spi_soc_data { + bool has_intr_mask_reg; +}; + struct tegra_spi_data { struct device *dev; struct spi_master *master; @@ -211,6 +217,7 @@ struct tegra_spi_data { u32 *tx_dma_buf; dma_addr_t tx_dma_phys; struct dma_async_tx_descriptor *tx_dma_desc; + const struct tegra_spi_soc_data *soc_data; }; static int tegra_spi_runtime_suspend(struct device *dev); @@ -554,11 +561,13 @@ static int tegra_spi_start_dma_based_transfer( dma_burst = 8; } - if (tspi->cur_direction & DATA_DIR_TX) - val |= SPI_IE_TX; + if (!tspi->soc_data->has_intr_mask_reg) { + if (tspi->cur_direction & DATA_DIR_TX) + val |= SPI_IE_TX; - if (tspi->cur_direction & DATA_DIR_RX) - val |= SPI_IE_RX; + if (tspi->cur_direction & DATA_DIR_RX) + val |= SPI_IE_RX; + } tegra_spi_writel(tspi, val, SPI_DMA_CTL); tspi->dma_control_reg = val; @@ -847,6 +856,12 @@ static int tegra_spi_setup(struct spi_device *spi) return ret; } + if (tspi->soc_data->has_intr_mask_reg) { + val = tegra_spi_readl(tspi, SPI_INTR_MASK); + val &= ~SPI_INTR_ALL_MASK; + tegra_spi_writel(tspi, val, SPI_INTR_MASK); + } + spin_lock_irqsave(&tspi->lock, flags); val = tspi->def_command1_reg; if (spi->mode & SPI_CS_HIGH) @@ -1135,8 +1150,29 @@ static irqreturn_t tegra_spi_isr(int irq, void *context_data) return IRQ_WAKE_THREAD; } +static struct tegra_spi_soc_data tegra114_spi_soc_data = { + .has_intr_mask_reg = false, +}; + +static struct tegra_spi_soc_data tegra124_spi_soc_data = { + .has_intr_mask_reg = false, +}; + +static struct tegra_spi_soc_data tegra210_spi_soc_data = { + .has_intr_mask_reg = true, +}; + static const struct of_device_id tegra_spi_of_match[] = { - { .compatible = "nvidia,tegra114-spi", }, + { + .compatible = "nvidia,tegra114-spi", + .data = &tegra114_spi_soc_data, + }, { + .compatible = "nvidia,tegra124-spi", + .data = &tegra124_spi_soc_data, + }, { + .compatible = "nvidia,tegra210-spi", + .data = &tegra210_spi_soc_data, + }, {} }; MODULE_DEVICE_TABLE(of, tegra_spi_of_match); @@ -1177,6 +1213,13 @@ static int tegra_spi_probe(struct platform_device *pdev) tspi->dev = &pdev->dev; spin_lock_init(&tspi->lock); + tspi->soc_data = of_device_get_match_data(&pdev->dev); + if (!tspi->soc_data) { + dev_err(&pdev->dev, "unsupported tegra\n"); + ret = -ENODEV; + goto exit_free_master; + } + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); tspi->base = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(tspi->base)) { -- cgit v1.2.3-59-g8ed1b From cc1b69fc5f9f52cf18295db05cad57187cee1c1d Mon Sep 17 00:00:00 2001 From: Sowjanya Komatineni Date: Mon, 15 Apr 2019 14:30:26 -0700 Subject: spi: tegra114: fix PIO transfer This patch fixes PIO mode transfer to use PIO bit in SPI_COMMAND1 register. Current driver uses DMA_EN instead of PIO bit. Signed-off-by: Sowjanya Komatineni Signed-off-by: Mark Brown --- drivers/spi/spi-tegra114.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/spi/spi-tegra114.c') diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index b57f10182fae..21e4fdad013f 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -641,8 +641,9 @@ static int tegra_spi_start_cpu_based_transfer( tspi->is_curr_dma_xfer = false; - val |= SPI_DMA_EN; - tegra_spi_writel(tspi, val, SPI_DMA_CTL); + val = tspi->command1_reg; + val |= SPI_PIO; + tegra_spi_writel(tspi, val, SPI_COMMAND1); return 0; } -- cgit v1.2.3-59-g8ed1b