4343#define ADMA_CH_CONFIG_MAX_BUFS 8
4444#define TEGRA186_ADMA_CH_CONFIG_OUTSTANDING_REQS (reqs ) (reqs << 4)
4545
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+
4650#define ADMA_CH_FIFO_CTRL 0x2c
4751#define ADMA_CH_TX_FIFO_SIZE_SHIFT 8
4852#define ADMA_CH_RX_FIFO_SIZE_SHIFT 0
@@ -96,6 +100,7 @@ struct tegra_adma_chip_data {
96100 unsigned int ch_fifo_size_mask ;
97101 unsigned int sreq_index_offset ;
98102 bool has_outstanding_reqs ;
103+ void (* set_global_pg_config )(struct tegra_adma * tdma );
99104};
100105
101106/*
@@ -151,6 +156,7 @@ struct tegra_adma {
151156 struct dma_device dma_dev ;
152157 struct device * dev ;
153158 void __iomem * base_addr ;
159+ void __iomem * ch_base_addr ;
154160 struct clk * ahub_clk ;
155161 unsigned int nr_channels ;
156162 unsigned long * dma_chan_mask ;
@@ -159,6 +165,7 @@ struct tegra_adma {
159165
160166 /* Used to store global command register state when suspending */
161167 unsigned int global_cmd ;
168+ unsigned int ch_page_no ;
162169
163170 const struct tegra_adma_chip_data * cdata ;
164171
@@ -176,6 +183,11 @@ static inline u32 tdma_read(struct tegra_adma *tdma, u32 reg)
176183 return readl (tdma -> base_addr + tdma -> cdata -> global_reg_offset + reg );
177184}
178185
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+
179191static inline void tdma_ch_write (struct tegra_adma_chan * tdc , u32 reg , u32 val )
180192{
181193 writel (val , tdc -> chan_addr + reg );
@@ -217,13 +229,30 @@ static int tegra_adma_slave_config(struct dma_chan *dc,
217229 return 0 ;
218230}
219231
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+
220246static int tegra_adma_init (struct tegra_adma * tdma )
221247{
222248 u32 status ;
223249 int ret ;
224250
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 ;
227256
228257 /* Assert soft reset */
229258 tdma_write (tdma , ADMA_GLOBAL_SOFT_RESET , 0x1 );
@@ -237,6 +266,9 @@ static int tegra_adma_init(struct tegra_adma *tdma)
237266 if (ret )
238267 return ret ;
239268
269+ if (tdma -> cdata -> set_global_pg_config )
270+ tdma -> cdata -> set_global_pg_config (tdma );
271+
240272 /* Enable global ADMA registers */
241273 tdma_write (tdma , ADMA_GLOBAL_CMD , 1 );
242274
@@ -736,7 +768,9 @@ static int __maybe_unused tegra_adma_runtime_suspend(struct device *dev)
736768 struct tegra_adma_chan * tdc ;
737769 int i ;
738770
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+
740774 if (!tdma -> global_cmd )
741775 goto clk_disable ;
742776
@@ -777,7 +811,11 @@ static int __maybe_unused tegra_adma_runtime_resume(struct device *dev)
777811 dev_err (dev , "ahub clk_enable failed: %d\n" , ret );
778812 return ret ;
779813 }
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+ }
781819
782820 if (!tdma -> global_cmd )
783821 return 0 ;
@@ -817,6 +855,7 @@ static const struct tegra_adma_chip_data tegra210_chip_data = {
817855 .ch_fifo_size_mask = 0xf ,
818856 .sreq_index_offset = 2 ,
819857 .has_outstanding_reqs = false,
858+ .set_global_pg_config = NULL ,
820859};
821860
822861static const struct tegra_adma_chip_data tegra186_chip_data = {
@@ -833,6 +872,7 @@ static const struct tegra_adma_chip_data tegra186_chip_data = {
833872 .ch_fifo_size_mask = 0x1f ,
834873 .sreq_index_offset = 4 ,
835874 .has_outstanding_reqs = true,
875+ .set_global_pg_config = tegra186_adma_global_page_config ,
836876};
837877
838878static const struct of_device_id tegra_adma_of_match [] = {
@@ -846,7 +886,8 @@ static int tegra_adma_probe(struct platform_device *pdev)
846886{
847887 const struct tegra_adma_chip_data * cdata ;
848888 struct tegra_adma * tdma ;
849- int ret , i ;
889+ struct resource * res_page , * res_base ;
890+ int ret , i , page_no ;
850891
851892 cdata = of_device_get_match_data (& pdev -> dev );
852893 if (!cdata ) {
@@ -865,9 +906,35 @@ static int tegra_adma_probe(struct platform_device *pdev)
865906 tdma -> nr_channels = cdata -> nr_channels ;
866907 platform_set_drvdata (pdev , tdma );
867908
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+ }
871938
872939 tdma -> ahub_clk = devm_clk_get (& pdev -> dev , "d_audio" );
873940 if (IS_ERR (tdma -> ahub_clk )) {
@@ -900,8 +967,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
900967 if (!test_bit (i , tdma -> dma_chan_mask ))
901968 continue ;
902969
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 );
905971
906972 tdc -> irq = of_irq_get (pdev -> dev .of_node , i );
907973 if (tdc -> irq <= 0 ) {
0 commit comments