soc: imx: Get iMX8MQ revision for B0 from ATF
diff mbox series

Message ID d85c6cfe79f9fc1e7761c952e29dfb2f71cff2c1.1556891520.git.agx@sigxcpu.org
State New
Headers show
Series
  • soc: imx: Get iMX8MQ revision for B0 from ATF
Related show

Commit Message

Guido Günther May 3, 2019, 1:53 p.m. UTC
This is similar to what the BSP does and needed to e.g. determine
necessary quirks for MIPI DSI.

Signed-off-by: Guido Günther <agx@sigxcpu.org>

---
From the list discussion and changelog it's not clear to me why a
different method was chosen for the B1 silicon so I left that in place
as is and only trigger on the B0 silicon I have here.
---
 drivers/soc/imx/soc-imx8.c | 49 ++++++++++++++++++++++++++++----------
 1 file changed, 37 insertions(+), 12 deletions(-)

Comments

Leonard Crestez May 7, 2019, 10:24 a.m. UTC | #1
On 03.05.2019 16:53, Guido Günther wrote:
> This is similar to what the BSP does and needed to e.g. determine
> necessary quirks for MIPI DSI.
> 
> Signed-off-by: Guido Günther <agx@sigxcpu.org>
> 
>  From the list discussion and changelog it's not clear to me why a
> different method was chosen for the B1 silicon so I left that in place
> as is and only trigger on the B0 silicon I have here.

Fetching revision without an ATF call was done for the sake of avoiding 
depending on ATF as much as vendor tree does. I'm not sure avoiding ATF 
dependencies is a good approach.

The imx8mq reference manual claims that 0x3036006c is should be soc 
revision but that incorrectly reports 0x00824010 meaning "A0" on all 
chips. So some nasty hacks are done in ATF instead by poking at ROM and 
OCOTP.

There were multiple discussions also for GPCv2 and 8mm about how much to 
rely on firmware. I personally think that duplicating ATF workarounds 
just makes supporting imx8m harder in Linux. Don't we want firmware to 
help us with silicon erratas?

> +#define IMX8MQ_ATF_GET_SOC_INFO		0xc2000006

Any reason not to use original FSL_SIP_GET_SOC_INFO constant name?

Since ATF can fetch revision for B1 as well it makes no sense to keep 
the old code if we switch to using a SIP call, just call ATF always.

ATF upstream currently has 8mq support but no SIP call for GET_SOC_INFO, 
that could be added easily.

--
Regards,
Leonard

Patch
diff mbox series

diff --git a/drivers/soc/imx/soc-imx8.c b/drivers/soc/imx/soc-imx8.c
index fc6429f9170a..363acd1151ee 100644
--- a/drivers/soc/imx/soc-imx8.c
+++ b/drivers/soc/imx/soc-imx8.c
@@ -3,6 +3,7 @@ 
  * Copyright 2019 NXP.
  */
 
+#include <linux/arm-smccc.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/of_address.h>
@@ -11,16 +12,37 @@ 
 #include <linux/platform_device.h>
 #include <linux/of.h>
 
+#define REV_B0				0x20
 #define REV_B1				0x21
 
+#define IMX8MQ_ATF_GET_SOC_INFO		0xc2000006
 #define IMX8MQ_SW_INFO_B1		0x40
 #define IMX8MQ_SW_MAGIC_B1		0xff0055aa
 
+
 struct imx8_soc_data {
 	char *name;
 	u32 (*soc_revision)(void);
 };
 
+
+static u32 __init imx8mq_soc_revision_from_atf(void)
+{
+	struct arm_smccc_res res;
+	u32 digprog;
+
+	arm_smccc_smc(IMX8MQ_ATF_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res);
+	digprog = res.a0;
+	/*
+	 * Bit [23:16] is the silicon ID
+	 * Bit[7:4] is the base layer revision,
+	 * Bit[3:0] is the metal layer revision
+	 * e.g. 0x10 stands for Tapeout 1.0
+	 */
+	return digprog & 0xff;
+}
+
+
 static u32 __init imx8mq_soc_revision(void)
 {
 	struct device_node *np;
@@ -29,20 +51,23 @@  static u32 __init imx8mq_soc_revision(void)
 	u32 rev = 0;
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-ocotp");
-	if (!np)
-		goto out;
-
-	ocotp_base = of_iomap(np, 0);
-	WARN_ON(!ocotp_base);
-
-	magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1);
-	if (magic == IMX8MQ_SW_MAGIC_B1)
-		rev = REV_B1;
-
-	iounmap(ocotp_base);
+	if (np) {
+		ocotp_base = of_iomap(np, 0);
+		WARN_ON(!ocotp_base);
+
+		magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1);
+		iounmap(ocotp_base);
+		of_node_put(np);
+		if (magic == IMX8MQ_SW_MAGIC_B1)
+			rev = REV_B1;
+	}
 
+	if (!rev) {
+		magic = imx8mq_soc_revision_from_atf();
+		if (magic == REV_B0)
+			rev = REV_B0;
+	}
 out:
-	of_node_put(np);
 	return rev;
 }