diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/nvgpu/common/falcon/falcon.c | 67 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/flcn_gk20a.c | 49 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/include/nvgpu/falcon.h | 2 |
3 files changed, 118 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/falcon/falcon.c b/drivers/gpu/nvgpu/common/falcon/falcon.c index c9ab69fe..116cb78c 100644 --- a/drivers/gpu/nvgpu/common/falcon/falcon.c +++ b/drivers/gpu/nvgpu/common/falcon/falcon.c | |||
@@ -180,6 +180,21 @@ int nvgpu_flcn_copy_to_dmem(struct nvgpu_falcon *flcn, | |||
180 | return flcn_ops->copy_to_dmem(flcn, dst, src, size, port); | 180 | return flcn_ops->copy_to_dmem(flcn, dst, src, size, port); |
181 | } | 181 | } |
182 | 182 | ||
183 | int nvgpu_flcn_copy_from_imem(struct nvgpu_falcon *flcn, | ||
184 | u32 src, u8 *dst, u32 size, u8 port) | ||
185 | { | ||
186 | struct nvgpu_falcon_ops *flcn_ops = &flcn->flcn_ops; | ||
187 | int status = -EINVAL; | ||
188 | |||
189 | if (flcn_ops->copy_from_imem) | ||
190 | status = flcn_ops->copy_from_imem(flcn, src, dst, size, port); | ||
191 | else | ||
192 | nvgpu_warn(flcn->g, "Invalid op on falcon 0x%x ", | ||
193 | flcn->flcn_id); | ||
194 | |||
195 | return status; | ||
196 | } | ||
197 | |||
183 | int nvgpu_flcn_copy_to_imem(struct nvgpu_falcon *flcn, | 198 | int nvgpu_flcn_copy_to_imem(struct nvgpu_falcon *flcn, |
184 | u32 dst, u8 *src, u32 size, u8 port, bool sec, u32 tag) | 199 | u32 dst, u8 *src, u32 size, u8 port, bool sec, u32 tag) |
185 | { | 200 | { |
@@ -196,6 +211,58 @@ int nvgpu_flcn_copy_to_imem(struct nvgpu_falcon *flcn, | |||
196 | return status; | 211 | return status; |
197 | } | 212 | } |
198 | 213 | ||
214 | static void nvgpu_flcn_print_mem(struct nvgpu_falcon *flcn, u32 src, | ||
215 | u32 size, u32 mem_type) | ||
216 | { | ||
217 | u32 buff[64] = {0}; | ||
218 | u32 total_block_read = 0; | ||
219 | u32 byte_read_count = 0; | ||
220 | u32 i = 0; | ||
221 | u32 status = 0; | ||
222 | |||
223 | nvgpu_info(flcn->g, " offset 0x%x size %d bytes", src, size); | ||
224 | |||
225 | total_block_read = size >> 8; | ||
226 | do { | ||
227 | byte_read_count = total_block_read ? sizeof(buff) : size; | ||
228 | |||
229 | if (!byte_read_count) | ||
230 | break; | ||
231 | |||
232 | if (mem_type == MEM_DMEM) | ||
233 | status = nvgpu_flcn_copy_from_dmem(flcn, src, | ||
234 | (u8 *)buff, byte_read_count, 0); | ||
235 | else | ||
236 | status = nvgpu_flcn_copy_from_imem(flcn, src, | ||
237 | (u8 *)buff, byte_read_count, 0); | ||
238 | |||
239 | if (status) { | ||
240 | nvgpu_err(flcn->g, "MEM print failed"); | ||
241 | break; | ||
242 | } | ||
243 | |||
244 | for (i = 0; i < (byte_read_count >> 2); i += 4) | ||
245 | nvgpu_info(flcn->g, "%#06x: %#010x %#010x %#010x %#010x", | ||
246 | src + (i << 2), buff[i], buff[i+1], | ||
247 | buff[i+2], buff[i+3]); | ||
248 | |||
249 | src += byte_read_count; | ||
250 | size -= byte_read_count; | ||
251 | } while (total_block_read--); | ||
252 | } | ||
253 | |||
254 | void nvgpu_flcn_print_dmem(struct nvgpu_falcon *flcn, u32 src, u32 size) | ||
255 | { | ||
256 | nvgpu_info(flcn->g, " PRINT DMEM "); | ||
257 | nvgpu_flcn_print_mem(flcn, src, size, MEM_DMEM); | ||
258 | } | ||
259 | |||
260 | void nvgpu_flcn_print_imem(struct nvgpu_falcon *flcn, u32 src, u32 size) | ||
261 | { | ||
262 | nvgpu_info(flcn->g, " PRINT IMEM "); | ||
263 | nvgpu_flcn_print_mem(flcn, src, size, MEM_IMEM); | ||
264 | } | ||
265 | |||
199 | int nvgpu_flcn_bootstrap(struct nvgpu_falcon *flcn, u32 boot_vector) | 266 | int nvgpu_flcn_bootstrap(struct nvgpu_falcon *flcn, u32 boot_vector) |
200 | { | 267 | { |
201 | struct nvgpu_falcon_ops *flcn_ops = &flcn->flcn_ops; | 268 | struct nvgpu_falcon_ops *flcn_ops = &flcn->flcn_ops; |
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 | ||
diff --git a/drivers/gpu/nvgpu/include/nvgpu/falcon.h b/drivers/gpu/nvgpu/include/nvgpu/falcon.h index cbda2ee3..5cc22f65 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/falcon.h +++ b/drivers/gpu/nvgpu/include/nvgpu/falcon.h | |||
@@ -189,6 +189,8 @@ u32 nvgpu_flcn_mailbox_read(struct nvgpu_falcon *flcn, u32 mailbox_index); | |||
189 | void nvgpu_flcn_mailbox_write(struct nvgpu_falcon *flcn, u32 mailbox_index, | 189 | void nvgpu_flcn_mailbox_write(struct nvgpu_falcon *flcn, u32 mailbox_index, |
190 | u32 data); | 190 | u32 data); |
191 | int nvgpu_flcn_bootstrap(struct nvgpu_falcon *flcn, u32 boot_vector); | 191 | int nvgpu_flcn_bootstrap(struct nvgpu_falcon *flcn, u32 boot_vector); |
192 | void nvgpu_flcn_print_dmem(struct nvgpu_falcon *flcn, u32 src, u32 size); | ||
193 | void nvgpu_flcn_print_imem(struct nvgpu_falcon *flcn, u32 src, u32 size); | ||
192 | void nvgpu_flcn_dump_stats(struct nvgpu_falcon *flcn); | 194 | void nvgpu_flcn_dump_stats(struct nvgpu_falcon *flcn); |
193 | 195 | ||
194 | void nvgpu_flcn_sw_init(struct gk20a *g, u32 flcn_id); | 196 | void nvgpu_flcn_sw_init(struct gk20a *g, u32 flcn_id); |