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

Commit cc32bcca authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: kgsl: Add support for iommu V2 programming for A4xx"

parents 3a000b9d cad1c57a
Loading
Loading
Loading
Loading
+132 −10
Original line number Diff line number Diff line
@@ -948,7 +948,8 @@ static unsigned int _adreno_iommu_setstate_v1(struct kgsl_device *device,
	return cmds - cmds_orig;
}

static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device,

static unsigned int _adreno_iommu_setstate_v2_a3xx(struct kgsl_device *device,
					unsigned int *cmds_orig,
					phys_addr_t pt_val,
					int num_iommu_units, uint32_t flags)
@@ -1046,10 +1047,6 @@ static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device,
			tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i,
					KGSL_IOMMU_CONTEXT_USER,
					KGSL_IOMMU_CTX_TLBSTATUS) >> 2;
			if (adreno_is_a4xx(adreno_dev))
				cmds += adreno_wait_reg_mem(cmds, tlbstatus, 0,
					KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF);
			else
			cmds += adreno_wait_reg_eq(cmds, tlbstatus, 0,
					KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF);
			/* release all commands with wait_for_me */
@@ -1062,6 +1059,127 @@ static unsigned int _adreno_iommu_setstate_v2(struct kgsl_device *device,

	return cmds - cmds_orig;
}


static unsigned int _adreno_iommu_setstate_v2_a4xx(struct kgsl_device *device,
					unsigned int *cmds_orig,
					phys_addr_t pt_val,
					int num_iommu_units, uint32_t flags)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	uint64_t ttbr0_val;
	unsigned int reg_pt_val;
	unsigned int *cmds = cmds_orig;
	int i;
	unsigned int ttbr0, tlbiall, tlbstatus, tlbsync;

	cmds += adreno_add_idle_cmds(adreno_dev, cmds);

	for (i = 0; i < num_iommu_units; i++) {
		ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu,
				i, KGSL_IOMMU_CONTEXT_USER);
		ttbr0_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK;
		ttbr0_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK);
		if (flags & KGSL_MMUFLAGS_PTUPDATE) {

			ttbr0 = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i,
						KGSL_IOMMU_CONTEXT_USER,
						KGSL_IOMMU_CTX_TTBR0) >> 2;

			/*
			 * glue commands together until next
			 * WAIT_FOR_ME
			 */
			cmds += adreno_wait_reg_mem(cmds,
					adreno_getreg(adreno_dev,
						ADRENO_REG_CP_WFI_PEND_CTR),
						1, 0xFFFFFFFF, 0xF);

			/* MMU-500 VBIF stall */
			*cmds++ = cp_type3_packet(CP_REG_RMW, 3);
			*cmds++ = A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL0;
			/* AND to unmask the HALT bit */
			*cmds++ = ~(VBIF_RECOVERABLE_HALT_CTRL);
			/* OR to set the HALT bit */
			*cmds++ = 0x1;

			/* Wait for acknowledgement */
			cmds += adreno_wait_reg_mem(cmds,
				A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL1,
					1, 0xFFFFFFFF, 0xF);

			/* set ttbr0 */
			if (sizeof(phys_addr_t) >
				sizeof(unsigned int)) {

				reg_pt_val =
					ttbr0_val & 0xFFFFFFFF;
				*cmds++ =
				cp_type3_packet(CP_WIDE_REG_WRITE, 2);
				*cmds++ = ttbr0;
				*cmds++ = reg_pt_val;

				reg_pt_val = (unsigned int)
				((ttbr0_val &
				0xFFFFFFFF00000000ULL) >> 32);
				*cmds++ =
				cp_type3_packet(CP_WIDE_REG_WRITE, 2);
				*cmds++ = ttbr0+1;
				*cmds++ = reg_pt_val;
			} else {

				reg_pt_val = ttbr0_val;
				*cmds++ =
				cp_type3_packet(CP_WIDE_REG_WRITE, 2);
				*cmds++ = ttbr0;
				*cmds++ = reg_pt_val;
			}

			/* MMU-500 VBIF unstall */
			*cmds++ = cp_type3_packet(CP_REG_RMW, 3);
			*cmds++ = A3XX_VBIF_DDR_OUTPUT_RECOVERABLE_HALT_CTRL0;
			/* AND to unmask the HALT bit */
			*cmds++ = ~(VBIF_RECOVERABLE_HALT_CTRL);
			/* OR to reset the HALT bit */
			*cmds++ = 0;

			/* release all commands with wait_for_me */
			*cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
			*cmds++ = 0;

		}
		if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
			tlbiall = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i,
						KGSL_IOMMU_CONTEXT_USER,
						KGSL_IOMMU_CTX_TLBIALL) >> 2;

			*cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2);
			*cmds++ = tlbiall;
			*cmds++ = 1;

			tlbsync = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i,
						KGSL_IOMMU_CONTEXT_USER,
						KGSL_IOMMU_CTX_TLBSYNC) >> 2;

			*cmds++ = cp_type3_packet(CP_WIDE_REG_WRITE, 2);
			*cmds++ = tlbsync;
			*cmds++ = 0;

			tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i,
					KGSL_IOMMU_CONTEXT_USER,
					KGSL_IOMMU_CTX_TLBSTATUS) >> 2;
			cmds += adreno_wait_reg_mem(cmds, tlbstatus, 0,
					KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF);
			/* release all commands with wait_for_me */
			*cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
			*cmds++ = 0;
		}
	}

	cmds += adreno_add_idle_cmds(adreno_dev, cmds);

	return cmds - cmds_orig;
}
/**
 * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu?
 * @adreno_dev: the device
@@ -1123,8 +1241,12 @@ static int adreno_iommu_setstate(struct kgsl_device *device,
		KGSL_IOMMU_SETSTATE_NOP_OFFSET);

	if (kgsl_msm_supports_iommu_v2())
		cmds += _adreno_iommu_setstate_v2(device, cmds, pt_val,
						num_iommu_units, flags);
		if (adreno_is_a4xx(adreno_dev))
			cmds += _adreno_iommu_setstate_v2_a4xx(device, cmds,
					pt_val, num_iommu_units, flags);
		else
			cmds += _adreno_iommu_setstate_v2_a3xx(device, cmds,
					pt_val, num_iommu_units, flags);
	else if (msm_soc_version_supports_iommu_v0())
		cmds += _adreno_iommu_setstate_v0(device, cmds, pt_val,
						num_iommu_units, flags);
@@ -1554,6 +1676,9 @@ int adreno_probe(struct platform_device *pdev)
		return status;
	}

	/* Identify the specific GPU */
	adreno_identify_gpu(adreno_dev);

	status = kgsl_device_platform_probe(device);
	if (status) {
		device->pdev = NULL;
@@ -1640,9 +1765,6 @@ static int adreno_init(struct kgsl_device *device)
	if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv))
		return 0;

	/* Identify the specific GPU */
	adreno_identify_gpu(adreno_dev);

	gpudev = ADRENO_GPU_DEVICE(adreno_dev);

	/* Power up the device */
