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

Commit dc781889 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: Clear pending GMU IRQs before enabling" into msm-4.9

parents 8c6269f9 e7b06b43
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -718,9 +718,9 @@
#define A6XX_GMU_GENERAL_7			0x1F9CC

#define A6XX_GMU_AO_INTERRUPT_EN		0x23B03
#define A6XX_GMU_HOST_INTERRUPT_CLR		0x23B04
#define A6XX_GMU_HOST_INTERRUPT_STATUS		0x23B05
#define A6XX_GMU_HOST_INTERRUPT_MASK		0x23B06
#define A6XX_GMU_AO_HOST_INTERRUPT_CLR		0x23B04
#define A6XX_GMU_AO_HOST_INTERRUPT_STATUS	0x23B05
#define A6XX_GMU_AO_HOST_INTERRUPT_MASK		0x23B06
#define A6XX_GPU_GMU_AO_GPU_CX_BUSY_STATUS	0x23B0C
#define A6XX_GMU_AHB_FENCE_STATUS		0x23B13
#define A6XX_GMU_RBBM_INT_UNMASKED_STATUS	0x23B15
+4 −3
Original line number Diff line number Diff line
@@ -618,9 +618,9 @@ enum adreno_regs {
	ADRENO_REG_VBIF_XIN_HALT_CTRL1,
	ADRENO_REG_VBIF_VERSION,
	ADRENO_REG_GMU_AO_INTERRUPT_EN,
	ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
	ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
	ADRENO_REG_GMU_HOST_INTERRUPT_MASK,
	ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
	ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS,
	ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
	ADRENO_REG_GMU_PWR_COL_KEEPALIVE,
	ADRENO_REG_GMU_AHB_FENCE_STATUS,
	ADRENO_REG_GMU_RPMH_POWER_STATE,
@@ -629,6 +629,7 @@ enum adreno_regs {
	ADRENO_REG_GMU_HFI_SFR_ADDR,
	ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
	ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
	ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
	ADRENO_REG_GMU_HOST2GMU_INTR_SET,
	ADRENO_REG_GMU_HOST2GMU_INTR_CLR,
	ADRENO_REG_GMU_HOST2GMU_INTR_RAW_INFO,
+10 −9
Original line number Diff line number Diff line
@@ -717,9 +717,8 @@ static int a6xx_gmu_hfi_start(struct kgsl_device *device)
{
	struct gmu_device *gmu = &device->gmu;

	kgsl_gmu_regwrite(device, A6XX_GMU_GMU2HOST_INTR_MASK,
			(HFI_IRQ_MASK & (~HFI_IRQ_MSGQ_MASK)));

	kgsl_gmu_regrmw(device, A6XX_GMU_GMU2HOST_INTR_MASK,
			HFI_IRQ_MSGQ_MASK, 0);
	kgsl_gmu_regwrite(device, A6XX_GMU_HFI_CTRL_INIT, 1);

	if (timed_poll_check(device,
@@ -2049,12 +2048,12 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
				A6XX_GMU_ALWAYS_ON_COUNTER_H),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_INTERRUPT_EN,
				A6XX_GMU_AO_INTERRUPT_EN),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
				A6XX_GMU_HOST_INTERRUPT_CLR),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
				A6XX_GMU_HOST_INTERRUPT_STATUS),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST_INTERRUPT_MASK,
				A6XX_GMU_HOST_INTERRUPT_MASK),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
				A6XX_GMU_AO_HOST_INTERRUPT_CLR),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS,
				A6XX_GMU_AO_HOST_INTERRUPT_STATUS),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
				A6XX_GMU_AO_HOST_INTERRUPT_MASK),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_PWR_COL_KEEPALIVE,
				A6XX_GMU_GMU_PWR_COL_KEEPALIVE),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_AHB_FENCE_STATUS,
