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

Commit 592d8c8c authored by Mihail Atanassov's avatar Mihail Atanassov Committed by Liviu Dudau
Browse files

drm: mali-dp: Check hw version matches device-tree



Refuse to bind if the device-tree compatible string
lists a different hardware version.

Reviewed-by: default avatarBrian Starkey <brian.starkey@arm.com>
Signed-off-by: default avatarMihail Atanassov <mihail.atanassov@arm.com>
Signed-off-by: default avatarLiviu Dudau <Liviu.Dudau@arm.com>
parent 6211b486
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -255,6 +255,46 @@ static const struct of_device_id malidp_drm_of_match[] = {
};
MODULE_DEVICE_TABLE(of, malidp_drm_of_match);

static bool malidp_is_compatible_hw_id(struct malidp_hw_device *hwdev,
				       const struct of_device_id *dev_id)
{
	u32 core_id;
	const char *compatstr_dp500 = "arm,mali-dp500";
	bool is_dp500;
	bool dt_is_dp500;

	/*
	 * The DP500 CORE_ID register is in a different location, so check it
	 * first. If the product id field matches, then this is DP500, otherwise
	 * check the DP550/650 CORE_ID register.
	 */
	core_id = malidp_hw_read(hwdev, MALIDP500_DC_BASE + MALIDP_DE_CORE_ID);
	/* Offset 0x18 will never read 0x500 on products other than DP500. */
	is_dp500 = (MALIDP_PRODUCT_ID(core_id) == 0x500);
	dt_is_dp500 = strnstr(dev_id->compatible, compatstr_dp500,
			      sizeof(dev_id->compatible)) != NULL;
	if (is_dp500 != dt_is_dp500) {
		DRM_ERROR("Device-tree expects %s, but hardware %s DP500.\n",
			  dev_id->compatible, is_dp500 ? "is" : "is not");
		return false;
	} else if (!dt_is_dp500) {
		u16 product_id;
		char buf[32];

		core_id = malidp_hw_read(hwdev,
					 MALIDP550_DC_BASE + MALIDP_DE_CORE_ID);
		product_id = MALIDP_PRODUCT_ID(core_id);
		snprintf(buf, sizeof(buf), "arm,mali-dp%X", product_id);
		if (!strnstr(dev_id->compatible, buf,
			     sizeof(dev_id->compatible))) {
			DRM_ERROR("Device-tree expects %s, but hardware is DP%03X.\n",
				  dev_id->compatible, product_id);
			return false;
		}
	}
	return true;
}

#define MAX_OUTPUT_CHANNELS	3

static int malidp_bind(struct device *dev)
@@ -265,6 +305,7 @@ static int malidp_bind(struct device *dev)
	struct malidp_drm *malidp;
	struct malidp_hw_device *hwdev;
	struct platform_device *pdev = to_platform_device(dev);
	struct of_device_id const *dev_id;
	/* number of lines for the R, G and B output */
	u8 output_width[MAX_OUTPUT_CHANNELS];
	int ret = 0, i;
@@ -327,6 +368,17 @@ static int malidp_bind(struct device *dev)
	clk_prepare_enable(hwdev->aclk);
	clk_prepare_enable(hwdev->mclk);

	dev_id = of_match_device(malidp_drm_of_match, dev);
	if (!dev_id) {
		ret = -EINVAL;
		goto query_hw_fail;
	}

	if (!malidp_is_compatible_hw_id(hwdev, dev_id)) {
		ret = -EINVAL;
		goto query_hw_fail;
	}

	ret = hwdev->query_hw(hwdev);
	if (ret) {
		DRM_ERROR("Invalid HW configuration\n");
+2 −0
Original line number Diff line number Diff line
@@ -92,6 +92,8 @@
#define MALIDP_DE_H_ACTIVE(x)		(((x) & 0x1fff) << 0)
#define MALIDP_DE_V_ACTIVE(x)		(((x) & 0x1fff) << 16)

#define MALIDP_PRODUCT_ID(__core_id) ((u32)(__core_id) >> 16)

/* register offsets and bits specific to DP500 */
#define MALIDP500_DC_BASE		0x00000
#define MALIDP500_DC_CONTROL		0x0000c