diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-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 cfd2b30a..49a1870d 100644 --- a/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | |||
@@ -195,6 +195,60 @@ static int gk20a_flcn_copy_from_dmem(struct nvgpu_falcon *flcn, | |||
195 | return 0; | 195 | return 0; |
196 | } | 196 | } |
197 | 197 | ||
198 | static int gk20a_flcn_copy_to_dmem(struct nvgpu_falcon *flcn, | ||
199 | u32 dst, u8 *src, u32 size, u8 port) | ||
200 | { | ||
201 | struct gk20a *g = flcn->g; | ||
202 | u32 base_addr = flcn->flcn_base; | ||
203 | u32 i, words, bytes; | ||
204 | u32 data, addr_mask; | ||
205 | u32 *src_u32 = (u32 *)src; | ||
206 | |||
207 | nvgpu_log_fn(g, "dest dmem offset - %x, size - %x", dst, size); | ||
208 | |||
209 | if (flcn_mem_overflow_check(flcn, dst, size, MEM_DMEM)) { | ||
210 | nvgpu_err(g, "incorrect parameters"); | ||
211 | return -EINVAL; | ||
212 | } | ||
213 | |||
214 | nvgpu_mutex_acquire(&flcn->copy_lock); | ||
215 | |||
216 | words = size >> 2; | ||
217 | bytes = size & 0x3; | ||
218 | |||
219 | addr_mask = falcon_falcon_dmemc_offs_m() | | ||
220 | falcon_falcon_dmemc_blk_m(); | ||
221 | |||
222 | dst &= addr_mask; | ||
223 | |||
224 | gk20a_writel(g, base_addr + falcon_falcon_dmemc_r(port), | ||
225 | dst | falcon_falcon_dmemc_aincw_f(1)); | ||
226 | |||
227 | for (i = 0; i < words; i++) | ||
228 | gk20a_writel(g, | ||
229 | base_addr + falcon_falcon_dmemd_r(port), src_u32[i]); | ||
230 | |||
231 | if (bytes > 0) { | ||
232 | data = 0; | ||
233 | for (i = 0; i < bytes; i++) | ||
234 | ((u8 *)&data)[i] = src[(words << 2) + i]; | ||
235 | gk20a_writel(g, falcon_falcon_dmemd_r(port), data); | ||
236 | } | ||
237 | |||
238 | size = ALIGN(size, 4); | ||
239 | data = gk20a_readl(g, | ||
240 | base_addr + falcon_falcon_dmemc_r(port)) & addr_mask; | ||
241 | if (data != ((dst + size) & addr_mask)) { | ||
242 | nvgpu_warn(g, "copy failed. bytes written %d, expected %d", | ||
243 | data - dst, size); | ||
244 | } | ||
245 | |||
246 | nvgpu_mutex_release(&flcn->copy_lock); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | |||
198 | static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) | 252 | static void gk20a_falcon_engine_dependency_ops(struct nvgpu_falcon *flcn) |
199 | { | 253 | { |
200 | struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops = | 254 | struct nvgpu_falcon_engine_dependency_ops *flcn_eng_dep_ops = |
@@ -224,6 +278,7 @@ static void gk20a_falcon_ops(struct nvgpu_falcon *flcn) | |||
224 | flcn_ops->is_falcon_idle = gk20a_is_falcon_idle; | 278 | flcn_ops->is_falcon_idle = gk20a_is_falcon_idle; |
225 | flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done; | 279 | flcn_ops->is_falcon_scrubbing_done = gk20a_is_falcon_scrubbing_done; |
226 | flcn_ops->copy_from_dmem = gk20a_flcn_copy_from_dmem; | 280 | flcn_ops->copy_from_dmem = gk20a_flcn_copy_from_dmem; |
281 | flcn_ops->copy_to_dmem = gk20a_flcn_copy_to_dmem; | ||
227 | 282 | ||
228 | gk20a_falcon_engine_dependency_ops(flcn); | 283 | gk20a_falcon_engine_dependency_ops(flcn); |
229 | } | 284 | } |