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

Commit 5dc19fc2 authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Add generic functions to read efuse settings



Fuses are being increasingly used to provide SoC level configuration.
There is no common or generic way to read fuses so every leaf driver
is left to their own devices.

Add a set of generic functions to map and read efuse memory. Use
adreno_efuse_read_u32() to map/read/unmap a single address. If you
need to read more than one address at a time bracket the reads with
adreno_efuse_map() and adreno_efuse_unmap() to save multiple ioremaps
in a row.

Change-Id: Ic0dedbad951d323193e07e7a47ee8e7517738c9d
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent 58783aac
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -10,7 +10,9 @@ Required properties:
- reg-names:		Resource names used for the physical address of device registers
			and shader memory. "kgsl_3d0_reg_memory" gives the physical address
			and length of device registers while "kgsl_3d0_shader_memory" gives
			physical address and length of device shader memory.
			physical address and length of device shader memory.  If
			specified, "qfprom_memory" gives the range for the efuse
			registers used for various configuration options.
- interrupts:		Interrupt mapping for GPU IRQ.
- interrupt-names:	String property to describe the name of the interrupt.
- qcom,id:		An integer used as an identification number for the device.
@@ -34,7 +36,6 @@ Required properties:
				"alt_mem_iface_clk", "rbbmtimer_clk",  "alwayson_clk"
				"core_clk" and "iface_clk" are required and others are optional

- qcom,gpu-efuse-leakage:	memory region for GPU power rail leakage.
- qcom,base-leakage-coefficient: Dynamic leakage coefficient.
- qcom,lm-limit:	Current limit for GPU limit management.

+3 −3
Original line number Diff line number Diff line
@@ -54,14 +54,14 @@
		label = "kgsl-3d0";
		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
		status = "ok";
		reg = <0xb00000 0x3f000>;
		reg-names = "kgsl_3d0_reg_memory";
		reg = <0xb00000 0x3f000
		       0x070000 0x0343C>;
		reg-names = "kgsl_3d0_reg_memory", "qfprom_memory";
		interrupts = <0 300 0>;
		interrupt-names = "kgsl_3d0_irq";
		qcom,id = <0>;

		qcom,chipid = <0x05030000>;
		qcom,gpu-efuse-leakage = <0x00070130 24>;
		qcom,base-leakage-coefficient = <34>;
		qcom,lm-limit = <6000>;

+63 −5
Original line number Diff line number Diff line
@@ -176,6 +176,58 @@ static inline int adreno_of_read_property(struct device_node *node,
	return ret;
}

static void __iomem *efuse_base;
static size_t efuse_len;

int adreno_efuse_map(struct adreno_device *adreno_dev)
{
	struct kgsl_device *device = &adreno_dev->dev;
	struct resource *res;

	if (efuse_base != NULL)
		return 0;

	res = platform_get_resource_byname(device->pdev, IORESOURCE_MEM,
		"qfprom_memory");

	if (res == NULL)
		return -ENODEV;

	efuse_base = ioremap(res->start, resource_size(res));
	if (efuse_base == NULL)
		return -ENODEV;

	efuse_len = resource_size(res);
	return 0;
}

void adreno_efuse_unmap(struct adreno_device *adreno_dev)
{
	if (efuse_base != NULL) {
		iounmap(efuse_base);
		efuse_base = NULL;
		efuse_len = 0;
	}
}

int adreno_efuse_read_u32(struct adreno_device *adreno_dev, unsigned int offset,
		unsigned int *val)
{
	if (efuse_base == NULL)
		return -ENODEV;

	if (offset >= efuse_len)
		return -ERANGE;

	if (val != NULL) {
		*val = readl_relaxed(efuse_base + offset);
		/* Make sure memory is updated before returning */
		rmb();
	}

	return 0;
}

