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

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

Merge changes I02b05e78,Ib3025235,Id8a465d1,I4a61f3a0 into msm-4.14

* changes:
  msm: kgsl: Fix uninitialized variable in adreno_ringbuffer_probe()
  msm: kgsl: Directly map and read soc hardware revision efuse
  msm: kgsl: Extend the preemption keep-alive bit
  Revert "msm: kgsl: Make sure RBBM_INT_0_STATUS is not transitory"
parents 6a364ff2 628db146
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -130,6 +130,13 @@ Optional Properties:
				mask   - mask for the relevant bits in the efuse register.
				shift  - number of bits to right shift to get the disable_gpu
				fuse bit value.

- qcom,soc-hw-rev-efuse:	SOC hardware revision fuse information in the format
				<offset bit_position mask>
				offset - offset of the efuse register from the base.
				bit_position - hardware revision starting bit in the efuse register.
				mask - mask for the relevant bits in the efuse register.

- qcom,highest-bank-bit:
				Specify the bit of the highest DDR bank. This
				is programmed into protected registers and also
@@ -230,7 +237,7 @@ Properties:
		Defines a SOC hardware revision.

Properties:
- reg:
-  qcom,soc-hw-revision:
		Identifier for the hardware revision - must match the value read
		from the hardware.
- qcom,chipid:
+47 −78
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
#include <linux/input.h>
#include <linux/io.h>
#include <soc/qcom/scm.h>
#include <linux/nvmem-consumer.h>

#include <linux/msm-bus-board.h>
#include <linux/msm-bus.h>
@@ -614,7 +613,6 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
	struct adreno_irq *irq_params = gpudev->irq;
	irqreturn_t ret = IRQ_NONE;
	unsigned int status = 0, fence = 0, fence_retries = 0, tmp, int_bit;
	unsigned int status_retries = 0;
	int i;

	atomic_inc(&adreno_dev->pending_irq_refcnt);
@@ -653,32 +651,6 @@ static irqreturn_t adreno_irq_handler(struct kgsl_device *device)

	adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status);

	/*
	 * Read status again to make sure the bits aren't transitory.
	 * Transitory bits mean that they are spurious interrupts and are
	 * seen while preemption is on going. Empirical experiments have
	 * shown that the transitory bits are a timing thing and they
	 * go away in the small time window between two or three consecutive
	 * reads. If they don't go away, log the message and return.
	 */
	while (status_retries < STATUS_RETRY_MAX) {
		unsigned int new_status;

		adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS,
			&new_status);

		if (status == new_status)
			break;

		status = new_status;
		status_retries++;
	}

	if (status_retries == STATUS_RETRY_MAX) {
		KGSL_DRV_CRIT_RATELIMIT(device, "STATUS bits are not stable\n");
			return ret;
	}

	/*
	 * Clear all the interrupt bits but ADRENO_INT_RBBM_AHB_ERROR. Because
	 * even if we clear it here, it will stay high until it is cleared
@@ -774,62 +746,30 @@ static struct {
			"qcom,gpu-quirk-limit-uche-gbif-rw" },
};

#if defined(CONFIG_NVMEM) && defined(CONFIG_QCOM_QFPROM)
static struct device_node *
adreno_get_soc_hw_revision_node(struct platform_device *pdev)
adreno_get_soc_hw_revision_node(struct adreno_device *adreno_dev,
	struct platform_device *pdev)
{
	struct device_node *node, *child;
	struct nvmem_cell *cell;
	ssize_t len;
	u32 *buf, hw_rev, rev;
	unsigned int rev;

	node = of_find_node_by_name(pdev->dev.of_node, "qcom,soc-hw-revisions");
	if (node == NULL)
		goto err;

	/* read the soc hw revision and select revision node */
	cell = nvmem_cell_get(&pdev->dev, "minor_rev");
	if (IS_ERR_OR_NULL(cell)) {
		if (PTR_ERR(cell) == -EPROBE_DEFER)
			return (void *)cell;

		KGSL_CORE_ERR("Unable to get nvmem cell: ret=%ld\n",
				PTR_ERR(cell));
		goto err;
	}

	buf = nvmem_cell_read(cell, &len);
	nvmem_cell_put(cell);

	if (IS_ERR_OR_NULL(buf)) {
		KGSL_CORE_ERR("Unable to read nvmem cell: ret=%ld\n",
				PTR_ERR(buf));
		goto err;
	}

	hw_rev = *buf;
	kfree(buf);
		return NULL;

	for_each_child_of_node(node, child) {
		if (of_property_read_u32(child, "reg", &rev))
		if (of_property_read_u32(child, "qcom,soc-hw-revision", &rev))
			continue;

		if (rev == hw_rev)
		if (rev == adreno_dev->soc_hw_rev)
			return child;
	}

err:
	/* fall back to parent node */
	return pdev->dev.of_node;
}
#else
static struct device_node *
adreno_get_soc_hw_revision_node(struct platform_device *pdev)
{
	return pdev->dev.of_node;
	KGSL_DRV_WARN(KGSL_DEVICE(adreno_dev),
		"No matching SOC HW revision found for efused HW rev=%u\n",
		adreno_dev->soc_hw_rev);
	return NULL;
}
#endif


static int adreno_update_soc_hw_revision_quirks(
		struct adreno_device *adreno_dev, struct platform_device *pdev)