@@ -2071,6 +2070,8 @@ static unsigned int a6xx_register_offsets[ADRENO_REG_REGISTER_MAX] = {
				A6XX_GMU_GMU2HOST_INTR_CLR),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
				A6XX_GMU_GMU2HOST_INTR_INFO),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
				A6XX_GMU_GMU2HOST_INTR_MASK),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST2GMU_INTR_SET,
				A6XX_GMU_HOST2GMU_INTR_SET),
	ADRENO_REG_DEFINE(ADRENO_REG_GMU_HOST2GMU_INTR_CLR,
+126 −72
Original line number Diff line number Diff line
@@ -748,44 +748,49 @@ static irqreturn_t gmu_irq_handler(int irq, void *data)
{
	struct gmu_device *gmu = data;
	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
	struct kgsl_hfi *hfi = &gmu->hfi;
	unsigned int status = 0;

	if (irq == gmu->gmu_interrupt_num) {
	adreno_read_gmureg(ADRENO_DEVICE(device),
				ADRENO_REG_GMU_HOST_INTERRUPT_STATUS,
				&status);
			ADRENO_REG_GMU_AO_HOST_INTERRUPT_STATUS, &status);
	adreno_write_gmureg(ADRENO_DEVICE(device),
			ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR, status);

		/* Ignore GMU_INT_RSCC_COMP interrupts */
	/* Ignore GMU_INT_RSCC_COMP and GMU_INT_DBD WAKEUP interrupts */
	if (status & GMU_INT_WDOG_BITE)
		dev_err_ratelimited(&gmu->pdev->dev,
					"GMU watchdog expired interrupt\n");
		if (status & GMU_INT_DBD_WAKEUP)
			dev_err_ratelimited(&gmu->pdev->dev,
					"GMU doorbell interrupt received\n");
				"GMU watchdog expired interrupt received\n");
	if (status & GMU_INT_HOST_AHB_BUS_ERR)
		dev_err_ratelimited(&gmu->pdev->dev,
				"AHB bus error interrupt received\n");
	if (status & ~GMU_AO_INT_MASK)
		dev_err_ratelimited(&gmu->pdev->dev,
				"Unhandled GMU interrupts 0x%lx\n",
				status & ~GMU_AO_INT_MASK);

	return IRQ_HANDLED;
}

static irqreturn_t hfi_irq_handler(int irq, void *data)
{
	struct kgsl_hfi *hfi = data;
	struct gmu_device *gmu = container_of(hfi, struct gmu_device, hfi);
	struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
	unsigned int status = 0;

		adreno_write_gmureg(ADRENO_DEVICE(device),
				ADRENO_REG_GMU_HOST_INTERRUPT_CLR,
				status);
	} else {
	adreno_read_gmureg(ADRENO_DEVICE(device),
				ADRENO_REG_GMU_GMU2HOST_INTR_INFO,
				&status);
			ADRENO_REG_GMU_GMU2HOST_INTR_INFO, &status);
	adreno_write_gmureg(ADRENO_DEVICE(device),
				ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
				status);
			ADRENO_REG_GMU_GMU2HOST_INTR_CLR, status);

		if (status & HFI_IRQ_MASK) {
	if (status & HFI_IRQ_MSGQ_MASK)
		tasklet_hi_schedule(&hfi->tasklet);
		} else
	if (status & HFI_IRQ_CM3_FAULT_MASK)
		dev_err_ratelimited(&gmu->pdev->dev,
					"Unhandled GMU interrupts %x\n",
					status);
	}
				"GMU CM3 fault interrupt received\n");
	if (status & ~HFI_IRQ_MASK)
		dev_err_ratelimited(&gmu->pdev->dev,
				"Unhandled HFI interrupts 0x%lx\n",
				status & ~HFI_IRQ_MASK);

	return IRQ_HANDLED;
}
@@ -978,6 +983,82 @@ static int gmu_regulators_probe(struct gmu_device *gmu,
	return 0;
}