+7 −0
Original line number Diff line number Diff line
@@ -153,6 +153,13 @@
/* Write register, ignoring context state for context sensitive registers */
#define CP_REG_WR_NO_CTXT  0x78

/*
 * for A4xx
 * Write to register with address that does not fit into type-0 pkt
 */
#define CP_WIDE_REG_WRITE           0x74


/* PFP waits until the FIFO between the PFP and the ME is empty */
#define CP_WAIT_FOR_ME		0x13

+16 −3
Original line number Diff line number Diff line
@@ -1174,6 +1174,8 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu)
	struct kgsl_iommu *iommu = mmu->device->mmu.priv;
	struct kgsl_iommu_unit *iommu_unit;
	int i = 0, ret = 0;
	struct kgsl_device *device = mmu->device;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);

	for (; i < pdata->iommu_count; i++) {
		struct kgsl_device_iommu_data data = pdata->iommu_data[i];
@@ -1209,6 +1211,10 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu)
			iommu_unit->iommu_halt_enable = 1;

		if (kgsl_msm_supports_iommu_v2())
			if (adreno_is_a405(adreno_dev)) {
				iommu_unit->ahb_base =
					KGSL_IOMMU_V2_AHB_BASE_A405;
			} else
				iommu_unit->ahb_base = KGSL_IOMMU_V2_AHB_BASE;
		else
			iommu_unit->ahb_base =
@@ -2146,12 +2152,19 @@ static void kgsl_iommu_set_pagefault(struct kgsl_mmu *mmu)
struct kgsl_protected_registers *kgsl_iommu_get_prot_regs(struct kgsl_mmu *mmu)
{
	static struct kgsl_protected_registers iommuv1_regs = { 0x4000, 14 };
	static struct kgsl_protected_registers iommuv2_regs = { 0x2800, 10 };
	static struct kgsl_protected_registers iommuv2_regs;

	if (msm_soc_version_supports_iommu_v0())
		return NULL;
	if (kgsl_msm_supports_iommu_v2())
	if (kgsl_msm_supports_iommu_v2()) {

		struct kgsl_iommu *iommu = mmu->priv;

		/* For V2 there is only one instance of iommu */
		iommuv2_regs.base = iommu->iommu_units[0].ahb_base >> 2;
		iommuv2_regs.range = 10;
		return &iommuv2_regs;
	}
	else
		return &iommuv1_regs;
}
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

/* IOMMU V2 AHB base is fixed */
#define KGSL_IOMMU_V2_AHB_BASE		0xA000
#define KGSL_IOMMU_V2_AHB_BASE_A405  0x48000
/* IOMMU_V2 AHB base points to ContextBank1 */
#define KGSL_IOMMU_CTX_AHB_OFFSET_V2   0