Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dmaengine: tegra210-adma: Add Tegra264 support

Add Tegra264 ADMA support with following changes:
- Add soc_data for Tegra264-specific variations.
- Tegra264 supports 64 channels and 10 pages, hence update the global
page configuration.
- In Tegra264 FIFO and outstanding request configs are moved to global
registers, hence add those registers offset in adma channel struct.
Also, 'has_outstanding_reqs' is removed and configuration moved to the
SoC data.
- Update channel direction and mode bit positions as per Tegra264.
- Register offsets are updated to align with Tegra264.

Signed-off-by: Sheetal <sheetal@nvidia.com>
Link: https://lore.kernel.org/r/20250512050010.1025259-3-sheetal@nvidia.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Sheetal and committed by
Vinod Koul
21e12738 b81cd165

+160 -25
+160 -25
drivers/dma/tegra210-adma.c
··· 27 27 28 28 #define ADMA_CH_INT_CLEAR 0x1c 29 29 #define ADMA_CH_CTRL 0x24 30 - #define ADMA_CH_CTRL_DIR(val) (((val) & 0xf) << 12) 30 + #define ADMA_CH_CTRL_DIR(val, mask, shift) (((val) & (mask)) << (shift)) 31 31 #define ADMA_CH_CTRL_DIR_AHUB2MEM 2 32 32 #define ADMA_CH_CTRL_DIR_MEM2AHUB 4 33 - #define ADMA_CH_CTRL_MODE_CONTINUOUS (2 << 8) 33 + #define ADMA_CH_CTRL_MODE_CONTINUOUS(shift) (2 << (shift)) 34 34 #define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1) 35 35 #define ADMA_CH_CTRL_XFER_PAUSE_SHIFT 0 36 36 ··· 41 41 #define ADMA_CH_CONFIG_MAX_BURST_SIZE 16 42 42 #define ADMA_CH_CONFIG_WEIGHT_FOR_WRR(val) ((val) & 0xf) 43 43 #define ADMA_CH_CONFIG_MAX_BUFS 8 44 - #define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(reqs) (reqs << 4) 44 + #define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(reqs) ((reqs) << 4) 45 + 46 + #define ADMA_GLOBAL_CH_CONFIG 0x400 47 + #define ADMA_GLOBAL_CH_CONFIG_WEIGHT_FOR_WRR(val) ((val) & 0x7) 48 + #define ADMA_GLOBAL_CH_CONFIG_OUTSTANDING_REQS(reqs) ((reqs) << 8) 45 49 46 50 #define TEGRA186_ADMA_GLOBAL_PAGE_CHGRP 0x30 47 51 #define TEGRA186_ADMA_GLOBAL_PAGE_RX_REQ 0x70 48 52 #define TEGRA186_ADMA_GLOBAL_PAGE_TX_REQ 0x84 53 + #define TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_0 0x44 54 + #define TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_1 0x48 55 + #define TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_0 0x100 56 + #define TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_1 0x104 57 + #define TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_0 0x180 58 + #define TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_1 0x184 59 + #define TEGRA264_ADMA_GLOBAL_PAGE_OFFSET 0x8 49 60 50 61 #define ADMA_CH_FIFO_CTRL 0x2c 51 62 #define ADMA_CH_TX_FIFO_SIZE_SHIFT 8 52 63 #define ADMA_CH_RX_FIFO_SIZE_SHIFT 0 64 + #define ADMA_GLOBAL_CH_FIFO_CTRL 0x300 53 65 54 66 #define ADMA_CH_LOWER_SRC_ADDR 0x34 55 67 #define ADMA_CH_LOWER_TRG_ADDR 0x3c ··· 85 73 * @adma_get_burst_config: Function callback used to set DMA burst size. 86 74 * @global_reg_offset: Register offset of DMA global register. 87 75 * @global_int_clear: Register offset of DMA global interrupt clear. 76 + * @global_ch_fifo_base: Global channel fifo ctrl base offset 77 + * @global_ch_config_base: Global channel config base offset 88 78 * @ch_req_tx_shift: Register offset for AHUB transmit channel select. 89 79 * @ch_req_rx_shift: Register offset for AHUB receive channel select. 80 + * @ch_dir_shift: Channel direction bit position. 81 + * @ch_mode_shift: Channel mode bit position. 90 82 * @ch_base_offset: Register offset of DMA channel registers. 83 + * @ch_tc_offset_diff: From TC register onwards offset differs for Tegra264 91 84 * @ch_fifo_ctrl: Default value for channel FIFO CTRL register. 85 + * @ch_config: Outstanding and WRR config values 92 86 * @ch_req_mask: Mask for Tx or Rx channel select. 87 + * @ch_dir_mask: Mask for channel direction. 93 88 * @ch_req_max: Maximum number of Tx or Rx channels available. 94 89 * @ch_reg_size: Size of DMA channel register space. 95 90 * @nr_channels: Number of DMA channels available. 96 91 * @ch_fifo_size_mask: Mask for FIFO size field. 97 92 * @sreq_index_offset: Slave channel index offset. 98 93 * @max_page: Maximum ADMA Channel Page. 99 - * @has_outstanding_reqs: If DMA channel can have outstanding requests. 100 94 * @set_global_pg_config: Global page programming. 101 95 */ 102 96 struct tegra_adma_chip_data { 103 97 unsigned int (*adma_get_burst_config)(unsigned int burst_size); 104 98 unsigned int global_reg_offset; 105 99 unsigned int global_int_clear; 100 + unsigned int global_ch_fifo_base; 101 + unsigned int global_ch_config_base; 106 102 unsigned int ch_req_tx_shift; 107 103 unsigned int ch_req_rx_shift; 104 + unsigned int ch_dir_shift; 105 + unsigned int ch_mode_shift; 108 106 unsigned int ch_base_offset; 107 + unsigned int ch_tc_offset_diff; 109 108 unsigned int ch_fifo_ctrl; 109 + unsigned int ch_config; 110 110 unsigned int ch_req_mask; 111 + unsigned int ch_dir_mask; 111 112 unsigned int ch_req_max; 112 113 unsigned int ch_reg_size; 113 114 unsigned int nr_channels; 114 115 unsigned int ch_fifo_size_mask; 115 116 unsigned int sreq_index_offset; 116 117 unsigned int max_page; 117 - bool has_outstanding_reqs; 118 118 void (*set_global_pg_config)(struct tegra_adma *tdma); 119 119 }; 120 120 ··· 136 112 struct tegra_adma_chan_regs { 137 113 unsigned int ctrl; 138 114 unsigned int config; 115 + unsigned int global_config; 139 116 unsigned int src_addr; 140 117 unsigned int trg_addr; 141 118 unsigned int fifo_ctrl; ··· 175 150 /* Transfer count and position info */ 176 151 unsigned int tx_buf_count; 177 152 unsigned int tx_buf_pos; 153 + 154 + unsigned int global_ch_fifo_offset; 155 + unsigned int global_ch_config_offset; 178 156 }; 179 157 180 158 /* ··· 272 244 tdma_write(tdma, TEGRA186_ADMA_GLOBAL_PAGE_CHGRP + (tdma->ch_page_no * 0x4), 0xff); 273 245 tdma_write(tdma, TEGRA186_ADMA_GLOBAL_PAGE_RX_REQ + (tdma->ch_page_no * 0x4), 0x1ffffff); 274 246 tdma_write(tdma, TEGRA186_ADMA_GLOBAL_PAGE_TX_REQ + (tdma->ch_page_no * 0x4), 0xffffff); 247 + } 248 + 249 + static void tegra264_adma_global_page_config(struct tegra_adma *tdma) 250 + { 251 + u32 global_page_offset = tdma->ch_page_no * TEGRA264_ADMA_GLOBAL_PAGE_OFFSET; 252 + 253 + /* If the default page (page1) is not used, then clear page1 registers */ 254 + if (tdma->ch_page_no) { 255 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_0, 0); 256 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_1, 0); 257 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_0, 0); 258 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_1, 0); 259 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_0, 0); 260 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_1, 0); 261 + } 262 + 263 + /* Program global registers for selected page */ 264 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_0 + global_page_offset, 0xffffffff); 265 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_1 + global_page_offset, 0xffffffff); 266 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_0 + global_page_offset, 0xffffffff); 267 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_1 + global_page_offset, 0x1); 268 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_0 + global_page_offset, 0xffffffff); 269 + tdma_write(tdma, TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_1 + global_page_offset, 0x1); 275 270 } 276 271 277 272 static int tegra_adma_init(struct tegra_adma *tdma) ··· 455 404 456 405 tdc->tx_buf_pos = 0; 457 406 tdc->tx_buf_count = 0; 458 - tdma_ch_write(tdc, ADMA_CH_TC, ch_regs->tc); 407 + tdma_ch_write(tdc, ADMA_CH_TC - tdc->tdma->cdata->ch_tc_offset_diff, ch_regs->tc); 459 408 tdma_ch_write(tdc, ADMA_CH_CTRL, ch_regs->ctrl); 460 - tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR, ch_regs->src_addr); 461 - tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR, ch_regs->trg_addr); 462 - tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_regs->fifo_ctrl); 409 + tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR - tdc->tdma->cdata->ch_tc_offset_diff, 410 + ch_regs->src_addr); 411 + tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR - tdc->tdma->cdata->ch_tc_offset_diff, 412 + ch_regs->trg_addr); 413 + 414 + if (!tdc->tdma->cdata->global_ch_fifo_base) 415 + tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_regs->fifo_ctrl); 416 + else if (tdc->global_ch_fifo_offset) 417 + tdma_write(tdc->tdma, tdc->global_ch_fifo_offset, ch_regs->fifo_ctrl); 418 + 419 + if (tdc->global_ch_config_offset) 420 + tdma_write(tdc->tdma, tdc->global_ch_config_offset, ch_regs->global_config); 421 + 463 422 tdma_ch_write(tdc, ADMA_CH_CONFIG, ch_regs->config); 464 423 465 424 /* Start ADMA */ ··· 482 421 { 483 422 struct tegra_adma_desc *desc = tdc->desc; 484 423 unsigned int max = ADMA_CH_XFER_STATUS_COUNT_MASK + 1; 485 - unsigned int pos = tdma_ch_read(tdc, ADMA_CH_XFER_STATUS); 424 + unsigned int pos = tdma_ch_read(tdc, ADMA_CH_XFER_STATUS - 425 + tdc->tdma->cdata->ch_tc_offset_diff); 486 426 unsigned int periods_remaining; 487 427 488 428 /* ··· 689 627 return -EINVAL; 690 628 } 691 629 692 - ch_regs->ctrl |= ADMA_CH_CTRL_DIR(adma_dir) | 693 - ADMA_CH_CTRL_MODE_CONTINUOUS | 630 + ch_regs->ctrl |= ADMA_CH_CTRL_DIR(adma_dir, cdata->ch_dir_mask, 631 + cdata->ch_dir_shift) | 632 + ADMA_CH_CTRL_MODE_CONTINUOUS(cdata->ch_mode_shift) | 694 633 ADMA_CH_CTRL_FLOWCTRL_EN; 695 634 ch_regs->config |= cdata->adma_get_burst_config(burst_size); 696 - ch_regs->config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1); 697 - if (cdata->has_outstanding_reqs) 698 - ch_regs->config |= TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(8); 635 + 636 + if (cdata->global_ch_config_base) 637 + ch_regs->global_config |= cdata->ch_config; 638 + else 639 + ch_regs->config |= cdata->ch_config; 699 640 700 641 /* 701 642 * 'sreq_index' represents the current ADMAIF channel number and as per ··· 853 788 /* skip if channel is not active */ 854 789 if (!ch_reg->cmd) 855 790 continue; 856 - ch_reg->tc = tdma_ch_read(tdc, ADMA_CH_TC); 857 - ch_reg->src_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_SRC_ADDR); 858 - ch_reg->trg_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_TRG_ADDR); 791 + ch_reg->tc = tdma_ch_read(tdc, ADMA_CH_TC - tdma->cdata->ch_tc_offset_diff); 792 + ch_reg->src_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_SRC_ADDR - 793 + tdma->cdata->ch_tc_offset_diff); 794 + ch_reg->trg_addr = tdma_ch_read(tdc, ADMA_CH_LOWER_TRG_ADDR - 795 + tdma->cdata->ch_tc_offset_diff); 859 796 ch_reg->ctrl = tdma_ch_read(tdc, ADMA_CH_CTRL); 860 - ch_reg->fifo_ctrl = tdma_ch_read(tdc, ADMA_CH_FIFO_CTRL); 797 + 798 + if (tdc->global_ch_config_offset) 799 + ch_reg->global_config = tdma_read(tdc->tdma, tdc->global_ch_config_offset); 800 + 801 + if (!tdc->tdma->cdata->global_ch_fifo_base) 802 + ch_reg->fifo_ctrl = tdma_ch_read(tdc, ADMA_CH_FIFO_CTRL); 803 + else if (tdc->global_ch_fifo_offset) 804 + ch_reg->fifo_ctrl = tdma_read(tdc->tdma, tdc->global_ch_fifo_offset); 805 + 861 806 ch_reg->config = tdma_ch_read(tdc, ADMA_CH_CONFIG); 807 + 862 808 } 863 809 864 810 clk_disable: ··· 908 832 /* skip if channel was not active earlier */ 909 833 if (!ch_reg->cmd) 910 834 continue; 911 - tdma_ch_write(tdc, ADMA_CH_TC, ch_reg->tc); 912 - tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR, ch_reg->src_addr); 913 - tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR, ch_reg->trg_addr); 835 + tdma_ch_write(tdc, ADMA_CH_TC - tdma->cdata->ch_tc_offset_diff, ch_reg->tc); 836 + tdma_ch_write(tdc, ADMA_CH_LOWER_SRC_ADDR - tdma->cdata->ch_tc_offset_diff, 837 + ch_reg->src_addr); 838 + tdma_ch_write(tdc, ADMA_CH_LOWER_TRG_ADDR - tdma->cdata->ch_tc_offset_diff, 839 + ch_reg->trg_addr); 914 840 tdma_ch_write(tdc, ADMA_CH_CTRL, ch_reg->ctrl); 915 - tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_reg->fifo_ctrl); 841 + 842 + if (!tdc->tdma->cdata->global_ch_fifo_base) 843 + tdma_ch_write(tdc, ADMA_CH_FIFO_CTRL, ch_reg->fifo_ctrl); 844 + else if (tdc->global_ch_fifo_offset) 845 + tdma_write(tdc->tdma, tdc->global_ch_fifo_offset, ch_reg->fifo_ctrl); 846 + 847 + if (tdc->global_ch_config_offset) 848 + tdma_write(tdc->tdma, tdc->global_ch_config_offset, ch_reg->global_config); 849 + 916 850 tdma_ch_write(tdc, ADMA_CH_CONFIG, ch_reg->config); 851 + 917 852 tdma_ch_write(tdc, ADMA_CH_CMD, ch_reg->cmd); 918 853 } 919 854 ··· 935 848 .adma_get_burst_config = tegra210_adma_get_burst_config, 936 849 .global_reg_offset = 0xc00, 937 850 .global_int_clear = 0x20, 851 + .global_ch_fifo_base = 0, 852 + .global_ch_config_base = 0, 938 853 .ch_req_tx_shift = 28, 939 854 .ch_req_rx_shift = 24, 855 + .ch_dir_shift = 12, 856 + .ch_mode_shift = 8, 940 857 .ch_base_offset = 0, 858 + .ch_tc_offset_diff = 0, 859 + .ch_config = ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1), 941 860 .ch_req_mask = 0xf, 861 + .ch_dir_mask = 0xf, 942 862 .ch_req_max = 10, 943 863 .ch_reg_size = 0x80, 944 864 .nr_channels = 22, 945 865 .ch_fifo_size_mask = 0xf, 946 866 .sreq_index_offset = 2, 947 867 .max_page = 0, 948 - .has_outstanding_reqs = false, 949 868 .set_global_pg_config = NULL, 950 869 }; 951 870 ··· 959 866 .adma_get_burst_config = tegra186_adma_get_burst_config, 960 867 .global_reg_offset = 0, 961 868 .global_int_clear = 0x402c, 869 + .global_ch_fifo_base = 0, 870 + .global_ch_config_base = 0, 962 871 .ch_req_tx_shift = 27, 963 872 .ch_req_rx_shift = 22, 873 + .ch_dir_shift = 12, 874 + .ch_mode_shift = 8, 964 875 .ch_base_offset = 0x10000, 876 + .ch_tc_offset_diff = 0, 877 + .ch_config = ADMA_CH_CONFIG_WEIGHT_FOR_WRR(1) | 878 + TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS(8), 965 879 .ch_req_mask = 0x1f, 880 + .ch_dir_mask = 0xf, 966 881 .ch_req_max = 20, 967 882 .ch_reg_size = 0x100, 968 883 .nr_channels = 32, 969 884 .ch_fifo_size_mask = 0x1f, 970 885 .sreq_index_offset = 4, 971 886 .max_page = 4, 972 - .has_outstanding_reqs = true, 973 887 .set_global_pg_config = tegra186_adma_global_page_config, 888 + }; 889 + 890 + static const struct tegra_adma_chip_data tegra264_chip_data = { 891 + .adma_get_burst_config = tegra186_adma_get_burst_config, 892 + .global_reg_offset = 0, 893 + .global_int_clear = 0x800c, 894 + .global_ch_fifo_base = ADMA_GLOBAL_CH_FIFO_CTRL, 895 + .global_ch_config_base = ADMA_GLOBAL_CH_CONFIG, 896 + .ch_req_tx_shift = 26, 897 + .ch_req_rx_shift = 20, 898 + .ch_dir_shift = 10, 899 + .ch_mode_shift = 7, 900 + .ch_base_offset = 0x10000, 901 + .ch_tc_offset_diff = 4, 902 + .ch_config = ADMA_GLOBAL_CH_CONFIG_WEIGHT_FOR_WRR(1) | 903 + ADMA_GLOBAL_CH_CONFIG_OUTSTANDING_REQS(8), 904 + .ch_req_mask = 0x3f, 905 + .ch_dir_mask = 7, 906 + .ch_req_max = 32, 907 + .ch_reg_size = 0x100, 908 + .nr_channels = 64, 909 + .ch_fifo_size_mask = 0x7f, 910 + .sreq_index_offset = 0, 911 + .max_page = 10, 912 + .set_global_pg_config = tegra264_adma_global_page_config, 974 913 }; 975 914 976 915 static const struct of_device_id tegra_adma_of_match[] = { 977 916 { .compatible = "nvidia,tegra210-adma", .data = &tegra210_chip_data }, 978 917 { .compatible = "nvidia,tegra186-adma", .data = &tegra186_chip_data }, 918 + { .compatible = "nvidia,tegra264-adma", .data = &tegra264_chip_data }, 979 919 { }, 980 920 }; 981 921 MODULE_DEVICE_TABLE(of, tegra_adma_of_match); ··· 1110 984 continue; 1111 985 1112 986 tdc->chan_addr = tdma->ch_base_addr + (cdata->ch_reg_size * i); 987 + 988 + if (tdma->base_addr) { 989 + if (cdata->global_ch_fifo_base) 990 + tdc->global_ch_fifo_offset = cdata->global_ch_fifo_base + (4 * i); 991 + 992 + if (cdata->global_ch_config_base) 993 + tdc->global_ch_config_offset = 994 + cdata->global_ch_config_base + (4 * i); 995 + } 1113 996 1114 997 tdc->irq = of_irq_get(pdev->dev.of_node, i); 1115 998 if (tdc->irq <= 0) {