static int gmu_irq_probe(struct gmu_device *gmu)
{
	int ret;
	struct kgsl_hfi *hfi = &gmu->hfi;

	hfi->hfi_interrupt_num = platform_get_irq_byname(gmu->pdev,
			"kgsl_hfi_irq");
	ret = devm_request_irq(&gmu->pdev->dev,
			hfi->hfi_interrupt_num,
			hfi_irq_handler, IRQF_TRIGGER_HIGH,
			"HFI", hfi);
	if (ret) {
		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
				hfi->hfi_interrupt_num, ret);
		return ret;
	}

	gmu->gmu_interrupt_num = platform_get_irq_byname(gmu->pdev,
			"kgsl_gmu_irq");
	ret = devm_request_irq(&gmu->pdev->dev,
			gmu->gmu_interrupt_num,
			gmu_irq_handler, IRQF_TRIGGER_HIGH,
			"GMU", gmu);
	if (ret)
		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
				gmu->gmu_interrupt_num, ret);

	return ret;
}

static void gmu_irq_enable(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct gmu_device *gmu = &device->gmu;
	struct kgsl_hfi *hfi = &gmu->hfi;

	/* Clear any pending IRQs before unmasking on GMU */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
			0xFFFFFFFF);
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
			0xFFFFFFFF);

	/* Unmask needed IRQs on GMU */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
			(unsigned int) ~HFI_IRQ_MASK);
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
			(unsigned int) ~GMU_AO_INT_MASK);

	/* Enable all IRQs on host */
	enable_irq(hfi->hfi_interrupt_num);
	enable_irq(gmu->gmu_interrupt_num);
}

static void gmu_irq_disable(struct kgsl_device *device)
{
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct gmu_device *gmu = &device->gmu;
	struct kgsl_hfi *hfi = &gmu->hfi;

	/* Disable all IRQs on host */
	disable_irq(gmu->gmu_interrupt_num);
	disable_irq(hfi->hfi_interrupt_num);

	/* Mask all IRQs on GMU */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_MASK,
			0xFFFFFFFF);
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_MASK,
			0xFFFFFFFF);

	/* Clear any pending IRQs before disabling */
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_AO_HOST_INTERRUPT_CLR,
			0xFFFFFFFF);
	adreno_write_gmureg(adreno_dev, ADRENO_REG_GMU_GMU2HOST_INTR_CLR,
			0xFFFFFFFF);
}

/* Do not access any GMU registers in GMU probe function */
int gmu_probe(struct kgsl_device *device)
{
@@ -1024,32 +1105,13 @@ int gmu_probe(struct kgsl_device *device)

	gmu->gmu2gpu_offset = (gmu->reg_phys - device->reg_phys) >> 2;

	/* Initialize HFI GMU interrupts */
	hfi->hfi_interrupt_num = platform_get_irq_byname(gmu->pdev,
						"kgsl_hfi_irq");
	ret = devm_request_irq(&gmu->pdev->dev,
				  hfi->hfi_interrupt_num,
				  gmu_irq_handler, IRQF_TRIGGER_HIGH,
				  "GMU", gmu);
	if (ret) {
		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
			      hfi->hfi_interrupt_num, ret);
		goto error;
	}

	gmu->gmu_interrupt_num = platform_get_irq_byname(gmu->pdev,
						"kgsl_gmu_irq");
	ret = devm_request_irq(&gmu->pdev->dev,
				  gmu->gmu_interrupt_num,
				  gmu_irq_handler, IRQF_TRIGGER_HIGH,
				  "GMU", gmu);
	if (ret) {
		dev_err(&gmu->pdev->dev, "request_irq(%d) failed: %d\n",
			      gmu->gmu_interrupt_num, ret);
	/* Initialize HFI and GMU interrupts */
	ret = gmu_irq_probe(gmu);
	if (ret)
		goto error;
	}

	/* Don't enable GMU interrupts until GMU started */
	/* We cannot use gmu_irq_disable because it writes registers */
	disable_irq(gmu->gmu_interrupt_num);
	disable_irq(hfi->hfi_interrupt_num);