/*
 * adreno_iommu_cb_probe() - Adreno iommu context bank probe
 *
@@ -751,8 +803,10 @@ adreno_identify_gpu(struct adreno_device *adreno_dev)
		if (reg_offsets->offset_0 != i && !reg_offsets->offsets[i])
			reg_offsets->offsets[i] = ADRENO_REG_UNUSED;
	}
	if (gpudev->gpudev_init)
		gpudev->gpudev_init(adreno_dev);

	/* Do target specific identification */
	if (gpudev->platform_setup != NULL)
		gpudev->platform_setup(adreno_dev);
}

static const struct platform_device_id adreno_id_table[] = {
@@ -976,15 +1030,16 @@ static int adreno_probe(struct platform_device *pdev)
	device->pdev = pdev;
	device->mmu.priv = &device_3d0_iommu;

	/* Get the chip ID from the DT and set up target specific parameters */
	adreno_identify_gpu(adreno_dev);

	/* Get the rest of the device tree */
	status = adreno_of_get_pdata(pdev);
	if (status) {
		device->pdev = NULL;
		return status;
	}

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

	/* Bro, do you even 64 bit? */
	if (ADRENO_FEATURE(adreno_dev, ADRENO_64BIT))
		device->mmu.features |= KGSL_MMU_64BIT;
@@ -1094,6 +1149,9 @@ static int adreno_remove(struct platform_device *pdev)
	kfree(adreno_ft_regs_val);
	adreno_ft_regs_val = NULL;

	if (efuse_base != NULL)
		iounmap(efuse_base);

	adreno_perfcounter_close(adreno_dev);
	kgsl_device_platform_remove(device);

+6 −1
Original line number Diff line number Diff line
@@ -659,7 +659,7 @@ struct adreno_gpudev {
	/* GPU specific function hooks */
	void (*irq_trace)(struct adreno_device *, unsigned int status);
	void (*snapshot)(struct adreno_device *, struct kgsl_snapshot *);
	void (*gpudev_init)(struct adreno_device *);
	void (*platform_setup)(struct adreno_device *);
	int (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *);
	int (*hw_init)(struct adreno_device *);
	int (*switch_to_unsecure_mode)(struct adreno_device *,
@@ -860,6 +860,11 @@ long adreno_ioctl_perfcounter_get(struct kgsl_device_private *dev_priv,
long adreno_ioctl_perfcounter_put(struct kgsl_device_private *dev_priv,
	unsigned int cmd, void *data);

int adreno_efuse_map(struct adreno_device *adreno_dev);
int adreno_efuse_read_u32(struct adreno_device *adreno_dev, unsigned int offset,
		unsigned int *val);
void adreno_efuse_unmap(struct adreno_device *adreno_dev);

#define ADRENO_TARGET(_name, _id) \
static inline int adreno_is_##_name(struct adreno_device *adreno_dev) \
{ \
+2 −7
Original line number Diff line number Diff line
@@ -606,11 +606,7 @@ int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev)
	return 0;
}

/*
 * a3xx_gpudev_init() - Initialize gpudev specific fields
 * @adreno_dev: Pointer to adreno device
 */
static void a3xx_gpudev_init(struct adreno_device *adreno_dev)
static void a3xx_platform_setup(struct adreno_device *adreno_dev)
{
	struct adreno_gpudev *gpudev;
	const struct adreno_reg_offsets *reg_offsets;
@@ -1837,8 +1833,7 @@ struct adreno_gpudev adreno_a3xx_gpudev = {
	.snapshot_data = &a3xx_snapshot_data,
	.num_prio_levels = 1,
	.vbif_xin_halt_ctrl0_mask = A3XX_VBIF_XIN_HALT_CTRL0_MASK,

	.gpudev_init = a3xx_gpudev_init,
	.platform_setup = a3xx_platform_setup,
	.rb_init = a3xx_rb_init,
	.microcode_read = a3xx_microcode_read,
	.microcode_load = a3xx_microcode_load,
Loading