soc: imx8mq: Read SOC revision from TF-A
authorLeonard Crestez <leonard.crestez@nxp.com>
Tue, 29 Oct 2019 23:17:39 +0000 (01:17 +0200)
committerShawn Guo <shawnguo@kernel.org>
Mon, 4 Nov 2019 03:32:12 +0000 (11:32 +0800)
SOC revision on older imx8mq is not available in fuses so on anything
other than B1 current code just reports "unknown".

TF-A already handles this by parsing the ROM and exposes the value
through a SMC call. Call this instead of reimplementing the workaround
in the kernel itself.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Reviewed-by: Abel Vesa <abel.vesa@nxp.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
drivers/soc/imx/soc-imx8.c

index fcbf745..d84ed73 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
 #include <linux/platform_device.h>
+#include <linux/arm-smccc.h>
 #include <linux/of.h>
 
 #define REV_B1                         0x21
@@ -16,6 +17,8 @@
 #define IMX8MQ_SW_INFO_B1              0x40
 #define IMX8MQ_SW_MAGIC_B1             0xff0055aa
 
+#define IMX_SIP_GET_SOC_INFO           0xc2000006
+
 #define OCOTP_UID_LOW                  0x410
 #define OCOTP_UID_HIGH                 0x420
 
@@ -29,6 +32,22 @@ struct imx8_soc_data {
 
 static u64 soc_uid;
 
+#ifdef CONFIG_HAVE_ARM_SMCCC
+static u32 imx8mq_soc_revision_from_atf(void)
+{
+       struct arm_smccc_res res;
+
+       arm_smccc_smc(IMX_SIP_GET_SOC_INFO, 0, 0, 0, 0, 0, 0, 0, &res);
+
+       if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
+               return 0;
+       else
+               return res.a0 & 0xff;
+}
+#else
+static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
+#endif
+
 static u32 __init imx8mq_soc_revision(void)
 {
        struct device_node *np;
@@ -43,9 +62,16 @@ static u32 __init imx8mq_soc_revision(void)
        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;
+       /*
+        * SOC revision on older imx8mq is not available in fuses so query
+        * the value from ATF instead.
+        */
+       rev = imx8mq_soc_revision_from_atf();
+       if (!rev) {
+               magic = readl_relaxed(ocotp_base + IMX8MQ_SW_INFO_B1);
+               if (magic == IMX8MQ_SW_MAGIC_B1)
+                       rev = REV_B1;
+       }
 
        soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
        soc_uid <<= 32;