43
43
#define ADMA_CH_CONFIG_MAX_BUFS 8
44
44
#define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS (reqs ) (reqs << 4)
45
45
46
+ #define TEGRA186_ADMA_GLOBAL_PAGE_CHGRP 0x30
47
+ #define TEGRA186_ADMA_GLOBAL_PAGE_RX_REQ 0x70
48
+ #define TEGRA186_ADMA_GLOBAL_PAGE_TX_REQ 0x84
49
+
46
50
#define ADMA_CH_FIFO_CTRL 0x2c
47
51
#define ADMA_CH_TX_FIFO_SIZE_SHIFT 8
48
52
#define ADMA_CH_RX_FIFO_SIZE_SHIFT 0
@@ -96,6 +100,7 @@ struct tegra_adma_chip_data {
96
100
unsigned int ch_fifo_size_mask ;
97
101
unsigned int sreq_index_offset ;
98
102
bool has_outstanding_reqs ;
103
+ void (* set_global_pg_config )(struct tegra_adma * tdma );
99
104
};
100
105
101
106
/*
@@ -151,6 +156,7 @@ struct tegra_adma {
151
156
struct dma_device dma_dev ;
152
157
struct device * dev ;
153
158
void __iomem * base_addr ;
159
+ void __iomem * ch_base_addr ;
154
160
struct clk * ahub_clk ;
155
161
unsigned int nr_channels ;
156
162
unsigned long * dma_chan_mask ;
@@ -159,6 +165,7 @@ struct tegra_adma {
159
165
160
166
/* Used to store global command register state when suspending */
161
167
unsigned int global_cmd ;
168
+ unsigned int ch_page_no ;
162
169
163
170
const struct tegra_adma_chip_data * cdata ;
164
171
@@ -176,6 +183,11 @@ static inline u32 tdma_read(struct tegra_adma *tdma, u32 reg)
176
183
return readl (tdma -> base_addr + tdma -> cdata -> global_reg_offset + reg );
177
184
}
178
185
186
+ static inline void tdma_ch_global_write (struct tegra_adma * tdma , u32 reg , u32 val )
187
+ {
188
+ writel (val , tdma -> ch_base_addr + tdma -> cdata -> global_reg_offset + reg );
189
+ }
190
+
179
191
static inline void tdma_ch_write (struct tegra_adma_chan * tdc , u32 reg , u32 val )
180
192
{
181
193
writel (val , tdc -> chan_addr + reg );
@@ -217,13 +229,30 @@ static int tegra_adma_slave_config(struct dma_chan *dc,
217
229
return 0 ;
218
230
}
219
231
232
+ static void tegra186_adma_global_page_config (struct tegra_adma * tdma )
233
+ {
234
+ /*
235
+ * Clear the default page1 channel group configs and program
236
+ * the global registers based on the actual page usage
237
+ */
238
+ tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_CHGRP , 0 );
239
+ tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_RX_REQ , 0 );
240
+ tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_TX_REQ , 0 );
241
+ tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_CHGRP + (tdma -> ch_page_no * 0x4 ), 0xff );
242
+ tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_RX_REQ + (tdma -> ch_page_no * 0x4 ), 0x1ffffff );
243
+ tdma_write (tdma , TEGRA186_ADMA_GLOBAL_PAGE_TX_REQ + (tdma -> ch_page_no * 0x4 ), 0xffffff );
244
+ }
245
+
220
246
static int tegra_adma_init (struct tegra_adma * tdma )
221
247
{
222
248
u32 status ;
223
249
int ret ;
224
250
225
- /* Clear any interrupts */
226
- tdma_write (tdma , tdma -> cdata -> ch_base_offset + tdma -> cdata -> global_int_clear , 0x1 );
251
+ /* Clear any channels group global interrupts */
252
+ tdma_ch_global_write (tdma , tdma -> cdata -> global_int_clear , 0x1 );
253
+
254
+ if (!tdma -> base_addr )
255
+ return 0 ;
227
256
228
257
/* Assert soft reset */
229
258
tdma_write (tdma , ADMA_GLOBAL_SOFT_RESET , 0x1 );
@@ -237,6 +266,9 @@ static int tegra_adma_init(struct tegra_adma *tdma)
237
266
if (ret )
238
267
return ret ;
239
268
269
+ if (tdma -> cdata -> set_global_pg_config )
270
+ tdma -> cdata -> set_global_pg_config (tdma );
271
+
240
272
/* Enable global ADMA registers */
241
273
tdma_write (tdma , ADMA_GLOBAL_CMD , 1 );
242
274
@@ -736,7 +768,9 @@ static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev)
736
768
struct tegra_adma_chan * tdc ;
737
769
int i ;
738
770
739
- tdma -> global_cmd = tdma_read (tdma , ADMA_GLOBAL_CMD );
771
+ if (tdma -> base_addr )
772
+ tdma -> global_cmd = tdma_read (tdma , ADMA_GLOBAL_CMD );
773
+
740
774
if (!tdma -> global_cmd )
741
775
goto clk_disable ;
742
776
@@ -777,7 +811,11 @@ static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
777
811
dev_err (dev , "ahub clk_enable failed: %d\n" , ret );
778
812
return ret ;
779
813
}
780
- tdma_write (tdma , ADMA_GLOBAL_CMD , tdma -> global_cmd );
814
+ if (tdma -> base_addr ) {
815
+ tdma_write (tdma , ADMA_GLOBAL_CMD , tdma -> global_cmd );
816
+ if (tdma -> cdata -> set_global_pg_config )
817
+ tdma -> cdata -> set_global_pg_config (tdma );
818
+ }
781
819
782
820
if (!tdma -> global_cmd )
783
821
return 0 ;
@@ -817,6 +855,7 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
817
855
.ch_fifo_size_mask = 0xf ,
818
856
.sreq_index_offset = 2 ,
819
857
.has_outstanding_reqs = false,
858
+ .set_global_pg_config = NULL ,
820
859
};
821
860
822
861
static const struct tegra_adma_chip_data tegra186_chip_data = {
@@ -833,6 +872,7 @@ static const struct tegra_adma_chip_data tegra186_chip_data = {
833
872
.ch_fifo_size_mask = 0x1f ,
834
873
.sreq_index_offset = 4 ,
835
874
.has_outstanding_reqs = true,
875
+ .set_global_pg_config = tegra186_adma_global_page_config ,
836
876
};
837
877
838
878
static const struct of_device_id tegra_adma_of_match [] = {
@@ -846,7 +886,8 @@ static int tegra_adma_probe(struct platform_device *pdev)
846
886
{
847
887
const struct tegra_adma_chip_data * cdata ;
848
888
struct tegra_adma * tdma ;
849
- int ret , i ;
889
+ struct resource * res_page , * res_base ;
890
+ int ret , i , page_no ;
850
891
851
892
cdata = of_device_get_match_data (& pdev -> dev );
852
893
if (!cdata ) {
@@ -865,9 +906,35 @@ static int tegra_adma_probe(struct platform_device *pdev)
865
906
tdma -> nr_channels = cdata -> nr_channels ;
866
907
platform_set_drvdata (pdev , tdma );
867
908
868
- tdma -> base_addr = devm_platform_ioremap_resource (pdev , 0 );
869
- if (IS_ERR (tdma -> base_addr ))
870
- return PTR_ERR (tdma -> base_addr );
909
+ res_page = platform_get_resource_byname (pdev , IORESOURCE_MEM , "page" );
910
+ if (res_page ) {
911
+ tdma -> ch_base_addr = devm_ioremap_resource (& pdev -> dev , res_page );
912
+ if (IS_ERR (tdma -> ch_base_addr ))
913
+ return PTR_ERR (tdma -> ch_base_addr );
914
+
915
+ res_base = platform_get_resource_byname (pdev , IORESOURCE_MEM , "global" );
916
+ if (res_base ) {
917
+ page_no = (res_page -> start - res_base -> start ) / cdata -> ch_base_offset ;
918
+ if (page_no <= 0 )
919
+ return - EINVAL ;
920
+ tdma -> ch_page_no = page_no - 1 ;
921
+ tdma -> base_addr = devm_ioremap_resource (& pdev -> dev , res_base );
922
+ if (IS_ERR (tdma -> base_addr ))
923
+ return PTR_ERR (tdma -> base_addr );
924
+ }
925
+ } else {
926
+ /* If no 'page' property found, then reg DT binding would be legacy */
927
+ res_base = platform_get_resource (pdev , IORESOURCE_MEM , 0 );
928
+ if (res_base ) {
929
+ tdma -> base_addr = devm_ioremap_resource (& pdev -> dev , res_base );
930
+ if (IS_ERR (tdma -> base_addr ))
931
+ return PTR_ERR (tdma -> base_addr );
932
+ } else {
933
+ return - ENODEV ;
934
+ }
935
+
936
+ tdma -> ch_base_addr = tdma -> base_addr + cdata -> ch_base_offset ;
937
+ }
871
938
872
939
tdma -> ahub_clk = devm_clk_get (& pdev -> dev , "d_audio" );
873
940
if (IS_ERR (tdma -> ahub_clk )) {
@@ -900,8 +967,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
900
967
if (!test_bit (i , tdma -> dma_chan_mask ))
901
968
continue ;
902
969
903
- tdc -> chan_addr = tdma -> base_addr + cdata -> ch_base_offset
904
- + (cdata -> ch_reg_size * i );
970
+ tdc -> chan_addr = tdma -> ch_base_addr + (cdata -> ch_reg_size * i );
905
971
906
972
tdc -> irq = of_irq_get (pdev -> dev .of_node , i );
907
973
if (tdc -> irq <= 0 ) {
0 commit comments