Message ID | 20221001122148.9158-5-kyarlagadda@nvidia.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/5] spi: tegra210-quad: Fix combined sequence | expand |
Hi Krishna, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on broonie-spi/for-next] [also build test WARNING on linus/master v6.0-rc7 next-20220930] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Krishna-Yarlagadda/spi-tegra210-quad-Fix-combined-sequence/20221001-202349 base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next config: hexagon-randconfig-r045-20220925 compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 791a7ae1ba3efd6bca96338e10ffde557ba83920) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/1c7e26dac0d8ad5c5cb6f42d07a57b943b369185 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Krishna-Yarlagadda/spi-tegra210-quad-Fix-combined-sequence/20221001-202349 git checkout 1c7e26dac0d8ad5c5cb6f42d07a57b943b369185 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/spi/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): >> drivers/spi/spi-tegra210-quad.c:669:42: warning: shift count >= width of type [-Wshift-count-overflow] tegra_qspi_writel(tqspi, ((tx_dma_phys >> 32) & 0xff), ^ ~~ drivers/spi/spi-tegra210-quad.c:696:42: warning: shift count >= width of type [-Wshift-count-overflow] tegra_qspi_writel(tqspi, ((rx_dma_phys >> 32) & 0xff), ^ ~~ 2 warnings generated. vim +669 drivers/spi/spi-tegra210-quad.c 614 615 static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct spi_transfer *t) 616 { 617 struct dma_slave_config dma_sconfig = { 0 }; 618 dma_addr_t rx_dma_phys, tx_dma_phys; 619 unsigned int len; 620 u8 dma_burst; 621 int ret = 0; 622 u32 val; 623 bool has_ext_dma = (tqspi->soc_data->has_dma & 624 QSPI_DMA_EXT) ? true : false; 625 626 if (tqspi->is_packed) { 627 ret = tegra_qspi_dma_map_xfer(tqspi, t); 628 if (ret < 0) 629 return ret; 630 } 631 632 val = QSPI_DMA_BLK_SET(tqspi->curr_dma_words - 1); 633 tegra_qspi_writel(tqspi, val, QSPI_DMA_BLK); 634 635 tegra_qspi_unmask_irq(tqspi); 636 637 if (tqspi->is_packed) 638 len = DIV_ROUND_UP(tqspi->curr_dma_words * tqspi->bytes_per_word, 4) * 4; 639 else 640 len = tqspi->curr_dma_words * 4; 641 642 /* set attention level based on length of transfer */ 643 if (has_ext_dma) { 644 val = 0; 645 if (len & 0xf) { 646 val |= QSPI_TX_TRIG_1 | QSPI_RX_TRIG_1; 647 dma_burst = 1; 648 } else if (((len) >> 4) & 0x1) { 649 val |= QSPI_TX_TRIG_4 | QSPI_RX_TRIG_4; 650 dma_burst = 4; 651 } else { 652 val |= QSPI_TX_TRIG_8 | QSPI_RX_TRIG_8; 653 dma_burst = 8; 654 } 655 } 656 657 tegra_qspi_writel(tqspi, val, QSPI_DMA_CTL); 658 tqspi->dma_control_reg = val; 659 660 dma_sconfig.device_fc = true; 661 if ((tqspi->cur_direction & DATA_DIR_TX) && !has_ext_dma) { 662 if (tqspi->is_packed) 663 tx_dma_phys = t->tx_dma; 664 else 665 tx_dma_phys = tqspi->tx_dma_phys; 666 tegra_qspi_copy_client_txbuf_to_qspi_txbuf(tqspi, t); 667 tegra_qspi_writel(tqspi, (tx_dma_phys & 0xffffffff), 668 QSPI_DMA_MEM_ADDRESS_REG); > 669 tegra_qspi_writel(tqspi, ((tx_dma_phys >> 32) & 0xff), 670 QSPI_DMA_HI_ADDRESS_REG); 671 } else if ((tqspi->cur_direction & DATA_DIR_TX) && has_ext_dma) { 672 dma_sconfig.dst_addr = tqspi->phys + QSPI_TX_FIFO; 673 dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 674 dma_sconfig.dst_maxburst = dma_burst; 675 ret = dmaengine_slave_config(tqspi->tx_dma_chan, &dma_sconfig); 676 if (ret < 0) { 677 dev_err(tqspi->dev, "failed DMA slave config: %d\n", ret); 678 return ret; 679 } 680 681 tegra_qspi_copy_client_txbuf_to_qspi_txbuf(tqspi, t); 682 ret = tegra_qspi_start_tx_dma(tqspi, t, len); 683 if (ret < 0) { 684 dev_err(tqspi->dev, "failed to starting TX DMA: %d\n", ret); 685 return ret; 686 } 687 } 688 689 if ((tqspi->cur_direction & DATA_DIR_RX) && !has_ext_dma) { 690 if (tqspi->is_packed) 691 rx_dma_phys = t->rx_dma; 692 else 693 rx_dma_phys = tqspi->rx_dma_phys; 694 tegra_qspi_writel(tqspi, (rx_dma_phys & 0xffffffff), 695 QSPI_DMA_MEM_ADDRESS_REG); 696 tegra_qspi_writel(tqspi, ((rx_dma_phys >> 32) & 0xff), 697 QSPI_DMA_HI_ADDRESS_REG); 698 } else if ((tqspi->cur_direction & DATA_DIR_RX) && has_ext_dma) { 699 dma_sconfig.src_addr = tqspi->phys + QSPI_RX_FIFO; 700 dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 701 dma_sconfig.src_maxburst = dma_burst; 702 ret = dmaengine_slave_config(tqspi->rx_dma_chan, &dma_sconfig); 703 if (ret < 0) { 704 dev_err(tqspi->dev, "failed DMA slave config: %d\n", ret); 705 return ret; 706 } 707 708 dma_sync_single_for_device(tqspi->dev, tqspi->rx_dma_phys, 709 tqspi->dma_buf_size, 710 DMA_FROM_DEVICE); 711 712 ret = tegra_qspi_start_rx_dma(tqspi, t, len); 713 if (ret < 0) { 714 dev_err(tqspi->dev, "failed to start RX DMA: %d\n", ret); 715 if (tqspi->cur_direction & DATA_DIR_TX) 716 dmaengine_terminate_all(tqspi->tx_dma_chan); 717 return ret; 718 } 719 } 720 721 tegra_qspi_writel(tqspi, tqspi->command1_reg, QSPI_COMMAND1); 722 723 tqspi->is_curr_dma_xfer = true; 724 tqspi->dma_control_reg = val; 725 val |= QSPI_DMA_EN; 726 tegra_qspi_writel(tqspi, val, QSPI_DMA_CTL); 727 728 return ret; 729 } 730
Hi Krishna, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on broonie-spi/for-next] [also build test WARNING on linus/master v6.0-rc7 next-20220930] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Krishna-Yarlagadda/spi-tegra210-quad-Fix-combined-sequence/20221001-202349 base: https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next config: m68k-allyesconfig compiler: m68k-linux-gcc (GCC) 12.1.0 reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/1c7e26dac0d8ad5c5cb6f42d07a57b943b369185 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Krishna-Yarlagadda/spi-tegra210-quad-Fix-combined-sequence/20221001-202349 git checkout 1c7e26dac0d8ad5c5cb6f42d07a57b943b369185 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> All warnings (new ones prefixed by >>): drivers/spi/spi-tegra210-quad.c: In function 'tegra_qspi_start_dma_based_transfer': >> drivers/spi/spi-tegra210-quad.c:669:56: warning: right shift count >= width of type [-Wshift-count-overflow] 669 | tegra_qspi_writel(tqspi, ((tx_dma_phys >> 32) & 0xff), | ^~ drivers/spi/spi-tegra210-quad.c:696:56: warning: right shift count >= width of type [-Wshift-count-overflow] 696 | tegra_qspi_writel(tqspi, ((rx_dma_phys >> 32) & 0xff), | ^~ vim +669 drivers/spi/spi-tegra210-quad.c 614 615 static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct spi_transfer *t) 616 { 617 struct dma_slave_config dma_sconfig = { 0 }; 618 dma_addr_t rx_dma_phys, tx_dma_phys; 619 unsigned int len; 620 u8 dma_burst; 621 int ret = 0; 622 u32 val; 623 bool has_ext_dma = (tqspi->soc_data->has_dma & 624 QSPI_DMA_EXT) ? true : false; 625 626 if (tqspi->is_packed) { 627 ret = tegra_qspi_dma_map_xfer(tqspi, t); 628 if (ret < 0) 629 return ret; 630 } 631 632 val = QSPI_DMA_BLK_SET(tqspi->curr_dma_words - 1); 633 tegra_qspi_writel(tqspi, val, QSPI_DMA_BLK); 634 635 tegra_qspi_unmask_irq(tqspi); 636 637 if (tqspi->is_packed) 638 len = DIV_ROUND_UP(tqspi->curr_dma_words * tqspi->bytes_per_word, 4) * 4; 639 else 640 len = tqspi->curr_dma_words * 4; 641 642 /* set attention level based on length of transfer */ 643 if (has_ext_dma) { 644 val = 0; 645 if (len & 0xf) { 646 val |= QSPI_TX_TRIG_1 | QSPI_RX_TRIG_1; 647 dma_burst = 1; 648 } else if (((len) >> 4) & 0x1) { 649 val |= QSPI_TX_TRIG_4 | QSPI_RX_TRIG_4; 650 dma_burst = 4; 651 } else { 652 val |= QSPI_TX_TRIG_8 | QSPI_RX_TRIG_8; 653 dma_burst = 8; 654 } 655 } 656 657 tegra_qspi_writel(tqspi, val, QSPI_DMA_CTL); 658 tqspi->dma_control_reg = val; 659 660 dma_sconfig.device_fc = true; 661 if ((tqspi->cur_direction & DATA_DIR_TX) && !has_ext_dma) { 662 if (tqspi->is_packed) 663 tx_dma_phys = t->tx_dma; 664 else 665 tx_dma_phys = tqspi->tx_dma_phys; 666 tegra_qspi_copy_client_txbuf_to_qspi_txbuf(tqspi, t); 667 tegra_qspi_writel(tqspi, (tx_dma_phys & 0xffffffff), 668 QSPI_DMA_MEM_ADDRESS_REG); > 669 tegra_qspi_writel(tqspi, ((tx_dma_phys >> 32) & 0xff), 670 QSPI_DMA_HI_ADDRESS_REG); 671 } else if ((tqspi->cur_direction & DATA_DIR_TX) && has_ext_dma) { 672 dma_sconfig.dst_addr = tqspi->phys + QSPI_TX_FIFO; 673 dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 674 dma_sconfig.dst_maxburst = dma_burst; 675 ret = dmaengine_slave_config(tqspi->tx_dma_chan, &dma_sconfig); 676 if (ret < 0) { 677 dev_err(tqspi->dev, "failed DMA slave config: %d\n", ret); 678 return ret; 679 } 680 681 tegra_qspi_copy_client_txbuf_to_qspi_txbuf(tqspi, t); 682 ret = tegra_qspi_start_tx_dma(tqspi, t, len); 683 if (ret < 0) { 684 dev_err(tqspi->dev, "failed to starting TX DMA: %d\n", ret); 685 return ret; 686 } 687 } 688 689 if ((tqspi->cur_direction & DATA_DIR_RX) && !has_ext_dma) { 690 if (tqspi->is_packed) 691 rx_dma_phys = t->rx_dma; 692 else 693 rx_dma_phys = tqspi->rx_dma_phys; 694 tegra_qspi_writel(tqspi, (rx_dma_phys & 0xffffffff), 695 QSPI_DMA_MEM_ADDRESS_REG); 696 tegra_qspi_writel(tqspi, ((rx_dma_phys >> 32) & 0xff), 697 QSPI_DMA_HI_ADDRESS_REG); 698 } else if ((tqspi->cur_direction & DATA_DIR_RX) && has_ext_dma) { 699 dma_sconfig.src_addr = tqspi->phys + QSPI_RX_FIFO; 700 dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 701 dma_sconfig.src_maxburst = dma_burst; 702 ret = dmaengine_slave_config(tqspi->rx_dma_chan, &dma_sconfig); 703 if (ret < 0) { 704 dev_err(tqspi->dev, "failed DMA slave config: %d\n", ret); 705 return ret; 706 } 707 708 dma_sync_single_for_device(tqspi->dev, tqspi->rx_dma_phys, 709 tqspi->dma_buf_size, 710 DMA_FROM_DEVICE); 711 712 ret = tegra_qspi_start_rx_dma(tqspi, t, len); 713 if (ret < 0) { 714 dev_err(tqspi->dev, "failed to start RX DMA: %d\n", ret); 715 if (tqspi->cur_direction & DATA_DIR_TX) 716 dmaengine_terminate_all(tqspi->tx_dma_chan); 717 return ret; 718 } 719 } 720 721 tegra_qspi_writel(tqspi, tqspi->command1_reg, QSPI_COMMAND1); 722 723 tqspi->is_curr_dma_xfer = true; 724 tqspi->dma_control_reg = val; 725 val |= QSPI_DMA_EN; 726 tegra_qspi_writel(tqspi, val, QSPI_DMA_CTL); 727 728 return ret; 729 } 730
Hi Krishna, On Sat, Oct 1, 2022 at 2:26 PM Krishna Yarlagadda <kyarlagadda@nvidia.com> wrote: > Enable Native DMA support for Tegra23 & Tegra24 > > Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> Thanks for your patch! > --- a/drivers/spi/spi-tegra210-quad.c > +++ b/drivers/spi/spi-tegra210-quad.c > @@ -163,7 +169,7 @@ > #define DATA_TRANSFER 3 > > struct tegra_qspi_soc_data { > - bool has_dma; > + int has_dma; unsigned int Please rename the variable to e.g. "dma_mode", as "has_<foo>" suggests it is a boolean flag. > bool cmb_xfer_capable; > unsigned int cs_count; > }; > @@ -629,23 +640,35 @@ static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct > len = tqspi->curr_dma_words * 4; > > /* set attention level based on length of transfer */ > - val = 0; > - if (len & 0xf) { > - val |= QSPI_TX_TRIG_1 | QSPI_RX_TRIG_1; > - dma_burst = 1; > - } else if (((len) >> 4) & 0x1) { > - val |= QSPI_TX_TRIG_4 | QSPI_RX_TRIG_4; > - dma_burst = 4; > - } else { > - val |= QSPI_TX_TRIG_8 | QSPI_RX_TRIG_8; > - dma_burst = 8; > + if (has_ext_dma) { > + val = 0; > + if (len & 0xf) { > + val |= QSPI_TX_TRIG_1 | QSPI_RX_TRIG_1; > + dma_burst = 1; > + } else if (((len) >> 4) & 0x1) { > + val |= QSPI_TX_TRIG_4 | QSPI_RX_TRIG_4; > + dma_burst = 4; > + } else { > + val |= QSPI_TX_TRIG_8 | QSPI_RX_TRIG_8; > + dma_burst = 8; > + } > } > > tegra_qspi_writel(tqspi, val, QSPI_DMA_CTL); > tqspi->dma_control_reg = val; > > dma_sconfig.device_fc = true; > - if (tqspi->cur_direction & DATA_DIR_TX) { > + if ((tqspi->cur_direction & DATA_DIR_TX) && !has_ext_dma) { > + if (tqspi->is_packed) > + tx_dma_phys = t->tx_dma; > + else > + tx_dma_phys = tqspi->tx_dma_phys; > + tegra_qspi_copy_client_txbuf_to_qspi_txbuf(tqspi, t); > + tegra_qspi_writel(tqspi, (tx_dma_phys & 0xffffffff), lower_32_bits(), for consistency with below. > + QSPI_DMA_MEM_ADDRESS_REG); > + tegra_qspi_writel(tqspi, ((tx_dma_phys >> 32) & 0xff), upper_32_bits(), to fix the build failures reported by 0-day ("warning: shift count >= width of type"). > + QSPI_DMA_HI_ADDRESS_REG); > + } else if ((tqspi->cur_direction & DATA_DIR_TX) && has_ext_dma) { > dma_sconfig.dst_addr = tqspi->phys + QSPI_TX_FIFO; > dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; > dma_sconfig.dst_maxburst = dma_burst; > @@ -1045,6 +1085,8 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, > struct spi_message *msg) > { > bool is_first_msg = true; > + bool has_ext_dma = (tqspi->soc_data->has_dma & > + QSPI_DMA_EXT) ? true : false; No need for the "? true : false" (everywhere) > struct spi_transfer *xfer; > struct spi_device *spi = msg->spi; > u8 transfer_phase = 0; Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
diff --git a/drivers/spi/spi-tegra210-quad.c b/drivers/spi/spi-tegra210-quad.c index 99811509dafa..edecb999a614 100644 --- a/drivers/spi/spi-tegra210-quad.c +++ b/drivers/spi/spi-tegra210-quad.c @@ -111,6 +111,9 @@ #define QSPI_DMA_BLK 0x024 #define QSPI_DMA_BLK_SET(x) (((x) & 0xffff) << 0) +#define QSPI_DMA_MEM_ADDRESS_REG 0x028 +#define QSPI_DMA_HI_ADDRESS_REG 0x02c + #define QSPI_TX_FIFO 0x108 #define QSPI_RX_FIFO 0x188 @@ -155,6 +158,9 @@ #define DATA_DIR_TX BIT(0) #define DATA_DIR_RX BIT(1) +#define QSPI_DMA_EXT BIT(0) +#define QSPI_DMA_INT BIT(1) + #define QSPI_DMA_TIMEOUT (msecs_to_jiffies(1000)) #define DEFAULT_QSPI_DMA_BUF_LEN (64 * 1024) #define CMD_TRANSFER 0 @@ -163,7 +169,7 @@ #define DATA_TRANSFER 3 struct tegra_qspi_soc_data { - bool has_dma; + int has_dma; bool cmb_xfer_capable; unsigned int cs_count; }; @@ -600,17 +606,22 @@ static void tegra_qspi_dma_unmap_xfer(struct tegra_qspi *tqspi, struct spi_trans len = DIV_ROUND_UP(tqspi->curr_dma_words * tqspi->bytes_per_word, 4) * 4; - dma_unmap_single(tqspi->dev, t->tx_dma, len, DMA_TO_DEVICE); - dma_unmap_single(tqspi->dev, t->rx_dma, len, DMA_FROM_DEVICE); + if (t->tx_buf) + dma_unmap_single(tqspi->dev, t->tx_dma, len, DMA_TO_DEVICE); + if (t->rx_buf) + dma_unmap_single(tqspi->dev, t->rx_dma, len, DMA_FROM_DEVICE); } static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct spi_transfer *t) { struct dma_slave_config dma_sconfig = { 0 }; + dma_addr_t rx_dma_phys, tx_dma_phys; unsigned int len; u8 dma_burst; int ret = 0; u32 val; + bool has_ext_dma = (tqspi->soc_data->has_dma & + QSPI_DMA_EXT) ? true : false; if (tqspi->is_packed) { ret = tegra_qspi_dma_map_xfer(tqspi, t); @@ -629,23 +640,35 @@ static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct len = tqspi->curr_dma_words * 4; /* set attention level based on length of transfer */ - val = 0; - if (len & 0xf) { - val |= QSPI_TX_TRIG_1 | QSPI_RX_TRIG_1; - dma_burst = 1; - } else if (((len) >> 4) & 0x1) { - val |= QSPI_TX_TRIG_4 | QSPI_RX_TRIG_4; - dma_burst = 4; - } else { - val |= QSPI_TX_TRIG_8 | QSPI_RX_TRIG_8; - dma_burst = 8; + if (has_ext_dma) { + val = 0; + if (len & 0xf) { + val |= QSPI_TX_TRIG_1 | QSPI_RX_TRIG_1; + dma_burst = 1; + } else if (((len) >> 4) & 0x1) { + val |= QSPI_TX_TRIG_4 | QSPI_RX_TRIG_4; + dma_burst = 4; + } else { + val |= QSPI_TX_TRIG_8 | QSPI_RX_TRIG_8; + dma_burst = 8; + } } tegra_qspi_writel(tqspi, val, QSPI_DMA_CTL); tqspi->dma_control_reg = val; dma_sconfig.device_fc = true; - if (tqspi->cur_direction & DATA_DIR_TX) { + if ((tqspi->cur_direction & DATA_DIR_TX) && !has_ext_dma) { + if (tqspi->is_packed) + tx_dma_phys = t->tx_dma; + else + tx_dma_phys = tqspi->tx_dma_phys; + tegra_qspi_copy_client_txbuf_to_qspi_txbuf(tqspi, t); + tegra_qspi_writel(tqspi, (tx_dma_phys & 0xffffffff), + QSPI_DMA_MEM_ADDRESS_REG); + tegra_qspi_writel(tqspi, ((tx_dma_phys >> 32) & 0xff), + QSPI_DMA_HI_ADDRESS_REG); + } else if ((tqspi->cur_direction & DATA_DIR_TX) && has_ext_dma) { dma_sconfig.dst_addr = tqspi->phys + QSPI_TX_FIFO; dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.dst_maxburst = dma_burst; @@ -663,7 +686,16 @@ static int tegra_qspi_start_dma_based_transfer(struct tegra_qspi *tqspi, struct } } - if (tqspi->cur_direction & DATA_DIR_RX) { + if ((tqspi->cur_direction & DATA_DIR_RX) && !has_ext_dma) { + if (tqspi->is_packed) + rx_dma_phys = t->rx_dma; + else + rx_dma_phys = tqspi->rx_dma_phys; + tegra_qspi_writel(tqspi, (rx_dma_phys & 0xffffffff), + QSPI_DMA_MEM_ADDRESS_REG); + tegra_qspi_writel(tqspi, ((rx_dma_phys >> 32) & 0xff), + QSPI_DMA_HI_ADDRESS_REG); + } else if ((tqspi->cur_direction & DATA_DIR_RX) && has_ext_dma) { dma_sconfig.src_addr = tqspi->phys + QSPI_RX_FIFO; dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; dma_sconfig.src_maxburst = dma_burst; @@ -751,13 +783,29 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi) u32 *dma_buf; int err; - dma_chan = dma_request_chan(tqspi->dev, "rx"); - if (IS_ERR(dma_chan)) { - err = PTR_ERR(dma_chan); - goto err_out; - } + if (!tqspi->soc_data->has_dma) + return -ENODEV; + + if (tqspi->soc_data->has_dma & QSPI_DMA_EXT) { + dma_chan = dma_request_chan(tqspi->dev, "rx"); + if (IS_ERR(dma_chan)) { + err = PTR_ERR(dma_chan); + goto err_out; + } - tqspi->rx_dma_chan = dma_chan; + tqspi->rx_dma_chan = dma_chan; + + dma_chan = dma_request_chan(tqspi->dev, "tx"); + if (IS_ERR(dma_chan)) { + err = PTR_ERR(dma_chan); + goto err_out; + } + + tqspi->tx_dma_chan = dma_chan; + } else { + tqspi->rx_dma_chan = NULL; + tqspi->tx_dma_chan = NULL; + } dma_buf = dma_alloc_coherent(tqspi->dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL); if (!dma_buf) { @@ -768,14 +816,6 @@ static int tegra_qspi_init_dma(struct tegra_qspi *tqspi) tqspi->rx_dma_buf = dma_buf; tqspi->rx_dma_phys = dma_phys; - dma_chan = dma_request_chan(tqspi->dev, "tx"); - if (IS_ERR(dma_chan)) { - err = PTR_ERR(dma_chan); - goto err_out; - } - - tqspi->tx_dma_chan = dma_chan; - dma_buf = dma_alloc_coherent(tqspi->dev, tqspi->dma_buf_size, &dma_phys, GFP_KERNEL); if (!dma_buf) { err = -ENOMEM; @@ -1045,6 +1085,8 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, struct spi_message *msg) { bool is_first_msg = true; + bool has_ext_dma = (tqspi->soc_data->has_dma & + QSPI_DMA_EXT) ? true : false; struct spi_transfer *xfer; struct spi_device *spi = msg->spi; u8 transfer_phase = 0; @@ -1109,12 +1151,12 @@ static int tegra_qspi_combined_seq_xfer(struct tegra_qspi *tqspi, if (WARN_ON(ret == 0)) { dev_err(tqspi->dev, "QSPI Transfer failed with timeout: %d\n", ret); - if (tqspi->is_curr_dma_xfer && + if (tqspi->is_curr_dma_xfer && has_ext_dma && (tqspi->cur_direction & DATA_DIR_TX)) dmaengine_terminate_all (tqspi->tx_dma_chan); - if (tqspi->is_curr_dma_xfer && + if (tqspi->is_curr_dma_xfer && has_ext_dma && (tqspi->cur_direction & DATA_DIR_RX)) dmaengine_terminate_all (tqspi->rx_dma_chan); @@ -1178,6 +1220,8 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, struct spi_device *spi = msg->spi; struct spi_transfer *transfer; bool is_first_msg = true; + bool has_ext_dma = (tqspi->soc_data->has_dma & + QSPI_DMA_EXT) ? true : false; int ret = 0, val = 0; msg->status = 0; @@ -1230,9 +1274,11 @@ static int tegra_qspi_non_combined_seq_xfer(struct tegra_qspi *tqspi, QSPI_DMA_TIMEOUT); if (WARN_ON(ret == 0)) { dev_err(tqspi->dev, "transfer timeout\n"); - if (tqspi->is_curr_dma_xfer && (tqspi->cur_direction & DATA_DIR_TX)) + if (tqspi->is_curr_dma_xfer && has_ext_dma && + (tqspi->cur_direction & DATA_DIR_TX)) dmaengine_terminate_all(tqspi->tx_dma_chan); - if (tqspi->is_curr_dma_xfer && (tqspi->cur_direction & DATA_DIR_RX)) + if (tqspi->is_curr_dma_xfer && has_ext_dma && + (tqspi->cur_direction & DATA_DIR_RX)) dmaengine_terminate_all(tqspi->rx_dma_chan); tegra_qspi_handle_error(tqspi); ret = -EIO; @@ -1365,8 +1411,20 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) unsigned long flags; long wait_status; int err = 0; + bool has_ext_dma = (tqspi->soc_data->has_dma & + QSPI_DMA_EXT) ? true : false; + + if (tqspi->cur_direction & DATA_DIR_TX && !has_ext_dma) { + if (tqspi->tx_status) + err += 1; + } + + if (tqspi->cur_direction & DATA_DIR_RX && !has_ext_dma) { + if (tqspi->rx_status) + err += 2; + } - if (tqspi->cur_direction & DATA_DIR_TX) { + if (tqspi->cur_direction & DATA_DIR_TX && has_ext_dma) { if (tqspi->tx_status) { dmaengine_terminate_all(tqspi->tx_dma_chan); err += 1; @@ -1381,7 +1439,7 @@ static irqreturn_t handle_dma_based_xfer(struct tegra_qspi *tqspi) } } - if (tqspi->cur_direction & DATA_DIR_RX) { + if (tqspi->cur_direction & DATA_DIR_RX && has_ext_dma) { if (tqspi->rx_status) { dmaengine_terminate_all(tqspi->rx_dma_chan); err += 2; @@ -1454,25 +1512,25 @@ static irqreturn_t tegra_qspi_isr_thread(int irq, void *context_data) } static struct tegra_qspi_soc_data tegra210_qspi_soc_data = { - .has_dma = true, + .has_dma = QSPI_DMA_EXT, .cmb_xfer_capable = false, .cs_count = 1, }; static struct tegra_qspi_soc_data tegra186_qspi_soc_data = { - .has_dma = true, + .has_dma = QSPI_DMA_EXT, .cmb_xfer_capable = true, .cs_count = 1, }; static struct tegra_qspi_soc_data tegra234_qspi_soc_data = { - .has_dma = false, + .has_dma = QSPI_DMA_INT, .cmb_xfer_capable = true, .cs_count = 1, }; static struct tegra_qspi_soc_data tegra241_qspi_soc_data = { - .has_dma = false, + .has_dma = QSPI_DMA_INT, .cmb_xfer_capable = true, .cs_count = 4, };
Enable Native DMA support for Tegra23 & Tegra24 Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com> --- drivers/spi/spi-tegra210-quad.c | 136 +++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 39 deletions(-)