@@ -1199,7 +1261,6 @@ int gmu_start(struct kgsl_device *device)
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
	struct gmu_device *gmu = &device->gmu;
	struct kgsl_hfi *hfi = &gmu->hfi;
	int bus_level = pwr->pwrlevels[pwr->default_pwrlevel].bus_freq;

	if (!kgsl_gmu_isenabled(device))
@@ -1234,8 +1295,7 @@ int gmu_start(struct kgsl_device *device)
		if (ret)
			goto error_bus;

		enable_irq(hfi->hfi_interrupt_num);
		enable_irq(gmu->gmu_interrupt_num);
		gmu_irq_enable(device);

		ret = hfi_start(gmu, GMU_COLD_BOOT);
		if (ret)
@@ -1253,8 +1313,7 @@ int gmu_start(struct kgsl_device *device)
		if (ret)
			goto error_clks;

		enable_irq(hfi->hfi_interrupt_num);
		enable_irq(gmu->gmu_interrupt_num);
		gmu_irq_enable(device);

		ret = hfi_start(gmu, GMU_WARM_BOOT);
		if (ret)
@@ -1292,8 +1351,7 @@ int gmu_start(struct kgsl_device *device)

error_gpu:
	hfi_stop(gmu);
	disable_irq(gmu->gmu_interrupt_num);
	disable_irq(hfi->hfi_interrupt_num);
	gmu_irq_disable(device);
	if (device->state == KGSL_STATE_INIT ||
			device->state == KGSL_STATE_SUSPEND) {
		if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
@@ -1315,7 +1373,6 @@ int gmu_start(struct kgsl_device *device)
void gmu_stop(struct kgsl_device *device)
{
	struct gmu_device *gmu = &device->gmu;
	struct kgsl_hfi *hfi = &gmu->hfi;
	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);

@@ -1333,9 +1390,7 @@ void gmu_stop(struct kgsl_device *device)
	/* Pending message in all queues are abandoned */
	hfi_stop(gmu);
	clear_bit(GMU_HFI_ON, &gmu->flags);

	disable_irq(gmu->gmu_interrupt_num);
	disable_irq(hfi->hfi_interrupt_num);
	gmu_irq_disable(device);

	gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_STOP, 0, 0);
	gmu_disable_clks(gmu);
@@ -1358,6 +1413,7 @@ void gmu_remove(struct kgsl_device *device)
	tasklet_kill(&hfi->tasklet);

	gmu_stop(device);
	gmu_irq_disable(device);

	while ((i < MAX_GMU_CLKS) && gmu->clks[i]) {
		gmu->clks[i] = NULL;
@@ -1365,14 +1421,12 @@ void gmu_remove(struct kgsl_device *device)
	}

	if (gmu->gmu_interrupt_num) {
		disable_irq(gmu->gmu_interrupt_num);
		devm_free_irq(&gmu->pdev->dev,
				gmu->gmu_interrupt_num, gmu);
		gmu->gmu_interrupt_num = 0;
	}

	if (hfi->hfi_interrupt_num) {
		disable_irq(hfi->hfi_interrupt_num);
		devm_free_irq(&gmu->pdev->dev,
				hfi->hfi_interrupt_num, gmu);
		hfi->hfi_interrupt_num = 0;
+0 −1
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@
#define GMU_INT_HOST_AHB_BUS_ERR	BIT(5)
#define GMU_AO_INT_MASK		\
		(GMU_INT_WDOG_BITE |	\
		GMU_INT_DBD_WAKEUP |	\
		GMU_INT_HOST_AHB_BUS_ERR)

#define MAX_GMUFW_SIZE	0x2000	/* in dwords */
Loading