diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a/flcn_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c index b52652e2..158f4d8b 100644 --- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | |||
@@ -269,6 +269,60 @@ 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_to_imem(struct nvgpu_falcon *flcn, u32 dst, | ||
273 | u8 *src, u32 size, u8 port, bool sec, u32 tag) | ||
274 | { | ||
275 | struct gk20a *g = flcn->g; | ||
276 | u32 base_addr = flcn->flcn_base; | ||
277 | u32 *src_u32 = (u32 *)src; | ||
278 | u32 words = 0; | ||
279 | u32 blk = 0; | ||
280 | u32 i = 0; | ||
281 | |||
282 | nvgpu_log_info(g, "upload %d bytes to 0x%x", size, dst); | ||
283 | |||
284 | if (flcn_mem_overflow_check(flcn, dst, size, MEM_IMEM)) { | ||
285 | nvgpu_err(g, "incorrect parameters"); | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | |||
289 | nvgpu_mutex_acquire(&flcn->copy_lock); | ||
290 | |||
291 | words = size >> 2; | ||
292 | blk = dst >> 8; | ||
293 | |||
294 | nvgpu_log_info(g, "upload %d words to 0x%x block %d, tag 0x%x", | ||
295 | words, dst, blk, tag); | ||
296 | |||
297 | gk20a_writel(g, base_addr + falcon_falcon_imemc_r(port), | ||
298 | falcon_falcon_imemc_offs_f(dst >> 2) | | ||
299 | falcon_falcon_imemc_blk_f(blk) | | ||
300 | /* Set Auto-Increment on write */ | ||
301 | falcon_falcon_imemc_aincw_f(1) | | ||
302 | sec << 28); | ||
303 | |||
304 | for (i = 0; i < words; i++) { | ||
305 | if (i % 64 == 0) { | ||
306 | /* tag is always 256B aligned */ | ||
307 | gk20a_writel(g, base_addr + falcon_falcon_imemt_r(0), | ||
308 | tag); | ||
309 | tag++; | ||
310 | } | ||
311 | |||
312 | gk20a_writel(g, base_addr + falcon_falcon_imemd_r(port), | ||
313 | src_u32[i]); | ||
314 | } | ||
315 | |||
316 | /* WARNING : setting remaining bytes in block to 0x0 */ | ||
317 | while (i % 64) { | ||
318 | gk20a_writel(g, base_addr + falcon_falcon_imemd_r(port), 0); | ||
319 | i++; | ||
320 | } | ||
321 | |||
322 | nvgpu_mutex_release(&flcn->copy_lock); | ||
323 | |||
324 | return 0; | ||
325 | } | ||
272 | 326 | ||
273 | static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) | 327 | static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) |
274 | { | 328 | { |
@@ -302,6 +356,7 @@ void gk20a_falcon_ops(struct nvgpu_falcon *flcn) | |||
302 | flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done; | 356 | flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done; |
303 | flcn_ops->copy_from_dmem = gk20a_flcn_copy_from_dmem; | 357 | flcn_ops->copy_from_dmem = gk20a_flcn_copy_from_dmem; |
304 | flcn_ops->copy_to_dmem = gk20a_flcn_copy_to_dmem; | 358 | flcn_ops->copy_to_dmem = gk20a_flcn_copy_to_dmem; |
359 | flcn_ops->copy_to_imem = gk20a_flcn_copy_to_imem; | ||
305 | 360 | ||
306 | gk20a_falcon_engine_dependency_ops(flcn); | 361 | gk20a_falcon_engine_dependency_ops(flcn); |
307 | } | 362 | } |