Loading drivers/gpu/msm/adreno_a6xx_gmu.c +34 −50 Original line number Diff line number Diff line Loading @@ -472,12 +472,6 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) return 0; } /* * Gmu FW header format: * <32-bit start addr> <32-bit size> <32-bit pad0> <32-bit pad1> <Payload> */ #define GMU_FW_HEADER_SIZE 4 #define GMU_ITCM_VA_START 0x0 #define GMU_ITCM_VA_END (GMU_ITCM_VA_START + 0x4000) /* 16 KB */ Loading @@ -490,50 +484,52 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) static int load_gmu_fw(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); uint32_t *fwptr = gmu->fw_image->hostptr; int i, j; int start_addr, size_in_bytes, num_dwords, tcm_slot, num_records; uint8_t *fw = (uint8_t *)gmu->fw_image->data; struct gmu_block_header *blk; uint32_t *fwptr; int j; int tcm_slot; while (fw < (uint8_t *)gmu->fw_image->data + gmu->fw_image->size) { blk = (struct gmu_block_header *)fw; fw += sizeof(*blk); /* Don't deal with zero size blocks */ if (blk->size == 0) continue; if ((blk->addr >= GMU_ITCM_VA_START) && (blk->addr < GMU_ITCM_VA_END)) { fwptr = (uint32_t *)fw; tcm_slot = (blk->addr - GMU_ITCM_VA_START) / sizeof(uint32_t); /* * Read first record. pad0 field of first record contains * number of records in the image. */ num_records = fwptr[2]; for (i = 0; i < num_records; i++) { start_addr = fwptr[0]; size_in_bytes = fwptr[1]; num_dwords = size_in_bytes / sizeof(uint32_t); fwptr += GMU_FW_HEADER_SIZE; if ((start_addr >= GMU_ITCM_VA_START) && (start_addr < GMU_ITCM_VA_END)) { tcm_slot = start_addr / sizeof(uint32_t); for (j = 0; j < num_dwords; j++) for (j = 0; j < blk->size / sizeof(uint32_t); j++) gmu_core_regwrite(device, A6XX_GMU_CM3_ITCM_START + tcm_slot + j, fwptr[j]); } else if ((start_addr >= GMU_DTCM_VA_START) && (start_addr < GMU_DTCM_VA_END)) { tcm_slot = (start_addr - GMU_DTCM_VA_START) } else if ((blk->addr >= GMU_DTCM_VA_START) && (blk->addr < GMU_DTCM_VA_END)) { fwptr = (uint32_t *)fw; tcm_slot = (blk->addr - GMU_DTCM_VA_START) / sizeof(uint32_t); for (j = 0; j < num_dwords; j++) for (j = 0; j < blk->size / sizeof(uint32_t); j++) gmu_core_regwrite(device, A6XX_GMU_CM3_DTCM_START + tcm_slot + j, fwptr[j]); } else if ((start_addr >= GMU_ICACHE_VA_START) && (start_addr < GMU_ICACHE_VA_END)) { if (!is_cached_fw_size_valid(size_in_bytes)) { } else if ((blk->addr >= GMU_ICACHE_VA_START) && (blk->addr < GMU_ICACHE_VA_END)) { if (!is_cached_fw_size_valid(blk->size)) { dev_err(&gmu->pdev->dev, "GMU firmware size too big\n"); return -EINVAL; } memcpy(gmu->icache_mem->hostptr, fwptr, size_in_bytes); memcpy(gmu->icache_mem->hostptr, fw, blk->size); } fwptr += num_dwords; fw += blk->size; } /* Proceed only after the FW is written */ Loading Loading @@ -1044,11 +1040,10 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device, */ static int a6xx_gmu_load_firmware(struct kgsl_device *device) { const struct firmware *fw = NULL; const struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); const struct adreno_gpu_core *gpucore = adreno_dev->gpucore; int image_size, ret = -EINVAL; int ret = -EINVAL; /* there is no GMU */ if (!gmu_core_isenabled(device)) Loading @@ -1061,22 +1056,11 @@ static int a6xx_gmu_load_firmware(struct kgsl_device *device) if (gpucore->gpmufw_name == NULL) return -EINVAL; ret = request_firmware(&fw, gpucore->gpmufw_name, device->dev); if (ret || fw == NULL) { ret = request_firmware(&gmu->fw_image, gpucore->gpmufw_name, device->dev); if (ret || gmu->fw_image == NULL) KGSL_CORE_ERR("request_firmware (%s) failed: %d\n", gpucore->gpmufw_name, ret); return ret; } image_size = PAGE_ALIGN(fw->size); ret = allocate_gmu_image(gmu, image_size); /* load into shared memory with GMU */ if (!ret) memcpy(gmu->fw_image->hostptr, fw->data, fw->size); release_firmware(fw); return ret; } Loading drivers/gpu/msm/kgsl_gmu.c +5 −21 Original line number Diff line number Diff line Loading @@ -235,26 +235,6 @@ static struct gmu_memdesc *allocate_gmu_kmem(struct gmu_device *gmu, return md; } /* * allocate_gmu_image() - allocates & maps memory for FW image, the size * shall come from the loaded f/w file. * @gmu: Pointer to GMU device * @size: Requested allocation size */ int allocate_gmu_image(struct gmu_device *gmu, unsigned int size) { /* Allocates & maps memory for GMU FW */ gmu->fw_image = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL, size, (IOMMU_READ | IOMMU_PRIV)); if (IS_ERR(gmu->fw_image)) { dev_err(&gmu->pdev->dev, "GMU firmware image allocation failed\n"); return -EINVAL; } return 0; } /* Checks if cached fw code size falls within the cached code segment range */ bool is_cached_fw_size_valid(uint32_t size_in_bytes) { Loading Loading @@ -360,7 +340,6 @@ static void gmu_kmem_close(struct gmu_device *gmu) gmu->hfi_mem = NULL; gmu->bw_mem = NULL; gmu->dump_mem = NULL; gmu->fw_image = NULL; gmu->gmu_log = NULL; /* Unmap all memories in GMU kernel memory pool */ Loading Loading @@ -1629,6 +1608,11 @@ static void gmu_remove(struct kgsl_device *device) gmu->pcl = 0; } if (gmu->fw_image) { release_firmware(gmu->fw_image); gmu->fw_image = NULL; } gmu_memory_close(gmu); for (i = 0; i < MAX_GMU_CLKS; i++) { Loading drivers/gpu/msm/kgsl_gmu.h +11 −3 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #define __KGSL_GMU_H #include "kgsl_gmu_core.h" #include <linux/firmware.h> #include "kgsl_hfi.h" #define MAX_GMUFW_SIZE 0x2000 /* in bytes */ Loading Loading @@ -55,6 +56,14 @@ #define OOB_BOOT_OPTION 0 #define OOB_SLUMBER_OPTION 1 /* Gmu FW block header format */ struct gmu_block_header { uint32_t addr; uint32_t size; uint32_t type; uint32_t value; }; /* For GMU Logs*/ #define LOGMEM_SIZE SZ_4K Loading Loading @@ -112,7 +121,7 @@ enum gmu_load_mode { * @reg_phys: GMU CSR physical address * @reg_len: GMU CSR range * @gmu_interrupt_num: GMU interrupt number * @fw_image: descriptor of GMU memory that has GMU image in it * @fw_image: GMU FW image * @hfi_mem: pointer to HFI shared memory * @bw_mem: pointer to BW data indirect buffer memory * @dump_mem: pointer to GMU debug dump memory Loading Loading @@ -148,7 +157,7 @@ struct gmu_device { unsigned long reg_phys; unsigned int reg_len; unsigned int gmu_interrupt_num; struct gmu_memdesc *fw_image; const struct firmware *fw_image; struct gmu_memdesc *hfi_mem; struct gmu_memdesc *bw_mem; struct gmu_memdesc *dump_mem; Loading Loading @@ -177,6 +186,5 @@ struct gmu_device { }; bool is_cached_fw_size_valid(uint32_t size_in_bytes); int allocate_gmu_image(struct gmu_device *gmu, unsigned int size); #endif /* __KGSL_GMU_H */ Loading
drivers/gpu/msm/adreno_a6xx_gmu.c +34 −50 Original line number Diff line number Diff line Loading @@ -472,12 +472,6 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) return 0; } /* * Gmu FW header format: * <32-bit start addr> <32-bit size> <32-bit pad0> <32-bit pad1> <Payload> */ #define GMU_FW_HEADER_SIZE 4 #define GMU_ITCM_VA_START 0x0 #define GMU_ITCM_VA_END (GMU_ITCM_VA_START + 0x4000) /* 16 KB */ Loading @@ -490,50 +484,52 @@ static int a6xx_rpmh_power_off_gpu(struct kgsl_device *device) static int load_gmu_fw(struct kgsl_device *device) { struct gmu_device *gmu = KGSL_GMU_DEVICE(device); uint32_t *fwptr = gmu->fw_image->hostptr; int i, j; int start_addr, size_in_bytes, num_dwords, tcm_slot, num_records; uint8_t *fw = (uint8_t *)gmu->fw_image->data; struct gmu_block_header *blk; uint32_t *fwptr; int j; int tcm_slot; while (fw < (uint8_t *)gmu->fw_image->data + gmu->fw_image->size) { blk = (struct gmu_block_header *)fw; fw += sizeof(*blk); /* Don't deal with zero size blocks */ if (blk->size == 0) continue; if ((blk->addr >= GMU_ITCM_VA_START) && (blk->addr < GMU_ITCM_VA_END)) { fwptr = (uint32_t *)fw; tcm_slot = (blk->addr - GMU_ITCM_VA_START) / sizeof(uint32_t); /* * Read first record. pad0 field of first record contains * number of records in the image. */ num_records = fwptr[2]; for (i = 0; i < num_records; i++) { start_addr = fwptr[0]; size_in_bytes = fwptr[1]; num_dwords = size_in_bytes / sizeof(uint32_t); fwptr += GMU_FW_HEADER_SIZE; if ((start_addr >= GMU_ITCM_VA_START) && (start_addr < GMU_ITCM_VA_END)) { tcm_slot = start_addr / sizeof(uint32_t); for (j = 0; j < num_dwords; j++) for (j = 0; j < blk->size / sizeof(uint32_t); j++) gmu_core_regwrite(device, A6XX_GMU_CM3_ITCM_START + tcm_slot + j, fwptr[j]); } else if ((start_addr >= GMU_DTCM_VA_START) && (start_addr < GMU_DTCM_VA_END)) { tcm_slot = (start_addr - GMU_DTCM_VA_START) } else if ((blk->addr >= GMU_DTCM_VA_START) && (blk->addr < GMU_DTCM_VA_END)) { fwptr = (uint32_t *)fw; tcm_slot = (blk->addr - GMU_DTCM_VA_START) / sizeof(uint32_t); for (j = 0; j < num_dwords; j++) for (j = 0; j < blk->size / sizeof(uint32_t); j++) gmu_core_regwrite(device, A6XX_GMU_CM3_DTCM_START + tcm_slot + j, fwptr[j]); } else if ((start_addr >= GMU_ICACHE_VA_START) && (start_addr < GMU_ICACHE_VA_END)) { if (!is_cached_fw_size_valid(size_in_bytes)) { } else if ((blk->addr >= GMU_ICACHE_VA_START) && (blk->addr < GMU_ICACHE_VA_END)) { if (!is_cached_fw_size_valid(blk->size)) { dev_err(&gmu->pdev->dev, "GMU firmware size too big\n"); return -EINVAL; } memcpy(gmu->icache_mem->hostptr, fwptr, size_in_bytes); memcpy(gmu->icache_mem->hostptr, fw, blk->size); } fwptr += num_dwords; fw += blk->size; } /* Proceed only after the FW is written */ Loading Loading @@ -1044,11 +1040,10 @@ static int a6xx_gmu_fw_start(struct kgsl_device *device, */ static int a6xx_gmu_load_firmware(struct kgsl_device *device) { const struct firmware *fw = NULL; const struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct gmu_device *gmu = KGSL_GMU_DEVICE(device); const struct adreno_gpu_core *gpucore = adreno_dev->gpucore; int image_size, ret = -EINVAL; int ret = -EINVAL; /* there is no GMU */ if (!gmu_core_isenabled(device)) Loading @@ -1061,22 +1056,11 @@ static int a6xx_gmu_load_firmware(struct kgsl_device *device) if (gpucore->gpmufw_name == NULL) return -EINVAL; ret = request_firmware(&fw, gpucore->gpmufw_name, device->dev); if (ret || fw == NULL) { ret = request_firmware(&gmu->fw_image, gpucore->gpmufw_name, device->dev); if (ret || gmu->fw_image == NULL) KGSL_CORE_ERR("request_firmware (%s) failed: %d\n", gpucore->gpmufw_name, ret); return ret; } image_size = PAGE_ALIGN(fw->size); ret = allocate_gmu_image(gmu, image_size); /* load into shared memory with GMU */ if (!ret) memcpy(gmu->fw_image->hostptr, fw->data, fw->size); release_firmware(fw); return ret; } Loading
drivers/gpu/msm/kgsl_gmu.c +5 −21 Original line number Diff line number Diff line Loading @@ -235,26 +235,6 @@ static struct gmu_memdesc *allocate_gmu_kmem(struct gmu_device *gmu, return md; } /* * allocate_gmu_image() - allocates & maps memory for FW image, the size * shall come from the loaded f/w file. * @gmu: Pointer to GMU device * @size: Requested allocation size */ int allocate_gmu_image(struct gmu_device *gmu, unsigned int size) { /* Allocates & maps memory for GMU FW */ gmu->fw_image = allocate_gmu_kmem(gmu, GMU_NONCACHED_KERNEL, size, (IOMMU_READ | IOMMU_PRIV)); if (IS_ERR(gmu->fw_image)) { dev_err(&gmu->pdev->dev, "GMU firmware image allocation failed\n"); return -EINVAL; } return 0; } /* Checks if cached fw code size falls within the cached code segment range */ bool is_cached_fw_size_valid(uint32_t size_in_bytes) { Loading Loading @@ -360,7 +340,6 @@ static void gmu_kmem_close(struct gmu_device *gmu) gmu->hfi_mem = NULL; gmu->bw_mem = NULL; gmu->dump_mem = NULL; gmu->fw_image = NULL; gmu->gmu_log = NULL; /* Unmap all memories in GMU kernel memory pool */ Loading Loading @@ -1629,6 +1608,11 @@ static void gmu_remove(struct kgsl_device *device) gmu->pcl = 0; } if (gmu->fw_image) { release_firmware(gmu->fw_image); gmu->fw_image = NULL; } gmu_memory_close(gmu); for (i = 0; i < MAX_GMU_CLKS; i++) { Loading
drivers/gpu/msm/kgsl_gmu.h +11 −3 Original line number Diff line number Diff line Loading @@ -14,6 +14,7 @@ #define __KGSL_GMU_H #include "kgsl_gmu_core.h" #include <linux/firmware.h> #include "kgsl_hfi.h" #define MAX_GMUFW_SIZE 0x2000 /* in bytes */ Loading Loading @@ -55,6 +56,14 @@ #define OOB_BOOT_OPTION 0 #define OOB_SLUMBER_OPTION 1 /* Gmu FW block header format */ struct gmu_block_header { uint32_t addr; uint32_t size; uint32_t type; uint32_t value; }; /* For GMU Logs*/ #define LOGMEM_SIZE SZ_4K Loading Loading @@ -112,7 +121,7 @@ enum gmu_load_mode { * @reg_phys: GMU CSR physical address * @reg_len: GMU CSR range * @gmu_interrupt_num: GMU interrupt number * @fw_image: descriptor of GMU memory that has GMU image in it * @fw_image: GMU FW image * @hfi_mem: pointer to HFI shared memory * @bw_mem: pointer to BW data indirect buffer memory * @dump_mem: pointer to GMU debug dump memory Loading Loading @@ -148,7 +157,7 @@ struct gmu_device { unsigned long reg_phys; unsigned int reg_len; unsigned int gmu_interrupt_num; struct gmu_memdesc *fw_image; const struct firmware *fw_image; struct gmu_memdesc *hfi_mem; struct gmu_memdesc *bw_mem; struct gmu_memdesc *dump_mem; Loading Loading @@ -177,6 +186,5 @@ struct gmu_device { }; bool is_cached_fw_size_valid(uint32_t size_in_bytes); int allocate_gmu_image(struct gmu_device *gmu, unsigned int size); #endif /* __KGSL_GMU_H */