drivers/gpu/drm/imagination/pvr_fw_riscv.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/imagination/pvr_fw_riscv.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/imagination/pvr_fw_riscv.c
Extension
.c
Size
5039 bytes
Lines
166
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct rogue_riscv_fw_boot_data {
	u64 coremem_code_dev_vaddr;
	u64 coremem_data_dev_vaddr;
	u32 coremem_code_fw_addr;
	u32 coremem_data_fw_addr;
	u32 coremem_code_size;
	u32 coremem_data_size;
	u32 flags;
	u32 reserved;
};

static int
pvr_riscv_fw_process(struct pvr_device *pvr_dev, const u8 *fw,
		     u8 *fw_code_ptr, u8 *fw_data_ptr, u8 *fw_core_code_ptr, u8 *fw_core_data_ptr,
		     u32 core_code_alloc_size)
{
	struct pvr_fw_device *fw_dev = &pvr_dev->fw_dev;
	struct pvr_fw_mem *fw_mem = &fw_dev->mem;
	struct rogue_riscv_fw_boot_data *boot_data;
	int err;

	err = pvr_fw_process_elf_command_stream(pvr_dev, fw, fw_code_ptr, fw_data_ptr,
						fw_core_code_ptr, fw_core_data_ptr);
	if (err)
		goto err_out;

	boot_data = (struct rogue_riscv_fw_boot_data *)fw_data_ptr;

	if (fw_mem->core_code_obj) {
		boot_data->coremem_code_dev_vaddr = pvr_fw_obj_get_gpu_addr(fw_mem->core_code_obj);
		pvr_fw_object_get_fw_addr(fw_mem->core_code_obj, &boot_data->coremem_code_fw_addr);
		boot_data->coremem_code_size = pvr_fw_obj_get_object_size(fw_mem->core_code_obj);
	}

	if (fw_mem->core_data_obj) {
		boot_data->coremem_data_dev_vaddr = pvr_fw_obj_get_gpu_addr(fw_mem->core_data_obj);
		pvr_fw_object_get_fw_addr(fw_mem->core_data_obj, &boot_data->coremem_data_fw_addr);
		boot_data->coremem_data_size = pvr_fw_obj_get_object_size(fw_mem->core_data_obj);
	}

	return 0;

err_out:
	return err;
}

static int
pvr_riscv_init(struct pvr_device *pvr_dev)
{
	pvr_fw_heap_info_init(pvr_dev, ROGUE_FW_HEAP_RISCV_SHIFT, 0);

	return 0;
}

static u32
pvr_riscv_get_fw_addr_with_offset(struct pvr_fw_object *fw_obj, u32 offset)
{
	u32 fw_addr = fw_obj->fw_addr_offset + offset;

	/* RISC-V cacheability is determined by address. */
	if (fw_obj->gem->flags & PVR_BO_FW_FLAGS_DEVICE_UNCACHED)
		fw_addr |= ROGUE_RISCVFW_REGION_BASE(SHARED_UNCACHED_DATA);
	else
		fw_addr |= ROGUE_RISCVFW_REGION_BASE(SHARED_CACHED_DATA);

	return fw_addr;
}

static int
pvr_riscv_vm_map(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
{
	struct pvr_gem_object *pvr_obj = fw_obj->gem;

	return pvr_vm_map(pvr_dev->kernel_vm_ctx, pvr_obj, 0, fw_obj->fw_mm_node.start,
			  pvr_gem_object_size(pvr_obj));
}

static void
pvr_riscv_vm_unmap(struct pvr_device *pvr_dev, struct pvr_fw_object *fw_obj)
{
	struct pvr_gem_object *pvr_obj = fw_obj->gem;

	pvr_vm_unmap_obj(pvr_dev->kernel_vm_ctx, pvr_obj,
			 fw_obj->fw_mm_node.start, fw_obj->fw_mm_node.size);
}

static bool
pvr_riscv_irq_pending(struct pvr_device *pvr_dev)
{
	return pvr_cr_read32(pvr_dev, ROGUE_CR_IRQ_OS0_EVENT_STATUS) &

Annotation

Implementation Notes