Lines Matching refs:ptdev

272 struct panthor_vm *panthor_fw_vm(struct panthor_device *ptdev)
274 return ptdev->fw->vm;
279 * @ptdev: Device.
284 panthor_fw_get_glb_iface(struct panthor_device *ptdev)
286 return &ptdev->fw->iface.global;
291 * @ptdev: Device.
297 panthor_fw_get_csg_iface(struct panthor_device *ptdev, u32 csg_slot)
299 if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS))
302 return &ptdev->fw->iface.groups[csg_slot];
307 * @ptdev: Device.
314 panthor_fw_get_cs_iface(struct panthor_device *ptdev, u32 csg_slot, u32 cs_slot)
316 if (drm_WARN_ON(&ptdev->base, csg_slot >= MAX_CSGS || cs_slot >= MAX_CS_PER_CSG))
319 return &ptdev->fw->iface.streams[csg_slot][cs_slot];
322 static bool panthor_fw_has_glb_state(struct panthor_device *ptdev)
324 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
329 static bool panthor_fw_has_64bit_ep_req(struct panthor_device *ptdev)
331 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
336 u64 panthor_fw_csg_endpoint_req_get(struct panthor_device *ptdev,
339 if (panthor_fw_has_64bit_ep_req(ptdev))
345 void panthor_fw_csg_endpoint_req_set(struct panthor_device *ptdev,
348 if (panthor_fw_has_64bit_ep_req(ptdev))
354 void panthor_fw_csg_endpoint_req_update(struct panthor_device *ptdev,
358 if (panthor_fw_has_64bit_ep_req(ptdev))
367 * @ptdev: Device.
376 static u32 panthor_fw_conv_timeout(struct panthor_device *ptdev, u32 timeout_us)
388 timer_rate = clk_get_rate(ptdev->clks.core);
391 if (drm_WARN_ON(&ptdev->base, !timer_rate)) {
402 if (drm_WARN_ON(&ptdev->base, mod_cycles > GLB_TIMER_VAL(~0)))
409 static int panthor_fw_binary_iter_read(struct panthor_device *ptdev,
416 drm_err(&ptdev->base, "Firmware too small\n");
425 static int panthor_fw_binary_sub_iter_init(struct panthor_device *ptdev,
433 drm_err(&ptdev->base, "Firmware entry too long\n");
444 static void panthor_fw_init_section_mem(struct panthor_device *ptdev,
455 if (drm_WARN_ON(&ptdev->base, ret))
470 * @ptdev: Device.
486 panthor_fw_alloc_queue_iface_mem(struct panthor_device *ptdev,
494 mem = panthor_kernel_bo_create(ptdev, ptdev->fw->vm, SZ_8K,
520 * @ptdev: Device.
526 panthor_fw_alloc_suspend_buf_mem(struct panthor_device *ptdev, size_t size)
528 return panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev), size,
535 static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
540 ssize_t vm_pgsz = panthor_vm_page_size(ptdev->fw->vm);
547 ret = panthor_fw_binary_iter_read(ptdev, iter, &hdr, sizeof(hdr));
552 drm_err(&ptdev->base, "Firmware corrupted, data.end < data.start (0x%x < 0x%x)\n",
558 drm_err(&ptdev->base, "Firmware corrupted, hdr.va.end < hdr.va.start (0x%x < 0x%x)\n",
564 drm_err(&ptdev->base, "Firmware corrupted, file truncated? data_end=0x%x > fw size=0x%zx\n",
570 drm_err(&ptdev->base, "Firmware corrupted, virtual addresses not page aligned: 0x%x-0x%x\n",
576 drm_err(&ptdev->base, "Firmware contains interface with unsupported flags (0x%x)\n",
582 drm_warn(&ptdev->base,
589 drm_err(&ptdev->base,
596 section = drmm_kzalloc(&ptdev->base, sizeof(*section), GFP_KERNEL);
600 list_add_tail(&section->node, &ptdev->fw->sections);
605 void *data = drmm_kmalloc(&ptdev->base, section->data.size, GFP_KERNEL);
615 char *name = drmm_kmalloc(&ptdev->base, name_len + 1, GFP_KERNEL);
649 section->mem = panthor_kernel_bo_create(ptdev, panthor_fw_vm(ptdev),
656 if (drm_WARN_ON(&ptdev->base, section->mem->va_node.start != hdr.va.start))
665 panthor_fw_init_section_mem(ptdev, section);
672 dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE);
676 ptdev->fw->shared_section = section;
681 static int panthor_fw_read_build_info(struct panthor_device *ptdev,
691 ret = panthor_fw_binary_iter_read(ptdev, iter, &hdr, sizeof(hdr));
697 drm_err(&ptdev->base, "Firmware build info corrupt\n");
709 drm_warn(&ptdev->base, "Firmware's git sha is not NULL terminated\n");
714 drm_info(&ptdev->base, "Firmware git sha: %s\n",
721 panthor_reload_fw_sections(struct panthor_device *ptdev, bool full_reload)
725 list_for_each_entry(section, &ptdev->fw->sections, node) {
731 panthor_fw_init_section_mem(ptdev, section);
733 if (!drm_WARN_ON(&ptdev->base, IS_ERR_OR_NULL(sgt)))
734 dma_sync_sgtable_for_device(ptdev->base.dev, sgt, DMA_TO_DEVICE);
738 static int panthor_fw_load_entry(struct panthor_device *ptdev,
746 ret = panthor_fw_binary_iter_read(ptdev, iter, &ehdr, sizeof(ehdr));
752 drm_err(&ptdev->base, "Firmware entry isn't 32 bit aligned, offset=0x%x size=0x%x\n",
757 if (panthor_fw_binary_sub_iter_init(ptdev, iter, &eiter,
763 return panthor_fw_load_section_entry(ptdev, fw, &eiter, ehdr);
765 return panthor_fw_read_build_info(ptdev, fw, &eiter, ehdr);
780 drm_err(&ptdev->base,
786 static int panthor_fw_load(struct panthor_device *ptdev)
795 (u32)GPU_ARCH_MAJOR(ptdev->gpu_info.gpu_id),
796 (u32)GPU_ARCH_MINOR(ptdev->gpu_info.gpu_id),
799 ret = request_firmware(&fw, fw_path, ptdev->base.dev);
801 drm_err(&ptdev->base, "Failed to load firmware image '%s'\n",
808 ret = panthor_fw_binary_iter_read(ptdev, &iter, &hdr, sizeof(hdr));
814 drm_err(&ptdev->base, "Invalid firmware magic\n");
820 drm_err(&ptdev->base, "Unsupported firmware binary header version %d.%d (expected %d.x)\n",
826 drm_err(&ptdev->base, "Firmware image is truncated\n");
833 ret = panthor_fw_load_entry(ptdev, fw, &iter);
838 if (!ptdev->fw->shared_section) {
839 drm_err(&ptdev->base, "Shared interface region not found\n");
851 * @ptdev: Device.
856 static void *iface_fw_to_cpu_addr(struct panthor_device *ptdev, u32 mcu_va)
858 u64 shared_mem_start = panthor_kernel_bo_gpuva(ptdev->fw->shared_section->mem);
860 panthor_kernel_bo_size(ptdev->fw->shared_section->mem);
864 return ptdev->fw->shared_section->mem->kmap + (mcu_va - shared_mem_start);
867 static int panthor_init_cs_iface(struct panthor_device *ptdev,
870 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
871 struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, csg_idx);
872 struct panthor_fw_cs_iface *cs_iface = &ptdev->fw->iface.streams[csg_idx][cs_idx];
873 u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem);
879 panthor_fw_get_cs_iface(ptdev, 0, 0);
885 cs_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset;
886 cs_iface->input = iface_fw_to_cpu_addr(ptdev, cs_iface->control->input_va);
887 cs_iface->output = iface_fw_to_cpu_addr(ptdev, cs_iface->control->output_va);
890 drm_err(&ptdev->base, "Invalid stream control interface input/output VA");
896 drm_err(&ptdev->base, "Expecting identical CS slots");
902 ptdev->csif_info.cs_reg_count = reg_count;
903 ptdev->csif_info.unpreserved_cs_reg_count = CSF_UNPRESERVED_REG_COUNT;
923 static int panthor_init_csg_iface(struct panthor_device *ptdev,
926 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
927 struct panthor_fw_csg_iface *csg_iface = &ptdev->fw->iface.groups[csg_idx];
928 u64 shared_section_sz = panthor_kernel_bo_size(ptdev->fw->shared_section->mem);
936 csg_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset;
937 csg_iface->input = iface_fw_to_cpu_addr(ptdev, csg_iface->control->input_va);
938 csg_iface->output = iface_fw_to_cpu_addr(ptdev, csg_iface->control->output_va);
945 drm_err(&ptdev->base, "Invalid group control interface input/output VA");
951 panthor_fw_get_csg_iface(ptdev, 0);
954 drm_err(&ptdev->base, "Expecting identical CSG slots");
960 int ret = panthor_init_cs_iface(ptdev, csg_idx, i);
969 static u32 panthor_get_instr_features(struct panthor_device *ptdev)
971 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
979 static int panthor_fw_init_ifaces(struct panthor_device *ptdev)
981 struct panthor_fw_global_iface *glb_iface = &ptdev->fw->iface.global;
984 if (!ptdev->fw->shared_section->mem->kmap)
988 glb_iface->control = ptdev->fw->shared_section->mem->kmap;
991 drm_err(&ptdev->base, "Firmware version is 0. Firmware may have failed to boot");
995 glb_iface->input = iface_fw_to_cpu_addr(ptdev, glb_iface->control->input_va);
996 glb_iface->output = iface_fw_to_cpu_addr(ptdev, glb_iface->control->output_va);
998 drm_err(&ptdev->base, "Invalid global control interface input/output VA");
1004 drm_err(&ptdev->base, "Invalid number of control groups");
1009 int ret = panthor_init_csg_iface(ptdev, i);
1015 drm_info(&ptdev->base, "CSF FW using interface v%d.%d.%d, Features %#x Instrumentation features %#x",
1020 panthor_get_instr_features(ptdev));
1024 static void panthor_fw_init_global_iface(struct panthor_device *ptdev)
1026 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
1029 glb_iface->input->core_en_mask = ptdev->gpu_info.shader_present;
1032 glb_iface->input->poweroff_timer = panthor_fw_conv_timeout(ptdev, PWROFF_HYSTERESIS_US);
1034 glb_iface->input->idle_timer = panthor_fw_conv_timeout(ptdev, IDLE_HYSTERESIS_US);
1044 if (panthor_fw_has_glb_state(ptdev))
1054 gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1);
1057 mod_delayed_work(ptdev->reset.wq, &ptdev->fw->watchdog.ping_work,
1061 static void panthor_job_irq_handler(struct panthor_device *ptdev, u32 status)
1063 gpu_write(ptdev, JOB_INT_CLEAR, status);
1065 if (!ptdev->fw->booted && (status & JOB_INT_GLOBAL_IF))
1066 ptdev->fw->booted = true;
1068 wake_up_all(&ptdev->fw->req_waitqueue);
1071 if (!ptdev->fw->booted)
1074 panthor_sched_report_fw_events(ptdev, status);
1078 static int panthor_fw_start(struct panthor_device *ptdev)
1082 ptdev->fw->booted = false;
1083 panthor_job_irq_resume(&ptdev->fw->irq, ~0);
1084 gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_AUTO);
1086 if (!wait_event_timeout(ptdev->fw->req_waitqueue,
1087 ptdev->fw->booted,
1089 if (!ptdev->fw->booted &&
1090 !(gpu_read(ptdev, JOB_INT_STAT) & JOB_INT_GLOBAL_IF))
1101 u32 status = gpu_read(ptdev, MCU_STATUS);
1103 drm_err(&ptdev->base, "Failed to boot MCU (status=%s)",
1111 static void panthor_fw_stop(struct panthor_device *ptdev)
1115 gpu_write(ptdev, MCU_CONTROL, MCU_CONTROL_DISABLE);
1116 if (gpu_read_poll_timeout(ptdev, MCU_STATUS, status,
1118 drm_err(&ptdev->base, "Failed to stop MCU");
1121 static bool panthor_fw_mcu_halted(struct panthor_device *ptdev)
1123 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
1126 halted = gpu_read(ptdev, MCU_STATUS) == MCU_STATUS_HALT;
1128 if (panthor_fw_has_glb_state(ptdev))
1134 static void panthor_fw_halt_mcu(struct panthor_device *ptdev)
1136 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
1138 if (panthor_fw_has_glb_state(ptdev))
1143 gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1);
1146 static bool panthor_fw_wait_mcu_halted(struct panthor_device *ptdev)
1151 MCU_HALT_TIMEOUT_US, 0, ptdev)) {
1152 drm_warn(&ptdev->base, "Timed out waiting for MCU to halt");
1159 static void panthor_fw_mcu_set_active(struct panthor_device *ptdev)
1161 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
1163 if (panthor_fw_has_glb_state(ptdev))
1171 * @ptdev: Device.
1177 void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang)
1180 cancel_delayed_work_sync(&ptdev->fw->watchdog.ping_work);
1182 ptdev->reset.fast = false;
1185 panthor_fw_halt_mcu(ptdev);
1186 if (!panthor_fw_wait_mcu_halted(ptdev))
1187 drm_warn(&ptdev->base, "Failed to cleanly suspend MCU");
1189 ptdev->reset.fast = true;
1192 panthor_job_irq_suspend(&ptdev->fw->irq);
1193 panthor_fw_stop(ptdev);
1198 * @ptdev: Device.
1203 int panthor_fw_post_reset(struct panthor_device *ptdev)
1208 ret = panthor_vm_active(ptdev->fw->vm);
1212 if (!ptdev->reset.fast) {
1217 panthor_reload_fw_sections(ptdev, true);
1226 panthor_fw_mcu_set_active(ptdev);
1229 ret = panthor_fw_start(ptdev);
1231 drm_err(&ptdev->base, "FW %s reset failed",
1232 ptdev->reset.fast ? "fast" : "slow");
1237 panthor_fw_init_global_iface(ptdev);
1243 * @ptdev: Device.
1253 void panthor_fw_unplug(struct panthor_device *ptdev)
1257 disable_delayed_work_sync(&ptdev->fw->watchdog.ping_work);
1259 if (!IS_ENABLED(CONFIG_PM) || pm_runtime_active(ptdev->base.dev)) {
1261 if (ptdev->fw->irq.irq)
1262 panthor_job_irq_suspend(&ptdev->fw->irq);
1264 panthor_fw_stop(ptdev);
1267 list_for_each_entry(section, &ptdev->fw->sections, node)
1275 panthor_vm_put(ptdev->fw->vm);
1276 ptdev->fw->vm = NULL;
1278 if (!IS_ENABLED(CONFIG_PM) || pm_runtime_active(ptdev->base.dev))
1279 panthor_hw_l2_power_off(ptdev);
1326 * @ptdev: Device.
1334 int panthor_fw_glb_wait_acks(struct panthor_device *ptdev,
1338 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
1341 if (drm_WARN_ON(&ptdev->base, req_mask & (~GLB_REQ_MASK | GLB_HALT)))
1346 &ptdev->fw->req_waitqueue,
1352 * @ptdev: Device.
1361 int panthor_fw_csg_wait_acks(struct panthor_device *ptdev, u32 csg_slot,
1364 struct panthor_fw_csg_iface *csg_iface = panthor_fw_get_csg_iface(ptdev, csg_slot);
1367 if (drm_WARN_ON(&ptdev->base, req_mask & ~CSG_REQ_MASK))
1372 &ptdev->fw->req_waitqueue,
1389 * @ptdev: Device.
1396 void panthor_fw_ring_csg_doorbells(struct panthor_device *ptdev, u32 csg_mask)
1398 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
1401 gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1);
1407 struct panthor_device *ptdev = fw->irq.ptdev;
1408 struct panthor_fw_global_iface *glb_iface = panthor_fw_get_glb_iface(ptdev);
1412 if (panthor_device_reset_is_pending(ptdev))
1416 gpu_write(ptdev, CSF_DOORBELL(CSF_GLB_DOORBELL_ID), 1);
1418 ret = panthor_fw_glb_wait_acks(ptdev, GLB_PING, &acked, 100);
1420 panthor_device_schedule_reset(ptdev);
1421 drm_err(&ptdev->base, "FW ping timeout, scheduling a reset");
1423 mod_delayed_work(ptdev->reset.wq, &fw->watchdog.ping_work,
1430 * @ptdev: Device.
1434 int panthor_fw_init(struct panthor_device *ptdev)
1439 fw = drmm_kzalloc(&ptdev->base, sizeof(*fw), GFP_KERNEL);
1443 ptdev->fw = fw;
1448 irq = platform_get_irq_byname(to_platform_device(ptdev->base.dev), "job");
1452 ret = panthor_request_job_irq(ptdev, &fw->irq, irq, 0);
1454 drm_err(&ptdev->base, "failed to request job irq");
1458 ret = panthor_hw_l2_power_on(ptdev);
1462 fw->vm = panthor_vm_create(ptdev, true,
1472 ret = panthor_fw_load(ptdev);
1480 ret = panthor_fw_start(ptdev);
1484 ret = panthor_fw_init_ifaces(ptdev);
1488 panthor_fw_init_global_iface(ptdev);
1492 panthor_fw_unplug(ptdev);