44 */
55
66#include <linux/genalloc.h>
7+ #include <linux/io.h>
78#include <linux/mailbox_client.h>
9+ #include <linux/of_address.h>
810#include <linux/platform_device.h>
911
1012#include <soc/tegra/bpmp.h>
@@ -18,7 +20,10 @@ struct tegra186_bpmp {
1820
1921 struct {
2022 struct gen_pool * pool ;
21- void __iomem * virt ;
23+ union {
24+ void __iomem * sram ;
25+ void * dram ;
26+ };
2227 dma_addr_t phys ;
2328 } tx , rx ;
2429
@@ -118,8 +123,13 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
118123 queue_size = tegra_ivc_total_queue_size (message_size );
119124 offset = queue_size * index ;
120125
121- iosys_map_set_vaddr_iomem (& rx , priv -> rx .virt + offset );
122- iosys_map_set_vaddr_iomem (& tx , priv -> tx .virt + offset );
126+ if (priv -> rx .pool ) {
127+ iosys_map_set_vaddr_iomem (& rx , priv -> rx .sram + offset );
128+ iosys_map_set_vaddr_iomem (& tx , priv -> tx .sram + offset );
129+ } else {
130+ iosys_map_set_vaddr (& rx , priv -> rx .dram + offset );
131+ iosys_map_set_vaddr (& tx , priv -> tx .dram + offset );
132+ }
123133
124134 err = tegra_ivc_init (channel -> ivc , NULL , & rx , priv -> rx .phys + offset , & tx ,
125135 priv -> tx .phys + offset , 1 , message_size , tegra186_bpmp_ivc_notify ,
@@ -158,27 +168,82 @@ static void mbox_handle_rx(struct mbox_client *client, void *data)
158168 tegra_bpmp_handle_rx (bpmp );
159169}
160170
161- static int tegra186_bpmp_init (struct tegra_bpmp * bpmp )
171+ static void tegra186_bpmp_teardown_channels (struct tegra_bpmp * bpmp )
162172{
163- struct tegra186_bpmp * priv ;
173+ struct tegra186_bpmp * priv = bpmp -> priv ;
164174 unsigned int i ;
175+
176+ for (i = 0 ; i < bpmp -> threaded .count ; i ++ ) {
177+ if (!bpmp -> threaded_channels [i ].bpmp )
178+ continue ;
179+
180+ tegra186_bpmp_channel_cleanup (& bpmp -> threaded_channels [i ]);
181+ }
182+
183+ tegra186_bpmp_channel_cleanup (bpmp -> rx_channel );
184+ tegra186_bpmp_channel_cleanup (bpmp -> tx_channel );
185+
186+ if (priv -> tx .pool ) {
187+ gen_pool_free (priv -> tx .pool , (unsigned long )priv -> tx .sram , 4096 );
188+ gen_pool_free (priv -> rx .pool , (unsigned long )priv -> rx .sram , 4096 );
189+ }
190+ }
191+
192+ static int tegra186_bpmp_dram_init (struct tegra_bpmp * bpmp )
193+ {
194+ struct tegra186_bpmp * priv = bpmp -> priv ;
195+ struct device_node * np ;
196+ struct resource res ;
197+ size_t size ;
165198 int err ;
166199
167- priv = devm_kzalloc (bpmp -> dev , sizeof ( * priv ), GFP_KERNEL );
168- if (!priv )
169- return - ENOMEM ;
200+ np = of_parse_phandle (bpmp -> dev -> of_node , "memory-region" , 0 );
201+ if (!np )
202+ return - ENODEV ;
170203
171- bpmp -> priv = priv ;
172- priv -> parent = bpmp ;
204+ err = of_address_to_resource (np , 0 , & res );
205+ if (err < 0 ) {
206+ dev_warn (bpmp -> dev , "failed to parse memory region: %d\n" , err );
207+ return err ;
208+ }
209+
210+ size = resource_size (& res );
211+
212+ if (size < SZ_8K ) {
213+ dev_warn (bpmp -> dev , "DRAM region must be larger than 8 KiB\n" );
214+ return - EINVAL ;
215+ }
216+
217+ priv -> tx .phys = res .start ;
218+ priv -> rx .phys = res .start + SZ_4K ;
219+
220+ priv -> tx .dram = devm_memremap (bpmp -> dev , priv -> tx .phys , size ,
221+ MEMREMAP_WC );
222+ if (IS_ERR (priv -> tx .dram )) {
223+ err = PTR_ERR (priv -> tx .dram );
224+ dev_warn (bpmp -> dev , "failed to map DRAM region: %d\n" , err );
225+ return err ;
226+ }
227+
228+ priv -> rx .dram = priv -> tx .dram + SZ_4K ;
229+
230+ return 0 ;
231+ }
232+
233+ static int tegra186_bpmp_sram_init (struct tegra_bpmp * bpmp )
234+ {
235+ struct tegra186_bpmp * priv = bpmp -> priv ;
236+ int err ;
173237
174238 priv -> tx .pool = of_gen_pool_get (bpmp -> dev -> of_node , "shmem" , 0 );
175239 if (!priv -> tx .pool ) {
176240 dev_err (bpmp -> dev , "TX shmem pool not found\n" );
177241 return - EPROBE_DEFER ;
178242 }
179243
180- priv -> tx .virt = (void __iomem * )gen_pool_dma_alloc (priv -> tx .pool , 4096 , & priv -> tx .phys );
181- if (!priv -> tx .virt ) {
244+ priv -> tx .sram = (void __iomem * )gen_pool_dma_alloc (priv -> tx .pool , 4096 ,
245+ & priv -> tx .phys );
246+ if (!priv -> tx .sram ) {
182247 dev_err (bpmp -> dev , "failed to allocate from TX pool\n" );
183248 return - ENOMEM ;
184249 }
@@ -190,32 +255,89 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
190255 goto free_tx ;
191256 }
192257
193- priv -> rx .virt = (void __iomem * )gen_pool_dma_alloc (priv -> rx .pool , 4096 , & priv -> rx .phys );
194- if (!priv -> rx .virt ) {
258+ priv -> rx .sram = (void __iomem * )gen_pool_dma_alloc (priv -> rx .pool , 4096 ,
259+ & priv -> rx .phys );
260+ if (!priv -> rx .sram ) {
195261 dev_err (bpmp -> dev , "failed to allocate from RX pool\n" );
196262 err = - ENOMEM ;
197263 goto free_tx ;
198264 }
199265
266+ return 0 ;
267+
268+ free_tx :
269+ gen_pool_free (priv -> tx .pool , (unsigned long )priv -> tx .sram , 4096 );
270+
271+ return err ;
272+ }
273+
274+ static int tegra186_bpmp_setup_channels (struct tegra_bpmp * bpmp )
275+ {
276+ unsigned int i ;
277+ int err ;
278+
279+ err = tegra186_bpmp_dram_init (bpmp );
280+ if (err == - ENODEV ) {
281+ err = tegra186_bpmp_sram_init (bpmp );
282+ if (err < 0 )
283+ return err ;
284+ }
285+
200286 err = tegra186_bpmp_channel_init (bpmp -> tx_channel , bpmp ,
201287 bpmp -> soc -> channels .cpu_tx .offset );
202288 if (err < 0 )
203- goto free_rx ;
289+ return err ;
204290
205291 err = tegra186_bpmp_channel_init (bpmp -> rx_channel , bpmp ,
206292 bpmp -> soc -> channels .cpu_rx .offset );
207- if (err < 0 )
208- goto cleanup_tx_channel ;
293+ if (err < 0 ) {
294+ tegra186_bpmp_channel_cleanup (bpmp -> tx_channel );
295+ return err ;
296+ }
209297
210298 for (i = 0 ; i < bpmp -> threaded .count ; i ++ ) {
211299 unsigned int index = bpmp -> soc -> channels .thread .offset + i ;
212300
213301 err = tegra186_bpmp_channel_init (& bpmp -> threaded_channels [i ],
214302 bpmp , index );
215303 if (err < 0 )
216- goto cleanup_channels ;
304+ break ;
217305 }
218306
307+ if (err < 0 )
308+ tegra186_bpmp_teardown_channels (bpmp );
309+
310+ return err ;
311+ }
312+
313+ static void tegra186_bpmp_reset_channels (struct tegra_bpmp * bpmp )
314+ {
315+ unsigned int i ;
316+
317+ /* reset message channels */
318+ tegra186_bpmp_channel_reset (bpmp -> tx_channel );
319+ tegra186_bpmp_channel_reset (bpmp -> rx_channel );
320+
321+ for (i = 0 ; i < bpmp -> threaded .count ; i ++ )
322+ tegra186_bpmp_channel_reset (& bpmp -> threaded_channels [i ]);
323+ }
324+
325+ static int tegra186_bpmp_init (struct tegra_bpmp * bpmp )
326+ {
327+ struct tegra186_bpmp * priv ;
328+ int err ;
329+
330+ priv = devm_kzalloc (bpmp -> dev , sizeof (* priv ), GFP_KERNEL );
331+ if (!priv )
332+ return - ENOMEM ;
333+
334+ priv -> parent = bpmp ;
335+ bpmp -> priv = priv ;
336+
337+ err = tegra186_bpmp_setup_channels (bpmp );
338+ if (err < 0 )
339+ return err ;
340+
219341 /* mbox registration */
220342 priv -> mbox .client .dev = bpmp -> dev ;
221343 priv -> mbox .client .rx_callback = mbox_handle_rx ;
@@ -226,63 +348,27 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
226348 if (IS_ERR (priv -> mbox .channel )) {
227349 err = PTR_ERR (priv -> mbox .channel );
228350 dev_err (bpmp -> dev , "failed to get HSP mailbox: %d\n" , err );
229- goto cleanup_channels ;
351+ tegra186_bpmp_teardown_channels (bpmp );
352+ return err ;
230353 }
231354
232- tegra186_bpmp_channel_reset (bpmp -> tx_channel );
233- tegra186_bpmp_channel_reset (bpmp -> rx_channel );
234-
235- for (i = 0 ; i < bpmp -> threaded .count ; i ++ )
236- tegra186_bpmp_channel_reset (& bpmp -> threaded_channels [i ]);
355+ tegra186_bpmp_reset_channels (bpmp );
237356
238357 return 0 ;
239-
240- cleanup_channels :
241- for (i = 0 ; i < bpmp -> threaded .count ; i ++ ) {
242- if (!bpmp -> threaded_channels [i ].bpmp )
243- continue ;
244-
245- tegra186_bpmp_channel_cleanup (& bpmp -> threaded_channels [i ]);
246- }
247-
248- tegra186_bpmp_channel_cleanup (bpmp -> rx_channel );
249- cleanup_tx_channel :
250- tegra186_bpmp_channel_cleanup (bpmp -> tx_channel );
251- free_rx :
252- gen_pool_free (priv -> rx .pool , (unsigned long )priv -> rx .virt , 4096 );
253- free_tx :
254- gen_pool_free (priv -> tx .pool , (unsigned long )priv -> tx .virt , 4096 );
255-
256- return err ;
257358}
258359
259360static void tegra186_bpmp_deinit (struct tegra_bpmp * bpmp )
260361{
261362 struct tegra186_bpmp * priv = bpmp -> priv ;
262- unsigned int i ;
263363
264364 mbox_free_channel (priv -> mbox .channel );
265365
266- for (i = 0 ; i < bpmp -> threaded .count ; i ++ )
267- tegra186_bpmp_channel_cleanup (& bpmp -> threaded_channels [i ]);
268-
269- tegra186_bpmp_channel_cleanup (bpmp -> rx_channel );
270- tegra186_bpmp_channel_cleanup (bpmp -> tx_channel );
271-
272- gen_pool_free (priv -> rx .pool , (unsigned long )priv -> rx .virt , 4096 );
273- gen_pool_free (priv -> tx .pool , (unsigned long )priv -> tx .virt , 4096 );
366+ tegra186_bpmp_teardown_channels (bpmp );
274367}
275368
276369static int tegra186_bpmp_resume (struct tegra_bpmp * bpmp )
277370{
278- unsigned int i ;
279-
280- /* reset message channels */
281- tegra186_bpmp_channel_reset (bpmp -> tx_channel );
282- tegra186_bpmp_channel_reset (bpmp -> rx_channel );
283-
284- for (i = 0 ; i < bpmp -> threaded .count ; i ++ )
285- tegra186_bpmp_channel_reset (& bpmp -> threaded_channels [i ]);
371+ tegra186_bpmp_reset_channels (bpmp );
286372
287373 return 0 ;
288374}
0 commit comments