2727
2828#define ADMA_CH_INT_CLEAR 0x1c
2929#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) )
3131#define ADMA_CH_CTRL_DIR_AHUB2MEM 2
3232#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) )
3434#define ADMA_CH_CTRL_FLOWCTRL_EN BIT(1)
3535#define ADMA_CH_CTRL_XFER_PAUSE_SHIFT 0
3636
4141#define ADMA_CH_CONFIG_MAX_BURST_SIZE 16
4242#define ADMA_CH_CONFIG_WEIGHT_FOR_WRR (val ) ((val) & 0xf)
4343#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)
4549
4650#define TEGRA186_ADMA_GLOBAL_PAGE_CHGRP 0x30
4751#define TEGRA186_ADMA_GLOBAL_PAGE_RX_REQ 0x70
4852#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
4960
5061#define ADMA_CH_FIFO_CTRL 0x2c
5162#define ADMA_CH_TX_FIFO_SIZE_SHIFT 8
5263#define ADMA_CH_RX_FIFO_SIZE_SHIFT 0
64+ #define ADMA_GLOBAL_CH_FIFO_CTRL 0x300
5365
5466#define ADMA_CH_LOWER_SRC_ADDR 0x34
5567#define ADMA_CH_LOWER_TRG_ADDR 0x3c
@@ -73,36 +85,48 @@ struct tegra_adma;
7385 * @adma_get_burst_config: Function callback used to set DMA burst size.
7486 * @global_reg_offset: Register offset of DMA global register.
7587 * @global_int_clear: Register offset of DMA global interrupt clear.
88+ * @global_ch_fifo_base: Global channel fifo ctrl base offset
89+ * @global_ch_config_base: Global channel config base offset
7690 * @ch_req_tx_shift: Register offset for AHUB transmit channel select.
7791 * @ch_req_rx_shift: Register offset for AHUB receive channel select.
92+ * @ch_dir_shift: Channel direction bit position.
93+ * @ch_mode_shift: Channel mode bit position.
7894 * @ch_base_offset: Register offset of DMA channel registers.
95+ * @ch_tc_offset_diff: From TC register onwards offset differs for Tegra264
7996 * @ch_fifo_ctrl: Default value for channel FIFO CTRL register.
97+ * @ch_config: Outstanding and WRR config values
8098 * @ch_req_mask: Mask for Tx or Rx channel select.
99+ * @ch_dir_mask: Mask for channel direction.
81100 * @ch_req_max: Maximum number of Tx or Rx channels available.
82101 * @ch_reg_size: Size of DMA channel register space.
83102 * @nr_channels: Number of DMA channels available.
84103 * @ch_fifo_size_mask: Mask for FIFO size field.
85104 * @sreq_index_offset: Slave channel index offset.
86105 * @max_page: Maximum ADMA Channel Page.
87- * @has_outstanding_reqs: If DMA channel can have outstanding requests.
88106 * @set_global_pg_config: Global page programming.
89107 */
90108struct tegra_adma_chip_data {
91109 unsigned int (* adma_get_burst_config )(unsigned int burst_size );
92110 unsigned int global_reg_offset ;
93111 unsigned int global_int_clear ;
112+ unsigned int global_ch_fifo_base ;
113+ unsigned int global_ch_config_base ;
94114 unsigned int ch_req_tx_shift ;
95115 unsigned int ch_req_rx_shift ;
116+ unsigned int ch_dir_shift ;
117+ unsigned int ch_mode_shift ;
96118 unsigned int ch_base_offset ;
119+ unsigned int ch_tc_offset_diff ;
97120 unsigned int ch_fifo_ctrl ;
121+ unsigned int ch_config ;
98122 unsigned int ch_req_mask ;
123+ unsigned int ch_dir_mask ;
99124 unsigned int ch_req_max ;
100125 unsigned int ch_reg_size ;
101126 unsigned int nr_channels ;
102127 unsigned int ch_fifo_size_mask ;
103128 unsigned int sreq_index_offset ;
104129 unsigned int max_page ;
105- bool has_outstanding_reqs ;
106130 void (* set_global_pg_config )(struct tegra_adma * tdma );
107131};
108132
@@ -112,6 +136,7 @@ struct tegra_adma_chip_data {
112136struct tegra_adma_chan_regs {
113137 unsigned int ctrl ;
114138 unsigned int config ;
139+ unsigned int global_config ;
115140 unsigned int src_addr ;
116141 unsigned int trg_addr ;
117142 unsigned int fifo_ctrl ;
@@ -150,6 +175,9 @@ struct tegra_adma_chan {
150175 /* Transfer count and position info */
151176 unsigned int tx_buf_count ;
152177 unsigned int tx_buf_pos ;
178+
179+ unsigned int global_ch_fifo_offset ;
180+ unsigned int global_ch_config_offset ;
153181};
154182
155183/*
@@ -246,6 +274,29 @@ static void tegra186_adma_global_page_config(struct tegra_adma *tdma)
246274 tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_TX_REQ + (tdma -> ch_page_no * 0x4 ), 0xffffff );
247275}
248276
277+ static void tegra264_adma_global_page_config (struct tegra_adma * tdma )
278+ {
279+ u32 global_page_offset = tdma -> ch_page_no * TEGRA264_ADMA_GLOBAL_PAGE_OFFSET ;
280+
281+ /* If the default page (page1) is not used, then clear page1 registers */
282+ if (tdma -> ch_page_no ) {
283+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_0 , 0 );
284+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_1 , 0 );
285+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_0 , 0 );
286+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_1 , 0 );
287+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_0 , 0 );
288+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_1 , 0 );
289+ }
290+
291+ /* Program global registers for selected page */
292+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_0 + global_page_offset , 0xffffffff );
293+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_CHGRP_1 + global_page_offset , 0xffffffff );
294+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_0 + global_page_offset , 0xffffffff );
295+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_RX_REQ_1 + global_page_offset , 0x1 );
296+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_0 + global_page_offset , 0xffffffff );
297+ tdma_write (tdma , TEGRA264_ADMA_GLOBAL_PAGE_TX_REQ_1 + global_page_offset , 0x1 );
298+ }
299+
249300static int tegra_adma_init (struct tegra_adma * tdma )
250301{
251302 u32 status ;
@@ -404,11 +455,21 @@ static void tegra_adma_start(struct tegra_adma_chan *tdc)
404455
405456 tdc -> tx_buf_pos = 0 ;
406457 tdc -> tx_buf_count = 0 ;
407- tdma_ch_write (tdc , ADMA_CH_TC , ch_regs -> tc );
458+ tdma_ch_write (tdc , ADMA_CH_TC - tdc -> tdma -> cdata -> ch_tc_offset_diff , ch_regs -> tc );
408459 tdma_ch_write (tdc , ADMA_CH_CTRL , ch_regs -> ctrl );
409- tdma_ch_write (tdc , ADMA_CH_LOWER_SRC_ADDR , ch_regs -> src_addr );
410- tdma_ch_write (tdc , ADMA_CH_LOWER_TRG_ADDR , ch_regs -> trg_addr );
411- tdma_ch_write (tdc , ADMA_CH_FIFO_CTRL , ch_regs -> fifo_ctrl );
460+ tdma_ch_write (tdc , ADMA_CH_LOWER_SRC_ADDR - tdc -> tdma -> cdata -> ch_tc_offset_diff ,
461+ ch_regs -> src_addr );
462+ tdma_ch_write (tdc , ADMA_CH_LOWER_TRG_ADDR - tdc -> tdma -> cdata -> ch_tc_offset_diff ,
463+ ch_regs -> trg_addr );
464+
465+ if (!tdc -> tdma -> cdata -> global_ch_fifo_base )
466+ tdma_ch_write (tdc , ADMA_CH_FIFO_CTRL , ch_regs -> fifo_ctrl );
467+ else if (tdc -> global_ch_fifo_offset )
468+ tdma_write (tdc -> tdma , tdc -> global_ch_fifo_offset , ch_regs -> fifo_ctrl );
469+
470+ if (tdc -> global_ch_config_offset )
471+ tdma_write (tdc -> tdma , tdc -> global_ch_config_offset , ch_regs -> global_config );
472+
412473 tdma_ch_write (tdc , ADMA_CH_CONFIG , ch_regs -> config );
413474
414475 /* Start ADMA */
@@ -421,7 +482,8 @@ static unsigned int tegra_adma_get_residue(struct tegra_adma_chan *tdc)
421482{
422483 struct tegra_adma_desc * desc = tdc -> desc ;
423484 unsigned int max = ADMA_CH_XFER_STATUS_COUNT_MASK + 1 ;
424- unsigned int pos = tdma_ch_read (tdc , ADMA_CH_XFER_STATUS );
485+ unsigned int pos = tdma_ch_read (tdc , ADMA_CH_XFER_STATUS -
486+ tdc -> tdma -> cdata -> ch_tc_offset_diff );
425487 unsigned int periods_remaining ;
426488
427489 /*
@@ -627,13 +689,16 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
627689 return - EINVAL ;
628690 }
629691
630- ch_regs -> ctrl |= ADMA_CH_CTRL_DIR (adma_dir ) |
631- ADMA_CH_CTRL_MODE_CONTINUOUS |
692+ ch_regs -> ctrl |= ADMA_CH_CTRL_DIR (adma_dir , cdata -> ch_dir_mask ,
693+ cdata -> ch_dir_shift ) |
694+ ADMA_CH_CTRL_MODE_CONTINUOUS (cdata -> ch_mode_shift ) |
632695 ADMA_CH_CTRL_FLOWCTRL_EN ;
633696 ch_regs -> config |= cdata -> adma_get_burst_config (burst_size );
634- ch_regs -> config |= ADMA_CH_CONFIG_WEIGHT_FOR_WRR (1 );
635- if (cdata -> has_outstanding_reqs )
636- ch_regs -> config |= TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS (8 );
697+
698+ if (cdata -> global_ch_config_base )
699+ ch_regs -> global_config |= cdata -> ch_config ;
700+ else
701+ ch_regs -> config |= cdata -> ch_config ;
637702
638703 /*
639704 * 'sreq_index' represents the current ADMAIF channel number and as per
@@ -788,12 +853,23 @@ static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev)
788853 /* skip if channel is not active */
789854 if (!ch_reg -> cmd )
790855 continue ;
791- ch_reg -> tc = tdma_ch_read (tdc , ADMA_CH_TC );
792- ch_reg -> src_addr = tdma_ch_read (tdc , ADMA_CH_LOWER_SRC_ADDR );
793- ch_reg -> trg_addr = tdma_ch_read (tdc , ADMA_CH_LOWER_TRG_ADDR );
856+ ch_reg -> tc = tdma_ch_read (tdc , ADMA_CH_TC - tdma -> cdata -> ch_tc_offset_diff );
857+ ch_reg -> src_addr = tdma_ch_read (tdc , ADMA_CH_LOWER_SRC_ADDR -
858+ tdma -> cdata -> ch_tc_offset_diff );
859+ ch_reg -> trg_addr = tdma_ch_read (tdc , ADMA_CH_LOWER_TRG_ADDR -
860+ tdma -> cdata -> ch_tc_offset_diff );
794861 ch_reg -> ctrl = tdma_ch_read (tdc , ADMA_CH_CTRL );
795- ch_reg -> fifo_ctrl = tdma_ch_read (tdc , ADMA_CH_FIFO_CTRL );
862+
863+ if (tdc -> global_ch_config_offset )
864+ ch_reg -> global_config = tdma_read (tdc -> tdma , tdc -> global_ch_config_offset );
865+
866+ if (!tdc -> tdma -> cdata -> global_ch_fifo_base )
867+ ch_reg -> fifo_ctrl = tdma_ch_read (tdc , ADMA_CH_FIFO_CTRL );
868+ else if (tdc -> global_ch_fifo_offset )
869+ ch_reg -> fifo_ctrl = tdma_read (tdc -> tdma , tdc -> global_ch_fifo_offset );
870+
796871 ch_reg -> config = tdma_ch_read (tdc , ADMA_CH_CONFIG );
872+
797873 }
798874
799875clk_disable :
@@ -832,12 +908,23 @@ static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
832908 /* skip if channel was not active earlier */
833909 if (!ch_reg -> cmd )
834910 continue ;
835- tdma_ch_write (tdc , ADMA_CH_TC , ch_reg -> tc );
836- tdma_ch_write (tdc , ADMA_CH_LOWER_SRC_ADDR , ch_reg -> src_addr );
837- tdma_ch_write (tdc , ADMA_CH_LOWER_TRG_ADDR , ch_reg -> trg_addr );
911+ tdma_ch_write (tdc , ADMA_CH_TC - tdma -> cdata -> ch_tc_offset_diff , ch_reg -> tc );
912+ tdma_ch_write (tdc , ADMA_CH_LOWER_SRC_ADDR - tdma -> cdata -> ch_tc_offset_diff ,
913+ ch_reg -> src_addr );
914+ tdma_ch_write (tdc , ADMA_CH_LOWER_TRG_ADDR - tdma -> cdata -> ch_tc_offset_diff ,
915+ ch_reg -> trg_addr );
838916 tdma_ch_write (tdc , ADMA_CH_CTRL , ch_reg -> ctrl );
839- tdma_ch_write (tdc , ADMA_CH_FIFO_CTRL , ch_reg -> fifo_ctrl );
917+
918+ if (!tdc -> tdma -> cdata -> global_ch_fifo_base )
919+ tdma_ch_write (tdc , ADMA_CH_FIFO_CTRL , ch_reg -> fifo_ctrl );
920+ else if (tdc -> global_ch_fifo_offset )
921+ tdma_write (tdc -> tdma , tdc -> global_ch_fifo_offset , ch_reg -> fifo_ctrl );
922+
923+ if (tdc -> global_ch_config_offset )
924+ tdma_write (tdc -> tdma , tdc -> global_ch_config_offset , ch_reg -> global_config );
925+
840926 tdma_ch_write (tdc , ADMA_CH_CONFIG , ch_reg -> config );
927+
841928 tdma_ch_write (tdc , ADMA_CH_CMD , ch_reg -> cmd );
842929 }
843930
@@ -848,41 +935,80 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
848935 .adma_get_burst_config = tegra210_adma_get_burst_config ,
849936 .global_reg_offset = 0xc00 ,
850937 .global_int_clear = 0x20 ,
938+ .global_ch_fifo_base = 0 ,
939+ .global_ch_config_base = 0 ,
851940 .ch_req_tx_shift = 28 ,
852941 .ch_req_rx_shift = 24 ,
942+ .ch_dir_shift = 12 ,
943+ .ch_mode_shift = 8 ,
853944 .ch_base_offset = 0 ,
945+ .ch_tc_offset_diff = 0 ,
946+ .ch_config = ADMA_CH_CONFIG_WEIGHT_FOR_WRR (1 ),
854947 .ch_req_mask = 0xf ,
948+ .ch_dir_mask = 0xf ,
855949 .ch_req_max = 10 ,
856950 .ch_reg_size = 0x80 ,
857951 .nr_channels = 22 ,
858952 .ch_fifo_size_mask = 0xf ,
859953 .sreq_index_offset = 2 ,
860954 .max_page = 0 ,
861- .has_outstanding_reqs = false,
862955 .set_global_pg_config = NULL ,
863956};
864957
865958static const struct tegra_adma_chip_data tegra186_chip_data = {
866959 .adma_get_burst_config = tegra186_adma_get_burst_config ,
867960 .global_reg_offset = 0 ,
868961 .global_int_clear = 0x402c ,
962+ .global_ch_fifo_base = 0 ,
963+ .global_ch_config_base = 0 ,
869964 .ch_req_tx_shift = 27 ,
870965 .ch_req_rx_shift = 22 ,
966+ .ch_dir_shift = 12 ,
967+ .ch_mode_shift = 8 ,
871968 .ch_base_offset = 0x10000 ,
969+ .ch_tc_offset_diff = 0 ,
970+ .ch_config = ADMA_CH_CONFIG_WEIGHT_FOR_WRR (1 ) |
971+ TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS (8 ),
872972 .ch_req_mask = 0x1f ,
973+ .ch_dir_mask = 0xf ,
873974 .ch_req_max = 20 ,
874975 .ch_reg_size = 0x100 ,
875976 .nr_channels = 32 ,
876977 .ch_fifo_size_mask = 0x1f ,
877978 .sreq_index_offset = 4 ,
878979 .max_page = 4 ,
879- .has_outstanding_reqs = true,
880980 .set_global_pg_config = tegra186_adma_global_page_config ,
881981};
882982
983+ static const struct tegra_adma_chip_data tegra264_chip_data = {
984+ .adma_get_burst_config = tegra186_adma_get_burst_config ,
985+ .global_reg_offset = 0 ,
986+ .global_int_clear = 0x800c ,
987+ .global_ch_fifo_base = ADMA_GLOBAL_CH_FIFO_CTRL ,
988+ .global_ch_config_base = ADMA_GLOBAL_CH_CONFIG ,
989+ .ch_req_tx_shift = 26 ,
990+ .ch_req_rx_shift = 20 ,
991+ .ch_dir_shift = 10 ,
992+ .ch_mode_shift = 7 ,
993+ .ch_base_offset = 0x10000 ,
994+ .ch_tc_offset_diff = 4 ,
995+ .ch_config = ADMA_GLOBAL_CH_CONFIG_WEIGHT_FOR_WRR (1 ) |
996+ ADMA_GLOBAL_CH_CONFIG_OUTSTANDING_REQS (8 ),
997+ .ch_req_mask = 0x3f ,
998+ .ch_dir_mask = 7 ,
999+ .ch_req_max = 32 ,
1000+ .ch_reg_size = 0x100 ,
1001+ .nr_channels = 64 ,
1002+ .ch_fifo_size_mask = 0x7f ,
1003+ .sreq_index_offset = 0 ,
1004+ .max_page = 10 ,
1005+ .set_global_pg_config = tegra264_adma_global_page_config ,
1006+ };
1007+
8831008static const struct of_device_id tegra_adma_of_match [] = {
8841009 { .compatible = "nvidia,tegra210-adma" , .data = & tegra210_chip_data },
8851010 { .compatible = "nvidia,tegra186-adma" , .data = & tegra186_chip_data },
1011+ { .compatible = "nvidia,tegra264-adma" , .data = & tegra264_chip_data },
8861012 { },
8871013};
8881014MODULE_DEVICE_TABLE (of , tegra_adma_of_match );
@@ -981,6 +1107,15 @@ static int tegra_adma_probe(struct platform_device *pdev)
9811107
9821108 tdc -> chan_addr = tdma -> ch_base_addr + (cdata -> ch_reg_size * i );
9831109
1110+ if (tdma -> base_addr ) {
1111+ if (cdata -> global_ch_fifo_base )
1112+ tdc -> global_ch_fifo_offset = cdata -> global_ch_fifo_base + (4 * i );
1113+
1114+ if (cdata -> global_ch_config_base )
1115+ tdc -> global_ch_config_offset =
1116+ cdata -> global_ch_config_base + (4 * i );
1117+ }
1118+
9841119 tdc -> irq = of_irq_get (pdev -> dev .of_node , i );
9851120 if (tdc -> irq <= 0 ) {
9861121 ret = tdc -> irq ?: - ENXIO ;
0 commit comments