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
@@ -73,36 +85,48 @@ struct tegra_adma;
73
85
* @adma_get_burst_config: Function callback used to set DMA burst size.
74
86
* @global_reg_offset: Register offset of DMA global register.
75
87
* @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
76
90
* @ch_req_tx_shift: Register offset for AHUB transmit channel select.
77
91
* @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.
78
94
* @ch_base_offset: Register offset of DMA channel registers.
95
+ * @ch_tc_offset_diff: From TC register onwards offset differs for Tegra264
79
96
* @ch_fifo_ctrl: Default value for channel FIFO CTRL register.
97
+ * @ch_config: Outstanding and WRR config values
80
98
* @ch_req_mask: Mask for Tx or Rx channel select.
99
+ * @ch_dir_mask: Mask for channel direction.
81
100
* @ch_req_max: Maximum number of Tx or Rx channels available.
82
101
* @ch_reg_size: Size of DMA channel register space.
83
102
* @nr_channels: Number of DMA channels available.
84
103
* @ch_fifo_size_mask: Mask for FIFO size field.
85
104
* @sreq_index_offset: Slave channel index offset.
86
105
* @max_page: Maximum ADMA Channel Page.
87
- * @has_outstanding_reqs: If DMA channel can have outstanding requests.
88
106
* @set_global_pg_config: Global page programming.
89
107
*/
90
108
struct tegra_adma_chip_data {
91
109
unsigned int (* adma_get_burst_config )(unsigned int burst_size );
92
110
unsigned int global_reg_offset ;
93
111
unsigned int global_int_clear ;
112
+ unsigned int global_ch_fifo_base ;
113
+ unsigned int global_ch_config_base ;
94
114
unsigned int ch_req_tx_shift ;
95
115
unsigned int ch_req_rx_shift ;
116
+ unsigned int ch_dir_shift ;
117
+ unsigned int ch_mode_shift ;
96
118
unsigned int ch_base_offset ;
119
+ unsigned int ch_tc_offset_diff ;
97
120
unsigned int ch_fifo_ctrl ;
121
+ unsigned int ch_config ;
98
122
unsigned int ch_req_mask ;
123
+ unsigned int ch_dir_mask ;
99
124
unsigned int ch_req_max ;
100
125
unsigned int ch_reg_size ;
101
126
unsigned int nr_channels ;
102
127
unsigned int ch_fifo_size_mask ;
103
128
unsigned int sreq_index_offset ;
104
129
unsigned int max_page ;
105
- bool has_outstanding_reqs ;
106
130
void (* set_global_pg_config )(struct tegra_adma * tdma );
107
131
};
108
132
@@ -112,6 +136,7 @@ struct tegra_adma_chip_data {
112
136
struct tegra_adma_chan_regs {
113
137
unsigned int ctrl ;
114
138
unsigned int config ;
139
+ unsigned int global_config ;
115
140
unsigned int src_addr ;
116
141
unsigned int trg_addr ;
117
142
unsigned int fifo_ctrl ;
@@ -150,6 +175,9 @@ struct tegra_adma_chan {
150
175
/* Transfer count and position info */
151
176
unsigned int tx_buf_count ;
152
177
unsigned int tx_buf_pos ;
178
+
179
+ unsigned int global_ch_fifo_offset ;
180
+ unsigned int global_ch_config_offset ;
153
181
};
154
182
155
183
/*
@@ -246,6 +274,29 @@ static void tegra186_adma_global_page_config(struct tegra_adma *tdma)
246
274
tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_TX_REQ + (tdma -> ch_page_no * 0x4 ), 0xffffff );
247
275
}
248
276
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
+
249
300
static int tegra_adma_init (struct tegra_adma * tdma )
250
301
{
251
302
u32 status ;
@@ -404,11 +455,21 @@ static void tegra_adma_start(struct tegra_adma_chan *tdc)
404
455
405
456
tdc -> tx_buf_pos = 0 ;
406
457
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 );
408
459
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
+
412
473
tdma_ch_write (tdc , ADMA_CH_CONFIG , ch_regs -> config );
413
474
414
475
/* Start ADMA */
@@ -421,7 +482,8 @@ static unsigned int tegra_adma_get_residue(struct tegra_adma_chan *tdc)
421
482
{
422
483
struct tegra_adma_desc * desc = tdc -> desc ;
423
484
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 );
425
487
unsigned int periods_remaining ;
426
488
427
489
/*
@@ -627,13 +689,16 @@ static int tegra_adma_set_xfer_params(struct tegra_adma_chan *tdc,
627
689
return - EINVAL ;
628
690
}
629
691
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 ) |
632
695
ADMA_CH_CTRL_FLOWCTRL_EN ;
633
696
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 ;
637
702
638
703
/*
639
704
* '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)
788
853
/* skip if channel is not active */
789
854
if (!ch_reg -> cmd )
790
855
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 );
794
861
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
+
796
871
ch_reg -> config = tdma_ch_read (tdc , ADMA_CH_CONFIG );
872
+
797
873
}
798
874
799
875
clk_disable :
@@ -832,12 +908,23 @@ static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
832
908
/* skip if channel was not active earlier */
833
909
if (!ch_reg -> cmd )
834
910
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 );
838
916
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
+
840
926
tdma_ch_write (tdc , ADMA_CH_CONFIG , ch_reg -> config );
927
+
841
928
tdma_ch_write (tdc , ADMA_CH_CMD , ch_reg -> cmd );
842
929
}
843
930
@@ -848,41 +935,80 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
848
935
.adma_get_burst_config = tegra210_adma_get_burst_config ,
849
936
.global_reg_offset = 0xc00 ,
850
937
.global_int_clear = 0x20 ,
938
+ .global_ch_fifo_base = 0 ,
939
+ .global_ch_config_base = 0 ,
851
940
.ch_req_tx_shift = 28 ,
852
941
.ch_req_rx_shift = 24 ,
942
+ .ch_dir_shift = 12 ,
943
+ .ch_mode_shift = 8 ,
853
944
.ch_base_offset = 0 ,
945
+ .ch_tc_offset_diff = 0 ,
946
+ .ch_config = ADMA_CH_CONFIG_WEIGHT_FOR_WRR (1 ),
854
947
.ch_req_mask = 0xf ,
948
+ .ch_dir_mask = 0xf ,
855
949
.ch_req_max = 10 ,
856
950
.ch_reg_size = 0x80 ,
857
951
.nr_channels = 22 ,
858
952
.ch_fifo_size_mask = 0xf ,
859
953
.sreq_index_offset = 2 ,
860
954
.max_page = 0 ,
861
- .has_outstanding_reqs = false,
862
955
.set_global_pg_config = NULL ,
863
956
};
864
957
865
958
static const struct tegra_adma_chip_data tegra186_chip_data = {
866
959
.adma_get_burst_config = tegra186_adma_get_burst_config ,
867
960
.global_reg_offset = 0 ,
868
961
.global_int_clear = 0x402c ,
962
+ .global_ch_fifo_base = 0 ,
963
+ .global_ch_config_base = 0 ,
869
964
.ch_req_tx_shift = 27 ,
870
965
.ch_req_rx_shift = 22 ,
966
+ .ch_dir_shift = 12 ,
967
+ .ch_mode_shift = 8 ,
871
968
.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 ),
872
972
.ch_req_mask = 0x1f ,
973
+ .ch_dir_mask = 0xf ,
873
974
.ch_req_max = 20 ,
874
975
.ch_reg_size = 0x100 ,
875
976
.nr_channels = 32 ,
876
977
.ch_fifo_size_mask = 0x1f ,
877
978
.sreq_index_offset = 4 ,
878
979
.max_page = 4 ,
879
- .has_outstanding_reqs = true,
880
980
.set_global_pg_config = tegra186_adma_global_page_config ,
881
981
};
882
982
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
+
883
1008
static const struct of_device_id tegra_adma_of_match [] = {
884
1009
{ .compatible = "nvidia,tegra210-adma" , .data = & tegra210_chip_data },
885
1010
{ .compatible = "nvidia,tegra186-adma" , .data = & tegra186_chip_data },
1011
+ { .compatible = "nvidia,tegra264-adma" , .data = & tegra264_chip_data },
886
1012
{ },
887
1013
};
888
1014
MODULE_DEVICE_TABLE (of , tegra_adma_of_match );
@@ -985,6 +1111,15 @@ static int tegra_adma_probe(struct platform_device *pdev)
985
1111
986
1112
tdc -> chan_addr = tdma -> ch_base_addr + (cdata -> ch_reg_size * i );
987
1113
1114
+ if (tdma -> base_addr ) {
1115
+ if (cdata -> global_ch_fifo_base )
1116
+ tdc -> global_ch_fifo_offset = cdata -> global_ch_fifo_base + (4 * i );
1117
+
1118
+ if (cdata -> global_ch_config_base )
1119
+ tdc -> global_ch_config_offset =
1120
+ cdata -> global_ch_config_base + (4 * i );
1121
+ }
1122
+
988
1123
tdc -> irq = of_irq_get (pdev -> dev .of_node , i );
989
1124
if (tdc -> irq <= 0 ) {
990
1125
ret = tdc -> irq ?: - ENXIO ;
0 commit comments