Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fef10555 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Store GMU firmware image in the GMU device structure"

parents 8a30fc87 b20e9b05
Loading
Loading
Loading
Loading
+34 −50
Original line number Diff line number Diff line
@@ -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 */

@@ -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 */
@@ -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))
@@ -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;
}
+5 −21
Original line number Diff line number Diff line
@@ -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)
{
@@ -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 */
@@ -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++) {
+11 −3
Original line number Diff line number Diff line
@@ -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 */
@@ -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

@@ -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
@@ -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;
@@ -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 */