@@ -837,9 +777,9 @@ static int adreno_update_soc_hw_revision_quirks(
	struct device_node *node;
	int i;

	node = adreno_get_soc_hw_revision_node(pdev);
	if (IS_ERR(node))
		return PTR_ERR(node);
	node = adreno_get_soc_hw_revision_node(adreno_dev, pdev);
	if (node == NULL)
		node = pdev->dev.of_node;

	/* get chip id, fall back to parent if revision node does not have it */
	if (of_property_read_u32(node, "qcom,chipid", &adreno_dev->chipid))
@@ -1172,6 +1112,36 @@ static void adreno_cx_dbgc_probe(struct kgsl_device *device)
		KGSL_DRV_WARN(device, "cx_dbgc ioremap failed\n");
}

static void adreno_efuse_read_soc_hw_rev(struct adreno_device *adreno_dev)
{
	unsigned int val;
	unsigned int soc_hw_rev[3];
	int ret;

	if (of_property_read_u32_array(
		KGSL_DEVICE(adreno_dev)->pdev->dev.of_node,
		"qcom,soc-hw-rev-efuse", soc_hw_rev, 3))
		return;

	ret = adreno_efuse_map(adreno_dev);
	if (ret) {
		KGSL_CORE_ERR(
			"Unable to map hardware revision fuse: ret=%d\n", ret);
		return;
	}

	ret = adreno_efuse_read_u32(adreno_dev, soc_hw_rev[0], &val);
	adreno_efuse_unmap(adreno_dev);

	if (ret) {
		KGSL_CORE_ERR(
			"Unable to read hardware revision fuse: ret=%d\n", ret);
		return;
	}

	adreno_dev->soc_hw_rev = (val >> soc_hw_rev[1]) & soc_hw_rev[2];
}

static bool adreno_is_gpu_disabled(struct adreno_device *adreno_dev)
{
	unsigned int row0;
@@ -1221,11 +1191,10 @@ static int adreno_probe(struct platform_device *pdev)
		return -ENODEV;
	}

	status = adreno_update_soc_hw_revision_quirks(adreno_dev, pdev);
	if (status) {
		device->pdev = NULL;
		return status;
	}
	/* Identify SOC hardware revision to be used */
	adreno_efuse_read_soc_hw_rev(adreno_dev);

	adreno_update_soc_hw_revision_quirks(adreno_dev, pdev);

	/* Get the chip ID from the DT and set up target specific parameters */
	adreno_identify_gpu(adreno_dev);
+2 −3
Original line number Diff line number Diff line
@@ -175,9 +175,6 @@
/* Number of times to poll the AHB fence in ISR */
#define FENCE_RETRY_MAX 100

/* Number of times to see if INT_0_STATUS changed or not */
#define STATUS_RETRY_MAX 3

/* One cannot wait forever for the core to idle, so set an upper limit to the
 * amount of time to wait for the core to go idle
 */
@@ -469,6 +466,7 @@ enum gpu_coresight_sources {
 * @gpuhtw_llc_slice: GPU pagetables system cache slice descriptor
 * @gpuhtw_llc_slice_enable: To enable the GPUHTW system cache slice or not
 * @zap_loaded: Used to track if zap was successfully loaded or not
 * @soc_hw_rev: Indicate which SOC hardware revision to use
 */
struct adreno_device {
	struct kgsl_device dev;    /* Must be first field in this struct */
@@ -541,6 +539,7 @@ struct adreno_device {
	void *gpuhtw_llc_slice;
	bool gpuhtw_llc_slice_enable;
	unsigned int zap_loaded;
	unsigned int soc_hw_rev;
};

/**
+7 −8
Original line number Diff line number Diff line
@@ -366,14 +366,6 @@ void a6xx_preemption_trigger(struct adreno_device *adreno_dev)
	/* Trigger the preemption */
	adreno_gmu_fenced_write(adreno_dev, ADRENO_REG_CP_PREEMPT, cntl,
		FENCE_STATUS_WRITEDROPPED1_MASK);

	/*
	 * Once preemption has been requested with the final register write,
	 * the preemption process starts and the GPU is considered busy.
	 * We can now safely clear the preemption keepalive bit, allowing
	 * power collapse to resume its regular activity.
	 */
	kgsl_gmu_regrmw(device, A6XX_GMU_AO_SPARE_CNTL, 0x2, 0x0);
}

void a6xx_preemption_callback(struct adreno_device *adreno_dev, int bit)
@@ -401,6 +393,13 @@ void a6xx_preemption_callback(struct adreno_device *adreno_dev, int bit)
		return;
	}

	/*
	 * We can now safely clear the preemption keepalive bit, allowing
	 * power collapse to resume its regular activity.
	 */
	kgsl_gmu_regrmw(KGSL_DEVICE(adreno_dev), A6XX_GMU_AO_SPARE_CNTL, 0x2,
			0x0);

	del_timer(&adreno_dev->preempt.timer);

	adreno_readreg(adreno_dev, ADRENO_REG_CP_PREEMPT_LEVEL_STATUS, &status);
+2 −1
Original line number Diff line number Diff line
@@ -262,7 +262,8 @@ int adreno_ringbuffer_probe(struct adreno_device *adreno_dev, bool nopreempt)
{
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
	int i, status;
	int i;
	int status = -ENOMEM;

	if (!adreno_is_a3xx(adreno_dev)) {
		status = kgsl_allocate_global(device, &device->scratch,