plat: imx8mq: Implement IMX_SIP_GET_SOC_INFO
authorLeonard Crestez <leonard.crestez@nxp.com>
Fri, 10 May 2019 10:07:41 +0000 (13:07 +0300)
committerLeonard Crestez <leonard.crestez@nxp.com>
Mon, 20 May 2019 08:24:54 +0000 (11:24 +0300)
The manual documents that 0x3036006c should contains the soc revision
for imx8mq but this always reports A0. Work around this by parsing the
ROM header and checking if OCOTP register 0x40 is stuck at 0xff0055aa.

Determining this inside TF-A makes life easier for OS, see for example
this linux discussion: https://lkml.org/lkml/2019/5/3/465

The soc revision can also be useful inside TF-A itself, for example for
the non-upstream DDR DVFS "busfreq" feature is affected by 8mq erratas.

The clock for OCOTP block can be disabled by OS so only initialize soc
revision once at boot time.

Change-Id: I9ca3f27840229ce8a28b53870e44da29f63c73aa
Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
plat/imx/common/imx_sip_svc.c
plat/imx/common/include/imx_sip_svc.h
plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c
plat/imx/imx8m/imx8mq/include/platform_def.h

index c27fbf2e371dec5705221a53e057d90ad7f547cb..45d18eff0706cc96ab8d44d11b3419464f9994c5 100644 (file)
@@ -26,6 +26,11 @@ static uintptr_t imx_sip_handler(unsigned int smc_fid,
                        u_register_t flags)
 {
        switch (smc_fid) {
+#if defined(PLAT_imx8mq)
+       case IMX_SIP_GET_SOC_INFO:
+               SMC_RET1(handle, imx_soc_info_handler(smc_fid, x1, x2, x3));
+               break;
+#endif
 #if (defined(PLAT_IMX8QM) || defined(PLAT_IMX8QX))
        case  IMX_SIP_SRTC:
                return imx_srtc_handler(smc_fid, handle, x1, x2, x3, x4);
index afe62d4a98a2028bbabbad2c18f0d4c06965c090..f532840d7351af002ac95949736d7ca4b5386981 100644 (file)
@@ -17,6 +17,8 @@
 #define IMX_SIP_BUILDINFO                      0xC2000003
 #define IMX_SIP_BUILDINFO_GET_COMMITHASH       0x00
 
+#define IMX_SIP_GET_SOC_INFO           0xC2000006
+
 #define IMX_SIP_WAKEUP_SRC             0xC2000009
 #define IMX_SIP_WAKEUP_SRC_SCU         0x1
 #define IMX_SIP_WAKEUP_SRC_IRQSTEER    0x2
 
 #define IMX_SIP_MISC_SET_TEMP          0xC200000C
 
+#if defined(PLAT_imx8mq)
+int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1,
+                        u_register_t x2, u_register_t x3);
+#endif
+
 #if (defined(PLAT_IMX8QM) || defined(PLAT_IMX8QX))
 int imx_cpufreq_handler(uint32_t smc_fid, u_register_t x1,
                        u_register_t x2, u_register_t x3);
index eadf8811f8b9cc8b52130f2c25b0fda843f277fa..ea60466f7ebbdf2a3be9c6e9f8e024115932afeb 100644 (file)
@@ -27,6 +27,7 @@
 
 static const mmap_region_t imx_mmap[] = {
        MAP_REGION_FLAT(GPV_BASE, GPV_SIZE, MT_DEVICE | MT_RW), /* GPV map */
+       MAP_REGION_FLAT(IMX_ROM_BASE, IMX_ROM_SIZE, MT_MEMORY | MT_RO), /* ROM map */
        MAP_REGION_FLAT(IMX_AIPS_BASE, IMX_AIPS_SIZE, MT_DEVICE | MT_RW), /* AIPS map */
        MAP_REGION_FLAT(IMX_GIC_BASE, IMX_GIC_SIZE, MT_DEVICE | MT_RW), /* GIC map */
        {0},
@@ -35,6 +36,45 @@ static const mmap_region_t imx_mmap[] = {
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
+static uint32_t imx_soc_revision;
+
+int imx_soc_info_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2,
+                               u_register_t x3)
+{
+       return imx_soc_revision;
+}
+
+#define ANAMIX_DIGPROG         0x6c
+#define ROM_SOC_INFO_A0                0x800
+#define ROM_SOC_INFO_B0                0x83C
+#define OCOTP_SOC_INFO_B1      0x40
+
+static void imx8mq_soc_info_init(void)
+{
+       uint32_t rom_version;
+       uint32_t ocotp_val;
+
+       imx_soc_revision = mmio_read_32(IMX_ANAMIX_BASE + ANAMIX_DIGPROG);
+       rom_version = mmio_read_8(IMX_ROM_BASE + ROM_SOC_INFO_A0);
+       if (rom_version == 0x10)
+               return;
+
+       rom_version = mmio_read_8(IMX_ROM_BASE + ROM_SOC_INFO_B0);
+       if (rom_version == 0x20) {
+               imx_soc_revision &= ~0xff;
+               imx_soc_revision |= rom_version;
+               return;
+       }
+
+       /* 0xff0055aa is magic number for B1 */
+       ocotp_val = mmio_read_32(IMX_OCOTP_BASE + OCOTP_SOC_INFO_B1);
+       if (ocotp_val == 0xff0055aa) {
+               imx_soc_revision &= ~0xff;
+               imx_soc_revision |= 0x21;
+               return;
+       }
+}
+
 /* get SPSR for BL33 entry */
 static uint32_t get_spsr_for_bl33_entry(void)
 {
@@ -128,6 +168,9 @@ void bl31_platform_setup(void)
        plat_gic_driver_init();
        plat_gic_init();
 
+       /* determine SOC revision for erratas */
+       imx8mq_soc_info_init();
+
        /* gpc init */
        imx_gpc_init();
 }
index b54201edc7c831cff8f7456f2a9ac0b6d35c22a7..0e678ca84482e2c42d708356f01fbab7941b965b 100644 (file)
@@ -59,6 +59,7 @@
 #define IMX_AIPS_SIZE                  U(0xC00000)
 #define IMX_AIPS1_BASE                 U(0x30200000)
 #define IMX_AIPS3_ARB_BASE             U(0x30800000)
+#define IMX_OCOTP_BASE                 U(0x30350000)
 #define IMX_ANAMIX_BASE                        U(0x30360000)
 #define IMX_CCM_BASE                   U(0x30380000)
 #define IMX_SRC_BASE                   U(0x30390000)
@@ -73,7 +74,9 @@
 #define IMX_DDRC_BASE                  U(0x3d400000)
 #define IMX_DDRPHY_BASE                        U(0x3c000000)
 #define IMX_DDR_IPS_BASE               U(0x3d000000)
+
 #define IMX_ROM_BASE                   U(0x00000000)
+#define IMX_ROM_SIZE                   U(0x20000)
 
 #define AIPSTZ1_BASE                   U(0x301f0000)
 #define AIPSTZ2_BASE                   U(0x305f0000)