diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c index 8a3c90d8..5cc3d28a 100644 --- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | |||
@@ -269,6 +269,54 @@ static int gk20a_flcn_copy_to_dmem(struct nvgpu_falcon *flcn, | |||
269 | return 0; | 269 | return 0; |
270 | } | 270 | } |
271 | 271 | ||
272 | static int gk20a_flcn_copy_from_imem(struct nvgpu_falcon *flcn, u32 src, | ||
273 | u8 *dst, u32 size, u8 port) | ||
274 | { | ||
275 | struct gk20a *g = flcn->g; | ||
276 | u32 base_addr = flcn->flcn_base; | ||
277 | u32 *dst_u32 = (u32 *)dst; | ||
278 | u32 words = 0; | ||
279 | u32 bytes = 0; | ||
280 | u32 data = 0; | ||
281 | u32 blk = 0; | ||
282 | u32 i = 0; | ||
283 | |||
284 | nvgpu_log_info(g, "download %d bytes from 0x%x", size, src); | ||
285 | |||
286 | if (flcn_mem_overflow_check(flcn, src, size, MEM_IMEM)) { | ||
287 | nvgpu_err(g, "incorrect parameters"); | ||
288 | return -EINVAL; | ||
289 | } | ||
290 | |||
291 | nvgpu_mutex_acquire(&flcn->copy_lock); | ||
292 | |||
293 | words = size >> 2; | ||
294 | bytes = size & 0x3; | ||
295 | blk = src >> 8; | ||
296 | |||
297 | nvgpu_log_info(g, "download %d words from 0x%x block %d", | ||
298 | words, src, blk); | ||
299 | |||
300 | gk20a_writel(g, base_addr + falcon_falcon_imemc_r(port), | ||
301 | falcon_falcon_imemc_offs_f(src >> 2) | | ||
302 | falcon_falcon_imemc_blk_f(blk) | | ||
303 | falcon_falcon_dmemc_aincr_f(1)); | ||
304 | |||
305 | for (i = 0; i < words; i++) | ||
306 | dst_u32[i] = gk20a_readl(g, | ||
307 | base_addr + falcon_falcon_imemd_r(port)); | ||
308 | |||
309 | if (bytes > 0) { | ||
310 | data = gk20a_readl(g, base_addr + falcon_falcon_imemd_r(port)); | ||
311 | for (i = 0; i < bytes; i++) | ||
312 | dst[(words << 2) + i] = ((u8 *)&data)[i]; | ||
313 | } | ||
314 | |||
315 | nvgpu_mutex_release(&flcn->copy_lock); | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
272 | static int gk20a_flcn_copy_to_imem(struct nvgpu_falcon *flcn, u32 dst, | 320 | static int gk20a_flcn_copy_to_imem(struct nvgpu_falcon *flcn, u32 dst, |
273 | u8 *src, u32 size, u8 port, bool sec, u32 tag) | 321 | u8 *src, u32 size, u8 port, bool sec, u32 tag) |
274 | { | 322 | { |
@@ -551,6 +599,7 @@ void gk20a_falcon_ops(struct nvgpu_falcon *flcn) | |||
551 | flcn_ops->copy_from_dmem = gk20a_flcn_copy_from_dmem; | 599 | flcn_ops->copy_from_dmem = gk20a_flcn_copy_from_dmem; |
552 | flcn_ops->copy_to_dmem = gk20a_flcn_copy_to_dmem; | 600 | flcn_ops->copy_to_dmem = gk20a_flcn_copy_to_dmem; |
553 | flcn_ops->copy_to_imem = gk20a_flcn_copy_to_imem; | 601 | flcn_ops->copy_to_imem = gk20a_flcn_copy_to_imem; |
602 | flcn_ops->copy_from_imem = gk20a_flcn_copy_from_imem; | ||
554 | flcn_ops->bootstrap = gk20a_falcon_bootstrap; | 603 | flcn_ops->bootstrap = gk20a_falcon_bootstrap; |
555 | flcn_ops->dump_falcon_stats = gk20a_falcon_dump_stats; | 604 | flcn_ops->dump_falcon_stats = gk20a_falcon_dump_stats; |
556 | 605 | ||